mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
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
13 changed files with 197 additions and 185 deletions
|
@ -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
|
||||
|
|
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 *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)
|
||||
|
|
16
cpus.c
16
cpus.c
|
@ -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);
|
||||
}
|
||||
|
|
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;
|
||||
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);
|
||||
|
|
1
exec.c
1
exec.c
|
@ -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>
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#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;
|
||||
|
|
20
qemu-timer.c
20
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 */
|
||||
|
||||
|
|
167
qemu-timer.h
167
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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue