#include <sys/time.h>
#include <zlib.h>
-/* Needed early for HOST_BSD etc. */
+/* Needed early for CONFIG_BSD etc. */
#include "config-host.h"
/* Needed early to override system queue definitions on BSD */
#include "sys-queue.h"
#include <dirent.h>
#include <netdb.h>
#include <sys/select.h>
-#ifdef HOST_BSD
+#ifdef CONFIG_BSD
#include <sys/stat.h>
#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <libutil.h>
#ifdef _WIN32
#include <windows.h>
-#include <malloc.h>
-#include <sys/timeb.h>
#include <mmsystem.h>
-#define getopt_long_only getopt_long
-#define memalign(align, size) malloc(size)
#endif
#ifdef CONFIG_SDL
#include "kvm.h"
#include "balloon.h"
#include "qemu-option.h"
+#include "qemu-config.h"
#include "disas.h"
#define DEFAULT_RAM_SIZE 128
+/* Maximum number of monitor devices */
+#define MAX_MONITOR_DEVICES 10
+
static const char *data_dir;
const char *bios_name = NULL;
/* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
int nb_nics;
NICInfo nd_table[MAX_NICS];
int vm_running;
-static int autostart;
+int autostart;
static int rtc_utc = 1;
static int rtc_date_offset = -1; /* -1 means no change */
-int cirrus_vga_enabled = 1;
-int std_vga_enabled = 0;
-int vmsvga_enabled = 0;
-int xenfb_enabled = 0;
+int vga_interface_type = VGA_CIRRUS;
#ifdef TARGET_SPARC
int graphic_width = 1024;
int graphic_height = 768;
int usb_enabled = 0;
int singlestep = 0;
int smp_cpus = 1;
+int max_cpus = 0;
+int smp_cores = 1;
+int smp_threads = 1;
const char *vnc_display;
int acpi_enabled = 1;
int no_hpet = 0;
-int virtio_balloon = 1;
-const char *virtio_balloon_devaddr;
int fd_bootchk = 1;
int no_reboot = 0;
int no_shutdown = 0;
int cursor_hide = 1;
int graphic_rotate = 0;
+uint8_t irq0override = 1;
#ifndef _WIN32
int daemonize = 0;
#endif
-WatchdogTimerModel *watchdog = NULL;
-int watchdog_action = WDT_RESET;
+const char *watchdog;
const char *option_rom[MAX_OPTION_ROMS];
int nb_option_roms;
int semihosting_enabled = 0;
static void set_proc_name(const char *s)
{
-#ifdef __linux__
+#if defined(__linux__) && defined(PR_SET_NAME)
char name[16];
if (!s)
return;
}
}
-void do_mouse_set(Monitor *mon, int index)
+void do_mouse_set(Monitor *mon, const QDict *qdict)
{
QEMUPutMouseEntry *cursor;
int i = 0;
+ int index = qdict_get_int(qdict, "index");
if (!qemu_put_mouse_event_head) {
monitor_printf(mon, "No mouse devices connected\n");
union {
uint64_t ll;
struct {
-#ifdef WORDS_BIGENDIAN
+#ifdef HOST_WORDS_BIGENDIAN
uint32_t high, low;
#else
uint32_t low, high;
exit(0);
}
- arg = strdup(opt);
+ arg = qemu_strdup(opt);
/* Reorder the array */
name = strtok(arg, ",");
name = strtok(NULL, ",");
}
- free(arg);
+ qemu_free(arg);
if (cur) {
/* Disable remaining timers */
return 0;
}
-static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
+int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
{
if (!timer_head)
return 0;
if (next_cpu) {
/* stop the currently executing cpu because a timer occured */
cpu_exit(next_cpu);
-#ifdef CONFIG_KQEMU
- if (next_cpu->kqemu_enabled) {
- kqemu_cpu_interrupt(next_cpu);
- }
-#endif
}
#endif
timer_alarm_pending = 1;
}
#endif
-int get_next_param_value(char *buf, int buf_size,
- const char *tag, const char **pstr)
-{
- const char *p;
- char option[128];
-
- p = *pstr;
- for(;;) {
- p = get_opt_name(option, sizeof(option), p, '=');
- if (*p != '=')
- break;
- p++;
- if (!strcmp(tag, option)) {
- *pstr = get_opt_value(buf, buf_size, p);
- if (**pstr == ',') {
- (*pstr)++;
- }
- return strlen(buf);
- } else {
- p = get_opt_value(NULL, 0, p);
- }
- if (*p != ',')
- break;
- p++;
- }
- return 0;
-}
-
-int get_param_value(char *buf, int buf_size,
- const char *tag, const char *str)
-{
- return get_next_param_value(buf, buf_size, tag, &str);
-}
-
-int check_params(char *buf, int buf_size,
- const char * const *params, const char *str)
-{
- const char *p;
- int i;
-
- p = str;
- while (*p != '\0') {
- p = get_opt_name(buf, buf_size, p, '=');
- if (*p != '=') {
- return -1;
- }
- p++;
- for (i = 0; params[i] != NULL; i++) {
- if (!strcmp(params[i], buf)) {
- break;
- }
- }
- if (params[i] == NULL) {
- return -1;
- }
- p = get_opt_value(NULL, 0, p);
- if (*p != ',') {
- break;
- }
- p++;
- }
- return 0;
-}
-
/***********************************************************/
/* Bluetooth support */
static int nb_hcis;
#define MTD_ALIAS "if=mtd"
#define SD_ALIAS "index=0,if=sd"
-DriveOpt *drive_add(const char *file, const char *fmt, ...)
+QemuOpts *drive_add(const char *file, const char *fmt, ...)
{
va_list ap;
- DriveOpt *dopt;
-
- dopt = qemu_mallocz(sizeof(*dopt));
+ char optstr[1024];
+ QemuOpts *opts;
- dopt->file = file;
va_start(ap, fmt);
- vsnprintf(dopt->opt,
- sizeof(dopt->opt), fmt, ap);
+ vsnprintf(optstr, sizeof(optstr), fmt, ap);
va_end(ap);
- TAILQ_INSERT_TAIL(&driveopts, dopt, next);
- return dopt;
-}
-
-void drive_remove(DriveOpt *dopt)
-{
- TAILQ_REMOVE(&driveopts, dopt, next);
- qemu_free(dopt);
+ opts = qemu_opts_parse(&qemu_drive_opts, optstr, NULL);
+ if (!opts) {
+ fprintf(stderr, "%s: huh? duplicate? (%s)\n",
+ __FUNCTION__, optstr);
+ return NULL;
+ }
+ if (file)
+ qemu_opt_set(opts, "file", file);
+ return opts;
}
DriveInfo *drive_get(BlockInterfaceType type, int bus, int unit)
return NULL;
}
-DriveInfo *drive_get_by_id(char *id)
+DriveInfo *drive_get_by_id(const char *id)
{
DriveInfo *dinfo;
TAILQ_FOREACH(dinfo, &drives, next) {
if (dinfo->bdrv != bdrv)
continue;
- drive_remove(dinfo->opt);
+ qemu_opts_del(dinfo->opts);
TAILQ_REMOVE(&drives, dinfo, next);
qemu_free(dinfo);
break;
}
}
-DriveInfo *drive_init(DriveOpt *arg, int snapshot, void *opaque,
+DriveInfo *drive_init(QemuOpts *opts, void *opaque,
int *fatal_error)
{
- char buf[128];
- char file[1024];
+ const char *buf;
+ const char *file = NULL;
char devname[128];
- char serial[21];
+ const char *serial;
const char *mediastr = "";
BlockInterfaceType type;
enum { MEDIA_DISK, MEDIA_CDROM } media;
int max_devs;
int index;
int cache;
+ int aio = 0;
int bdrv_flags, onerror;
const char *devaddr;
DriveInfo *dinfo;
- char *str = arg->opt;
- static const char * const params[] = { "bus", "unit", "if", "index",
- "cyls", "heads", "secs", "trans",
- "media", "snapshot", "file",
- "cache", "format", "serial",
- "werror", "addr", "id",
- NULL };
- *fatal_error = 1;
+ int snapshot = 0;
- if (check_params(buf, sizeof(buf), params, str) < 0) {
- fprintf(stderr, "qemu: unknown parameter '%s' in '%s'\n",
- buf, str);
- return NULL;
- }
+ *fatal_error = 1;
- file[0] = 0;
- cyls = heads = secs = 0;
- bus_id = 0;
- unit_id = -1;
translation = BIOS_ATA_TRANSLATION_AUTO;
- index = -1;
cache = 1;
- if (machine->use_scsi) {
+ if (machine && machine->use_scsi) {
type = IF_SCSI;
max_devs = MAX_SCSI_DEVS;
pstrcpy(devname, sizeof(devname), "scsi");
media = MEDIA_DISK;
/* extract parameters */
+ bus_id = qemu_opt_get_number(opts, "bus", 0);
+ unit_id = qemu_opt_get_number(opts, "unit", -1);
+ index = qemu_opt_get_number(opts, "index", -1);
- if (get_param_value(buf, sizeof(buf), "bus", str)) {
- bus_id = strtol(buf, NULL, 0);
- if (bus_id < 0) {
- fprintf(stderr, "qemu: '%s' invalid bus id\n", str);
- return NULL;
- }
- }
+ cyls = qemu_opt_get_number(opts, "cyls", 0);
+ heads = qemu_opt_get_number(opts, "heads", 0);
+ secs = qemu_opt_get_number(opts, "secs", 0);
- if (get_param_value(buf, sizeof(buf), "unit", str)) {
- unit_id = strtol(buf, NULL, 0);
- if (unit_id < 0) {
- fprintf(stderr, "qemu: '%s' invalid unit id\n", str);
- return NULL;
- }
- }
+ snapshot = qemu_opt_get_bool(opts, "snapshot", 0);
- if (get_param_value(buf, sizeof(buf), "if", str)) {
+ file = qemu_opt_get(opts, "file");
+ serial = qemu_opt_get(opts, "serial");
+
+ if ((buf = qemu_opt_get(opts, "if")) != NULL) {
pstrcpy(devname, sizeof(devname), buf);
if (!strcmp(buf, "ide")) {
type = IF_IDE;
} else if (!strcmp(buf, "xen")) {
type = IF_XEN;
max_devs = 0;
+ } else if (!strcmp(buf, "none")) {
+ type = IF_NONE;
+ max_devs = 0;
} else {
- fprintf(stderr, "qemu: '%s' unsupported bus type '%s'\n", str, buf);
+ fprintf(stderr, "qemu: unsupported bus type '%s'\n", buf);
return NULL;
}
}
- if (get_param_value(buf, sizeof(buf), "index", str)) {
- index = strtol(buf, NULL, 0);
- if (index < 0) {
- fprintf(stderr, "qemu: '%s' invalid index\n", str);
- return NULL;
- }
- }
-
- if (get_param_value(buf, sizeof(buf), "cyls", str)) {
- cyls = strtol(buf, NULL, 0);
- }
-
- if (get_param_value(buf, sizeof(buf), "heads", str)) {
- heads = strtol(buf, NULL, 0);
- }
-
- if (get_param_value(buf, sizeof(buf), "secs", str)) {
- secs = strtol(buf, NULL, 0);
- }
-
if (cyls || heads || secs) {
if (cyls < 1 || cyls > 16383) {
- fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", str);
+ fprintf(stderr, "qemu: '%s' invalid physical cyls number\n", buf);
return NULL;
}
if (heads < 1 || heads > 16) {
- fprintf(stderr, "qemu: '%s' invalid physical heads number\n", str);
+ fprintf(stderr, "qemu: '%s' invalid physical heads number\n", buf);
return NULL;
}
if (secs < 1 || secs > 63) {
- fprintf(stderr, "qemu: '%s' invalid physical secs number\n", str);
+ fprintf(stderr, "qemu: '%s' invalid physical secs number\n", buf);
return NULL;
}
}
- if (get_param_value(buf, sizeof(buf), "trans", str)) {
+ if ((buf = qemu_opt_get(opts, "trans")) != NULL) {
if (!cyls) {
fprintf(stderr,
"qemu: '%s' trans must be used with cyls,heads and secs\n",
- str);
+ buf);
return NULL;
}
if (!strcmp(buf, "none"))
else if (!strcmp(buf, "auto"))
translation = BIOS_ATA_TRANSLATION_AUTO;
else {
- fprintf(stderr, "qemu: '%s' invalid translation type\n", str);
+ fprintf(stderr, "qemu: '%s' invalid translation type\n", buf);
return NULL;
}
}
- if (get_param_value(buf, sizeof(buf), "media", str)) {
+ if ((buf = qemu_opt_get(opts, "media")) != NULL) {
if (!strcmp(buf, "disk")) {
media = MEDIA_DISK;
} else if (!strcmp(buf, "cdrom")) {
if (cyls || secs || heads) {
fprintf(stderr,
- "qemu: '%s' invalid physical CHS format\n", str);
+ "qemu: '%s' invalid physical CHS format\n", buf);
return NULL;
}
media = MEDIA_CDROM;
} else {
- fprintf(stderr, "qemu: '%s' invalid media\n", str);
+ fprintf(stderr, "qemu: '%s' invalid media\n", buf);
return NULL;
}
}
- if (get_param_value(buf, sizeof(buf), "snapshot", str)) {
- if (!strcmp(buf, "on"))
- snapshot = 1;
- else if (!strcmp(buf, "off"))
- snapshot = 0;
- else {
- fprintf(stderr, "qemu: '%s' invalid snapshot option\n", str);
- return NULL;
- }
- }
-
- if (get_param_value(buf, sizeof(buf), "cache", str)) {
+ if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
if (!strcmp(buf, "off") || !strcmp(buf, "none"))
cache = 0;
else if (!strcmp(buf, "writethrough"))
}
}
- if (get_param_value(buf, sizeof(buf), "format", str)) {
+#ifdef CONFIG_LINUX_AIO
+ if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
+ if (!strcmp(buf, "threads"))
+ aio = 0;
+ else if (!strcmp(buf, "native"))
+ aio = 1;
+ else {
+ fprintf(stderr, "qemu: invalid aio option\n");
+ return NULL;
+ }
+ }
+#endif
+
+ if ((buf = qemu_opt_get(opts, "format")) != NULL) {
if (strcmp(buf, "?") == 0) {
fprintf(stderr, "qemu: Supported formats:");
bdrv_iterate_format(bdrv_format_print, NULL);
}
}
- if (arg->file == NULL)
- get_param_value(file, sizeof(file), "file", str);
- else
- pstrcpy(file, sizeof(file), arg->file);
-
- if (!get_param_value(serial, sizeof(serial), "serial", str))
- memset(serial, 0, sizeof(serial));
-
onerror = BLOCK_ERR_STOP_ENOSPC;
- if (get_param_value(buf, sizeof(serial), "werror", str)) {
+ if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO) {
fprintf(stderr, "werror is no supported by this format\n");
return NULL;
}
}
- devaddr = NULL;
- if (get_param_value(buf, sizeof(buf), "addr", str)) {
+ if ((devaddr = qemu_opt_get(opts, "addr")) != NULL) {
if (type != IF_VIRTIO) {
- fprintf(stderr, "addr is not supported by in '%s'\n", str);
+ fprintf(stderr, "addr is not supported\n");
return NULL;
}
- devaddr = strdup(buf);
}
/* compute bus and unit according index */
if (index != -1) {
if (bus_id != 0 || unit_id != -1) {
fprintf(stderr,
- "qemu: '%s' index cannot be used with bus and unit\n", str);
+ "qemu: index cannot be used with bus and unit\n");
return NULL;
}
if (max_devs == 0)
/* check unit id */
if (max_devs && unit_id >= max_devs) {
- fprintf(stderr, "qemu: '%s' unit %d too big (max is %d)\n",
- str, unit_id, max_devs - 1);
+ fprintf(stderr, "qemu: unit %d too big (max is %d)\n",
+ unit_id, max_devs - 1);
return NULL;
}
/* init */
dinfo = qemu_mallocz(sizeof(*dinfo));
- if (!get_param_value(buf, sizeof(buf), "id", str)) {
+ if ((buf = qemu_opts_id(opts)) != NULL) {
+ dinfo->id = qemu_strdup(buf);
+ } else {
/* no id supplied -> create one */
+ dinfo->id = qemu_mallocz(32);
if (type == IF_IDE || type == IF_SCSI)
mediastr = (media == MEDIA_CDROM) ? "-cd" : "-hd";
if (max_devs)
- snprintf(buf, sizeof(buf), "%s%i%s%i",
+ snprintf(dinfo->id, 32, "%s%i%s%i",
devname, bus_id, mediastr, unit_id);
else
- snprintf(buf, sizeof(buf), "%s%s%i",
+ snprintf(dinfo->id, 32, "%s%s%i",
devname, mediastr, unit_id);
}
- dinfo->id = qemu_strdup(buf);
dinfo->bdrv = bdrv_new(dinfo->id);
dinfo->devaddr = devaddr;
dinfo->type = type;
dinfo->bus = bus_id;
dinfo->unit = unit_id;
dinfo->onerror = onerror;
- dinfo->opt = arg;
- strncpy(dinfo->serial, serial, sizeof(serial));
+ dinfo->opts = opts;
+ if (serial)
+ strncpy(dinfo->serial, serial, sizeof(serial));
TAILQ_INSERT_TAIL(&drives, dinfo, next);
switch(type) {
break;
case IF_PFLASH:
case IF_MTD:
+ case IF_NONE:
+ break;
case IF_VIRTIO:
+ /* add virtio block device */
+ opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
+ qemu_opt_set(opts, "driver", "virtio-blk-pci");
+ qemu_opt_set(opts, "drive", dinfo->id);
+ if (devaddr)
+ qemu_opt_set(opts, "addr", devaddr);
break;
case IF_COUNT:
abort();
}
- if (!file[0]) {
+ if (!file) {
*fatal_error = 0;
return NULL;
}
bdrv_flags |= BDRV_O_NOCACHE;
else if (cache == 2) /* write-back */
bdrv_flags |= BDRV_O_CACHE_WB;
+
+ if (aio == 1) {
+ bdrv_flags |= BDRV_O_NATIVE_AIO;
+ } else {
+ bdrv_flags &= ~BDRV_O_NATIVE_AIO;
+ }
+
if (bdrv_open2(dinfo->bdrv, file, bdrv_flags, drv) < 0) {
fprintf(stderr, "qemu: could not open disk image %s\n",
file);
return NULL;
}
+
if (bdrv_key_required(dinfo->bdrv))
autostart = 0;
*fatal_error = 0;
return dinfo;
}
+static int drive_init_func(QemuOpts *opts, void *opaque)
+{
+ QEMUMachine *machine = opaque;
+ int fatal_error = 0;
+
+ if (drive_init(opts, machine, &fatal_error) == NULL) {
+ if (fatal_error)
+ return 1;
+ }
+ return 0;
+}
+
+static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
+{
+ if (NULL == qemu_opt_get(opts, "snapshot")) {
+ qemu_opt_set(opts, "snapshot", "on");
+ }
+ return 0;
+}
+
void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
{
boot_set_handler = func;
return;
}
-/***********************************************************/
-/* 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)
+static void smp_parse(const char *optarg)
{
- 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;
+ int smp, sockets = 0, threads = 0, cores = 0;
+ char *endptr;
+ char option[128];
- hub = usb_hub_init(VM_USB_HUB_SIZE);
- usb_attach(port, hub);
- port = free_usb_ports;
+ smp = strtoul(optarg, &endptr, 10);
+ if (endptr != optarg) {
+ if (*endptr == ',') {
+ endptr++;
+ }
}
-
- free_usb_ports = port->next;
- port->next = used_usb_ports;
- used_usb_ports = port;
- usb_attach(port, dev);
- return 0;
+ if (get_param_value(option, 128, "sockets", endptr) != 0)
+ sockets = strtoull(option, NULL, 10);
+ if (get_param_value(option, 128, "cores", endptr) != 0)
+ cores = strtoull(option, NULL, 10);
+ if (get_param_value(option, 128, "threads", endptr) != 0)
+ threads = strtoull(option, NULL, 10);
+ if (get_param_value(option, 128, "maxcpus", endptr) != 0)
+ max_cpus = strtoull(option, NULL, 10);
+
+ /* compute missing values, prefer sockets over cores over threads */
+ if (smp == 0 || sockets == 0) {
+ sockets = sockets > 0 ? sockets : 1;
+ cores = cores > 0 ? cores : 1;
+ threads = threads > 0 ? threads : 1;
+ if (smp == 0) {
+ smp = cores * threads * sockets;
+ } else {
+ sockets = smp / (cores * threads);
+ }
+ } else {
+ if (cores == 0) {
+ threads = threads > 0 ? threads : 1;
+ cores = smp / (sockets * threads);
+ } else {
+ if (sockets == 0) {
+ sockets = smp / (cores * threads);
+ } else {
+ threads = smp / (cores * sockets);
+ }
+ }
+ }
+ smp_cpus = smp;
+ smp_cores = cores > 0 ? cores : 1;
+ smp_threads = threads > 0 ? threads : 1;
+ if (max_cpus == 0)
+ max_cpus = smp_cpus;
}
+/***********************************************************/
+/* USB devices */
+
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;
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
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;
}
if (strstart(devname, "host:", &p))
return usb_host_device_close(p);
- if (!used_usb_ports)
+ if (!usb_enabled)
return -1;
p = strchr(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)
return usb_device_add(cmdline, 0);
}
-void do_usb_add(Monitor *mon, const char *devname)
+void do_usb_add(Monitor *mon, const QDict *qdict)
{
- usb_device_add(devname, 1);
+ usb_device_add(qdict_get_str(qdict, "devname"), 1);
}
-void do_usb_del(Monitor *mon, const char *devname)
+void do_usb_del(Monitor *mon, const QDict *qdict)
{
- usb_device_del(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);
- }
+ usb_device_del(qdict_get_str(qdict, "devname"));
}
/***********************************************************/
if (kvm_enabled())
kvm_init_vcpu(env);
+ env->nr_cores = smp_cores;
+ env->nr_threads = smp_threads;
return;
}
if (env) {
cpu_exit(env);
-#ifdef USE_KQEMU
- if (env->kqemu_enabled)
- kqemu_cpu_interrupt(env);
-#endif
- }
+ }
}
#define qemu_mutex_lock_iothread() do { } while (0)
block_io_signals();
qemu_thread_self(env->thread);
+ if (kvm_enabled())
+ kvm_init_vcpu(env);
/* signal CPU creation */
qemu_mutex_lock(&qemu_global_mutex);
static void kvm_start_vcpu(CPUState *env)
{
- kvm_init_vcpu(env);
env->thread = qemu_mallocz(sizeof(QemuThread));
env->halt_cond = qemu_mallocz(sizeof(QemuCond));
qemu_cond_init(env->halt_cond);
kvm_start_vcpu(env);
else
tcg_init_vcpu(env);
+ env->nr_cores = smp_cores;
+ env->nr_threads = smp_threads;
}
void qemu_notify_event(void)
return 1;
}
+qemu_irq qemu_system_powerdown;
+
static void main_loop(void)
{
int r;
qemu_system_reset();
resume_all_vcpus();
}
- if (qemu_powerdown_requested())
- qemu_system_powerdown();
+ if (qemu_powerdown_requested()) {
+ qemu_irq_raise(qemu_system_powerdown);
+ }
if ((r = qemu_vmstop_requested()))
vm_stop(r);
}
l = !e ? strlen (p) : (size_t) (e - p);
for (c = soundhw; c->name; ++c) {
- if (!strncmp (c->name, p, l)) {
+ if (!strncmp (c->name, p, l) && !c->name[l]) {
c->enabled = 1;
break;
}
{
const char *opts;
- cirrus_vga_enabled = 0;
- std_vga_enabled = 0;
- vmsvga_enabled = 0;
- xenfb_enabled = 0;
+ vga_interface_type = VGA_NONE;
if (strstart(p, "std", &opts)) {
- std_vga_enabled = 1;
+ vga_interface_type = VGA_STD;
} else if (strstart(p, "cirrus", &opts)) {
- cirrus_vga_enabled = 1;
+ vga_interface_type = VGA_CIRRUS;
} else if (strstart(p, "vmware", &opts)) {
- vmsvga_enabled = 1;
+ vga_interface_type = VGA_VMWARE;
} else if (strstart(p, "xenfb", &opts)) {
- xenfb_enabled = 1;
+ vga_interface_type = VGA_XENFB;
} else if (!strstart(p, "none", &opts)) {
invalid_vga:
fprintf(stderr, "Unknown vga type: %s\n", p);
#ifdef TARGET_I386
static int balloon_parse(const char *arg)
{
- char buf[128];
- const char *p;
+ QemuOpts *opts;
- if (!strcmp(arg, "none")) {
- virtio_balloon = 0;
- } else if (!strncmp(arg, "virtio", 6)) {
- virtio_balloon = 1;
- if (arg[6] == ',') {
- p = arg + 7;
- if (get_param_value(buf, sizeof(buf), "addr", p)) {
- virtio_balloon_devaddr = strdup(buf);
- }
+ if (strcmp(arg, "none") == 0) {
+ return 0;
+ }
+
+ if (!strncmp(arg, "virtio", 6)) {
+ if (arg[6] == ',') {
+ /* have params -> parse them */
+ opts = qemu_opts_parse(&qemu_device_opts, arg+7, NULL);
+ if (!opts)
+ return -1;
+ } else {
+ /* create empty opts */
+ opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
}
- } else {
- return -1;
+ qemu_opt_set(opts, "driver", "virtio-balloon-pci");
+ return 0;
}
- return 0;
+
+ return -1;
}
#endif
char *dir;
char *p = NULL;
char *res;
-#ifdef PATH_MAX
char buf[PATH_MAX];
-#endif
size_t max_len;
#if defined(__linux__)
/* 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;
}
res = NULL;
}
}
-#ifndef PATH_MAX
- free(p);
-#endif
+
return res;
}
#undef SHARE_SUFFIX
/* 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:
return buf;
}
+static int device_init_func(QemuOpts *opts, void *opaque)
+{
+ DeviceState *dev;
+
+ dev = qdev_device_add(opts);
+ if (!dev)
+ return -1;
+ return 0;
+}
+
struct device_config {
enum {
- DEV_GENERIC, /* -device */
DEV_USB, /* -usbdevice */
DEV_BT, /* -bt */
} type;
return 0;
}
-static int generic_parse(const char *cmdline)
-{
- DeviceState *dev;
-
- dev = qdev_device_add(cmdline);
- if (!dev)
- return -1;
- return 0;
-}
-
int main(int argc, char **argv, char **envp)
{
const char *gdbstub_dev = NULL;
int cyls, heads, secs, translation;
const char *net_clients[MAX_NET_CLIENTS];
int nb_net_clients;
- DriveOpt *dopt, *hda_opt = NULL;
+ QemuOpts *hda_opts = NULL, *opts;
int optind;
const char *r, *optarg;
- CharDriverState *monitor_hd = NULL;
- const char *monitor_device;
+ CharDriverState *monitor_hds[MAX_MONITOR_DEVICES];
+ const char *monitor_devices[MAX_MONITOR_DEVICES];
+ int monitor_device_index;
const char *serial_devices[MAX_SERIAL_PORTS];
int serial_device_index;
const char *parallel_devices[MAX_PARALLEL_PORTS];
CPUState *env;
int show_vnc_port = 0;
+ qemu_errors_to_file(stderr);
qemu_cache_utils_init(envp);
LIST_INIT (&vm_change_state_head);
kernel_cmdline = "";
cyls = heads = secs = 0;
translation = BIOS_ATA_TRANSLATION_AUTO;
- monitor_device = "vc:80Cx24C";
serial_devices[0] = "vc:80Cx24C";
for(i = 1; i < MAX_SERIAL_PORTS; i++)
virtio_consoles[i] = NULL;
virtio_console_index = 0;
+ monitor_devices[0] = "vc:80Cx24C";
+ for (i = 1; i < MAX_MONITOR_DEVICES; i++) {
+ monitor_devices[i] = NULL;
+ }
+ monitor_device_index = 0;
+
for (i = 0; i < MAX_NODES; i++) {
node_mem[i] = 0;
node_cpumask[i] = 0;
tb_size = 0;
autostart= 1;
- register_watchdogs();
-
optind = 1;
for(;;) {
if (optind >= argc)
break;
r = argv[optind];
if (r[0] != '-') {
- hda_opt = drive_add(argv[optind++], HD_ALIAS, 0);
+ hda_opts = drive_add(argv[optind++], HD_ALIAS, 0);
} else {
const QEMUOption *popt;
break;
case QEMU_OPTION_hda:
if (cyls == 0)
- hda_opt = drive_add(optarg, HD_ALIAS, 0);
+ hda_opts = drive_add(optarg, HD_ALIAS, 0);
else
- hda_opt = drive_add(optarg, HD_ALIAS
+ hda_opts = drive_add(optarg, HD_ALIAS
",cyls=%d,heads=%d,secs=%d%s",
0, cyls, heads, secs,
translation == BIOS_ATA_TRANSLATION_LBA ?
case QEMU_OPTION_drive:
drive_add(NULL, "%s", optarg);
break;
+ case QEMU_OPTION_set:
+ if (qemu_set_option(optarg) != 0)
+ exit(1);
+ break;
case QEMU_OPTION_mtdblock:
drive_add(optarg, MTD_ALIAS);
break;
fprintf(stderr, "qemu: invalid physical CHS format\n");
exit(1);
}
- if (hda_opt != NULL)
- snprintf(hda_opt->opt,
- sizeof(hda_opt->opt),
- HD_ALIAS ",cyls=%d,heads=%d,secs=%d%s",
- 0, cyls, heads, secs,
- translation == BIOS_ATA_TRANSLATION_LBA ?
- ",trans=lba" :
- translation == BIOS_ATA_TRANSLATION_NONE ?
- ",trans=none" : "");
+ if (hda_opts != NULL) {
+ char num[16];
+ snprintf(num, sizeof(num), "%d", cyls);
+ qemu_opt_set(hda_opts, "cyls", num);
+ snprintf(num, sizeof(num), "%d", heads);
+ qemu_opt_set(hda_opts, "heads", num);
+ snprintf(num, sizeof(num), "%d", secs);
+ qemu_opt_set(hda_opts, "secs", num);
+ if (translation == BIOS_ATA_TRANSLATION_LBA)
+ qemu_opt_set(hda_opts, "trans", "lba");
+ if (translation == BIOS_ATA_TRANSLATION_NONE)
+ qemu_opt_set(hda_opts, "trans", "none");
+ }
}
break;
case QEMU_OPTION_numa:
}
/* On 32-bit hosts, QEMU is limited by virtual address space */
- if (value > (2047 << 20)
-#ifndef CONFIG_KQEMU
- && HOST_LONG_BITS == 32
-#endif
- ) {
+ if (value > (2047 << 20) && HOST_LONG_BITS == 32) {
fprintf(stderr, "qemu: at most 2047 MB RAM can be simulated\n");
exit(1);
}
break;
}
case QEMU_OPTION_monitor:
- monitor_device = optarg;
+ if (monitor_device_index >= MAX_MONITOR_DEVICES) {
+ fprintf(stderr, "qemu: too many monitor devices\n");
+ exit(1);
+ }
+ 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) {
serial_device_index++;
break;
case QEMU_OPTION_watchdog:
- i = select_watchdog(optarg);
- if (i > 0)
- exit (i == 1 ? 1 : 0);
+ if (watchdog) {
+ fprintf(stderr,
+ "qemu: only one watchdog option may be given\n");
+ return 1;
+ }
+ watchdog = optarg;
break;
case QEMU_OPTION_watchdog_action:
if (select_watchdog_action(optarg) == -1) {
}
break;
#endif
-#ifdef CONFIG_KQEMU
- case QEMU_OPTION_enable_kqemu:
- kqemu_allowed = 1;
- break;
- case QEMU_OPTION_kernel_kqemu:
- kqemu_allowed = 2;
- break;
-#endif
#ifdef CONFIG_KVM
case QEMU_OPTION_enable_kvm:
kvm_allowed = 1;
-#ifdef CONFIG_KQEMU
- kqemu_allowed = 0;
-#endif
break;
#endif
case QEMU_OPTION_usb:
add_device_config(DEV_USB, optarg);
break;
case QEMU_OPTION_device:
- add_device_config(DEV_GENERIC, optarg);
+ opts = qemu_opts_parse(&qemu_device_opts, optarg, "driver");
+ if (!opts) {
+ fprintf(stderr, "parse error: %s\n", optarg);
+ exit(1);
+ }
break;
case QEMU_OPTION_smp:
- smp_cpus = atoi(optarg);
+ smp_parse(optarg);
if (smp_cpus < 1) {
fprintf(stderr, "Invalid number of CPUs\n");
exit(1);
}
+ if (max_cpus < smp_cpus) {
+ fprintf(stderr, "maxcpus must be equal to or greater than "
+ "smp\n");
+ exit(1);
+ }
+ if (max_cpus > 255) {
+ fprintf(stderr, "Unsupported number of maxcpus\n");
+ exit(1);
+ }
break;
case QEMU_OPTION_vnc:
display_type = DT_VNC;
}
}
+ 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) {
data_dir = CONFIG_QEMU_SHAREDIR;
}
-#if defined(CONFIG_KVM) && defined(CONFIG_KQEMU)
- if (kvm_allowed && kqemu_allowed) {
- fprintf(stderr,
- "You can not enable both KVM and kqemu at the same time\n");
- exit(1);
- }
-#endif
+ /*
+ * Default to max_cpus = smp_cpus, in case the user doesn't
+ * specify a max_cpus value.
+ */
+ if (!max_cpus)
+ max_cpus = smp_cpus;
machine->max_cpus = machine->max_cpus ?: 1; /* Default to UP */
if (smp_cpus > machine->max_cpus) {
serial_devices[0] = "stdio";
if (parallel_device_index == 0)
parallel_devices[0] = "null";
- if (strncmp(monitor_device, "vc", 2) == 0)
- monitor_device = "stdio";
+ if (strncmp(monitor_devices[0], "vc", 2) == 0) {
+ monitor_devices[0] = "stdio";
+ }
}
#ifndef _WIN32
}
#endif
-#ifdef CONFIG_KQEMU
- if (smp_cpus > 1)
- kqemu_allowed = 0;
-#endif
if (qemu_init_main_loop()) {
fprintf(stderr, "qemu_init_main_loop failed\n");
exit(1);
exit(1);
}
+#ifndef _WIN32
+ /* Win32 doesn't support line-buffering and requires size >= 2 */
setvbuf(stdout, NULL, _IOLBF, 0);
+#endif
init_timers();
if (init_timer_alarm() < 0) {
if (ram_size == 0)
ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
-#ifdef CONFIG_KQEMU
- /* FIXME: This is a nasty hack because kqemu can't cope with dynamic
- guest ram allocation. It needs to go away. */
- if (kqemu_allowed) {
- kqemu_phys_ram_size = ram_size + 8 * 1024 * 1024 + 4 * 1024 * 1024;
- kqemu_phys_ram_base = qemu_vmalloc(kqemu_phys_ram_size);
- if (!kqemu_phys_ram_base) {
- fprintf(stderr, "Could not allocate physical memory\n");
- exit(1);
- }
- }
-#endif
-
/* init the dynamic translator */
cpu_exec_init_all(tb_size * 1024 * 1024);
drive_add(NULL, SD_ALIAS);
/* open the virtual block devices */
-
- TAILQ_FOREACH(dopt, &driveopts, next) {
- int fatal_error;
- if (drive_init(dopt, snapshot, machine, &fatal_error) == NULL)
- if (fatal_error)
- exit(1);
- }
+ if (snapshot)
+ qemu_opts_foreach(&qemu_drive_opts, drive_enable_snapshot, NULL, 0);
+ 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);
register_savevm_live("ram", 0, 3, ram_save_live, NULL, ram_load, NULL);
-#ifndef _WIN32
- /* must be after terminal init, SDL library changes signal handlers */
- sighandler_setup();
-#endif
-
/* Maintain compatibility with multiple stdio monitors */
- if (!strcmp(monitor_device,"stdio")) {
+ if (!strcmp(monitor_devices[0],"stdio")) {
for (i = 0; i < MAX_SERIAL_PORTS; i++) {
const char *devname = serial_devices[i];
if (devname && !strcmp(devname,"mon:stdio")) {
- monitor_device = NULL;
+ monitor_devices[0] = NULL;
break;
} else if (devname && !strcmp(devname,"stdio")) {
- monitor_device = NULL;
+ monitor_devices[0] = NULL;
serial_devices[i] = "mon:stdio";
break;
}
}
}
- if (kvm_enabled()) {
- int ret;
-
- ret = kvm_init(smp_cpus);
- if (ret < 0) {
- fprintf(stderr, "failed to initialize KVM\n");
- exit(1);
- }
- }
-
- if (monitor_device) {
- monitor_hd = qemu_chr_open("monitor", monitor_device, NULL);
- if (!monitor_hd) {
- fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
- exit(1);
+ for (i = 0; i < MAX_MONITOR_DEVICES; i++) {
+ const char *devname = monitor_devices[i];
+ if (devname && strcmp(devname, "none")) {
+ char label[32];
+ if (i == 0) {
+ snprintf(label, sizeof(label), "monitor");
+ } else {
+ snprintf(label, sizeof(label), "monitor%d", i);
+ }
+ monitor_hds[i] = qemu_chr_open(label, devname, NULL);
+ if (!monitor_hds[i]) {
+ fprintf(stderr, "qemu: could not open monitor device '%s'\n",
+ devname);
+ exit(1);
+ }
}
}
module_call_init(MODULE_INIT_DEVICE);
+ if (watchdog) {
+ i = select_watchdog(watchdog);
+ if (i > 0)
+ exit (i == 1 ? 1 : 0);
+ }
+
if (machine->compat_props) {
qdev_prop_register_compat(machine->compat_props);
}
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
+#ifndef _WIN32
+ /* must be after terminal init, SDL library changes signal handlers */
+ sighandler_setup();
+#endif
+
for (env = first_cpu; env != NULL; env = env->next_cpu) {
for (i = 0; i < nb_numa_nodes; i++) {
if (node_cpumask[i] & (1 << env->cpu_index)) {
}
/* init generic devices */
- if (foreach_device_config(DEV_GENERIC, generic_parse))
+ if (qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) != 0)
exit(1);
if (!display_state)
text_consoles_set_display(display_state);
qemu_chr_initial_reset();
- if (monitor_device && monitor_hd)
- monitor_init(monitor_hd, MONITOR_USE_READLINE | MONITOR_IS_DEFAULT);
+ for (i = 0; i < MAX_MONITOR_DEVICES; i++) {
+ if (monitor_devices[i] && monitor_hds[i]) {
+ monitor_init(monitor_hds[i],
+ MONITOR_USE_READLINE |
+ ((i == 0) ? MONITOR_IS_DEFAULT : 0));
+ }
+ }
for(i = 0; i < MAX_SERIAL_PORTS; i++) {
const char *devname = serial_devices[i];
exit(1);
}
- if (loadvm)
- do_loadvm(cur_mon, loadvm);
+ if (loadvm) {
+ if (load_vmstate(cur_mon, loadvm) < 0) {
+ autostart = 0;
+ }
+ }
- if (incoming)
+ if (incoming) {
qemu_start_incoming_migration(incoming);
-
- if (autostart)
+ } else if (autostart) {
vm_start();
+ }
#ifndef _WIN32
if (daemonize) {