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);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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 New Issue