mirror of https://github.com/xemu-project/xemu.git
Compile qemu-timer only once
Arrange various declarations so that also non-CPU code can access them, adjust users. Move CPU specific code to cpus.c. Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
This commit is contained in:
parent
5c4532ee78
commit
29e922b61f
|
@ -105,6 +105,7 @@ common-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o
|
||||||
common-obj-$(CONFIG_COCOA) += cocoa.o
|
common-obj-$(CONFIG_COCOA) += cocoa.o
|
||||||
common-obj-$(CONFIG_IOTHREAD) += qemu-thread.o
|
common-obj-$(CONFIG_IOTHREAD) += qemu-thread.o
|
||||||
common-obj-y += notify.o
|
common-obj-y += notify.o
|
||||||
|
common-obj-y += qemu-timer.o
|
||||||
|
|
||||||
slirp-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
|
slirp-obj-y = cksum.o if.o ip_icmp.o ip_input.o ip_output.o
|
||||||
slirp-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
|
slirp-obj-y += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o
|
||||||
|
|
|
@ -162,7 +162,6 @@ endif #CONFIG_BSD_USER
|
||||||
ifdef CONFIG_SOFTMMU
|
ifdef CONFIG_SOFTMMU
|
||||||
|
|
||||||
obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o
|
obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o
|
||||||
obj-y += qemu-timer.o
|
|
||||||
# virtio has to be here due to weird dependency between PCI and virtio-net.
|
# virtio has to be here due to weird dependency between PCI and virtio-net.
|
||||||
# need to fix this properly
|
# need to fix this properly
|
||||||
obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
|
obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o
|
||||||
|
|
147
cpu-all.h
147
cpu-all.h
|
@ -771,10 +771,6 @@ void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...)
|
||||||
extern CPUState *first_cpu;
|
extern CPUState *first_cpu;
|
||||||
extern CPUState *cpu_single_env;
|
extern CPUState *cpu_single_env;
|
||||||
|
|
||||||
int64_t qemu_icount_round(int64_t count);
|
|
||||||
extern int64_t qemu_icount;
|
|
||||||
extern int use_icount;
|
|
||||||
|
|
||||||
#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
|
#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
|
||||||
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
|
#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
|
||||||
#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
|
#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
|
||||||
|
@ -921,149 +917,6 @@ void dump_exec_info(FILE *f,
|
||||||
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
|
int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
|
||||||
uint8_t *buf, int len, int is_write);
|
uint8_t *buf, int len, int is_write);
|
||||||
|
|
||||||
/*******************************************/
|
|
||||||
/* host CPU ticks (if available) */
|
|
||||||
|
|
||||||
#if defined(_ARCH_PPC)
|
|
||||||
|
|
||||||
static inline int64_t cpu_get_real_ticks(void)
|
|
||||||
{
|
|
||||||
int64_t retval;
|
|
||||||
#ifdef _ARCH_PPC64
|
|
||||||
/* This reads timebase in one 64bit go and includes Cell workaround from:
|
|
||||||
http://ozlabs.org/pipermail/linuxppc-dev/2006-October/027052.html
|
|
||||||
*/
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"mftb %0\n\t"
|
|
||||||
"cmpwi %0,0\n\t"
|
|
||||||
"beq- $-8"
|
|
||||||
: "=r" (retval));
|
|
||||||
#else
|
|
||||||
/* http://ozlabs.org/pipermail/linuxppc-dev/1999-October/003889.html */
|
|
||||||
unsigned long junk;
|
|
||||||
__asm__ __volatile__ (
|
|
||||||
"mftbu %1\n\t"
|
|
||||||
"mftb %L0\n\t"
|
|
||||||
"mftbu %0\n\t"
|
|
||||||
"cmpw %0,%1\n\t"
|
|
||||||
"bne $-16"
|
|
||||||
: "=r" (retval), "=r" (junk));
|
|
||||||
#endif
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__i386__)
|
|
||||||
|
|
||||||
static inline int64_t cpu_get_real_ticks(void)
|
|
||||||
{
|
|
||||||
int64_t val;
|
|
||||||
asm volatile ("rdtsc" : "=A" (val));
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__x86_64__)
|
|
||||||
|
|
||||||
static inline 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__hppa__)
|
|
||||||
|
|
||||||
static inline int64_t cpu_get_real_ticks(void)
|
|
||||||
{
|
|
||||||
int val;
|
|
||||||
asm volatile ("mfctl %%cr16, %0" : "=r"(val));
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__ia64)
|
|
||||||
|
|
||||||
static inline int64_t cpu_get_real_ticks(void)
|
|
||||||
{
|
|
||||||
int64_t val;
|
|
||||||
asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__s390__)
|
|
||||||
|
|
||||||
static inline int64_t cpu_get_real_ticks(void)
|
|
||||||
{
|
|
||||||
int64_t val;
|
|
||||||
asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
|
|
||||||
|
|
||||||
static inline int64_t cpu_get_real_ticks (void)
|
|
||||||
{
|
|
||||||
#if defined(_LP64)
|
|
||||||
uint64_t rval;
|
|
||||||
asm volatile("rd %%tick,%0" : "=r"(rval));
|
|
||||||
return rval;
|
|
||||||
#else
|
|
||||||
union {
|
|
||||||
uint64_t i64;
|
|
||||||
struct {
|
|
||||||
uint32_t high;
|
|
||||||
uint32_t low;
|
|
||||||
} i32;
|
|
||||||
} rval;
|
|
||||||
asm volatile("rd %%tick,%1; srlx %1,32,%0"
|
|
||||||
: "=r"(rval.i32.high), "=r"(rval.i32.low));
|
|
||||||
return rval.i64;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__mips__) && \
|
|
||||||
((defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__))
|
|
||||||
/*
|
|
||||||
* binutils wants to use rdhwr only on mips32r2
|
|
||||||
* but as linux kernel emulate it, it's fine
|
|
||||||
* to use it.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
#define MIPS_RDHWR(rd, value) { \
|
|
||||||
__asm__ __volatile__ ( \
|
|
||||||
".set push\n\t" \
|
|
||||||
".set mips32r2\n\t" \
|
|
||||||
"rdhwr %0, "rd"\n\t" \
|
|
||||||
".set pop" \
|
|
||||||
: "=r" (value)); \
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int64_t cpu_get_real_ticks(void)
|
|
||||||
{
|
|
||||||
/* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */
|
|
||||||
uint32_t count;
|
|
||||||
static uint32_t cyc_per_count = 0;
|
|
||||||
|
|
||||||
if (!cyc_per_count)
|
|
||||||
MIPS_RDHWR("$3", cyc_per_count);
|
|
||||||
|
|
||||||
MIPS_RDHWR("$2", count);
|
|
||||||
return (int64_t)(count * cyc_per_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
/* The host CPU doesn't have an easily accessible cycle counter.
|
|
||||||
Just return a monotonically increasing value. This will be
|
|
||||||
totally wrong, but hopefully better than nothing. */
|
|
||||||
static inline int64_t cpu_get_real_ticks (void)
|
|
||||||
{
|
|
||||||
static int64_t ticks = 0;
|
|
||||||
return ticks++;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* profiling */
|
/* profiling */
|
||||||
#ifdef CONFIG_PROFILER
|
#ifdef CONFIG_PROFILER
|
||||||
static inline int64_t profile_getclock(void)
|
static inline int64_t profile_getclock(void)
|
||||||
|
|
16
cpus.c
16
cpus.c
|
@ -771,3 +771,19 @@ void set_cpu_log(const char *optarg)
|
||||||
}
|
}
|
||||||
cpu_set_log(mask);
|
cpu_set_log(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the virtual CPU time, based on the instruction counter. */
|
||||||
|
int64_t cpu_get_icount(void)
|
||||||
|
{
|
||||||
|
int64_t icount;
|
||||||
|
CPUState *env = cpu_single_env;;
|
||||||
|
|
||||||
|
icount = qemu_icount;
|
||||||
|
if (env) {
|
||||||
|
if (!can_do_io(env)) {
|
||||||
|
fprintf(stderr, "Bad clock read\n");
|
||||||
|
}
|
||||||
|
icount -= (env->icount_decr.u16.low + env->icount_extra);
|
||||||
|
}
|
||||||
|
return qemu_icount_bias + (icount << icount_time_shift);
|
||||||
|
}
|
||||||
|
|
14
exec-all.h
14
exec-all.h
|
@ -337,20 +337,6 @@ static inline tb_page_addr_t get_page_addr_code(CPUState *env1, target_ulong add
|
||||||
+ env1->tlb_table[mmu_idx][page_index].addend;
|
+ env1->tlb_table[mmu_idx][page_index].addend;
|
||||||
return qemu_ram_addr_from_host(p);
|
return qemu_ram_addr_from_host(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Deterministic execution requires that IO only be performed on the last
|
|
||||||
instruction of a TB so that interrupts take effect immediately. */
|
|
||||||
static inline int can_do_io(CPUState *env)
|
|
||||||
{
|
|
||||||
if (!use_icount)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
/* If not executing code then assume we are ok. */
|
|
||||||
if (!env->current_tb)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return env->can_do_io != 0;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
typedef void (CPUDebugExcpHandler)(CPUState *env);
|
typedef void (CPUDebugExcpHandler)(CPUState *env);
|
||||||
|
|
1
exec.c
1
exec.c
|
@ -38,6 +38,7 @@
|
||||||
#include "hw/hw.h"
|
#include "hw/hw.h"
|
||||||
#include "osdep.h"
|
#include "osdep.h"
|
||||||
#include "kvm.h"
|
#include "kvm.h"
|
||||||
|
#include "qemu-timer.h"
|
||||||
#if defined(CONFIG_USER_ONLY)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
#include <qemu.h>
|
#include <qemu.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
#include "qemu-timer.h"
|
||||||
|
|
||||||
/* Helpers for instruction counting code generation. */
|
/* Helpers for instruction counting code generation. */
|
||||||
|
|
||||||
static TCGArg *icount_arg;
|
static TCGArg *icount_arg;
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
/* For tb_lock */
|
/* For tb_lock */
|
||||||
#include "exec-all.h"
|
#include "exec-all.h"
|
||||||
|
|
||||||
|
#include "qemu-timer.h"
|
||||||
#include "envlist.h"
|
#include "envlist.h"
|
||||||
|
|
||||||
#define DEBUG_LOGFILE "/tmp/qemu.log"
|
#define DEBUG_LOGFILE "/tmp/qemu.log"
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
|
|
||||||
#define QEMU_BUILD_BUG_ON(x) typedef char __build_bug_on__##__LINE__[(x)?-1:1];
|
#define QEMU_BUILD_BUG_ON(x) typedef char __build_bug_on__##__LINE__[(x)?-1:1];
|
||||||
|
|
||||||
|
typedef struct QEMUTimer QEMUTimer;
|
||||||
|
typedef struct QEMUFile QEMUFile;
|
||||||
|
typedef struct QEMUBH QEMUBH;
|
||||||
|
|
||||||
/* Hack around the mess dyngen-exec.h causes: We need QEMU_NORETURN in files that
|
/* Hack around the mess dyngen-exec.h causes: We need QEMU_NORETURN in files that
|
||||||
cannot include the following headers without conflicts. This condition has
|
cannot include the following headers without conflicts. This condition has
|
||||||
to be removed once dyngen is gone. */
|
to be removed once dyngen is gone. */
|
||||||
|
@ -96,8 +100,6 @@ static inline char *realpath(const char *path, char *resolved_path)
|
||||||
#endif /* !defined(NEED_CPU_H) */
|
#endif /* !defined(NEED_CPU_H) */
|
||||||
|
|
||||||
/* bottom halves */
|
/* bottom halves */
|
||||||
typedef struct QEMUBH QEMUBH;
|
|
||||||
|
|
||||||
typedef void QEMUBHFunc(void *opaque);
|
typedef void QEMUBHFunc(void *opaque);
|
||||||
|
|
||||||
void async_context_push(void);
|
void async_context_push(void);
|
||||||
|
@ -211,11 +213,9 @@ typedef struct CharDriverState CharDriverState;
|
||||||
typedef struct MACAddr MACAddr;
|
typedef struct MACAddr MACAddr;
|
||||||
typedef struct VLANState VLANState;
|
typedef struct VLANState VLANState;
|
||||||
typedef struct VLANClientState VLANClientState;
|
typedef struct VLANClientState VLANClientState;
|
||||||
typedef struct QEMUFile QEMUFile;
|
|
||||||
typedef struct i2c_bus i2c_bus;
|
typedef struct i2c_bus i2c_bus;
|
||||||
typedef struct i2c_slave i2c_slave;
|
typedef struct i2c_slave i2c_slave;
|
||||||
typedef struct SMBusDevice SMBusDevice;
|
typedef struct SMBusDevice SMBusDevice;
|
||||||
typedef struct QEMUTimer QEMUTimer;
|
|
||||||
typedef struct PCIHostState PCIHostState;
|
typedef struct PCIHostState PCIHostState;
|
||||||
typedef struct PCIExpressHost PCIExpressHost;
|
typedef struct PCIExpressHost PCIExpressHost;
|
||||||
typedef struct PCIBus PCIBus;
|
typedef struct PCIBus PCIBus;
|
||||||
|
|
20
qemu-timer.c
20
qemu-timer.c
|
@ -53,16 +53,14 @@
|
||||||
#include <mmsystem.h>
|
#include <mmsystem.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "cpu-defs.h"
|
|
||||||
#include "qemu-timer.h"
|
#include "qemu-timer.h"
|
||||||
#include "exec-all.h"
|
|
||||||
|
|
||||||
/* Conversion factor from emulated instructions to virtual clock ticks. */
|
/* Conversion factor from emulated instructions to virtual clock ticks. */
|
||||||
static int icount_time_shift;
|
int icount_time_shift;
|
||||||
/* Arbitrarily pick 1MIPS as the minimum allowable speed. */
|
/* Arbitrarily pick 1MIPS as the minimum allowable speed. */
|
||||||
#define MAX_ICOUNT_SHIFT 10
|
#define MAX_ICOUNT_SHIFT 10
|
||||||
/* Compensate for varying guest execution speed. */
|
/* Compensate for varying guest execution speed. */
|
||||||
static int64_t qemu_icount_bias;
|
int64_t qemu_icount_bias;
|
||||||
static QEMUTimer *icount_rt_timer;
|
static QEMUTimer *icount_rt_timer;
|
||||||
static QEMUTimer *icount_vm_timer;
|
static QEMUTimer *icount_vm_timer;
|
||||||
|
|
||||||
|
@ -138,20 +136,6 @@ static int64_t get_clock(void)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Return the virtual CPU time, based on the instruction counter. */
|
|
||||||
static int64_t cpu_get_icount(void)
|
|
||||||
{
|
|
||||||
int64_t icount;
|
|
||||||
CPUState *env = cpu_single_env;;
|
|
||||||
icount = qemu_icount;
|
|
||||||
if (env) {
|
|
||||||
if (!can_do_io(env))
|
|
||||||
fprintf(stderr, "Bad clock read\n");
|
|
||||||
icount -= (env->icount_decr.u16.low + env->icount_extra);
|
|
||||||
}
|
|
||||||
return qemu_icount_bias + (icount << icount_time_shift);
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
/* guest cycle counter */
|
/* guest cycle counter */
|
||||||
|
|
||||||
|
|
167
qemu-timer.h
167
qemu-timer.h
|
@ -1,6 +1,8 @@
|
||||||
#ifndef QEMU_TIMER_H
|
#ifndef QEMU_TIMER_H
|
||||||
#define QEMU_TIMER_H
|
#define QEMU_TIMER_H
|
||||||
|
|
||||||
|
#include "qemu-common.h"
|
||||||
|
|
||||||
/* timers */
|
/* timers */
|
||||||
|
|
||||||
typedef struct QEMUClock QEMUClock;
|
typedef struct QEMUClock QEMUClock;
|
||||||
|
@ -69,4 +71,169 @@ void ptimer_stop(ptimer_state *s);
|
||||||
void qemu_put_ptimer(QEMUFile *f, ptimer_state *s);
|
void qemu_put_ptimer(QEMUFile *f, ptimer_state *s);
|
||||||
void qemu_get_ptimer(QEMUFile *f, ptimer_state *s);
|
void qemu_get_ptimer(QEMUFile *f, ptimer_state *s);
|
||||||
|
|
||||||
|
/* icount */
|
||||||
|
int64_t qemu_icount_round(int64_t count);
|
||||||
|
extern int64_t qemu_icount;
|
||||||
|
extern int use_icount;
|
||||||
|
extern int icount_time_shift;
|
||||||
|
extern int64_t qemu_icount_bias;
|
||||||
|
int64_t cpu_get_icount(void);
|
||||||
|
|
||||||
|
/*******************************************/
|
||||||
|
/* host CPU ticks (if available) */
|
||||||
|
|
||||||
|
#if defined(_ARCH_PPC)
|
||||||
|
|
||||||
|
static inline int64_t cpu_get_real_ticks(void)
|
||||||
|
{
|
||||||
|
int64_t retval;
|
||||||
|
#ifdef _ARCH_PPC64
|
||||||
|
/* This reads timebase in one 64bit go and includes Cell workaround from:
|
||||||
|
http://ozlabs.org/pipermail/linuxppc-dev/2006-October/027052.html
|
||||||
|
*/
|
||||||
|
__asm__ __volatile__ ("mftb %0\n\t"
|
||||||
|
"cmpwi %0,0\n\t"
|
||||||
|
"beq- $-8"
|
||||||
|
: "=r" (retval));
|
||||||
|
#else
|
||||||
|
/* http://ozlabs.org/pipermail/linuxppc-dev/1999-October/003889.html */
|
||||||
|
unsigned long junk;
|
||||||
|
__asm__ __volatile__ ("mftbu %1\n\t"
|
||||||
|
"mftb %L0\n\t"
|
||||||
|
"mftbu %0\n\t"
|
||||||
|
"cmpw %0,%1\n\t"
|
||||||
|
"bne $-16"
|
||||||
|
: "=r" (retval), "=r" (junk));
|
||||||
|
#endif
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__i386__)
|
||||||
|
|
||||||
|
static inline int64_t cpu_get_real_ticks(void)
|
||||||
|
{
|
||||||
|
int64_t val;
|
||||||
|
asm volatile ("rdtsc" : "=A" (val));
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__x86_64__)
|
||||||
|
|
||||||
|
static inline 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__hppa__)
|
||||||
|
|
||||||
|
static inline int64_t cpu_get_real_ticks(void)
|
||||||
|
{
|
||||||
|
int val;
|
||||||
|
asm volatile ("mfctl %%cr16, %0" : "=r"(val));
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__ia64)
|
||||||
|
|
||||||
|
static inline int64_t cpu_get_real_ticks(void)
|
||||||
|
{
|
||||||
|
int64_t val;
|
||||||
|
asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__s390__)
|
||||||
|
|
||||||
|
static inline int64_t cpu_get_real_ticks(void)
|
||||||
|
{
|
||||||
|
int64_t val;
|
||||||
|
asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__sparc_v8plus__) || defined(__sparc_v8plusa__) || defined(__sparc_v9__)
|
||||||
|
|
||||||
|
static inline int64_t cpu_get_real_ticks (void)
|
||||||
|
{
|
||||||
|
#if defined(_LP64)
|
||||||
|
uint64_t rval;
|
||||||
|
asm volatile("rd %%tick,%0" : "=r"(rval));
|
||||||
|
return rval;
|
||||||
|
#else
|
||||||
|
union {
|
||||||
|
uint64_t i64;
|
||||||
|
struct {
|
||||||
|
uint32_t high;
|
||||||
|
uint32_t low;
|
||||||
|
} i32;
|
||||||
|
} rval;
|
||||||
|
asm volatile("rd %%tick,%1; srlx %1,32,%0"
|
||||||
|
: "=r"(rval.i32.high), "=r"(rval.i32.low));
|
||||||
|
return rval.i64;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif defined(__mips__) && \
|
||||||
|
((defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__))
|
||||||
|
/*
|
||||||
|
* binutils wants to use rdhwr only on mips32r2
|
||||||
|
* but as linux kernel emulate it, it's fine
|
||||||
|
* to use it.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define MIPS_RDHWR(rd, value) { \
|
||||||
|
__asm__ __volatile__ (".set push\n\t" \
|
||||||
|
".set mips32r2\n\t" \
|
||||||
|
"rdhwr %0, "rd"\n\t" \
|
||||||
|
".set pop" \
|
||||||
|
: "=r" (value)); \
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int64_t cpu_get_real_ticks(void)
|
||||||
|
{
|
||||||
|
/* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */
|
||||||
|
uint32_t count;
|
||||||
|
static uint32_t cyc_per_count = 0;
|
||||||
|
|
||||||
|
if (!cyc_per_count) {
|
||||||
|
MIPS_RDHWR("$3", cyc_per_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
MIPS_RDHWR("$2", count);
|
||||||
|
return (int64_t)(count * cyc_per_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
/* The host CPU doesn't have an easily accessible cycle counter.
|
||||||
|
Just return a monotonically increasing value. This will be
|
||||||
|
totally wrong, but hopefully better than nothing. */
|
||||||
|
static inline int64_t cpu_get_real_ticks (void)
|
||||||
|
{
|
||||||
|
static int64_t ticks = 0;
|
||||||
|
return ticks++;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef NEED_CPU_H
|
||||||
|
/* Deterministic execution requires that IO only be performed on the last
|
||||||
|
instruction of a TB so that interrupts take effect immediately. */
|
||||||
|
static inline int can_do_io(CPUState *env)
|
||||||
|
{
|
||||||
|
if (!use_icount)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* If not executing code then assume we are ok. */
|
||||||
|
if (!env->current_tb)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return env->can_do_io != 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
* You should have received a copy of the GNU Lesser General Public
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
#include "qemu-timer.h"
|
||||||
|
|
||||||
#define DATA_SIZE (1 << SHIFT)
|
#define DATA_SIZE (1 << SHIFT)
|
||||||
|
|
||||||
#if DATA_SIZE == 8
|
#if DATA_SIZE == 8
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#include "exec-all.h"
|
#include "exec-all.h"
|
||||||
#include "disas.h"
|
#include "disas.h"
|
||||||
#include "tcg.h"
|
#include "tcg.h"
|
||||||
|
#include "qemu-timer.h"
|
||||||
|
|
||||||
/* code generation context */
|
/* code generation context */
|
||||||
TCGContext tcg_ctx;
|
TCGContext tcg_ctx;
|
||||||
|
|
Loading…
Reference in New Issue