aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--hw/pc.c7
-rw-r--r--linux-user/main.c40
-rw-r--r--target-i386/cpu.h2
-rw-r--r--target-i386/helper.c13
-rw-r--r--tests/qruncom.c5
5 files changed, 56 insertions, 11 deletions
diff --git a/hw/pc.c b/hw/pc.c
index 895f3e1bd2..75a590bfbb 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -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)
{