new timer API - new API to save/restore the virtual machine state
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@690 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
b0a21b5334
commit
8a7ddc38a6
53
monitor.c
53
monitor.c
@ -281,6 +281,50 @@ static void do_log(int argc, const char **argv)
|
|||||||
cpu_set_log(mask);
|
cpu_set_log(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void do_savevm(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
if (argc != 2) {
|
||||||
|
help_cmd(argv[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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) {
|
||||||
|
help_cmd(argv[0]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
vm_stop(EXCP_INTERRUPT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_cont(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
vm_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_gdbserver(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
int port;
|
||||||
|
|
||||||
|
port = DEFAULT_GDBSTUB_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[] = {
|
static term_cmd_t term_cmds[] = {
|
||||||
{ "help|?", do_help,
|
{ "help|?", do_help,
|
||||||
"[cmd]", "show the help" },
|
"[cmd]", "show the help" },
|
||||||
@ -298,6 +342,13 @@ static term_cmd_t term_cmds[] = {
|
|||||||
"filename", "save screen into PPM image 'filename'" },
|
"filename", "save screen into PPM image 'filename'" },
|
||||||
{ "log", do_log,
|
{ "log", do_log,
|
||||||
"item1[,...]", "activate logging of the specified items to '/tmp/qemu.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, },
|
{ NULL, NULL, },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -601,5 +652,5 @@ void monitor_init(void)
|
|||||||
QEMU_VERSION);
|
QEMU_VERSION);
|
||||||
term_show_prompt();
|
term_show_prompt();
|
||||||
}
|
}
|
||||||
add_fd_read_handler(0, term_can_read, term_read, NULL);
|
qemu_add_fd_read_handler(0, term_can_read, term_read, NULL);
|
||||||
}
|
}
|
||||||
|
4
oss.c
4
oss.c
@ -459,11 +459,11 @@ int AUD_get_free (void)
|
|||||||
uint64_t ua_elapsed;
|
uint64_t ua_elapsed;
|
||||||
uint64_t al_elapsed;
|
uint64_t al_elapsed;
|
||||||
|
|
||||||
ticks = cpu_get_ticks ();
|
ticks = qemu_get_clock(rt_clock);
|
||||||
delta = ticks - old_ticks;
|
delta = ticks - old_ticks;
|
||||||
old_ticks = 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;
|
al_elapsed = ua_elapsed & ~3ULL;
|
||||||
|
|
||||||
ldebug ("tid elapsed %llu bytes\n", ua_elapsed);
|
ldebug ("tid elapsed %llu bytes\n", ua_elapsed);
|
||||||
|
25
sdl.c
25
sdl.c
@ -49,6 +49,7 @@
|
|||||||
|
|
||||||
static SDL_Surface *screen;
|
static SDL_Surface *screen;
|
||||||
static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
|
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)
|
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)
|
static void sdl_grab_start(void)
|
||||||
{
|
{
|
||||||
SDL_WM_SetCaption("QEMU - Press Ctrl-Shift to exit grab", "QEMU");
|
|
||||||
SDL_ShowCursor(0);
|
SDL_ShowCursor(0);
|
||||||
SDL_WM_GrabInput(SDL_GRAB_ON);
|
SDL_WM_GrabInput(SDL_GRAB_ON);
|
||||||
/* dummy read to avoid moving the mouse */
|
/* dummy read to avoid moving the mouse */
|
||||||
SDL_GetRelativeMouseState(NULL, NULL);
|
SDL_GetRelativeMouseState(NULL, NULL);
|
||||||
gui_grab = 1;
|
gui_grab = 1;
|
||||||
|
sdl_update_caption();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sdl_grab_end(void)
|
static void sdl_grab_end(void)
|
||||||
{
|
{
|
||||||
SDL_WM_SetCaption("QEMU", "QEMU");
|
|
||||||
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
||||||
SDL_ShowCursor(1);
|
SDL_ShowCursor(1);
|
||||||
gui_grab = 0;
|
gui_grab = 0;
|
||||||
|
sdl_update_caption();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sdl_send_mouse_event(void)
|
static void sdl_send_mouse_event(void)
|
||||||
@ -209,6 +223,11 @@ static void sdl_refresh(DisplayState *ds)
|
|||||||
{
|
{
|
||||||
SDL_Event ev1, *ev = &ev1;
|
SDL_Event ev1, *ev = &ev1;
|
||||||
|
|
||||||
|
if (last_vm_running != vm_running) {
|
||||||
|
last_vm_running = vm_running;
|
||||||
|
sdl_update_caption();
|
||||||
|
}
|
||||||
|
|
||||||
vga_update_display();
|
vga_update_display();
|
||||||
while (SDL_PollEvent(ev)) {
|
while (SDL_PollEvent(ev)) {
|
||||||
switch (ev->type) {
|
switch (ev->type) {
|
||||||
@ -281,7 +300,7 @@ void sdl_display_init(DisplayState *ds)
|
|||||||
ds->dpy_refresh = sdl_refresh;
|
ds->dpy_refresh = sdl_refresh;
|
||||||
|
|
||||||
sdl_resize(ds, 640, 400);
|
sdl_resize(ds, 640, 400);
|
||||||
SDL_WM_SetCaption("QEMU", "QEMU");
|
sdl_update_caption();
|
||||||
SDL_EnableKeyRepeat(250, 50);
|
SDL_EnableKeyRepeat(250, 50);
|
||||||
gui_grab = 0;
|
gui_grab = 0;
|
||||||
|
|
||||||
|
151
vl.h
151
vl.h
@ -24,12 +24,12 @@
|
|||||||
#ifndef VL_H
|
#ifndef VL_H
|
||||||
#define VL_H
|
#define VL_H
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
|
|
||||||
/* vl.c */
|
/* vl.c */
|
||||||
extern int reset_requested;
|
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 void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data);
|
||||||
typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address);
|
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);
|
IOPortReadFunc *func, void *opaque);
|
||||||
int register_ioport_write(int start, int length, int size,
|
int register_ioport_write(int start, int length, int size,
|
||||||
IOPortWriteFunc *func, void *opaque);
|
IOPortWriteFunc *func, void *opaque);
|
||||||
int64_t cpu_get_ticks(void);
|
|
||||||
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);
|
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);
|
||||||
|
|
||||||
void hw_error(const char *fmt, ...);
|
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);
|
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 */
|
/* network redirectors support */
|
||||||
|
|
||||||
#define MAX_NICS 8
|
#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 void IOReadHandler(void *opaque, const uint8_t *buf, int size);
|
||||||
typedef int IOCanRWHandler(void *opaque);
|
typedef int IOCanRWHandler(void *opaque);
|
||||||
|
|
||||||
int add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read,
|
int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read,
|
||||||
IOReadHandler *fd_read, void *opaque);
|
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 */
|
/* block.c */
|
||||||
typedef struct BlockDriverState BlockDriverState;
|
typedef struct BlockDriverState BlockDriverState;
|
||||||
@ -210,16 +323,11 @@ void kbd_init(void);
|
|||||||
|
|
||||||
/* mc146818rtc.c */
|
/* mc146818rtc.c */
|
||||||
|
|
||||||
typedef struct RTCState {
|
typedef struct RTCState RTCState;
|
||||||
uint8_t cmos_data[128];
|
|
||||||
uint8_t cmos_index;
|
|
||||||
int irq;
|
|
||||||
} RTCState;
|
|
||||||
|
|
||||||
extern RTCState rtc_state;
|
RTCState *rtc_init(int base, int irq);
|
||||||
|
void rtc_set_memory(RTCState *s, int addr, int val);
|
||||||
void rtc_init(int base, int irq);
|
void rtc_set_date(RTCState *s, const struct tm *tm);
|
||||||
void rtc_timer(void);
|
|
||||||
|
|
||||||
/* serial.c */
|
/* serial.c */
|
||||||
|
|
||||||
@ -249,14 +357,17 @@ typedef struct PITChannelState {
|
|||||||
uint8_t bcd; /* not supported */
|
uint8_t bcd; /* not supported */
|
||||||
uint8_t gate; /* timer start */
|
uint8_t gate; /* timer start */
|
||||||
int64_t count_load_time;
|
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;
|
} PITChannelState;
|
||||||
|
|
||||||
extern PITChannelState pit_channels[3];
|
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);
|
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);
|
int pit_get_out_edges(PITChannelState *s);
|
||||||
|
|
||||||
/* pc.c */
|
/* pc.c */
|
||||||
@ -271,4 +382,10 @@ void term_printf(const char *fmt, ...);
|
|||||||
void term_flush(void);
|
void term_flush(void);
|
||||||
void term_print_help(void);
|
void term_print_help(void);
|
||||||
|
|
||||||
|
/* gdbstub.c */
|
||||||
|
|
||||||
|
#define DEFAULT_GDBSTUB_PORT 1234
|
||||||
|
|
||||||
|
int gdbserver_start(int port);
|
||||||
|
|
||||||
#endif /* VL_H */
|
#endif /* VL_H */
|
||||||
|
Loading…
Reference in New Issue
Block a user