From 2b75cff78732867b2007fc7f78ad2d66865ec79b Mon Sep 17 00:00:00 2001 From: Fabian Date: Sun, 28 Jan 2018 14:02:00 -0600 Subject: [PATCH] Make tsc_offset 64-bit integer, save and restore it correctly --- src/cpu.js | 13 +++++++++---- src/native/cpu.c | 17 ++++++++++++++--- src/native/cpu.h | 1 + src/native/global_pointers.h | 6 ++++-- src/native/instructions_0f.c | 8 ++------ 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/src/cpu.js b/src/cpu.js index 617c3eb6..87df5cf0 100644 --- a/src/cpu.js +++ b/src/cpu.js @@ -148,7 +148,8 @@ function CPU(bus, wm, codegen, coverage_logger) this.mul32_result = new Int32Array(wm.memory.buffer, 544, 2); this.div32_result = new Float64Array(2); - this.tsc_offset = new Int32Array(wm.memory.buffer, 652, 1); + this.tsc_offset = new Uint32Array(wm.memory.buffer, 544, 2); // 64 bit + this.current_tsc = new Uint32Array(wm.memory.buffer, 956, 2); // 64 bit this.phys_addr = new Int32Array(wm.memory.buffer, 656, 1); @@ -240,7 +241,7 @@ function CPU(bus, wm, codegen, coverage_logger) this.update_operand_size(); - this.tsc_offset[0] = v86.microtick(); + wm.exports["_set_tsc"](0, 0); this.debug_init(); @@ -369,6 +370,9 @@ CPU.prototype.get_state = function() state[41] = this.dreg; state[42] = this.mem8; + this.wm.exports["_store_current_tsc"](); + state[43] = this.current_tsc; + state[45] = this.devices.virtio; state[46] = this.devices.apic; state[47] = this.devices.rtc; @@ -453,6 +457,8 @@ CPU.prototype.set_state = function(state) this.dreg.set(state[41]); this.mem8.set(state[42]); + this.wm.exports["_set_tsc"](state[43][0], state[43][1]); + this.devices.virtio = state[45]; this.devices.apic = state[46]; this.devices.rtc = state[47]; @@ -491,7 +497,6 @@ CPU.prototype.set_state = function(state) this.fpu_opcode[0] = state[75]; this.full_clear_tlb(); - // tsc_offset? this.update_operand_size(); }; @@ -628,7 +633,7 @@ CPU.prototype.reset = function() this.last_op2.fill(0); this.last_op_size.fill(0); - this.tsc_offset[0] = v86.microtick(); + this.wm.exports["_set_tsc"](0, 0); this.instruction_pointer[0] = 0xFFFF0; this.switch_cs_real_mode(0xF000); diff --git a/src/native/cpu.c b/src/native/cpu.c index a83e8713..5d2cba24 100644 --- a/src/native/cpu.c +++ b/src/native/cpu.c @@ -1241,9 +1241,20 @@ int32_t decr_ecx_asize() return is_asize_32() ? --reg32s[ECX] : --reg16[CX]; } +void set_tsc(uint32_t low, uint32_t high) +{ + uint64_t new_value = low | (uint64_t)high << 32; + uint64_t current_value = read_tsc(); + *tsc_offset = current_value - new_value; +} + uint64_t read_tsc() { - double_t n = microtick() - tsc_offset[0]; // XXX: float - n = n * TSC_RATE; - return n; + double_t n = microtick() * TSC_RATE; + return (uint64_t)n - *tsc_offset; +} + +void store_current_tsc() +{ + *current_tsc = read_tsc(); } diff --git a/src/native/cpu.h b/src/native/cpu.h index be27bde8..ffe575e0 100644 --- a/src/native/cpu.h +++ b/src/native/cpu.h @@ -133,6 +133,7 @@ int32_t get_reg_asize(int32_t reg); void set_ecx_asize(int32_t value); void add_reg_asize(int32_t reg, int32_t value); int32_t decr_ecx_asize(void); +void set_tsc(uint32_t, uint32_t); uint64_t read_tsc(void); bool vm86_mode(void); int32_t getiopl(void); diff --git a/src/native/global_pointers.h b/src/native/global_pointers.h index efa4a8ac..dd8e3dc9 100644 --- a/src/native/global_pointers.h +++ b/src/native/global_pointers.h @@ -23,7 +23,7 @@ static int32_t* const flags = (int32_t* const) 536; static bool* const page_fault = (bool* const) 540; -// gap 12 +static uint64_t* const tsc_offset = (uint64_t* const) 544; static bool* const a20_enabled = (bool* const) 552; static int32_t* const instruction_pointer = (int32_t* const) 556; @@ -45,7 +45,7 @@ static int32_t* const sysenter_cs = (int32_t* const) 636; static int32_t* const sysenter_esp = (int32_t* const) 640; static int32_t* const sysenter_eip = (int32_t* const) 644; static uint8_t* const prefixes = (uint8_t* const) 648; -static int32_t* const tsc_offset = (int32_t* const) 652; +// gap static int32_t* const phys_addr = (int32_t* const) 656; static int32_t* const phys_addr_high = (int32_t* const) 660; static uint32_t* const timestamp_counter = (uint32_t* const) 664; @@ -69,6 +69,8 @@ static int32_t* const mxcsr = (int32_t* const) 824; static union reg128* const reg_xmm = (union reg128* const) 828; // length 128 +static uint64_t* const current_tsc = (uint64_t* const) 956; + static uint8_t* const codegen_buffers = (uint8_t* const) 2048; // length 2048 static uint8_t* const tlb_info = (uint8_t* const) 4096; // length 0x100000 diff --git a/src/native/instructions_0f.c b/src/native/instructions_0f.c index 768c2127..ee2d6fd3 100644 --- a/src/native/instructions_0f.c +++ b/src/native/instructions_0f.c @@ -736,10 +736,7 @@ void instr_0F30() { break; case IA32_TIME_STAMP_COUNTER: - { - uint64_t new_tick = (low) + 0x100000000 * (high); - tsc_offset[0] = microtick() - new_tick / TSC_RATE; // XXX: float - } + set_tsc(low, high); break; case IA32_BIOS_SIGN_ID: @@ -768,13 +765,12 @@ void instr_0F31() { if(!cpl[0] || !(cr[4] & CR4_TSD)) { - //dbg_assert(isFinite(n), "non-finite tsc: " + n); uint64_t tsc = read_tsc(); reg32s[EAX] = tsc; reg32s[EDX] = tsc >> 32; - //dbg_log("rdtsc edx:eax=" + h(reg32[EDX], 8) + ":" + h(reg32[EAX], 8)); + //dbg_log("rdtsc edx:eax=%x:%x", reg32s[EDX], reg32s[EAX]); } else {