mirror of https://github.com/xemu-project/xemu.git
new clock logic: cpu ticks and virtual clocks are no longer proportional - added timestamps on the stdio console
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2049 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
effedbc915
commit
1dce7c3c22
13
hw/pc.c
13
hw/pc.c
|
@ -58,10 +58,19 @@ static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TSC handling */
|
/* TSC handling */
|
||||||
|
|
||||||
uint64_t cpu_get_tsc(CPUX86State *env)
|
uint64_t cpu_get_tsc(CPUX86State *env)
|
||||||
{
|
{
|
||||||
return qemu_get_clock(vm_clock);
|
/* Note: when using kqemu, it is more logical to return the host TSC
|
||||||
|
because kqemu does not trap the RDTSC instruction for
|
||||||
|
performance reasons */
|
||||||
|
#if USE_KQEMU
|
||||||
|
if (env->kqemu_enabled) {
|
||||||
|
return cpu_get_real_ticks();
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
return cpu_get_ticks();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* IRQ handling */
|
/* IRQ handling */
|
||||||
|
|
|
@ -107,29 +107,7 @@ int cpu_get_pic_interrupt(CPUState *env)
|
||||||
|
|
||||||
/* timers for rdtsc */
|
/* timers for rdtsc */
|
||||||
|
|
||||||
#if defined(__i386__)
|
#if 0
|
||||||
|
|
||||||
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;
|
static uint64_t emu_time;
|
||||||
|
|
||||||
|
|
380
vl.c
380
vl.c
|
@ -482,184 +482,6 @@ int kbd_mouse_is_absolute(void)
|
||||||
return qemu_put_mouse_event_absolute;
|
return qemu_put_mouse_event_absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************/
|
|
||||||
/* timers */
|
|
||||||
|
|
||||||
#if defined(__powerpc__)
|
|
||||||
|
|
||||||
static inline uint32_t get_tbl(void)
|
|
||||||
{
|
|
||||||
uint32_t tbl;
|
|
||||||
asm volatile("mftb %0" : "=r" (tbl));
|
|
||||||
return tbl;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t get_tbu(void)
|
|
||||||
{
|
|
||||||
uint32_t tbl;
|
|
||||||
asm volatile("mftbu %0" : "=r" (tbl));
|
|
||||||
return tbl;
|
|
||||||
}
|
|
||||||
|
|
||||||
int64_t cpu_get_real_ticks(void)
|
|
||||||
{
|
|
||||||
uint32_t l, h, h1;
|
|
||||||
/* NOTE: we test if wrapping has occurred */
|
|
||||||
do {
|
|
||||||
h = get_tbu();
|
|
||||||
l = get_tbl();
|
|
||||||
h1 = get_tbu();
|
|
||||||
} while (h != h1);
|
|
||||||
return ((int64_t)h << 32) | l;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__i386__)
|
|
||||||
|
|
||||||
int64_t cpu_get_real_ticks(void)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32
|
|
||||||
LARGE_INTEGER ti;
|
|
||||||
QueryPerformanceCounter(&ti);
|
|
||||||
return ti.QuadPart;
|
|
||||||
#else
|
|
||||||
int64_t val;
|
|
||||||
asm volatile ("rdtsc" : "=A" (val));
|
|
||||||
return val;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__ia64)
|
|
||||||
|
|
||||||
int64_t cpu_get_real_ticks(void)
|
|
||||||
{
|
|
||||||
int64_t val;
|
|
||||||
asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif defined(__s390__)
|
|
||||||
|
|
||||||
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__) && defined(HOST_SOLARIS)
|
|
||||||
|
|
||||||
uint64_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
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
#error unsupported CPU
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static int64_t cpu_ticks_prev;
|
|
||||||
static int64_t cpu_ticks_offset;
|
|
||||||
static int cpu_ticks_enabled;
|
|
||||||
|
|
||||||
static inline int64_t cpu_get_ticks(void)
|
|
||||||
{
|
|
||||||
if (!cpu_ticks_enabled) {
|
|
||||||
return cpu_ticks_offset;
|
|
||||||
} else {
|
|
||||||
int64_t ticks;
|
|
||||||
ticks = cpu_get_real_ticks();
|
|
||||||
if (cpu_ticks_prev > ticks) {
|
|
||||||
/* Note: non increasing ticks may happen if the host uses
|
|
||||||
software suspend */
|
|
||||||
cpu_ticks_offset += cpu_ticks_prev - ticks;
|
|
||||||
}
|
|
||||||
cpu_ticks_prev = ticks;
|
|
||||||
return ticks + cpu_ticks_offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* enable cpu_get_ticks() */
|
|
||||||
void cpu_enable_ticks(void)
|
|
||||||
{
|
|
||||||
if (!cpu_ticks_enabled) {
|
|
||||||
cpu_ticks_offset -= cpu_get_real_ticks();
|
|
||||||
cpu_ticks_enabled = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* disable cpu_get_ticks() : the clock is stopped. You must not call
|
|
||||||
cpu_get_ticks() after that. */
|
|
||||||
void cpu_disable_ticks(void)
|
|
||||||
{
|
|
||||||
if (cpu_ticks_enabled) {
|
|
||||||
cpu_ticks_offset = cpu_get_ticks();
|
|
||||||
cpu_ticks_enabled = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
void cpu_calibrate_ticks(void)
|
|
||||||
{
|
|
||||||
LARGE_INTEGER freq;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = QueryPerformanceFrequency(&freq);
|
|
||||||
if (ret == 0) {
|
|
||||||
fprintf(stderr, "Could not calibrate ticks\n");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
ticks_per_sec = freq.QuadPart;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
static int64_t get_clock(void)
|
|
||||||
{
|
|
||||||
struct timeval tv;
|
|
||||||
gettimeofday(&tv, NULL);
|
|
||||||
return tv.tv_sec * 1000000LL + tv.tv_usec;
|
|
||||||
}
|
|
||||||
|
|
||||||
void cpu_calibrate_ticks(void)
|
|
||||||
{
|
|
||||||
int64_t usec, ticks;
|
|
||||||
|
|
||||||
usec = get_clock();
|
|
||||||
ticks = cpu_get_real_ticks();
|
|
||||||
usleep(50 * 1000);
|
|
||||||
usec = get_clock() - usec;
|
|
||||||
ticks = cpu_get_real_ticks() - ticks;
|
|
||||||
ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;
|
|
||||||
}
|
|
||||||
#endif /* !_WIN32 */
|
|
||||||
|
|
||||||
/* compute with 96 bit intermediate result: (a*b)/c */
|
/* compute with 96 bit intermediate result: (a*b)/c */
|
||||||
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
|
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
|
||||||
{
|
{
|
||||||
|
@ -684,6 +506,131 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
|
||||||
return res.ll;
|
return res.ll;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************/
|
||||||
|
/* real time host monotonic timer */
|
||||||
|
|
||||||
|
#define QEMU_TIMER_BASE 1000000000LL
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
|
||||||
|
static int64_t clock_freq;
|
||||||
|
|
||||||
|
static void init_get_clock(void)
|
||||||
|
{
|
||||||
|
ret = QueryPerformanceFrequency(&freq);
|
||||||
|
if (ret == 0) {
|
||||||
|
fprintf(stderr, "Could not calibrate ticks\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
clock_freq = freq.QuadPart;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t get_clock(void)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER ti;
|
||||||
|
QueryPerformanceCounter(&ti);
|
||||||
|
return muldiv64(ti.QuadPart, QEMU_TIMER_BASE, clock_freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static int use_rt_clock;
|
||||||
|
|
||||||
|
static void init_get_clock(void)
|
||||||
|
{
|
||||||
|
use_rt_clock = 0;
|
||||||
|
#if defined(__linux__)
|
||||||
|
{
|
||||||
|
struct timespec ts;
|
||||||
|
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
|
||||||
|
use_rt_clock = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static int64_t get_clock(void)
|
||||||
|
{
|
||||||
|
#if defined(__linux__)
|
||||||
|
if (use_rt_clock) {
|
||||||
|
struct timespec ts;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||||
|
return ts.tv_sec * 1000000000LL + ts.tv_nsec;
|
||||||
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
/* XXX: using gettimeofday leads to problems if the date
|
||||||
|
changes, so it should be avoided. */
|
||||||
|
struct timeval tv;
|
||||||
|
gettimeofday(&tv, NULL);
|
||||||
|
return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/***********************************************************/
|
||||||
|
/* guest cycle counter */
|
||||||
|
|
||||||
|
static int64_t cpu_ticks_prev;
|
||||||
|
static int64_t cpu_ticks_offset;
|
||||||
|
static int64_t cpu_clock_offset;
|
||||||
|
static int cpu_ticks_enabled;
|
||||||
|
|
||||||
|
/* return the host CPU cycle counter and handle stop/restart */
|
||||||
|
int64_t cpu_get_ticks(void)
|
||||||
|
{
|
||||||
|
if (!cpu_ticks_enabled) {
|
||||||
|
return cpu_ticks_offset;
|
||||||
|
} else {
|
||||||
|
int64_t ticks;
|
||||||
|
ticks = cpu_get_real_ticks();
|
||||||
|
if (cpu_ticks_prev > ticks) {
|
||||||
|
/* Note: non increasing ticks may happen if the host uses
|
||||||
|
software suspend */
|
||||||
|
cpu_ticks_offset += cpu_ticks_prev - ticks;
|
||||||
|
}
|
||||||
|
cpu_ticks_prev = ticks;
|
||||||
|
return ticks + cpu_ticks_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* return the host CPU monotonic timer and handle stop/restart */
|
||||||
|
static int64_t cpu_get_clock(void)
|
||||||
|
{
|
||||||
|
int64_t ti;
|
||||||
|
if (!cpu_ticks_enabled) {
|
||||||
|
return cpu_clock_offset;
|
||||||
|
} else {
|
||||||
|
ti = get_clock();
|
||||||
|
return ti + cpu_clock_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable cpu_get_ticks() */
|
||||||
|
void cpu_enable_ticks(void)
|
||||||
|
{
|
||||||
|
if (!cpu_ticks_enabled) {
|
||||||
|
cpu_ticks_offset -= cpu_get_real_ticks();
|
||||||
|
cpu_clock_offset -= get_clock();
|
||||||
|
cpu_ticks_enabled = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* disable cpu_get_ticks() : the clock is stopped. You must not call
|
||||||
|
cpu_get_ticks() after that. */
|
||||||
|
void cpu_disable_ticks(void)
|
||||||
|
{
|
||||||
|
if (cpu_ticks_enabled) {
|
||||||
|
cpu_ticks_offset = cpu_get_ticks();
|
||||||
|
cpu_clock_offset = cpu_get_clock();
|
||||||
|
cpu_ticks_enabled = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********************************************************/
|
||||||
|
/* timers */
|
||||||
|
|
||||||
#define QEMU_TIMER_REALTIME 0
|
#define QEMU_TIMER_REALTIME 0
|
||||||
#define QEMU_TIMER_VIRTUAL 1
|
#define QEMU_TIMER_VIRTUAL 1
|
||||||
|
|
||||||
|
@ -822,28 +769,21 @@ int64_t qemu_get_clock(QEMUClock *clock)
|
||||||
{
|
{
|
||||||
switch(clock->type) {
|
switch(clock->type) {
|
||||||
case QEMU_TIMER_REALTIME:
|
case QEMU_TIMER_REALTIME:
|
||||||
#ifdef _WIN32
|
return get_clock() / 1000000;
|
||||||
return GetTickCount();
|
|
||||||
#else
|
|
||||||
{
|
|
||||||
struct tms tp;
|
|
||||||
|
|
||||||
/* Note that using gettimeofday() is not a good solution
|
|
||||||
for timers because its value change when the date is
|
|
||||||
modified. */
|
|
||||||
if (timer_freq == 100) {
|
|
||||||
return times(&tp) * 10;
|
|
||||||
} else {
|
|
||||||
return ((int64_t)times(&tp) * 1000) / timer_freq;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
default:
|
default:
|
||||||
case QEMU_TIMER_VIRTUAL:
|
case QEMU_TIMER_VIRTUAL:
|
||||||
return cpu_get_ticks();
|
return cpu_get_clock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void init_timers(void)
|
||||||
|
{
|
||||||
|
init_get_clock();
|
||||||
|
ticks_per_sec = QEMU_TIMER_BASE;
|
||||||
|
rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);
|
||||||
|
vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);
|
||||||
|
}
|
||||||
|
|
||||||
/* save a timer */
|
/* save a timer */
|
||||||
void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
|
void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
|
||||||
{
|
{
|
||||||
|
@ -985,11 +925,8 @@ static int start_rtc_timer(void)
|
||||||
|
|
||||||
#endif /* !defined(_WIN32) */
|
#endif /* !defined(_WIN32) */
|
||||||
|
|
||||||
static void init_timers(void)
|
static void init_timer_alarm(void)
|
||||||
{
|
{
|
||||||
rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);
|
|
||||||
vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
{
|
{
|
||||||
int count=0;
|
int count=0;
|
||||||
|
@ -1354,7 +1291,9 @@ CharDriverState *qemu_chr_open_pipe(const char *filename)
|
||||||
|
|
||||||
static int term_got_escape, client_index;
|
static int term_got_escape, client_index;
|
||||||
static uint8_t term_fifo[TERM_FIFO_MAX_SIZE];
|
static uint8_t term_fifo[TERM_FIFO_MAX_SIZE];
|
||||||
int term_fifo_size;
|
static int term_fifo_size;
|
||||||
|
static int term_timestamps;
|
||||||
|
static int64_t term_timestamps_start;
|
||||||
|
|
||||||
void term_print_help(void)
|
void term_print_help(void)
|
||||||
{
|
{
|
||||||
|
@ -1363,6 +1302,7 @@ void term_print_help(void)
|
||||||
"C-a x exit emulator\n"
|
"C-a x exit emulator\n"
|
||||||
"C-a s save disk data back to file (if -snapshot)\n"
|
"C-a s save disk data back to file (if -snapshot)\n"
|
||||||
"C-a b send break (magic sysrq)\n"
|
"C-a b send break (magic sysrq)\n"
|
||||||
|
"C-a t toggle console timestamps\n"
|
||||||
"C-a c switch between console and monitor\n"
|
"C-a c switch between console and monitor\n"
|
||||||
"C-a C-a send C-a\n"
|
"C-a C-a send C-a\n"
|
||||||
);
|
);
|
||||||
|
@ -1409,6 +1349,10 @@ static void stdio_received_byte(int ch)
|
||||||
goto send_char;
|
goto send_char;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 't':
|
||||||
|
term_timestamps = !term_timestamps;
|
||||||
|
term_timestamps_start = -1;
|
||||||
|
break;
|
||||||
case TERM_ESCAPE:
|
case TERM_ESCAPE:
|
||||||
goto send_char;
|
goto send_char;
|
||||||
}
|
}
|
||||||
|
@ -1466,6 +1410,39 @@ static void stdio_read(void *opaque)
|
||||||
stdio_received_byte(buf[0]);
|
stdio_received_byte(buf[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||||
|
{
|
||||||
|
FDCharDriver *s = chr->opaque;
|
||||||
|
if (!term_timestamps) {
|
||||||
|
return unix_write(s->fd_out, buf, len);
|
||||||
|
} else {
|
||||||
|
int i;
|
||||||
|
char buf1[64];
|
||||||
|
|
||||||
|
for(i = 0; i < len; i++) {
|
||||||
|
unix_write(s->fd_out, buf + i, 1);
|
||||||
|
if (buf[i] == '\n') {
|
||||||
|
int64_t ti;
|
||||||
|
int secs;
|
||||||
|
|
||||||
|
ti = get_clock();
|
||||||
|
if (term_timestamps_start == -1)
|
||||||
|
term_timestamps_start = ti;
|
||||||
|
ti -= term_timestamps_start;
|
||||||
|
secs = ti / 1000000000;
|
||||||
|
snprintf(buf1, sizeof(buf1),
|
||||||
|
"[%02d:%02d:%02d.%03d] ",
|
||||||
|
secs / 3600,
|
||||||
|
(secs / 60) % 60,
|
||||||
|
secs % 60,
|
||||||
|
(int)((ti / 1000000) % 1000));
|
||||||
|
unix_write(s->fd_out, buf1, strlen(buf1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* init terminal so that we can grab keys */
|
/* init terminal so that we can grab keys */
|
||||||
static struct termios oldtty;
|
static struct termios oldtty;
|
||||||
static int old_fd0_flags;
|
static int old_fd0_flags;
|
||||||
|
@ -1511,6 +1488,7 @@ CharDriverState *qemu_chr_open_stdio(void)
|
||||||
if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
|
if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
|
||||||
return NULL;
|
return NULL;
|
||||||
chr = qemu_chr_open_fd(0, 1);
|
chr = qemu_chr_open_fd(0, 1);
|
||||||
|
chr->chr_write = stdio_write;
|
||||||
if (stdio_nb_clients == 0)
|
if (stdio_nb_clients == 0)
|
||||||
qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, NULL);
|
qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, NULL);
|
||||||
client_index = stdio_nb_clients;
|
client_index = stdio_nb_clients;
|
||||||
|
@ -5638,6 +5616,7 @@ int main(int argc, char **argv)
|
||||||
SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
|
SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
|
||||||
#endif
|
#endif
|
||||||
init_timers();
|
init_timers();
|
||||||
|
init_timer_alarm();
|
||||||
|
|
||||||
register_machines();
|
register_machines();
|
||||||
machine = first_machine;
|
machine = first_machine;
|
||||||
|
@ -6128,7 +6107,6 @@ int main(int argc, char **argv)
|
||||||
register_savevm("ram", 0, 1, ram_save, ram_load, NULL);
|
register_savevm("ram", 0, 1, ram_save, ram_load, NULL);
|
||||||
|
|
||||||
init_ioports();
|
init_ioports();
|
||||||
cpu_calibrate_ticks();
|
|
||||||
|
|
||||||
/* terminal init */
|
/* terminal init */
|
||||||
if (nographic) {
|
if (nographic) {
|
||||||
|
|
1
vl.h
1
vl.h
|
@ -390,6 +390,7 @@ int qemu_timer_pending(QEMUTimer *ts);
|
||||||
extern int64_t ticks_per_sec;
|
extern int64_t ticks_per_sec;
|
||||||
extern int pit_min_timer_count;
|
extern int pit_min_timer_count;
|
||||||
|
|
||||||
|
int64_t cpu_get_ticks(void);
|
||||||
void cpu_enable_ticks(void);
|
void cpu_enable_ticks(void);
|
||||||
void cpu_disable_ticks(void);
|
void cpu_disable_ticks(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue