mirror of
https://gitlab.com/qemu-project/qemu
synced 2024-11-05 20:35:44 +00:00
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
5 changed files with 1106 additions and 193 deletions
53
monitor.c
53
monitor.c
|
@ -281,6 +281,50 @@ static void do_log(int argc, const char **argv)
|
|||
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[] = {
|
||||
{ "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)
|
|||
QEMU_VERSION);
|
||||
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 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);
|
||||
|
|
25
sdl.c
25
sdl.c
|
@ -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");
|
||||
SDL_ShowCursor(0);
|
||||
SDL_WM_GrabInput(SDL_GRAB_ON);
|
||||
/* dummy read to avoid moving the mouse */
|
||||
SDL_GetRelativeMouseState(NULL, NULL);
|
||||
gui_grab = 1;
|
||||
sdl_update_caption();
|
||||
}
|
||||
|
||||
static void sdl_grab_end(void)
|
||||
{
|
||||
SDL_WM_SetCaption("QEMU", "QEMU");
|
||||
SDL_WM_GrabInput(SDL_GRAB_OFF);
|
||||
SDL_ShowCursor(1);
|
||||
gui_grab = 0;
|
||||
sdl_update_caption();
|
||||
}
|
||||
|
||||
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;
|
||||
sdl_update_caption();
|
||||
}
|
||||
|
||||
vga_update_display();
|
||||
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_update_caption();
|
||||
SDL_EnableKeyRepeat(250, 50);
|
||||
gui_grab = 0;
|
||||
|
||||
|
|
151
vl.h
151
vl.h
|
@ -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;
|
||||
typedef struct RTCState RTCState;
|
||||
|
||||
extern RTCState rtc_state;
|
||||
|
||||
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 */
|
||||
|
||||
#define DEFAULT_GDBSTUB_PORT 1234
|
||||
|
||||
int gdbserver_start(int port);
|
||||
|
||||
#endif /* VL_H */
|
||||
|
|
Loading…
Reference in a new issue