Commit 8a7ddc38 authored by bellard's avatar bellard

new timer API - new API to save/restore the virtual machine state

git-svn-id: svn:// c046a42c-6fe2-441c-8c8c-71466251a162
parent b0a21b53
......@@ -281,6 +281,50 @@ static void do_log(int argc, const char **argv)
static void do_savevm(int argc, const char **argv)
if (argc != 2) {
if (qemu_savevm(argv[1]) < 0)
term_printf("I/O error when saving VM to '%s'\n", argv[1]);
static void do_loadvm(int argc, const char **argv)
if (argc != 2) {
if (qemu_loadvm(argv[1]) < 0)
term_printf("I/O error when loading VM from '%s'\n", argv[1]);
static void do_stop(int argc, const char **argv)
static void do_cont(int argc, const char **argv)
static void do_gdbserver(int argc, const char **argv)
int port;
if (argc >= 2)
port = atoi(argv[1]);
if (gdbserver_start(port) < 0) {
qemu_printf("Could not open gdbserver socket on port %d\n", port);
} else {
qemu_printf("Waiting gdb connection on port %d\n", port);
static term_cmd_t term_cmds[] = {
{ "help|?", do_help,
"[cmd]", "show the help" },
......@@ -298,6 +342,13 @@ static term_cmd_t term_cmds[] = {
"filename", "save screen into PPM image 'filename'" },
{ "log", do_log,
"item1[,...]", "activate logging of the specified items to '/tmp/qemu.log'" },
{ "savevm", do_savevm,
"filename", "save the whole virtual machine state to 'filename'" },
{ "loadvm", do_loadvm,
"filename", "restore the whole virtual machine state from 'filename'" },
{ "stop", do_stop, "", "stop emulation", },
{ "c|cont", do_cont, "", "resume emulation", },
{ "gdbserver", do_gdbserver, "[port]", "start gdbserver session (default port=1234)", },
{ NULL, NULL, },
......@@ -601,5 +652,5 @@ void monitor_init(void)
add_fd_read_handler(0, term_can_read, term_read, NULL);
qemu_add_fd_read_handler(0, term_can_read, term_read, NULL);
......@@ -459,11 +459,11 @@ int AUD_get_free (void)
uint64_t ua_elapsed;
uint64_t al_elapsed;
ticks = cpu_get_ticks ();
ticks = qemu_get_clock(rt_clock);
delta = ticks - old_ticks;
old_ticks = ticks;
ua_elapsed = (delta * bytes_per_second) / ticks_per_sec;
ua_elapsed = (delta * bytes_per_second) / 1000;
al_elapsed = ua_elapsed & ~3ULL;
ldebug ("tid elapsed %llu bytes\n", ua_elapsed);
......@@ -49,6 +49,7 @@
static SDL_Surface *screen;
static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
static int last_vm_running;
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
......@@ -165,22 +166,35 @@ static void sdl_process_key(SDL_KeyboardEvent *ev)
static void sdl_update_caption(void)
char buf[1024];
strcpy(buf, "QEMU");
if (!vm_running) {
strcat(buf, " [Stopped]");
if (gui_grab) {
strcat(buf, " - Press Ctrl-Shift to exit grab");
SDL_WM_SetCaption(buf, "QEMU");
static void sdl_grab_start(void)
SDL_WM_SetCaption("QEMU - Press Ctrl-Shift to exit grab", "QEMU");
/* dummy read to avoid moving the mouse */
SDL_GetRelativeMouseState(NULL, NULL);
gui_grab = 1;
static void sdl_grab_end(void)
SDL_WM_SetCaption("QEMU", "QEMU");
gui_grab = 0;
static void sdl_send_mouse_event(void)
......@@ -209,6 +223,11 @@ static void sdl_refresh(DisplayState *ds)
SDL_Event ev1, *ev = &ev1;
if (last_vm_running != vm_running) {
last_vm_running = vm_running;
while (SDL_PollEvent(ev)) {
switch (ev->type) {
......@@ -281,7 +300,7 @@ void sdl_display_init(DisplayState *ds)
ds->dpy_refresh = sdl_refresh;
sdl_resize(ds, 640, 400);
SDL_WM_SetCaption("QEMU", "QEMU");
SDL_EnableKeyRepeat(250, 50);
gui_grab = 0;
This diff is collapsed.
......@@ -24,12 +24,12 @@
#ifndef VL_H
#define VL_H
#include <time.h>
#include "cpu.h"
/* vl.c */
extern int reset_requested;
extern int64_t ticks_per_sec;
extern int pit_min_timer_count;
typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data);
typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address);
......@@ -38,7 +38,6 @@ int register_ioport_read(int start, int length, int size,
IOPortReadFunc *func, void *opaque);
int register_ioport_write(int start, int length, int size,
IOPortWriteFunc *func, void *opaque);
int64_t cpu_get_ticks(void);
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);
void hw_error(const char *fmt, ...);
......@@ -51,6 +50,16 @@ char *pstrcat(char *buf, int buf_size, const char *s);
int serial_open_device(void);
extern int vm_running;
typedef void VMStopHandler(void *opaque, int reason);
int qemu_add_vm_stop_handler(VMStopHandler *cb, void *opaque);
void qemu_del_vm_stop_handler(VMStopHandler *cb, void *opaque);
void vm_start(void);
void vm_stop(int reason);
/* network redirectors support */
#define MAX_NICS 8
......@@ -71,8 +80,112 @@ void net_send_packet(NetDriverState *nd, const uint8_t *buf, int size);
typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
typedef int IOCanRWHandler(void *opaque);
int add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read,
IOReadHandler *fd_read, void *opaque);
int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read,
IOReadHandler *fd_read, void *opaque);
void qemu_del_fd_read_handler(int fd);
/* timers */
typedef struct QEMUClock QEMUClock;
typedef struct QEMUTimer QEMUTimer;
typedef void QEMUTimerCB(void *opaque);
/* The real time clock should be used only for stuff which does not
change the virtual machine state, as it is run even if the virtual
machine is stopped. The real time clock has a frequency or 1000
Hz. */
extern QEMUClock *rt_clock;
/* Rge virtual clock is only run during the emulation. It is stopped
when the virtual machine is stopped. Virtual timers use a high
precision clock, usually cpu cycles (use ticks_per_sec). */
extern QEMUClock *vm_clock;
int64_t qemu_get_clock(QEMUClock *clock);
QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque);
void qemu_free_timer(QEMUTimer *ts);
void qemu_del_timer(QEMUTimer *ts);
void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
int qemu_timer_pending(QEMUTimer *ts);
extern int64_t ticks_per_sec;
extern int pit_min_timer_count;
void cpu_enable_ticks(void);
void cpu_disable_ticks(void);
/* VM Load/Save */
typedef FILE QEMUFile;
void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
void qemu_put_byte(QEMUFile *f, int v);
void qemu_put_be16(QEMUFile *f, unsigned int v);
void qemu_put_be32(QEMUFile *f, unsigned int v);
void qemu_put_be64(QEMUFile *f, uint64_t v);
int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size);
int qemu_get_byte(QEMUFile *f);
unsigned int qemu_get_be16(QEMUFile *f);
unsigned int qemu_get_be32(QEMUFile *f);
uint64_t qemu_get_be64(QEMUFile *f);
static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
qemu_put_be64(f, *pv);
static inline void qemu_put_be32s(QEMUFile *f, const uint32_t *pv)
qemu_put_be32(f, *pv);
static inline void qemu_put_be16s(QEMUFile *f, const uint16_t *pv)
qemu_put_be16(f, *pv);
static inline void qemu_put_8s(QEMUFile *f, const uint8_t *pv)
qemu_put_byte(f, *pv);
static inline void qemu_get_be64s(QEMUFile *f, uint64_t *pv)
*pv = qemu_get_be64(f);
static inline void qemu_get_be32s(QEMUFile *f, uint32_t *pv)
*pv = qemu_get_be32(f);
static inline void qemu_get_be16s(QEMUFile *f, uint16_t *pv)
*pv = qemu_get_be16(f);
static inline void qemu_get_8s(QEMUFile *f, uint8_t *pv)
*pv = qemu_get_byte(f);
int64_t qemu_ftell(QEMUFile *f);
int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence);
typedef void SaveStateHandler(QEMUFile *f, void *opaque);
typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
int qemu_loadvm(const char *filename);
int qemu_savevm(const char *filename);
int register_savevm(const char *idstr,
int instance_id,
int version_id,
SaveStateHandler *save_state,
LoadStateHandler *load_state,
void *opaque);
void qemu_get_timer(QEMUFile *f, QEMUTimer *ts);
void qemu_put_timer(QEMUFile *f, QEMUTimer *ts);
/* block.c */
typedef struct BlockDriverState BlockDriverState;
......@@ -210,16 +323,11 @@ void kbd_init(void);
/* mc146818rtc.c */
typedef struct RTCState {
uint8_t cmos_data[128];
uint8_t cmos_index;
int irq;
} RTCState;
extern RTCState rtc_state;
typedef struct RTCState RTCState;
void rtc_init(int base, int irq);
void rtc_timer(void);
RTCState *rtc_init(int base, int irq);
void rtc_set_memory(RTCState *s, int addr, int val);
void rtc_set_date(RTCState *s, const struct tm *tm);
/* serial.c */
......@@ -249,14 +357,17 @@ typedef struct PITChannelState {
uint8_t bcd; /* not supported */
uint8_t gate; /* timer start */
int64_t count_load_time;
int64_t count_last_edge_check_time;
/* irq handling */
int64_t next_transition_time;
QEMUTimer *irq_timer;
int irq;
} PITChannelState;
extern PITChannelState pit_channels[3];
void pit_init(int base);
void pit_init(int base, int irq);
void pit_set_gate(PITChannelState *s, int val);
int pit_get_out(PITChannelState *s);
int pit_get_out(PITChannelState *s, int64_t current_time);
int pit_get_out_edges(PITChannelState *s);
/* pc.c */
......@@ -271,4 +382,10 @@ void term_printf(const char *fmt, ...);
void term_flush(void);
void term_print_help(void);
/* gdbstub.c */
int gdbserver_start(int port);
#endif /* VL_H */
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