diff options
-rw-r--r-- | Makefile.objs | 1 | ||||
-rw-r--r-- | Makefile.target | 1 | ||||
-rw-r--r-- | cpu-all.h | 147 | ||||
-rw-r--r-- | cpus.c | 16 | ||||
-rw-r--r-- | exec-all.h | 14 | ||||
-rw-r--r-- | exec.c | 1 | ||||
-rw-r--r-- | gen-icount.h | 2 | ||||
-rw-r--r-- | linux-user/main.c | 2 | ||||
-rw-r--r-- | qemu-common.h | 8 | ||||
-rw-r--r-- | qemu-timer.c | 20 | ||||
-rw-r--r-- | qemu-timer.h | 167 | ||||
-rw-r--r-- | softmmu_template.h | 2 | ||||
-rw-r--r-- | translate-all.c | 1 |
13 files changed, 197 insertions, 185 deletions
diff --git a/Makefile.objs b/Makefile.objs index c02f9d5..7ac8920 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -105,6 +105,7 @@ common-obj-$(CONFIG_VNC_SASL) += vnc-auth-sasl.o common-obj-$(CONFIG_COCOA) += cocoa.o common-obj-$(CONFIG_IOTHREAD) += qemu-thread.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 += slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o diff --git a/Makefile.target b/Makefile.target index 5ed20ec..a90add6 100644 --- a/Makefile.target +++ b/Makefile.target @@ -162,7 +162,6 @@ endif #CONFIG_BSD_USER ifdef CONFIG_SOFTMMU 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. # need to fix this properly obj-y += virtio-blk.o virtio-balloon.o virtio-net.o virtio-serial-bus.o @@ -771,10 +771,6 @@ void QEMU_NORETURN cpu_abort(CPUState *env, const char *fmt, ...) extern CPUState *first_cpu; 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_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */ #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, 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 */ #ifdef CONFIG_PROFILER static inline int64_t profile_getclock(void) @@ -771,3 +771,19 @@ void set_cpu_log(const char *optarg) } 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); +} @@ -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; 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 typedef void (CPUDebugExcpHandler)(CPUState *env); @@ -38,6 +38,7 @@ #include "hw/hw.h" #include "osdep.h" #include "kvm.h" +#include "qemu-timer.h" #if defined(CONFIG_USER_ONLY) #include <qemu.h> #include <signal.h> diff --git a/gen-icount.h b/gen-icount.h index 3268f72..8879da6 100644 --- a/gen-icount.h +++ b/gen-icount.h @@ -1,3 +1,5 @@ +#include "qemu-timer.h" + /* Helpers for instruction counting code generation. */ static TCGArg *icount_arg; diff --git a/linux-user/main.c b/linux-user/main.c index e5ff8a9..ca49cc4 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -32,7 +32,7 @@ /* For tb_lock */ #include "exec-all.h" - +#include "qemu-timer.h" #include "envlist.h" #define DEBUG_LOGFILE "/tmp/qemu.log" diff --git a/qemu-common.h b/qemu-common.h index d881a39..d4b5b46 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -13,6 +13,10 @@ #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 cannot include the following headers without conflicts. This condition has 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) */ /* bottom halves */ -typedef struct QEMUBH QEMUBH; - typedef void QEMUBHFunc(void *opaque); void async_context_push(void); @@ -211,11 +213,9 @@ typedef struct CharDriverState CharDriverState; typedef struct MACAddr MACAddr; typedef struct VLANState VLANState; typedef struct VLANClientState VLANClientState; -typedef struct QEMUFile QEMUFile; typedef struct i2c_bus i2c_bus; typedef struct i2c_slave i2c_slave; typedef struct SMBusDevice SMBusDevice; -typedef struct QEMUTimer QEMUTimer; typedef struct PCIHostState PCIHostState; typedef struct PCIExpressHost PCIExpressHost; typedef struct PCIBus PCIBus; diff --git a/qemu-timer.c b/qemu-timer.c index e6076ca..bdc8206 100644 --- a/qemu-timer.c +++ b/qemu-timer.c @@ -53,16 +53,14 @@ #include <mmsystem.h> #endif -#include "cpu-defs.h" #include "qemu-timer.h" -#include "exec-all.h" /* 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. */ #define MAX_ICOUNT_SHIFT 10 /* 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_vm_timer; @@ -138,20 +136,6 @@ static int64_t get_clock(void) } #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 */ diff --git a/qemu-timer.h b/qemu-timer.h index fca11eb..a7eac98 100644 --- a/qemu-timer.h +++ b/qemu-timer.h @@ -1,6 +1,8 @@ #ifndef QEMU_TIMER_H #define QEMU_TIMER_H +#include "qemu-common.h" + /* timers */ 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_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 diff --git a/softmmu_template.h b/softmmu_template.h index ac9b9a9..2f37c34 100644 --- a/softmmu_template.h +++ b/softmmu_template.h @@ -16,6 +16,8 @@ * 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/>. */ +#include "qemu-timer.h" + #define DATA_SIZE (1 << SHIFT) #if DATA_SIZE == 8 diff --git a/translate-all.c b/translate-all.c index 8ef8a0b..6f8136b 100644 --- a/translate-all.c +++ b/translate-all.c @@ -29,6 +29,7 @@ #include "exec-all.h" #include "disas.h" #include "tcg.h" +#include "qemu-timer.h" /* code generation context */ TCGContext tcg_ctx; |