X-Git-Url: http://git.maemo.org/git/?a=blobdiff_plain;f=vl.c;h=1f95a37c1863e605778a7b09cb4dbb7ca36cebc4;hb=3c619b5975d68bb07b2e7274b2f8068b11acd772;hp=ff0e5432a509341d0c9b3d6cc91ef54f16dc2005;hpb=4d00781419371beea3704229f8ce1ca772d41ec8;p=qemu diff --git a/vl.c b/vl.c index ff0e543..1f95a37 100644 --- a/vl.c +++ b/vl.c @@ -186,7 +186,6 @@ enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; static DisplayState *display_state; DisplayType display_type = DT_DEFAULT; const char* keyboard_layout = NULL; -int64_t ticks_per_sec; ram_addr_t ram_size; int nb_nics; NICInfo nd_table[MAX_NICS]; @@ -529,8 +528,6 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) /***********************************************************/ /* real time host monotonic timer */ -#define QEMU_TIMER_BASE 1000000000LL - #ifdef WIN32 static int64_t clock_freq; @@ -551,7 +548,7 @@ static int64_t get_clock(void) { LARGE_INTEGER ti; QueryPerformanceCounter(&ti); - return muldiv64(ti.QuadPart, QEMU_TIMER_BASE, clock_freq); + return muldiv64(ti.QuadPart, get_ticks_per_sec(), clock_freq); } #else @@ -609,10 +606,15 @@ static int64_t cpu_get_icount(void) /***********************************************************/ /* 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; +typedef struct TimersState { + int64_t cpu_ticks_prev; + int64_t cpu_ticks_offset; + int64_t cpu_clock_offset; + int32_t cpu_ticks_enabled; + int64_t dummy; +} TimersState; + +TimersState timers_state; /* return the host CPU cycle counter and handle stop/restart */ int64_t cpu_get_ticks(void) @@ -620,18 +622,18 @@ int64_t cpu_get_ticks(void) if (use_icount) { return cpu_get_icount(); } - if (!cpu_ticks_enabled) { - return cpu_ticks_offset; + if (!timers_state.cpu_ticks_enabled) { + return timers_state.cpu_ticks_offset; } else { int64_t ticks; ticks = cpu_get_real_ticks(); - if (cpu_ticks_prev > ticks) { + if (timers_state.cpu_ticks_prev > ticks) { /* Note: non increasing ticks may happen if the host uses software suspend */ - cpu_ticks_offset += cpu_ticks_prev - ticks; + timers_state.cpu_ticks_offset += timers_state.cpu_ticks_prev - ticks; } - cpu_ticks_prev = ticks; - return ticks + cpu_ticks_offset; + timers_state.cpu_ticks_prev = ticks; + return ticks + timers_state.cpu_ticks_offset; } } @@ -639,21 +641,21 @@ int64_t cpu_get_ticks(void) static int64_t cpu_get_clock(void) { int64_t ti; - if (!cpu_ticks_enabled) { - return cpu_clock_offset; + if (!timers_state.cpu_ticks_enabled) { + return timers_state.cpu_clock_offset; } else { ti = get_clock(); - return ti + cpu_clock_offset; + return ti + timers_state.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; + if (!timers_state.cpu_ticks_enabled) { + timers_state.cpu_ticks_offset -= cpu_get_real_ticks(); + timers_state.cpu_clock_offset -= get_clock(); + timers_state.cpu_ticks_enabled = 1; } } @@ -661,10 +663,10 @@ void cpu_enable_ticks(void) 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; + if (timers_state.cpu_ticks_enabled) { + timers_state.cpu_ticks_offset = cpu_get_ticks(); + timers_state.cpu_clock_offset = cpu_get_clock(); + timers_state.cpu_ticks_enabled = 0; } } @@ -754,7 +756,7 @@ static void rtc_stop_timer(struct qemu_alarm_timer *t); fairly approximate, so ignore small variation. When the guest is idle real and virtual time will be aligned in the IO wait loop. */ -#define ICOUNT_WOBBLE (QEMU_TIMER_BASE / 10) +#define ICOUNT_WOBBLE (get_ticks_per_sec() / 10) static void icount_adjust(void) { @@ -796,7 +798,7 @@ static void icount_adjust_rt(void * opaque) static void icount_adjust_vm(void * opaque) { qemu_mod_timer(icount_vm_timer, - qemu_get_clock(vm_clock) + QEMU_TIMER_BASE / 10); + qemu_get_clock(vm_clock) + get_ticks_per_sec() / 10); icount_adjust(); } @@ -812,7 +814,7 @@ static void init_icount_adjust(void) qemu_get_clock(rt_clock) + 1000); icount_vm_timer = qemu_new_timer(vm_clock, icount_adjust_vm, NULL); qemu_mod_timer(icount_vm_timer, - qemu_get_clock(vm_clock) + QEMU_TIMER_BASE / 10); + qemu_get_clock(vm_clock) + get_ticks_per_sec() / 10); } static struct qemu_alarm_timer alarm_timers[] = { @@ -858,7 +860,7 @@ static void configure_alarms(char const *opt) exit(0); } - arg = strdup(opt); + arg = qemu_strdup(opt); /* Reorder the array */ name = strtok(arg, ","); @@ -887,7 +889,7 @@ next: name = strtok(NULL, ","); } - free(arg); + qemu_free(arg); if (cur) { /* Disable remaining timers */ @@ -1035,7 +1037,6 @@ int64_t qemu_get_clock(QEMUClock *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); } @@ -1065,30 +1066,18 @@ void qemu_get_timer(QEMUFile *f, QEMUTimer *ts) } } -static void timer_save(QEMUFile *f, void *opaque) -{ - if (cpu_ticks_enabled) { - hw_error("cannot save state if virtual timers are running"); - } - qemu_put_be64(f, cpu_ticks_offset); - qemu_put_be64(f, ticks_per_sec); - qemu_put_be64(f, cpu_clock_offset); -} - -static int timer_load(QEMUFile *f, void *opaque, int version_id) -{ - if (version_id != 1 && version_id != 2) - return -EINVAL; - if (cpu_ticks_enabled) { - return -EINVAL; - } - cpu_ticks_offset=qemu_get_be64(f); - ticks_per_sec=qemu_get_be64(f); - if (version_id == 2) { - cpu_clock_offset=qemu_get_be64(f); +static const VMStateDescription vmstate_timers = { + .name = "timer", + .version_id = 2, + .minimum_version_id = 1, + .minimum_version_id_old = 1, + .fields = (VMStateField []) { + VMSTATE_INT64(cpu_ticks_offset, TimersState), + VMSTATE_INT64(dummy, TimersState), + VMSTATE_INT64_V(cpu_clock_offset, TimersState, 2), + VMSTATE_END_OF_LIST() } - return 0; -} +}; static void qemu_event_increment(void); @@ -1116,10 +1105,10 @@ static void host_alarm_handler(int host_signum) delta_cum += delta; if (++count == DISP_FREQ) { printf("timer: min=%" PRId64 " us max=%" PRId64 " us avg=%" PRId64 " us avg_freq=%0.3f Hz\n", - muldiv64(delta_min, 1000000, ticks_per_sec), - muldiv64(delta_max, 1000000, ticks_per_sec), - muldiv64(delta_cum, 1000000 / DISP_FREQ, ticks_per_sec), - (double)ticks_per_sec / ((double)delta_cum / DISP_FREQ)); + muldiv64(delta_min, 1000000, get_ticks_per_sec()), + muldiv64(delta_max, 1000000, get_ticks_per_sec()), + muldiv64(delta_cum, 1000000 / DISP_FREQ, get_ticks_per_sec()), + (double)get_ticks_per_sec() / ((double)delta_cum / DISP_FREQ)); count = 0; delta_min = INT64_MAX; delta_max = 0; @@ -2434,72 +2423,56 @@ static void smp_parse(const char *optarg) /***********************************************************/ /* USB devices */ -static USBPort *used_usb_ports; -static USBPort *free_usb_ports; - -/* ??? Maybe change this to register a hub to keep track of the topology. */ -void qemu_register_usb_port(USBPort *port, void *opaque, int index, - usb_attachfn attach) -{ - port->opaque = opaque; - port->index = index; - port->attach = attach; - port->next = free_usb_ports; - free_usb_ports = port; -} - -int usb_device_add_dev(USBDevice *dev) -{ - USBPort *port; - - /* Find a USB port to add the device to. */ - port = free_usb_ports; - if (!port->next) { - USBDevice *hub; - - /* Create a new hub and chain it on. */ - free_usb_ports = NULL; - port->next = used_usb_ports; - used_usb_ports = port; - - hub = usb_hub_init(VM_USB_HUB_SIZE); - usb_attach(port, hub); - port = free_usb_ports; - } - - free_usb_ports = port->next; - port->next = used_usb_ports; - used_usb_ports = port; - usb_attach(port, dev); - return 0; -} - static void usb_msd_password_cb(void *opaque, int err) { USBDevice *dev = opaque; if (!err) - usb_device_add_dev(dev); + usb_device_attach(dev); else - dev->handle_destroy(dev); + dev->info->handle_destroy(dev); } +static struct { + const char *name; + const char *qdev; +} usbdevs[] = { + { + .name = "mouse", + .qdev = "QEMU USB Mouse", + },{ + .name = "tablet", + .qdev = "QEMU USB Tablet", + },{ + .name = "keyboard", + .qdev = "QEMU USB Keyboard", + },{ + .name = "wacom-tablet", + .qdev = "QEMU PenPartner Tablet", + } +}; + static int usb_device_add(const char *devname, int is_hotplug) { const char *p; - USBDevice *dev; + USBBus *bus = usb_bus_find(-1 /* any */); + USBDevice *dev = NULL; + int i; - if (!free_usb_ports) + if (!usb_enabled) return -1; + /* simple devices which don't need extra care */ + for (i = 0; i < ARRAY_SIZE(usbdevs); i++) { + if (strcmp(devname, usbdevs[i].name) != 0) + continue; + dev = usb_create_simple(bus, usbdevs[i].qdev); + goto done; + } + + /* the other ones */ if (strstart(devname, "host:", &p)) { dev = usb_host_device_open(p); - } else if (!strcmp(devname, "mouse")) { - dev = usb_mouse_init(); - } else if (!strcmp(devname, "tablet")) { - dev = usb_tablet_init(); - } else if (!strcmp(devname, "keyboard")) { - dev = usb_keyboard_init(); } else if (strstart(devname, "disk:", &p)) { BlockDriverState *bs; @@ -2515,8 +2488,6 @@ static int usb_device_add(const char *devname, int is_hotplug) return 0; } } - } else if (!strcmp(devname, "wacom-tablet")) { - dev = usb_wacom_init(); } else if (strstart(devname, "serial:", &p)) { dev = usb_serial_init(p); #ifdef CONFIG_BRLAPI @@ -2539,37 +2510,7 @@ static int usb_device_add(const char *devname, int is_hotplug) if (!dev) return -1; - return usb_device_add_dev(dev); -} - -int usb_device_del_addr(int bus_num, int addr) -{ - USBPort *port; - USBPort **lastp; - USBDevice *dev; - - if (!used_usb_ports) - return -1; - - if (bus_num != 0) - return -1; - - lastp = &used_usb_ports; - port = used_usb_ports; - while (port && port->dev->addr != addr) { - lastp = &port->next; - port = port->next; - } - - if (!port) - return -1; - - dev = port->dev; - *lastp = port->next; - usb_attach(port, NULL); - dev->handle_destroy(dev); - port->next = free_usb_ports; - free_usb_ports = port; +done: return 0; } @@ -2581,7 +2522,7 @@ static int usb_device_del(const char *devname) if (strstart(devname, "host:", &p)) return usb_host_device_close(p); - if (!used_usb_ports) + if (!usb_enabled) return -1; p = strchr(devname, '.'); @@ -2590,7 +2531,7 @@ static int usb_device_del(const char *devname) bus_num = strtoul(devname, NULL, 0); addr = strtoul(p + 1, NULL, 0); - return usb_device_del_addr(bus_num, addr); + return usb_device_delete_addr(bus_num, addr); } static int usb_parse(const char *cmdline) @@ -2608,40 +2549,6 @@ void do_usb_del(Monitor *mon, const QDict *qdict) usb_device_del(qdict_get_str(qdict, "devname")); } -void usb_info(Monitor *mon) -{ - USBDevice *dev; - USBPort *port; - const char *speed_str; - - if (!usb_enabled) { - monitor_printf(mon, "USB support not enabled\n"); - return; - } - - for (port = used_usb_ports; port; port = port->next) { - dev = port->dev; - if (!dev) - continue; - switch(dev->speed) { - case USB_SPEED_LOW: - speed_str = "1.5"; - break; - case USB_SPEED_FULL: - speed_str = "12"; - break; - case USB_SPEED_HIGH: - speed_str = "480"; - break; - default: - speed_str = "?"; - break; - } - monitor_printf(mon, " Device %d.%d, Speed %s Mb/s, Product %s\n", - 0, dev->addr, speed_str, dev->devname); - } -} - /***********************************************************/ /* PCMCIA/Cardbus */ @@ -2874,97 +2781,7 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) /***********************************************************/ /* ram save/restore */ -static int ram_get_page(QEMUFile *f, uint8_t *buf, int len) -{ - int v; - - v = qemu_get_byte(f); - switch(v) { - case 0: - if (qemu_get_buffer(f, buf, len) != len) - return -EIO; - break; - case 1: - v = qemu_get_byte(f); - memset(buf, v, len); - break; - default: - return -EINVAL; - } - - if (qemu_file_has_error(f)) - return -EIO; - - return 0; -} - -static int ram_load_v1(QEMUFile *f, void *opaque) -{ - int ret; - ram_addr_t i; - - if (qemu_get_be32(f) != last_ram_offset) - return -EINVAL; - for(i = 0; i < last_ram_offset; i+= TARGET_PAGE_SIZE) { - ret = ram_get_page(f, qemu_get_ram_ptr(i), TARGET_PAGE_SIZE); - if (ret) - return ret; - } - return 0; -} - -#define BDRV_HASH_BLOCK_SIZE 1024 -#define IOBUF_SIZE 4096 -#define RAM_CBLOCK_MAGIC 0xfabe - -typedef struct RamDecompressState { - z_stream zstream; - QEMUFile *f; - uint8_t buf[IOBUF_SIZE]; -} RamDecompressState; - -static int ram_decompress_open(RamDecompressState *s, QEMUFile *f) -{ - int ret; - memset(s, 0, sizeof(*s)); - s->f = f; - ret = inflateInit(&s->zstream); - if (ret != Z_OK) - return -1; - return 0; -} - -static int ram_decompress_buf(RamDecompressState *s, uint8_t *buf, int len) -{ - int ret, clen; - - s->zstream.avail_out = len; - s->zstream.next_out = buf; - while (s->zstream.avail_out > 0) { - if (s->zstream.avail_in == 0) { - if (qemu_get_be16(s->f) != RAM_CBLOCK_MAGIC) - return -1; - clen = qemu_get_be16(s->f); - if (clen > IOBUF_SIZE) - return -1; - qemu_get_buffer(s->f, s->buf, clen); - s->zstream.avail_in = clen; - s->zstream.next_in = s->buf; - } - ret = inflate(&s->zstream, Z_PARTIAL_FLUSH); - if (ret != Z_OK && ret != Z_STREAM_END) { - return -1; - } - } - return 0; -} - -static void ram_decompress_close(RamDecompressState *s) -{ - inflateEnd(&s->zstream); -} - -#define RAM_SAVE_FLAG_FULL 0x01 +#define RAM_SAVE_FLAG_FULL 0x01 /* Obsolete, not used anymore */ #define RAM_SAVE_FLAG_COMPRESS 0x02 #define RAM_SAVE_FLAG_MEM_SIZE 0x04 #define RAM_SAVE_FLAG_PAGE 0x08 @@ -3112,50 +2929,11 @@ static int ram_save_live(QEMUFile *f, int stage, void *opaque) return (stage == 2) && (expected_time <= migrate_max_downtime()); } -static int ram_load_dead(QEMUFile *f, void *opaque) -{ - RamDecompressState s1, *s = &s1; - uint8_t buf[10]; - ram_addr_t i; - - if (ram_decompress_open(s, f) < 0) - return -EINVAL; - for(i = 0; i < last_ram_offset; i+= BDRV_HASH_BLOCK_SIZE) { - if (ram_decompress_buf(s, buf, 1) < 0) { - fprintf(stderr, "Error while reading ram block header\n"); - goto error; - } - if (buf[0] == 0) { - if (ram_decompress_buf(s, qemu_get_ram_ptr(i), - BDRV_HASH_BLOCK_SIZE) < 0) { - fprintf(stderr, "Error while reading ram block address=0x%08" PRIx64, (uint64_t)i); - goto error; - } - } else { - error: - printf("Error block header\n"); - return -EINVAL; - } - } - ram_decompress_close(s); - - return 0; -} - static int ram_load(QEMUFile *f, void *opaque, int version_id) { ram_addr_t addr; int flags; - if (version_id == 1) - return ram_load_v1(f, opaque); - - if (version_id == 2) { - if (qemu_get_be32(f) != last_ram_offset) - return -EINVAL; - return ram_load_dead(f, opaque); - } - if (version_id != 3) return -EINVAL; @@ -3170,11 +2948,6 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) return -EINVAL; } - if (flags & RAM_SAVE_FLAG_FULL) { - if (ram_load_dead(f, opaque) < 0) - return -EINVAL; - } - if (flags & RAM_SAVE_FLAG_COMPRESS) { uint8_t ch = qemu_get_byte(f); memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE); @@ -3753,7 +3526,8 @@ static void *kvm_cpu_thread_fn(void *arg) block_io_signals(); qemu_thread_self(env->thread); - kvm_init_vcpu(env); + if (kvm_enabled()) + kvm_init_vcpu(env); /* signal CPU creation */ qemu_mutex_lock(&qemu_global_mutex); @@ -4707,9 +4481,7 @@ static char *find_datadir(const char *argv0) char *dir; char *p = NULL; char *res; -#ifdef PATH_MAX char buf[PATH_MAX]; -#endif size_t max_len; #if defined(__linux__) @@ -4734,10 +4506,7 @@ static char *find_datadir(const char *argv0) /* If we don't have any way of figuring out the actual executable location then try argv[0]. */ if (!p) { -#ifdef PATH_MAX - p = buf; -#endif - p = realpath(argv0, p); + p = realpath(argv0, buf); if (!p) { return NULL; } @@ -4756,9 +4525,7 @@ static char *find_datadir(const char *argv0) res = NULL; } } -#ifndef PATH_MAX - free(p); -#endif + return res; } #undef SHARE_SUFFIX @@ -4774,7 +4541,7 @@ char *qemu_find_file(int type, const char *name) /* If name contains path separators then try it as a straight path. */ if ((strchr(name, '/') || strchr(name, '\\')) && access(name, R_OK) == 0) { - return strdup(name); + return qemu_strdup(name); } switch (type) { case QEMU_FILE_TYPE_BIOS: @@ -5369,6 +5136,16 @@ int main(int argc, char **argv, char **envp) monitor_devices[monitor_device_index] = optarg; monitor_device_index++; break; + case QEMU_OPTION_chardev: + opts = qemu_opts_parse(&qemu_chardev_opts, optarg, "backend"); + if (!opts) { + fprintf(stderr, "parse error: %s\n", optarg); + exit(1); + } + if (NULL == qemu_chr_open_opts(opts, NULL)) { + exit(1); + } + break; case QEMU_OPTION_serial: if (serial_device_index >= MAX_SERIAL_PORTS) { fprintf(stderr, "qemu: too many serial ports\n"); @@ -5647,6 +5424,16 @@ int main(int argc, char **argv, char **envp) } } + if (kvm_enabled()) { + int ret; + + ret = kvm_init(smp_cpus); + if (ret < 0) { + fprintf(stderr, "failed to initialize KVM\n"); + exit(1); + } + } + /* If no data_dir is specified then try to find it relative to the executable path. */ if (!data_dir) { @@ -5821,7 +5608,7 @@ int main(int argc, char **argv, char **envp) if (qemu_opts_foreach(&qemu_drive_opts, drive_init_func, machine, 1) != 0) exit(1); - register_savevm("timer", 0, 2, timer_save, timer_load, NULL); + vmstate_register(0, &vmstate_timers ,&timers_state); register_savevm_live("ram", 0, 3, ram_save_live, NULL, ram_load, NULL); /* Maintain compatibility with multiple stdio monitors */ @@ -5881,16 +5668,6 @@ int main(int argc, char **argv, char **envp) } } - if (kvm_enabled()) { - int ret; - - ret = kvm_init(smp_cpus); - if (ret < 0) { - fprintf(stderr, "failed to initialize KVM\n"); - exit(1); - } - } - for (i = 0; i < MAX_MONITOR_DEVICES; i++) { const char *devname = monitor_devices[i]; if (devname && strcmp(devname, "none")) {