diff options
-rw-r--r-- | hw/pc.c | 7 | ||||
-rw-r--r-- | linux-user/main.c | 40 | ||||
-rw-r--r-- | target-i386/cpu.h | 2 | ||||
-rw-r--r-- | target-i386/helper.c | 13 | ||||
-rw-r--r-- | tests/qruncom.c | 5 |
5 files changed, 56 insertions, 11 deletions
@@ -57,6 +57,13 @@ static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data) pic_set_irq(13, 0); } +/* TSC handling */ + +uint64_t cpu_get_tsc(CPUX86State *env) +{ + return qemu_get_clock(vm_clock); +} + /* PC cmos mappings */ #define REG_EQUIPMENT_BYTE 0x14 diff --git a/linux-user/main.c b/linux-user/main.c index ae4f6a5ac7..c0759bfefc 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -99,10 +99,50 @@ int cpu_get_pic_interrupt(CPUState *env) return -1; } +/* timers for rdtsc */ + +#if defined(__i386__) + +int64_t cpu_get_real_ticks(void) +{ + int64_t val; + asm volatile ("rdtsc" : "=A" (val)); + return val; +} + +#elif defined(__x86_64__) + +int64_t cpu_get_real_ticks(void) +{ + uint32_t low,high; + int64_t val; + asm volatile("rdtsc" : "=a" (low), "=d" (high)); + val = high; + val <<= 32; + val |= low; + return val; +} + +#else + +static uint64_t emu_time; + +int64_t cpu_get_real_ticks(void) +{ + return emu_time++; +} + +#endif + #ifdef TARGET_I386 /***********************************************************/ /* CPUX86 core interface */ +uint64_t cpu_get_tsc(CPUX86State *env) +{ + return cpu_get_real_ticks(); +} + static void write_dt(void *ptr, unsigned long addr, unsigned long limit, int flags) { diff --git a/target-i386/cpu.h b/target-i386/cpu.h index 19340d2579..9f16a487f0 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -443,6 +443,8 @@ int cpu_x86_signal_handler(int host_signum, struct siginfo *info, void *puc); void cpu_x86_set_a20(CPUX86State *env, int a20_state); +uint64_t cpu_get_tsc(CPUX86State *env); + /* will be suppressed */ void cpu_x86_update_cr0(CPUX86State *env, uint32_t new_cr0); diff --git a/target-i386/helper.c b/target-i386/helper.c index f2305e32c4..5782babc20 100644 --- a/target-i386/helper.c +++ b/target-i386/helper.c @@ -1775,20 +1775,11 @@ void helper_invlpg(unsigned int addr) cpu_x86_flush_tlb(env, addr); } -/* rdtsc */ -#if !defined(__i386__) && !defined(__x86_64__) -uint64_t emu_time; -#endif - void helper_rdtsc(void) { uint64_t val; -#if defined(__i386__) || defined(__x86_64__) - asm volatile ("rdtsc" : "=A" (val)); -#else - /* better than nothing: the time increases */ - val = emu_time++; -#endif + + val = cpu_get_tsc(env); EAX = val; EDX = val >> 32; } diff --git a/tests/qruncom.c b/tests/qruncom.c index 491ecbc60e..fcc069f6d0 100644 --- a/tests/qruncom.c +++ b/tests/qruncom.c @@ -55,6 +55,11 @@ int cpu_get_pic_interrupt(CPUState *env) return -1; } +uint64_t cpu_get_tsc(CPUState *env) +{ + return 0; +} + static void set_gate(void *ptr, unsigned int type, unsigned int dpl, unsigned long addr, unsigned int sel) { |