Commit 29e922b6 authored by Blue Swirl's avatar Blue Swirl

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: default avatarBlue Swirl <blauwirbel@gmail.com>
parent 5c4532ee
......@@ -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
......
......@@ -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>
......
#include "qemu-timer.h"
/* Helpers for instruction counting code generation. */
static TCGArg *icount_arg;
......
......@@ -32,7 +32,7 @@
/* For tb_lock */
#include "exec-all.h"
#include "qemu-timer.h"
#include "envlist.h"
#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];
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;
......
......@@ -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 */
......
#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
......@@ -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
......
......@@ -29,6 +29,7 @@
#include "exec-all.h"
#include "disas.h"
#include "tcg.h"
#include "qemu-timer.h"
/* code generation context */
TCGContext tcg_ctx;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment