aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile11
-rw-r--r--QMP/qmp-spec.txt5
-rwxr-xr-xconfigure18
-rw-r--r--console.c10
-rw-r--r--cpu-defs.h2
-rw-r--r--hw/boards.h6
-rw-r--r--hw/bt-hid.c4
-rw-r--r--hw/cirrus_vga.c5
-rw-r--r--hw/grackle_pci.c4
-rw-r--r--hw/ide/cmd646.c4
-rw-r--r--hw/ide/piix.c8
-rw-r--r--hw/mc146818rtc.c17
-rw-r--r--hw/pc.c2
-rw-r--r--hw/pci-hotplug.c18
-rw-r--r--hw/pci.c11
-rw-r--r--hw/qdev-properties.c25
-rw-r--r--hw/qdev.c2
-rw-r--r--hw/qdev.h10
-rw-r--r--hw/s390-virtio.c4
-rw-r--r--hw/syborg_virtio.c12
-rw-r--r--hw/unin_pci.c30
-rw-r--r--hw/usb-bt.c5
-rw-r--r--hw/usb-bus.c13
-rw-r--r--hw/usb-hid.c14
-rw-r--r--hw/usb-hub.c3
-rw-r--r--hw/usb-msd.c6
-rw-r--r--hw/usb-net.c5
-rw-r--r--hw/usb-ohci.c5
-rw-r--r--hw/usb-serial.c12
-rw-r--r--hw/usb-uhci.c8
-rw-r--r--hw/usb-wacom.c5
-rw-r--r--hw/usb.h4
-rw-r--r--hw/virtio-pci.c14
-rw-r--r--hw/virtio.c11
-rw-r--r--hw/virtio.h6
-rw-r--r--hw/vmware_vga.c6
-rw-r--r--linux-user/main.c1
-rw-r--r--monitor.c161
-rw-r--r--monitor.h1
-rw-r--r--net.c5
-rw-r--r--net.h1
-rw-r--r--qdict.c28
-rw-r--r--qdict.h3
-rw-r--r--qemu-char.c2
-rw-r--r--qemu-char.h1
-rw-r--r--qemu-config.c75
-rw-r--r--qemu-config.h3
-rw-r--r--qemu-malloc.c19
-rw-r--r--qemu-monitor.hx3
-rw-r--r--qemu-objects.h24
-rw-r--r--qemu-option.c4
-rw-r--r--qemu-options.hx22
-rw-r--r--qerror.c85
-rw-r--r--qerror.h56
-rw-r--r--rules.mak3
-rw-r--r--target-i386/machine.c1
-rw-r--r--usb-bsd.c9
-rw-r--r--usb-linux.c10
-rw-r--r--vl.c490
-rw-r--r--vnc.c8
60 files changed, 923 insertions, 417 deletions
diff --git a/Makefile b/Makefile
index 12638f29e..82164a20b 100644
--- a/Makefile
+++ b/Makefile
@@ -94,6 +94,12 @@ ALL_SUBDIRS=$(TARGET_DIRS) $(patsubst %,pc-bios/%, $(ROMS))
recurse-all: $(SUBDIR_RULES) $(ROMSUBDIR_RULES)
#######################################################################
+# QObject
+qobject-obj-y = qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o
+qobject-obj-y += qjson.o json-lexer.o json-streamer.o json-parser.o
+qobject-obj-y += qerror.o
+
+#######################################################################
# block-obj-y is code used by both qemu system emulation and qemu-img
block-obj-y = cutils.o cache-utils.o qemu-malloc.o qemu-option.o module.o
@@ -133,6 +139,7 @@ net-obj-y += $(addprefix net/, $(net-nested-y))
obj-y = $(block-obj-y)
obj-y += $(net-obj-y)
+obj-y += $(qobject-obj-y)
obj-y += readline.o console.o
obj-y += tcg-runtime.o host-utils.o
@@ -165,8 +172,6 @@ obj-y += buffered_file.o migration.o migration-tcp.o qemu-sockets.o
obj-y += qemu-char.o aio.o savevm.o
obj-y += msmouse.o ps2.o
obj-y += qdev.o qdev-properties.o
-obj-y += qint.o qstring.o qdict.o qlist.o qfloat.o qbool.o json-lexer.o
-obj-y += json-streamer.o json-parser.o qjson.o qerror.o
obj-y += qemu-config.o block-migration.o
obj-$(CONFIG_BRLAPI) += baum.o
@@ -254,7 +259,7 @@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
check-qint: check-qint.o qint.o qemu-malloc.o
check-qstring: check-qstring.o qstring.o qemu-malloc.o
-check-qdict: check-qdict.o qdict.o qint.o qstring.o qemu-malloc.o
+check-qdict: check-qdict.o qdict.o qint.o qstring.o qbool.o qemu-malloc.o qlist.o
check-qlist: check-qlist.o qlist.o qint.o qemu-malloc.o
check-qfloat: check-qfloat.o qfloat.o qemu-malloc.o
check-qjson: check-qjson.o qfloat.o qint.o qdict.o qstring.o qlist.o qbool.o qjson.o json-streamer.o json-lexer.o json-parser.o qemu-malloc.o
diff --git a/QMP/qmp-spec.txt b/QMP/qmp-spec.txt
index 8429789a9..1cbd21cd4 100644
--- a/QMP/qmp-spec.txt
+++ b/QMP/qmp-spec.txt
@@ -102,13 +102,16 @@ completed because of an error condition.
The format is:
-{ "error": { "class": json-string, "data": json-value }, "id": json-value }
+{ "error": { "class": json-string, "data": json-value, "desc": json-string },
+ "id": json-value }
Where,
- The "class" member contains the error class name (eg. "ServiceUnavailable")
- The "data" member contains specific error data and is defined in a
per-command basis, it will be an empty json-object if the error has no data
+- The "desc" member is a human-readable error message. Clients should
+ not attempt to parse this message.
- The "id" member contains the transaction identification associated with
the command execution (if issued by the Client)
diff --git a/configure b/configure
index e804a92e4..b851c45c8 100755
--- a/configure
+++ b/configure
@@ -271,6 +271,7 @@ cpu_emulation="yes"
kvm_kmod="no"
check_utests="no"
user_pie="no"
+zero_malloc=""
# OS specific
if check_define __linux__ ; then
@@ -1930,8 +1931,9 @@ fi
# Consult white-list to determine whether to enable werror
# by default. Only enable by default for git builds
+z_version=`cut -f3 -d. $source_path/VERSION`
+
if test -z "$werror" ; then
- z_version=`cut -f3 -d. $source_path/VERSION`
if test "$z_version" = "50" -a \
"$linux" = "yes" ; then
werror="yes"
@@ -1940,6 +1942,16 @@ if test -z "$werror" ; then
fi
fi
+# Disable zero malloc errors for official releases unless explicitly told to
+# enable/disable
+if test -z "$zero_malloc" ; then
+ if test "$z_version" = "50" ; then
+ zero_malloc="no"
+ else
+ zero_malloc="yes"
+ fi
+fi
+
if test "$werror" = "yes" ; then
QEMU_CFLAGS="-Werror $QEMU_CFLAGS"
fi
@@ -2273,6 +2285,10 @@ fi
echo "CONFIG_UNAME_RELEASE=\"$uname_release\"" >> $config_host_mak
+if test "$zero_malloc" = "yes" ; then
+ echo "CONFIG_ZERO_MALLOC=y" >> $config_host_mak
+fi
+
# USB host support
case "$usb" in
linux)
diff --git a/console.c b/console.c
index 82ddbe4d9..8086bd6f2 100644
--- a/console.c
+++ b/console.c
@@ -1384,6 +1384,16 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds, QemuOpt
s->t_attrib = s->t_attrib_default;
text_console_resize(s);
+ if (chr->label) {
+ char msg[128];
+ int len;
+
+ s->t_attrib.bgcol = COLOR_BLUE;
+ len = snprintf(msg, sizeof(msg), "%s console\r\n", chr->label);
+ console_puts(chr, (uint8_t*)msg, len);
+ s->t_attrib = s->t_attrib_default;
+ }
+
qemu_chr_generic_open(chr);
if (chr->init)
chr->init(chr);
diff --git a/cpu-defs.h b/cpu-defs.h
index cf502e992..0e4ed1616 100644
--- a/cpu-defs.h
+++ b/cpu-defs.h
@@ -188,7 +188,7 @@ struct KVMCPUState {
\
/* Core interrupt code */ \
jmp_buf jmp_env; \
- int exception_index; \
+ int32_t exception_index; \
\
CPUState *next_cpu; /* next CPU sharing TB cache */ \
int cpu_index; /* CPU index (informative) */ \
diff --git a/hw/boards.h b/hw/boards.h
index d8893413d..8fe0fbc8f 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -19,8 +19,12 @@ typedef struct QEMUMachine {
QEMUMachineInitFunc *init;
int use_scsi;
int max_cpus;
+ int no_serial:1,
+ no_parallel:1,
+ use_virtcon:1,
+ no_vga:1;
int is_default;
- CompatProperty *compat_props;
+ GlobalProperty *compat_props;
struct QEMUMachine *next;
} QEMUMachine;
diff --git a/hw/bt-hid.c b/hw/bt-hid.c
index 020176eac..abdfd35e8 100644
--- a/hw/bt-hid.c
+++ b/hw/bt-hid.c
@@ -552,7 +552,7 @@ static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net,
BT_HID_MTU, bt_hid_new_interrupt_ch);
s->usbdev = dev;
- s->btdev.device.lmp_name = s->usbdev->devname;
+ s->btdev.device.lmp_name = s->usbdev->product_desc;
usb_hid_datain_cb(s->usbdev, s, bt_hid_datain);
s->btdev.device.handle_destroy = bt_hid_destroy;
@@ -566,6 +566,6 @@ static struct bt_device_s *bt_hid_init(struct bt_scatternet_s *net,
struct bt_device_s *bt_keyboard_init(struct bt_scatternet_s *net)
{
- USBDevice *dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Keyboard");
+ USBDevice *dev = usb_create_simple(NULL /* FIXME */, "usb-kbd");
return bt_hid_init(net, dev, class_keyboard);
}
diff --git a/hw/cirrus_vga.c b/hw/cirrus_vga.c
index ea9487339..3c7193b1d 100644
--- a/hw/cirrus_vga.c
+++ b/hw/cirrus_vga.c
@@ -3235,11 +3235,12 @@ static int pci_cirrus_vga_initfn(PCIDevice *dev)
void pci_cirrus_vga_init(PCIBus *bus)
{
- pci_create_simple(bus, -1, "Cirrus VGA");
+ pci_create_simple(bus, -1, "cirrus-vga");
}
static PCIDeviceInfo cirrus_vga_info = {
- .qdev.name = "Cirrus VGA",
+ .qdev.name = "cirrus-vga",
+ .qdev.desc = "Cirrus CLGD 54xx VGA",
.qdev.size = sizeof(PCICirrusVGAState),
.qdev.vmsd = &vmstate_pci_cirrus_vga,
.init = pci_cirrus_vga_initfn,
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 089d1fba0..ee4fed53e 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -178,7 +178,7 @@ static PCIDeviceInfo grackle_pci_host_info = {
};
static PCIDeviceInfo dec_21154_pci_host_info = {
- .qdev.name = "DEC 21154",
+ .qdev.name = "dec-21154",
.qdev.size = sizeof(PCIDevice),
.init = dec_21154_pci_host_init,
};
@@ -188,7 +188,7 @@ static void grackle_register_devices(void)
sysbus_register_dev("grackle", sizeof(GrackleState),
pci_grackle_init_device);
pci_qdev_register(&grackle_pci_host_info);
- sysbus_register_dev("DEC 21154", sizeof(GrackleState),
+ sysbus_register_dev("dec-21154", sizeof(GrackleState),
pci_dec_21154_init_device);
pci_qdev_register(&dec_21154_pci_host_info);
}
diff --git a/hw/ide/cmd646.c b/hw/ide/cmd646.c
index 3b7c60608..e1e626e2a 100644
--- a/hw/ide/cmd646.c
+++ b/hw/ide/cmd646.c
@@ -245,7 +245,7 @@ void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table,
{
PCIDevice *dev;
- dev = pci_create(bus, -1, "CMD646 IDE");
+ dev = pci_create(bus, -1, "cmd646-ide");
qdev_prop_set_uint32(&dev->qdev, "secondary", secondary_ide_enabled);
qdev_init_nofail(&dev->qdev);
@@ -254,7 +254,7 @@ void pci_cmd646_ide_init(PCIBus *bus, DriveInfo **hd_table,
static PCIDeviceInfo cmd646_ide_info[] = {
{
- .qdev.name = "CMD646 IDE",
+ .qdev.name = "cmd646-ide",
.qdev.size = sizeof(PCIIDEState),
.init = pci_cmd646_ide_initfn,
.qdev.props = (Property[]) {
diff --git a/hw/ide/piix.c b/hw/ide/piix.c
index ec93f29b5..de3648023 100644
--- a/hw/ide/piix.c
+++ b/hw/ide/piix.c
@@ -161,7 +161,7 @@ void pci_piix3_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
{
PCIDevice *dev;
- dev = pci_create_simple(bus, devfn, "PIIX3 IDE");
+ dev = pci_create_simple(bus, devfn, "piix3-ide");
pci_ide_create_devs(dev, hd_table);
}
@@ -171,18 +171,18 @@ void pci_piix4_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
{
PCIDevice *dev;
- dev = pci_create_simple(bus, devfn, "PIIX4 IDE");
+ dev = pci_create_simple(bus, devfn, "piix4-ide");
pci_ide_create_devs(dev, hd_table);
}
static PCIDeviceInfo piix_ide_info[] = {
{
- .qdev.name = "PIIX3 IDE",
+ .qdev.name = "piix3-ide",
.qdev.size = sizeof(PCIIDEState),
.qdev.no_user = 1,
.init = pci_piix3_ide_initfn,
},{
- .qdev.name = "PIIX4 IDE",
+ .qdev.name = "piix4-ide",
.qdev.size = sizeof(PCIIDEState),
.qdev.no_user = 1,
.init = pci_piix4_ide_initfn,
diff --git a/hw/mc146818rtc.c b/hw/mc146818rtc.c
index b8c7b0c1b..e4d55c7c7 100644
--- a/hw/mc146818rtc.c
+++ b/hw/mc146818rtc.c
@@ -30,6 +30,8 @@
//#define DEBUG_CMOS
+#define RTC_REINJECT_ON_ACK_COUNT 1000
+
#define RTC_SECONDS 0
#define RTC_SECONDS_ALARM 1
#define RTC_MINUTES 2
@@ -76,6 +78,7 @@ struct RTCState {
int64_t next_periodic_time;
/* second update */
int64_t next_second_time;
+ uint16_t irq_reinject_on_ack_count;
uint32_t irq_coalesced;
uint32_t period;
QEMUTimer *coalesced_timer;
@@ -180,6 +183,8 @@ static void rtc_periodic_timer(void *opaque)
s->cmos_data[RTC_REG_C] |= 0xc0;
#ifdef TARGET_I386
if(rtc_td_hack) {
+ if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT)
+ s->irq_reinject_on_ack_count = 0;
apic_reset_irq_delivered();
rtc_irq_raise(s->irq);
if (!apic_get_irq_delivered()) {
@@ -458,6 +463,18 @@ static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
case RTC_REG_C:
ret = s->cmos_data[s->cmos_index];
qemu_irq_lower(s->irq);
+#ifdef TARGET_I386
+ if(s->irq_coalesced &&
+ s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) {
+ s->irq_reinject_on_ack_count++;
+ apic_reset_irq_delivered();
+ qemu_irq_raise(s->irq);
+ if (apic_get_irq_delivered())
+ s->irq_coalesced--;
+ break;
+ }
+#endif
+
s->cmos_data[RTC_REG_C] = 0x00;
break;
default:
diff --git a/hw/pc.c b/hw/pc.c
index c702c1f05..97685d56e 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -1345,7 +1345,7 @@ static QEMUMachine pc_machine_v0_10 = {
.desc = "Standard PC, qemu 0.10",
.init = pc_init_pci,
.max_cpus = 255,
- .compat_props = (CompatProperty[]) {
+ .compat_props = (GlobalProperty[]) {
{
.driver = "virtio-blk-pci",
.property = "class",
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 6e4277671..a69786357 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -41,7 +41,18 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
const char *opts_str)
{
QemuOpts *opts;
- int ret;
+ PCIBus *bus;
+ int ret, devfn;
+
+ bus = pci_get_bus_devfn(&devfn, devaddr);
+ if (!bus) {
+ monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
+ return NULL;
+ }
+ if (!((BusState*)bus)->allow_hotplug) {
+ monitor_printf(mon, "PCI bus doesn't support hotplug\n");
+ return NULL;
+ }
opts = qemu_opts_parse(&qemu_net_opts, opts_str ? opts_str : "", NULL);
if (!opts) {
@@ -83,6 +94,7 @@ static int scsi_hot_add(DeviceState *adapter, DriveInfo *dinfo, int printinfo)
*/
dinfo->unit = qemu_opt_get_number(dinfo->opts, "unit", -1);
scsidev = scsi_bus_legacy_add_drive(scsibus, dinfo, dinfo->unit);
+ dinfo->unit = scsidev->id;
if (printinfo)
qemu_error("OK bus %d, unit %d\n", scsibus->busnr, scsidev->id);
@@ -180,6 +192,10 @@ static PCIDevice *qemu_pci_hot_add_storage(Monitor *mon,
monitor_printf(mon, "Invalid PCI device address %s\n", devaddr);
return NULL;
}
+ if (!((BusState*)bus)->allow_hotplug) {
+ monitor_printf(mon, "PCI bus doesn't support hotplug\n");
+ return NULL;
+ }
switch (type) {
case IF_SCSI:
diff --git a/hw/pci.c b/hw/pci.c
index 593102449..110a5fc07 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -633,11 +633,13 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
if (!bus->devices[devfn])
goto found;
}
- hw_error("PCI: no devfn available for %s, all in use\n", name);
+ qemu_error("PCI: no devfn available for %s, all in use\n", name);
+ return NULL;
found: ;
} else if (bus->devices[devfn]) {
- hw_error("PCI: devfn %d not available for %s, in use by %s\n", devfn,
+ qemu_error("PCI: devfn %d not available for %s, in use by %s\n", devfn,
name, bus->devices[devfn]->name);
+ return NULL;
}
pci_dev->bus = bus;
pci_dev->devfn = devfn;
@@ -678,6 +680,9 @@ PCIDevice *pci_register_device(PCIBus *bus, const char *name,
pci_dev = do_pci_register_device(pci_dev, bus, name, devfn,
config_read, config_write,
PCI_HEADER_TYPE_NORMAL);
+ if (pci_dev == NULL) {
+ hw_error("PCI: can't register device\n");
+ }
return pci_dev;
}
static target_phys_addr_t pci_to_cpu_addr(target_phys_addr_t addr)
@@ -1486,6 +1491,8 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base)
pci_dev = do_pci_register_device(pci_dev, bus, base->name, devfn,
info->config_read, info->config_write,
info->header_type);
+ if (pci_dev == NULL)
+ return -1;
rc = info->init(pci_dev);
if (rc != 0)
return rc;
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index bda669938..fb07279ba 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -593,22 +593,29 @@ void qdev_prop_set_defaults(DeviceState *dev, Property *props)
}
}
-static CompatProperty *compat_props;
+static QTAILQ_HEAD(, GlobalProperty) global_props = QTAILQ_HEAD_INITIALIZER(global_props);
-void qdev_prop_register_compat(CompatProperty *props)
+void qdev_prop_register_global(GlobalProperty *prop)
{
- compat_props = props;
+ QTAILQ_INSERT_TAIL(&global_props, prop, next);
}
-void qdev_prop_set_compat(DeviceState *dev)
+void qdev_prop_register_global_list(GlobalProperty *props)
{
- CompatProperty *prop;
+ int i;
- if (!compat_props) {
- return;
+ for (i = 0; props[i].driver != NULL; i++) {
+ qdev_prop_register_global(props+i);
}
- for (prop = compat_props; prop->driver != NULL; prop++) {
- if (strcmp(dev->info->name, prop->driver) != 0) {
+}
+
+void qdev_prop_set_globals(DeviceState *dev)
+{
+ GlobalProperty *prop;
+
+ QTAILQ_FOREACH(prop, &global_props, next) {
+ if (strcmp(dev->info->name, prop->driver) != 0 &&
+ strcmp(dev->info->bus_info->name, prop->driver) != 0) {
continue;
}
if (qdev_prop_parse(dev, prop->property, prop->value) != 0) {
diff --git a/hw/qdev.c b/hw/qdev.c
index 13c9fe236..b6bd4aeab 100644
--- a/hw/qdev.c
+++ b/hw/qdev.c
@@ -103,7 +103,7 @@ DeviceState *qdev_create(BusState *bus, const char *name)
dev->parent_bus = bus;
qdev_prop_set_defaults(dev, dev->info->props);
qdev_prop_set_defaults(dev, dev->parent_bus->info->props);
- qdev_prop_set_compat(dev);
+ qdev_prop_set_globals(dev);
QLIST_INSERT_HEAD(&bus->children, dev, sibling);
if (qdev_hotplug) {
assert(bus->allow_hotplug);
diff --git a/hw/qdev.h b/hw/qdev.h
index 8d53754d4..bbcdba185 100644
--- a/hw/qdev.h
+++ b/hw/qdev.h
@@ -92,11 +92,12 @@ struct PropertyInfo {
int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
};
-struct CompatProperty {
+typedef struct GlobalProperty {
const char *driver;
const char *property;
const char *value;
-};
+ QTAILQ_ENTRY(GlobalProperty) next;
+} GlobalProperty;
/*** Board API. This should go away once we have a machine config file. ***/
@@ -256,8 +257,9 @@ void qdev_prop_set_macaddr(DeviceState *dev, const char *name, uint8_t *value);
void qdev_prop_set_ptr(DeviceState *dev, const char *name, void *value);
void qdev_prop_set_defaults(DeviceState *dev, Property *props);
-void qdev_prop_register_compat(CompatProperty *props);
-void qdev_prop_set_compat(DeviceState *dev);
+void qdev_prop_register_global(GlobalProperty *prop);
+void qdev_prop_register_global_list(GlobalProperty *props);
+void qdev_prop_set_globals(DeviceState *dev);
/* This is a nasty hack to allow passing a NULL bus to qdev_create. */
extern struct BusInfo system_bus_info;
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index cc21ee6da..51c032adc 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -243,6 +243,10 @@ static QEMUMachine s390_machine = {
.alias = "s390",
.desc = "VirtIO based S390 machine",
.init = s390_init,
+ .no_serial = 1,
+ .no_parallel = 1,
+ .use_virtcon = 1.
+ .no_vga = 1,
.max_cpus = 255,
.is_default = 1,
};
diff --git a/hw/syborg_virtio.c b/hw/syborg_virtio.c
index 6cf5a15c2..a84206a11 100644
--- a/hw/syborg_virtio.c
+++ b/hw/syborg_virtio.c
@@ -87,7 +87,7 @@ static uint32_t syborg_virtio_readl(void *opaque, target_phys_addr_t offset)
break;
case SYBORG_VIRTIO_HOST_FEATURES:
ret = vdev->get_features(vdev);
- ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+ ret |= vdev->binding->get_features(s);
break;
case SYBORG_VIRTIO_GUEST_FEATURES:
ret = vdev->features;
@@ -242,8 +242,16 @@ static void syborg_virtio_update_irq(void *opaque, uint16_t vector)
qemu_set_irq(proxy->irq, level != 0);
}
+static unsigned syborg_virtio_get_features(void *opaque)
+{
+ unsigned ret = 0;
+ ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+ return ret;
+}
+
static VirtIOBindings syborg_virtio_bindings = {
- .notify = syborg_virtio_update_irq
+ .notify = syborg_virtio_update_irq,
+ .get_features = syborg_virtio_get_features,
};
static int syborg_virtio_init(SyborgVirtIOProxy *proxy, VirtIODevice *vdev)
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 5b3f118fc..f07c96644 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -148,7 +148,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
/* Use values found on a real PowerMac */
/* Uninorth main bus */
- dev = qdev_create(NULL, "Uni-north main");
+ dev = qdev_create(NULL, "uni-north-main");
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
d = FROM_SYSBUS(UNINState, s);
@@ -157,7 +157,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
pic, 11 << 3, 4);
#if 0
- pci_create_simple(d->host_state.bus, 11 << 3, "Uni-north main");
+ pci_create_simple(d->host_state.bus, 11 << 3, "uni-north-main");
#endif
sysbus_mmio_map(s, 0, 0xf2800000);
@@ -166,12 +166,12 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
/* DEC 21154 bridge */
#if 0
/* XXX: not activated as PPC BIOS doesn't handle multiple buses properly */
- pci_create_simple(d->host_state.bus, 12 << 3, "DEC 21154");
+ pci_create_simple(d->host_state.bus, 12 << 3, "dec-21154");
#endif
/* Uninorth AGP bus */
- pci_create_simple(d->host_state.bus, 11 << 3, "Uni-north AGP");
- dev = qdev_create(NULL, "Uni-north AGP");
+ pci_create_simple(d->host_state.bus, 11 << 3, "uni-north-AGP");
+ dev = qdev_create(NULL, "uni-north-AGP");
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
sysbus_mmio_map(s, 0, 0xf0800000);
@@ -180,8 +180,8 @@ PCIBus *pci_pmac_init(qemu_irq *pic)
/* Uninorth internal bus */
#if 0
/* XXX: not needed for now */
- pci_create_simple(d->host_state.bus, 14 << 3, "Uni-north internal");
- dev = qdev_create(NULL, "Uni-north internal");
+ pci_create_simple(d->host_state.bus, 14 << 3, "uni-north-internal");
+ dev = qdev_create(NULL, "uni-north-internal");
qdev_init_nofail(dev);
s = sysbus_from_qdev(dev);
sysbus_mmio_map(s, 0, 0xf4800000);
@@ -260,41 +260,41 @@ static int unin_internal_pci_host_init(PCIDevice *d)
}
static PCIDeviceInfo unin_main_pci_host_info = {
- .qdev.name = "Uni-north main",
+ .qdev.name = "uni-north-main",
.qdev.size = sizeof(PCIDevice),
.init = unin_main_pci_host_init,
};
static PCIDeviceInfo dec_21154_pci_host_info = {
- .qdev.name = "DEC 21154",
+ .qdev.name = "dec-21154",
.qdev.size = sizeof(PCIDevice),
.init = dec_21154_pci_host_init,
};
static PCIDeviceInfo unin_agp_pci_host_info = {
- .qdev.name = "Uni-north AGP",
+ .qdev.name = "uni-north-AGP",
.qdev.size = sizeof(PCIDevice),
.init = unin_agp_pci_host_init,
};
static PCIDeviceInfo unin_internal_pci_host_info = {
- .qdev.name = "Uni-north internal",
+ .qdev.name = "uni-north-internal",
.qdev.size = sizeof(PCIDevice),
.init = unin_internal_pci_host_init,
};
static void unin_register_devices(void)
{
- sysbus_register_dev("Uni-north main", sizeof(UNINState),
+ sysbus_register_dev("uni-north-main", sizeof(UNINState),
pci_unin_main_init_device);
pci_qdev_register(&unin_main_pci_host_info);
- sysbus_register_dev("DEC 21154", sizeof(UNINState),
+ sysbus_register_dev("dec-21154", sizeof(UNINState),
pci_dec_21154_init_device);
pci_qdev_register(&dec_21154_pci_host_info);
- sysbus_register_dev("Uni-north AGP", sizeof(UNINState),
+ sysbus_register_dev("uni-north-AGP", sizeof(UNINState),
pci_unin_agp_init_device);
pci_qdev_register(&unin_agp_pci_host_info);
- sysbus_register_dev("Uni-north internal", sizeof(UNINState),
+ sysbus_register_dev("uni-north-internal", sizeof(UNINState),
pci_unin_internal_init_device);
pci_qdev_register(&unin_internal_pci_host_info);
}
diff --git a/hw/usb-bt.c b/hw/usb-bt.c
index 18d7a98b4..56d1a6ce4 100644
--- a/hw/usb-bt.c
+++ b/hw/usb-bt.c
@@ -630,7 +630,7 @@ USBDevice *usb_bt_init(HCIInfo *hci)
if (!hci)
return NULL;
- dev = usb_create_simple(NULL /* FIXME */, "QEMU BT dongle");
+ dev = usb_create_simple(NULL /* FIXME */, "usb-bt-dongle");
s = DO_UPCAST(struct USBBtState, dev, dev);
s->dev.opaque = s;
@@ -645,7 +645,8 @@ USBDevice *usb_bt_init(HCIInfo *hci)
}
static struct USBDeviceInfo bt_info = {
- .qdev.name = "QEMU BT dongle",
+ .product_desc = "QEMU BT dongle",
+ .qdev.name = "usb-bt-dongle",
.qdev.size = sizeof(struct USBBtState),
.init = usb_bt_initfn,
.handle_packet = usb_generic_handle_packet,
diff --git a/hw/usb-bus.c b/hw/usb-bus.c
index 99d185e79..54027dfc4 100644
--- a/hw/usb-bus.c
+++ b/hw/usb-bus.c
@@ -43,7 +43,7 @@ static int usb_qdev_init(DeviceState *qdev, DeviceInfo *base)
USBDeviceInfo *info = DO_UPCAST(USBDeviceInfo, qdev, base);
int rc;
- pstrcpy(dev->devname, sizeof(dev->devname), qdev->info->name);
+ pstrcpy(dev->product_desc, sizeof(dev->product_desc), info->product_desc);
dev->info = info;
dev->auto_attach = 1;
rc = dev->info->init(dev);
@@ -131,7 +131,7 @@ static void do_attach(USBDevice *dev)
if (dev->attached) {
fprintf(stderr, "Warning: tried to attach usb device %s twice\n",
- dev->devname);
+ dev->product_desc);
return;
}
dev->attached++;
@@ -153,7 +153,7 @@ int usb_device_attach(USBDevice *dev)
if (bus->nfree == 1) {
/* Create a new hub and chain it on. */
- hub = usb_create_simple(bus, "QEMU USB Hub");
+ hub = usb_create_simple(bus, "usb-hub");
}
do_attach(dev);
return 0;
@@ -166,7 +166,7 @@ int usb_device_detach(USBDevice *dev)
if (!dev->attached) {
fprintf(stderr, "Warning: tried to detach unattached usb device %s\n",
- dev->devname);
+ dev->product_desc);
return -1;
}
dev->attached--;
@@ -228,7 +228,7 @@ static void usb_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
monitor_printf(mon, "%*saddr %d.%d, speed %s, name %s%s\n",
indent, "", bus->busnr, dev->addr,
- usb_speed(dev->speed), dev->devname,
+ usb_speed(dev->speed), dev->product_desc,
dev->attached ? ", attached" : "");
}
@@ -249,7 +249,8 @@ void usb_info(Monitor *mon)
if (!dev)
continue;
monitor_printf(mon, " Device %d.%d, Speed %s Mb/s, Product %s\n",
- bus->busnr, dev->addr, usb_speed(dev->speed), dev->devname);
+ bus->busnr, dev->addr, usb_speed(dev->speed),
+ dev->product_desc);
}
}
}
diff --git a/hw/usb-hid.c b/hw/usb-hid.c
index f4a2a481e..6abb62993 100644
--- a/hw/usb-hid.c
+++ b/hw/usb-hid.c
@@ -701,7 +701,7 @@ static int usb_hid_handle_control(USBDevice *dev, int request, int value,
break;
case 2:
/* product description */
- ret = set_usb_string(data, s->dev.devname);
+ ret = set_usb_string(data, s->dev.product_desc);
break;
case 3:
/* vendor description */
@@ -880,8 +880,8 @@ void usb_hid_datain_cb(USBDevice *dev, void *opaque, void (*datain)(void *))
static struct USBDeviceInfo hid_info[] = {
{
- .qdev.name = "QEMU USB Tablet",
- .qdev.alias = "usb-tablet",
+ .product_desc = "QEMU USB Tablet",
+ .qdev.name = "usb-tablet",
.usbdevice_name = "tablet",
.qdev.size = sizeof(USBHIDState),
.init = usb_tablet_initfn,
@@ -891,8 +891,8 @@ static struct USBDeviceInfo hid_info[] = {
.handle_data = usb_hid_handle_data,
.handle_destroy = usb_hid_handle_destroy,
},{
- .qdev.name = "QEMU USB Mouse",
- .qdev.alias = "usb-mouse",
+ .product_desc = "QEMU USB Mouse",
+ .qdev.name = "usb-mouse",
.usbdevice_name = "mouse",
.qdev.size = sizeof(USBHIDState),
.init = usb_mouse_initfn,
@@ -902,8 +902,8 @@ static struct USBDeviceInfo hid_info[] = {
.handle_data = usb_hid_handle_data,
.handle_destroy = usb_hid_handle_destroy,
},{
- .qdev.name = "QEMU USB Keyboard",
- .qdev.alias = "usb-kbd",
+ .product_desc = "QEMU USB Keyboard",
+ .qdev.name = "usb-kbd",
.usbdevice_name = "keyboard",
.qdev.size = sizeof(USBHIDState),
.init = usb_keyboard_initfn,
diff --git a/hw/usb-hub.c b/hw/usb-hub.c
index e5a093877..acf7f6072 100644
--- a/hw/usb-hub.c
+++ b/hw/usb-hub.c
@@ -544,7 +544,8 @@ static int usb_hub_initfn(USBDevice *dev)
}
static struct USBDeviceInfo hub_info = {
- .qdev.name = "QEMU USB Hub",
+ .product_desc = "QEMU USB Hub",
+ .qdev.name = "usb-hub",
.qdev.size = sizeof(USBHubState),
.init = usb_hub_initfn,
.handle_packet = usb_hub_handle_packet,
diff --git a/hw/usb-msd.c b/hw/usb-msd.c
index bb39b625a..1fb62ad13 100644
--- a/hw/usb-msd.c
+++ b/hw/usb-msd.c
@@ -591,7 +591,7 @@ static USBDevice *usb_msd_init(const char *filename)
}
/* create guest device */
- dev = usb_create(NULL /* FIXME */, "QEMU USB MSD");
+ dev = usb_create(NULL /* FIXME */, "usb-storage");
qdev_prop_set_drive(&dev->qdev, "drive", dinfo);
if (qdev_init(&dev->qdev) < 0)
return NULL;
@@ -600,8 +600,8 @@ static USBDevice *usb_msd_init(const char *filename)
}
static struct USBDeviceInfo msd_info = {
- .qdev.name = "QEMU USB MSD",
- .qdev.alias = "usb-storage",
+ .product_desc = "QEMU USB MSD",
+ .qdev.name = "usb-storage",
.qdev.size = sizeof(MSDState),
.init = usb_msd_initfn,
.handle_packet = usb_generic_handle_packet,
diff --git a/hw/usb-net.c b/hw/usb-net.c
index 2556e05dd..122a0d849 100644
--- a/hw/usb-net.c
+++ b/hw/usb-net.c
@@ -1463,7 +1463,7 @@ USBDevice *usb_net_init(NICInfo *nd)
USBDevice *dev;
USBNetState *s;
- dev = usb_create_simple(NULL /* FIXME */, "QEMU USB Network Interface");
+ dev = usb_create_simple(NULL /* FIXME */, "usb-net");
s = DO_UPCAST(USBNetState, dev, dev);
memcpy(s->conf.macaddr.a, nd->macaddr, sizeof(nd->macaddr));
@@ -1487,7 +1487,8 @@ USBDevice *usb_net_init(NICInfo *nd)
}
static struct USBDeviceInfo net_info = {
- .qdev.name = "QEMU USB Network Interface",
+ .product_desc = "QEMU USB Network Interface",
+ .qdev.name = "usb-net",
.qdev.size = sizeof(USBNetState),
.init = usb_net_initfn,
.handle_packet = usb_generic_handle_packet,
diff --git a/hw/usb-ohci.c b/hw/usb-ohci.c
index 7ab3a9861..a8a014cb1 100644
--- a/hw/usb-ohci.c
+++ b/hw/usb-ohci.c
@@ -1736,7 +1736,7 @@ static int usb_ohci_initfn_pci(struct PCIDevice *dev)
void usb_ohci_init_pci(struct PCIBus *bus, int devfn)
{
- pci_create_simple(bus, devfn, "OHCI USB PCI");
+ pci_create_simple(bus, devfn, "pci-ohci");
}
void usb_ohci_init_pxa(target_phys_addr_t base, int num_ports, int devfn,
@@ -1762,8 +1762,7 @@ void usb_ohci_init_sm501(uint32_t mmio_base, uint32_t localmem_base,
}
static PCIDeviceInfo ohci_info = {
- .qdev.name = "OHCI USB PCI",
- .qdev.alias = "pci-ohci",
+ .qdev.name = "pci-ohci",
.qdev.desc = "Apple USB Controller",
.qdev.size = sizeof(OHCIPCIState),
.init = usb_ohci_initfn_pci,
diff --git a/hw/usb-serial.c b/hw/usb-serial.c
index 223d4c385..2775cf0f0 100644
--- a/hw/usb-serial.c
+++ b/hw/usb-serial.c
@@ -577,7 +577,7 @@ static USBDevice *usb_serial_init(const char *filename)
if (!cdrv)
return NULL;
- dev = usb_create(NULL /* FIXME */, "QEMU USB Serial");
+ dev = usb_create(NULL /* FIXME */, "usb-serial");
qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
if (vendorid)
qdev_prop_set_uint16(&dev->qdev, "vendorid", vendorid);
@@ -597,7 +597,7 @@ static USBDevice *usb_braille_init(const char *unused)
if (!cdrv)
return NULL;
- dev = usb_create(NULL /* FIXME */, "QEMU USB Braille");
+ dev = usb_create(NULL /* FIXME */, "usb-braille");
qdev_prop_set_chr(&dev->qdev, "chardev", cdrv);
qdev_init(&dev->qdev);
@@ -605,8 +605,8 @@ static USBDevice *usb_braille_init(const char *unused)
}
static struct USBDeviceInfo serial_info = {
- .qdev.name = "QEMU USB Serial",
- .qdev.alias = "usb-serial",
+ .product_desc = "QEMU USB Serial",
+ .qdev.name = "usb-serial",
.qdev.size = sizeof(USBSerialState),
.init = usb_serial_initfn,
.handle_packet = usb_generic_handle_packet,
@@ -625,8 +625,8 @@ static struct USBDeviceInfo serial_info = {
};
static struct USBDeviceInfo braille_info = {
- .qdev.name = "QEMU USB Braille",
- .qdev.alias = "usb-braille",
+ .product_desc = "QEMU USB Braille",
+ .qdev.name = "usb-braille",
.qdev.size = sizeof(USBSerialState),
.init = usb_serial_initfn,
.handle_packet = usb_generic_handle_packet,
diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c
index ba26a4efc..dc52737ae 100644
--- a/hw/usb-uhci.c
+++ b/hw/usb-uhci.c
@@ -1111,12 +1111,12 @@ static int usb_uhci_piix4_initfn(PCIDevice *dev)
static PCIDeviceInfo uhci_info[] = {
{
- .qdev.name = "PIIX3 USB-UHCI",
+ .qdev.name = "piix3-usb-uhci",
.qdev.size = sizeof(UHCIState),
.qdev.vmsd = &vmstate_uhci,
.init = usb_uhci_piix3_initfn,
},{
- .qdev.name = "PIIX4 USB-UHCI",
+ .qdev.name = "piix4-usb-uhci",
.qdev.size = sizeof(UHCIState),
.qdev.vmsd = &vmstate_uhci,
.init = usb_uhci_piix4_initfn,
@@ -1133,10 +1133,10 @@ device_init(uhci_register);
void usb_uhci_piix3_init(PCIBus *bus, int devfn)
{
- pci_create_simple(bus, devfn, "PIIX3 USB-UHCI");
+ pci_create_simple(bus, devfn, "piix3-usb-uhci");
}
void usb_uhci_piix4_init(PCIBus *bus, int devfn)
{
- pci_create_simple(bus, devfn, "PIIX4 USB-UHCI");
+ pci_create_simple(bus, devfn, "piix4-usb-uhci");
}
diff --git a/hw/usb-wacom.c b/hw/usb-wacom.c
index ef6137637..fe052eb75 100644
--- a/hw/usb-wacom.c
+++ b/hw/usb-wacom.c
@@ -409,8 +409,9 @@ static int usb_wacom_initfn(USBDevice *dev)
}
static struct USBDeviceInfo wacom_info = {
- .qdev.name = "QEMU PenPartner Tablet",
- .qdev.alias = "wacom-tablet",
+ .product_desc = "QEMU PenPartner Tablet",
+ .qdev.name = "usb-wacom-tablet",
+ .qdev.desc = "QEMU PenPartner Tablet",
.usbdevice_name = "wacom-tablet",
.qdev.size = sizeof(USBWacomState),
.init = usb_wacom_initfn,
diff --git a/hw/usb.h b/hw/usb.h
index 351c466c7..068458850 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -132,7 +132,7 @@ struct USBDevice {
int speed;
uint8_t addr;
- char devname[32];
+ char product_desc[32];
int auto_attach;
int attached;
@@ -185,6 +185,8 @@ struct USBDeviceInfo {
*/
int (*handle_data)(USBDevice *dev, USBPacket *p);
+ const char *product_desc;
+
/* handle legacy -usbdevice command line options */
const char *usbdevice_name;
USBDevice *(*usbdevice_init)(const char *params);
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index d222ce03f..450013091 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -236,9 +236,7 @@ static uint32_t virtio_ioport_read(VirtIOPCIProxy *proxy, uint32_t addr)
switch (addr) {
case VIRTIO_PCI_HOST_FEATURES:
ret = vdev->get_features(vdev);
- ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
- ret |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
- ret |= (1 << VIRTIO_F_BAD_FEATURE);
+ ret |= vdev->binding->get_features(proxy);
break;
case VIRTIO_PCI_GUEST_FEATURES:
ret = vdev->features;
@@ -382,12 +380,22 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
msix_write_config(pci_dev, address, val, len);
}
+static unsigned virtio_pci_get_features(void *opaque)
+{
+ unsigned ret = 0;
+ ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+ ret |= (1 << VIRTIO_RING_F_INDIRECT_DESC);
+ ret |= (1 << VIRTIO_F_BAD_FEATURE);
+ return ret;
+}
+
static const VirtIOBindings virtio_pci_bindings = {
.notify = virtio_pci_notify,
.save_config = virtio_pci_save_config,
.load_config = virtio_pci_load_config,
.save_queue = virtio_pci_save_queue,
.load_queue = virtio_pci_load_queue,
+ .get_features = virtio_pci_get_features,
};
static void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev,
diff --git a/hw/virtio.c b/hw/virtio.c
index 1f92171f6..cecd0dc04 100644
--- a/hw/virtio.c
+++ b/hw/virtio.c
@@ -651,6 +651,9 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
int virtio_load(VirtIODevice *vdev, QEMUFile *f)
{
int num, i, ret;
+ uint32_t features;
+ uint32_t supported_features = vdev->get_features(vdev) |
+ vdev->binding->get_features(vdev->binding_opaque);
if (vdev->binding->load_config) {
ret = vdev->binding->load_config(vdev->binding_opaque, f);
@@ -661,7 +664,13 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f)
qemu_get_8s(f, &vdev->status);
qemu_get_8s(f, &vdev->isr);
qemu_get_be16s(f, &vdev->queue_sel);
- qemu_get_be32s(f, &vdev->features);
+ qemu_get_be32s(f, &features);
+ if (features & ~supported_features) {
+ fprintf(stderr, "Features 0x%x unsupported. Allowed features: 0x%x\n",
+ features, supported_features);
+ return -1;
+ }
+ vdev->features = features;
vdev->config_len = qemu_get_be32(f);
qemu_get_buffer(f, vdev->config, vdev->config_len);
diff --git a/hw/virtio.h b/hw/virtio.h
index 15ad91076..35532a6f2 100644
--- a/hw/virtio.h
+++ b/hw/virtio.h
@@ -31,6 +31,11 @@
/* We've given up on this device. */
#define VIRTIO_CONFIG_S_FAILED 0x80
+/* Some virtio feature bits (currently bits 28 through 31) are reserved for the
+ * transport being used (eg. virtio_ring), the rest are per-device feature bits. */
+#define VIRTIO_TRANSPORT_F_START 28
+#define VIRTIO_TRANSPORT_F_END 32
+
/* We notify when the ring is completely used, even if the guest is suppressing
* callbacks */
#define VIRTIO_F_NOTIFY_ON_EMPTY 24
@@ -82,6 +87,7 @@ typedef struct {
void (*save_queue)(void * opaque, int n, QEMUFile *f);
int (*load_config)(void * opaque, QEMUFile *f);
int (*load_queue)(void * opaque, int n, QEMUFile *f);
+ unsigned (*get_features)(void * opaque);
} VirtIOBindings;
#define VIRTIO_PCI_QUEUE_MAX 16
diff --git a/hw/vmware_vga.c b/hw/vmware_vga.c
index 240731a1b..f3e3749e9 100644
--- a/hw/vmware_vga.c
+++ b/hw/vmware_vga.c
@@ -22,6 +22,7 @@
* THE SOFTWARE.
*/
#include "hw.h"
+#include "loader.h"
#include "console.h"
#include "pci.h"
#include "vmware_vga.h"
@@ -1124,6 +1125,7 @@ static void vmsvga_init(struct vmsvga_state_s *s, int vga_ram_size)
cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
vga_ram_size, s->vga.vram_offset);
#endif
+ rom_add_vga(VGABIOS_FILENAME);
}
static void pci_vmsvga_map_ioport(PCIDevice *pci_dev, int region_num,
@@ -1194,11 +1196,11 @@ static int pci_vmsvga_initfn(PCIDevice *dev)
void pci_vmsvga_init(PCIBus *bus)
{
- pci_create_simple(bus, -1, "QEMUware SVGA");
+ pci_create_simple(bus, -1, "vmware-svga");
}
static PCIDeviceInfo vmsvga_info = {
- .qdev.name = "QEMUware SVGA",
+ .qdev.name = "vmware-svga",
.qdev.size = sizeof(struct pci_vmsvga_state_s),
.qdev.vmsd = &vmstate_vmware_vga,
.init = pci_vmsvga_initfn,
diff --git a/linux-user/main.c b/linux-user/main.c
index 5fbcda2a3..e51539eff 100644
--- a/linux-user/main.c
+++ b/linux-user/main.c
@@ -593,6 +593,7 @@ static int do_strex(CPUARMState *env)
}
rc = 0;
fail:
+ env->regs[15] += 4;
env->regs[(env->exclusive_info >> 4) & 0xf] = rc;
done:
end_exclusive();
diff --git a/monitor.c b/monitor.c
index 06d16462f..035ad9ed5 100644
--- a/monitor.c
+++ b/monitor.c
@@ -151,7 +151,10 @@ static void monitor_read_command(Monitor *mon, int show_prompt)
static int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
void *opaque)
{
- if (mon->rs) {
+ if (monitor_ctrl_mode(mon)) {
+ qemu_error_new(QERR_MISSING_PARAMETER, "password");
+ return -EINVAL;
+ } else if (mon->rs) {
readline_start(mon->rs, "Password: ", 1, readline_func, opaque);
/* prompt is printed on return from the command handler */
return 0;
@@ -305,6 +308,7 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data)
}
} else {
/* error response */
+ qdict_put(mon->error->error, "desc", qerror_human(mon->error));
qdict_put(qmp, "error", mon->error->error);
QINCREF(mon->error->error);
QDECREF(mon->error);
@@ -517,10 +521,34 @@ static void do_info_name(Monitor *mon)
monitor_printf(mon, "%s\n", qemu_name);
}
+static QObject *get_cmd_dict(const char *name)
+{
+ const char *p;
+
+ /* Remove '|' from some commands */
+ p = strchr(name, '|');
+ if (p) {
+ p++;
+ } else {
+ p = name;
+ }
+
+ return qobject_from_jsonf("{ 'name': %s }", p);
+}
+
/**
* do_info_commands(): List QMP available commands
*
- * Return a QList of QStrings.
+ * Each command is represented by a QDict, the returned QObject is a QList
+ * of all commands.
+ *
+ * The QDict contains:
+ *
+ * - "name": command's name
+ *
+ * Example:
+ *
+ * { [ { "name": "query-balloon" }, { "name": "system_powerdown" } ] }
*/
static void do_info_commands(Monitor *mon, QObject **ret_data)
{
@@ -531,7 +559,7 @@ static void do_info_commands(Monitor *mon, QObject **ret_data)
for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
if (monitor_handler_ported(cmd) && !compare_cmd(cmd->name, "info")) {
- qlist_append(cmd_list, qstring_from_str(cmd->name));
+ qlist_append_obj(cmd_list, get_cmd_dict(cmd->name));
}
}
@@ -539,7 +567,7 @@ static void do_info_commands(Monitor *mon, QObject **ret_data)
if (monitor_handler_ported(cmd)) {
char buf[128];
snprintf(buf, sizeof(buf), "query-%s", cmd->name);
- qlist_append(cmd_list, qstring_from_str(buf));
+ qlist_append_obj(cmd_list, get_cmd_dict(buf));
}
}
@@ -611,8 +639,9 @@ static void print_cpu_iter(QObject *obj, void *opaque)
assert(qobject_type(obj) == QTYPE_QDICT);
cpu = qobject_to_qdict(obj);
- if (strcmp(qdict_get_str(cpu, "current"), "yes") == 0)
+ if (qdict_get_bool(cpu, "current")) {
active = '*';
+ }
monitor_printf(mon, "%c CPU #%d: ", active, (int)qdict_get_int(cpu, "CPU"));
@@ -632,8 +661,9 @@ static void print_cpu_iter(QObject *obj, void *opaque)
(target_long) qdict_get_int(cpu, "PC"));
#endif
- if (strcmp(qdict_get_str(cpu, "halted"), "yes") == 0)
+ if (qdict_get_bool(cpu, "halted")) {
monitor_printf(mon, " (halted)");
+ }
monitor_printf(mon, " thread_id=%" PRId64 " ",
qdict_get_int(cpu, "thread_id"));
@@ -653,12 +683,21 @@ static void monitor_print_cpus(Monitor *mon, const QObject *data)
/**
* do_info_cpus(): Show CPU information
*
- * Return a QList with a QDict for each CPU.
+ * Return a QList. Each CPU is represented by a QDict, which contains:
+ *
+ * - "cpu": CPU index
+ * - "current": true if this is the current CPU, false otherwise
+ * - "halted": true if the cpu is halted, false otherwise
+ * - Current program counter. The key's name depends on the architecture:
+ * "pc": i386/x86)64
+ * "nip": PPC
+ * "pc" and "npc": sparc
+ * "PC": mips
*
- * For example:
+ * Example:
*
- * [ { "CPU": 0, "current": "yes", "pc": 0x..., "halted": "no" },
- * { "CPU": 1, "current": "no", "pc": 0x..., "halted": "yes" } ]
+ * [ { "CPU": 0, "current": true, "halted": false, "pc": 3227107138 },
+ * { "CPU": 1, "current": false, "halted": true, "pc": 7108165 } ]
*/
static void do_info_cpus(Monitor *mon, QObject **ret_data)
{
@@ -671,15 +710,19 @@ static void do_info_cpus(Monitor *mon, QObject **ret_data)
mon_get_cpu();
for(env = first_cpu; env != NULL; env = env->next_cpu) {
- const char *answer;
- QDict *cpu = qdict_new();
+ QDict *cpu;
+ QObject *obj;
cpu_synchronize_state(env);
kvm_save_mpstate(env);
- qdict_put(cpu, "CPU", qint_from_int(env->cpu_index));
- answer = (env == mon->mon_cpu) ? "yes" : "no";
- qdict_put(cpu, "current", qstring_from_str(answer));
+ obj = qobject_from_jsonf("{ 'CPU': %d, 'current': %i, 'halted': %i }",
+ env->cpu_index, env == mon->mon_cpu,
+ env->halted);
+ assert(obj != NULL);
+
+ cpu = qobject_to_qdict(obj);
+
#if defined(TARGET_I386)
qdict_put(cpu, "pc", qint_from_int(env->eip + env->segs[R_CS].base));
#elif defined(TARGET_PPC)
@@ -690,8 +733,6 @@ static void do_info_cpus(Monitor *mon, QObject **ret_data)
#elif defined(TARGET_MIPS)
qdict_put(cpu, "PC", qint_from_int(env->active_tc.PC));
#endif
- answer = env->halted ? "yes" : "no";
- qdict_put(cpu, "halted", qstring_from_str(answer));
qdict_put(cpu, "thread_id", qint_from_int(env->thread_id));
qlist_append(cpu_list, cpu);
@@ -774,11 +815,12 @@ static int eject_device(Monitor *mon, BlockDriverState *bs, int force)
if (bdrv_is_inserted(bs)) {
if (!force) {
if (!bdrv_is_removable(bs)) {
- monitor_printf(mon, "device is not removable\n");
+ qemu_error_new(QERR_DEVICE_NOT_REMOVABLE,
+ bdrv_get_device_name(bs));
return -1;
}
if (bdrv_is_locked(bs)) {
- monitor_printf(mon, "device is locked\n");
+ qemu_error_new(QERR_DEVICE_LOCKED, bdrv_get_device_name(bs));
return -1;
}
}
@@ -795,7 +837,7 @@ static void do_eject(Monitor *mon, const QDict *qdict, QObject **ret_data)
bs = bdrv_find(filename);
if (!bs) {
- monitor_printf(mon, "device not found\n");
+ qemu_error_new(QERR_DEVICE_NOT_FOUND, filename);
return;
}
eject_device(mon, bs, force);
@@ -825,13 +867,13 @@ static void do_change_block(Monitor *mon, const char *device,
bs = bdrv_find(device);
if (!bs) {
- monitor_printf(mon, "device not found\n");
+ qemu_error_new(QERR_DEVICE_NOT_FOUND, device);
return;
}
if (fmt) {
drv = bdrv_find_whitelisted_format(fmt);
if (!drv) {
- monitor_printf(mon, "invalid format %s\n", fmt);
+ qemu_error_new(QERR_INVALID_BLOCK_FORMAT, fmt);
return;
}
}
@@ -841,12 +883,17 @@ static void do_change_block(Monitor *mon, const char *device,
monitor_read_bdrv_key_start(mon, bs, NULL, NULL);
}
-static void change_vnc_password_cb(Monitor *mon, const char *password,
- void *opaque)
+static void change_vnc_password(const char *password)
{
if (vnc_display_password(NULL, password) < 0)
- monitor_printf(mon, "could not set VNC server password\n");
+ qemu_error_new(QERR_SET_PASSWD_FAILED);
+}
+
+static void change_vnc_password_cb(Monitor *mon, const char *password,
+ void *opaque)
+{
+ change_vnc_password(password);
monitor_read_command(mon, 1);
}
@@ -858,17 +905,20 @@ static void do_change_vnc(Monitor *mon, const char *target, const char *arg)
char password[9];
strncpy(password, arg, sizeof(password));
password[sizeof(password) - 1] = '\0';
- change_vnc_password_cb(mon, password, NULL);
+ change_vnc_password(password);
} else {
monitor_read_password(mon, change_vnc_password_cb, NULL);
}
} else {
if (vnc_display_open(NULL, target) < 0)
- monitor_printf(mon, "could not start VNC server on %s\n", target);
+ qemu_error_new(QERR_VNC_SERVER_FAILED, target);
}
}
-static void do_change(Monitor *mon, const QDict *qdict)
+/**
+ * do_change(): Change a removable medium, or VNC configuration
+ */
+static void do_change(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const char *device = qdict_get_str(qdict, "device");
const char *target = qdict_get_str(qdict, "target");
@@ -1938,12 +1988,24 @@ static void do_balloon(Monitor *mon, const QDict *qdict, QObject **ret_data)
static void monitor_print_balloon(Monitor *mon, const QObject *data)
{
- monitor_printf(mon, "balloon: actual=%d\n",
- (int)qint_get_int(qobject_to_qint(data)));
+ QDict *qdict;
+
+ qdict = qobject_to_qdict(data);
+
+ monitor_printf(mon, "balloon: actual=%" PRId64 "\n",
+ qdict_get_int(qdict, "balloon") >> 20);
}
/**
* do_info_balloon(): Balloon information
+ *
+ * Return a QDict with the following information:
+ *
+ * - "balloon": current balloon value in bytes
+ *
+ * Example:
+ *
+ * { "balloon": 1073741824 }
*/
static void do_info_balloon(Monitor *mon, QObject **ret_data)
{
@@ -1955,7 +2017,8 @@ static void do_info_balloon(Monitor *mon, QObject **ret_data)
else if (actual == 0)
qemu_error_new(QERR_DEVICE_NOT_ACTIVE, "balloon");
else
- *ret_data = QOBJECT(qint_from_int((int)(actual >> 20)));
+ *ret_data = qobject_from_jsonf("{ 'balloon': %" PRId64 "}",
+ (int64_t) actual);
}
static qemu_acl *find_acl(Monitor *mon, const char *name)
@@ -2091,19 +2154,21 @@ static void do_getfd(Monitor *mon, const QDict *qdict, QObject **ret_data)
fd = qemu_chr_get_msgfd(mon->chr);
if (fd == -1) {
- monitor_printf(mon, "getfd: no file descriptor supplied via SCM_RIGHTS\n");
+ qemu_error_new(QERR_FD_NOT_SUPPLIED);
return;
}
if (qemu_isdigit(fdname[0])) {
- monitor_printf(mon, "getfd: monitor names may not begin with a number\n");
+ qemu_error_new(QERR_INVALID_PARAMETER, "fdname");
return;
}
fd = dup(fd);
if (fd == -1) {
- monitor_printf(mon, "Failed to dup() file descriptor: %s\n",
- strerror(errno));
+ if (errno == EMFILE)
+ qemu_error_new(QERR_TOO_MANY_FILES);
+ else
+ qemu_error_new(QERR_UNDEFINED_ERROR);
return;
}
@@ -2141,8 +2206,7 @@ static void do_closefd(Monitor *mon, const QDict *qdict, QObject **ret_data)
return;
}
- monitor_printf(mon, "Failed to find file descriptor named %s\n",
- fdname);
+ qemu_error_new(QERR_FD_NOT_FOUND, fdname);
}
static void do_loadvm(Monitor *mon, const QDict *qdict)
@@ -4056,24 +4120,6 @@ static void monitor_event(void *opaque, int event)
* End:
*/
-const char *monitor_cmdline_parse(const char *cmdline, int *flags)
-{
- const char *dev;
-
- if (strstart(cmdline, "control,", &dev)) {
- if (strstart(dev, "vc", NULL)) {
- fprintf(stderr, "qemu: control mode is for low-level interaction ");
- fprintf(stderr, "cannot be used with device 'vc'\n");
- exit(1);
- }
- *flags &= ~MONITOR_USE_READLINE;
- *flags |= MONITOR_USE_CONTROL;
- return dev;
- }
-
- return cmdline;
-}
-
void monitor_init(CharDriverState *chr, int flags)
{
static int is_first_init = 1;
@@ -4135,6 +4181,11 @@ void monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
return;
}
+ if (monitor_ctrl_mode(mon)) {
+ qemu_error_new(QERR_DEVICE_ENCRYPTED, bdrv_get_device_name(bs));
+ return;
+ }
+
monitor_printf(mon, "%s (%s) is encrypted.\n", bdrv_get_device_name(bs),
bdrv_get_encrypted_filename(bs));
diff --git a/monitor.h b/monitor.h
index 38cc2238a..6ed117a92 100644
--- a/monitor.h
+++ b/monitor.h
@@ -24,7 +24,6 @@ typedef enum MonitorEvent {
} MonitorEvent;
void monitor_protocol_event(MonitorEvent event, QObject *data);
-const char *monitor_cmdline_parse(const char *cmdline, int *flags);
void monitor_init(CharDriverState *chr, int flags);
int monitor_suspend(Monitor *mon);
diff --git a/net.c b/net.c
index 13bdbb2ca..6ef93e615 100644
--- a/net.c
+++ b/net.c
@@ -39,6 +39,8 @@
static QTAILQ_HEAD(, VLANState) vlans;
static QTAILQ_HEAD(, VLANClientState) non_vlan_clients;
+int default_net = 1;
+
/***********************************************************/
/* network device redirectors */
@@ -1317,7 +1319,7 @@ static int net_init_netdev(QemuOpts *opts, void *dummy)
int net_init_clients(void)
{
- if (QTAILQ_EMPTY(&qemu_net_opts.head)) {
+ if (default_net) {
/* if no clients, we use a default config */
qemu_opts_set(&qemu_net_opts, NULL, "type", "nic");
#ifdef CONFIG_SLIRP
@@ -1353,5 +1355,6 @@ int net_client_parse(QemuOptsList *opts_list, const char *optarg)
return -1;
}
+ default_net = 0;
return 0;
}
diff --git a/net.h b/net.h
index d583d590a..4971fcbbb 100644
--- a/net.h
+++ b/net.h
@@ -139,6 +139,7 @@ struct NICInfo {
extern int nb_nics;
extern NICInfo nd_table[MAX_NICS];
+extern int default_net;
/* BT HCI info */
diff --git a/qdict.c b/qdict.c
index 0e04cb1fe..ef73265f4 100644
--- a/qdict.c
+++ b/qdict.c
@@ -12,6 +12,7 @@
#include "qint.h"
#include "qdict.h"
+#include "qbool.h"
#include "qstring.h"
#include "qobject.h"
#include "qemu-queue.h"
@@ -189,6 +190,33 @@ int64_t qdict_get_int(const QDict *qdict, const char *key)
}
/**
+ * qdict_get_bool(): Get a bool mapped by 'key'
+ *
+ * This function assumes that 'key' exists and it stores a
+ * QBool object.
+ *
+ * Return bool mapped by 'key'.
+ */
+int qdict_get_bool(const QDict *qdict, const char *key)
+{
+ QObject *obj = qdict_get_obj(qdict, key, QTYPE_QBOOL);
+ return qbool_get_int(qobject_to_qbool(obj));
+}
+
+/**
+ * qdict_get_qlist(): Get the QList mapped by 'key'
+ *
+ * This function assumes that 'key' exists and it stores a
+ * QList object.
+ *
+ * Return QList mapped by 'key'.
+ */
+QList *qdict_get_qlist(const QDict *qdict, const char *key)
+{
+ return qobject_to_qlist(qdict_get_obj(qdict, key, QTYPE_QLIST));
+}
+
+/**
* qdict_get_str(): Get a pointer to the stored string mapped
* by 'key'
*
diff --git a/qdict.h b/qdict.h
index 14b26330f..5fef1ea4e 100644
--- a/qdict.h
+++ b/qdict.h
@@ -2,6 +2,7 @@
#define QDICT_H
#include "qobject.h"
+#include "qlist.h"
#include "qemu-queue.h"
#include <stdint.h>
@@ -37,6 +38,8 @@ void qdict_iter(const QDict *qdict,
/* High level helpers */
int64_t qdict_get_int(const QDict *qdict, const char *key);
+int qdict_get_bool(const QDict *qdict, const char *key);
+QList *qdict_get_qlist(const QDict *qdict, const char *key);
const char *qdict_get_str(const QDict *qdict, const char *key);
int64_t qdict_get_try_int(const QDict *qdict, const char *key,
int64_t err_value);
diff --git a/qemu-char.c b/qemu-char.c
index da5c15c4f..c6008c395 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2231,7 +2231,7 @@ static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
return NULL;
}
-static QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
+QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
{
char host[65], port[33], width[8], height[8];
int pos;
diff --git a/qemu-char.h b/qemu-char.h
index 9957db1f5..7fa8e5cc1 100644
--- a/qemu-char.h
+++ b/qemu-char.h
@@ -69,6 +69,7 @@ struct CharDriverState {
QTAILQ_ENTRY(CharDriverState) next;
};
+QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
CharDriverState *qemu_chr_open_opts(QemuOpts *opts,
void (*init)(struct CharDriverState *s));
CharDriverState *qemu_chr_open(const char *label, const char *filename, void (*init)(struct CharDriverState *s));
diff --git a/qemu-config.c b/qemu-config.c
index 6dd173120..2caf76c93 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -2,6 +2,7 @@
#include "qemu-option.h"
#include "qemu-config.h"
#include "sysemu.h"
+#include "hw/qdev.h"
QemuOptsList qemu_drive_opts = {
.name = "drive",
@@ -209,6 +210,42 @@ QemuOptsList qemu_rtc_opts = {
},
};
+QemuOptsList qemu_global_opts = {
+ .name = "global",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_global_opts.head),
+ .desc = {
+ {
+ .name = "driver",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "property",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "value",
+ .type = QEMU_OPT_STRING,
+ },
+ { /* end if list */ }
+ },
+};
+
+QemuOptsList qemu_mon_opts = {
+ .name = "mon",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head),
+ .desc = {
+ {
+ .name = "mode",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "chardev",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "default",
+ .type = QEMU_OPT_BOOL,
+ },
+ { /* end if list */ }
+ },
+};
+
static QemuOptsList *lists[] = {
&qemu_drive_opts,
&qemu_chardev_opts,
@@ -216,6 +253,8 @@ static QemuOptsList *lists[] = {
&qemu_netdev_opts,
&qemu_net_opts,
&qemu_rtc_opts,
+ &qemu_global_opts,
+ &qemu_mon_opts,
NULL,
};
@@ -264,6 +303,42 @@ int qemu_set_option(const char *str)
return 0;
}
+int qemu_global_option(const char *str)
+{
+ char driver[64], property[64];
+ QemuOpts *opts;
+ int rc, offset;
+
+ rc = sscanf(str, "%63[^.].%63[^=]%n", driver, property, &offset);
+ if (rc < 2 || str[offset] != '=') {
+ qemu_error("can't parse: \"%s\"\n", str);
+ return -1;
+ }
+
+ opts = qemu_opts_create(&qemu_global_opts, NULL, 0);
+ qemu_opt_set(opts, "driver", driver);
+ qemu_opt_set(opts, "property", property);
+ qemu_opt_set(opts, "value", str+offset+1);
+ return 0;
+}
+
+static int qemu_add_one_global(QemuOpts *opts, void *opaque)
+{
+ GlobalProperty *g;
+
+ g = qemu_mallocz(sizeof(*g));
+ g->driver = qemu_opt_get(opts, "driver");
+ g->property = qemu_opt_get(opts, "property");
+ g->value = qemu_opt_get(opts, "value");
+ qdev_prop_register_global(g);
+ return 0;
+}
+
+void qemu_add_globals(void)
+{
+ qemu_opts_foreach(&qemu_global_opts, qemu_add_one_global, NULL, 0);
+}
+
struct ConfigWriteData {
QemuOptsList *list;
FILE *fp;
diff --git a/qemu-config.h b/qemu-config.h
index b56485165..34dfadc5f 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -7,8 +7,11 @@ extern QemuOptsList qemu_device_opts;
extern QemuOptsList qemu_netdev_opts;
extern QemuOptsList qemu_net_opts;
extern QemuOptsList qemu_rtc_opts;
+extern QemuOptsList qemu_mon_opts;
int qemu_set_option(const char *str);
+int qemu_global_option(const char *str);
+void qemu_add_globals(void);
void qemu_config_write(FILE *fp);
int qemu_config_parse(FILE *fp);
diff --git a/qemu-malloc.c b/qemu-malloc.c
index 295d1856e..5d9e34d69 100644
--- a/qemu-malloc.c
+++ b/qemu-malloc.c
@@ -42,22 +42,29 @@ void qemu_free(void *ptr)
free(ptr);
}
+static int allow_zero_malloc(void)
+{
+#if defined(CONFIG_ZERO_MALLOC)
+ return 1;
+#else
+ return 0;
+#endif
+}
+
void *qemu_malloc(size_t size)
{
- if (!size) {
+ if (!size && !allow_zero_malloc()) {
abort();
}
- return oom_check(malloc(size));
+ return oom_check(malloc(size ? size : 1));
}
void *qemu_realloc(void *ptr, size_t size)
{
if (size) {
return oom_check(realloc(ptr, size));
- } else {
- if (ptr) {
- return realloc(ptr, size);
- }
+ } else if (allow_zero_malloc()) {
+ return oom_check(realloc(ptr, size ? size : 1));
}
abort();
}
diff --git a/qemu-monitor.hx b/qemu-monitor.hx
index fdcdaa498..ff722b52f 100644
--- a/qemu-monitor.hx
+++ b/qemu-monitor.hx
@@ -147,7 +147,8 @@ ETEXI
.args_type = "device:B,target:F,arg:s?",
.params = "device filename [format]",
.help = "change a removable medium, optional format",
- .mhandler.cmd = do_change,
+ .user_print = monitor_user_noop,
+ .mhandler.cmd_new = do_change,
},
STEXI
diff --git a/qemu-objects.h b/qemu-objects.h
new file mode 100644
index 000000000..e1d1e0ca7
--- /dev/null
+++ b/qemu-objects.h
@@ -0,0 +1,24 @@
+/*
+ * Include all QEMU objects.
+ *
+ * Copyright (C) 2009 Red Hat Inc.
+ *
+ * Authors:
+ * Luiz Capitulino <lcapitulino@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#ifndef QEMU_OBJECTS_H
+#define QEMU_OBJECTS_H
+
+#include "qobject.h"
+#include "qint.h"
+#include "qfloat.h"
+#include "qbool.h"
+#include "qstring.h"
+#include "qdict.h"
+#include "qlist.h"
+#include "qjson.h"
+
+#endif /* QEMU_OBJECTS_H */
diff --git a/qemu-option.c b/qemu-option.c
index b00910900..24392fcb4 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -705,7 +705,7 @@ int qemu_opts_print(QemuOpts *opts, void *dummy)
int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname)
{
- char option[128], value[128];
+ char option[128], value[1024];
const char *p,*pe,*pc;
for (p = params; *p != '\0'; p++) {
@@ -751,7 +751,7 @@ int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname
QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, const char *firstname)
{
- char value[128], *id = NULL;
+ char value[1024], *id = NULL;
const char *p;
QemuOpts *opts;
diff --git a/qemu-options.hx b/qemu-options.hx
index fff751b01..812d0670a 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -110,6 +110,9 @@ DEF("set", HAS_ARG, QEMU_OPTION_set,
"-set group.id.arg=value\n"
" set <arg> parameter for item <id> of type <group>\n"
" i.e. -set drive.$id.file=/path/to/image\n")
+DEF("global", HAS_ARG, QEMU_OPTION_global,
+ "-global driver.property=value\n"
+ " set a global default for a driver property\n")
STEXI
@item -drive @var{option}[,@var{option}[,@var{option}[,...]]]
@@ -1578,14 +1581,22 @@ Use @code{-parallel none} to disable all parallel ports.
ETEXI
DEF("monitor", HAS_ARG, QEMU_OPTION_monitor, \
- "-monitor [control,]dev redirect the monitor to char device 'dev'\n")
+ "-monitor dev redirect the monitor to char device 'dev'\n")
STEXI
-@item -monitor [@var{control},]@var{dev}
+@item -monitor @var{dev}
Redirect the monitor to host device @var{dev} (same devices as the
serial port).
The default device is @code{vc} in graphical mode and @code{stdio} in
non graphical mode.
-The option @var{control} enables the QEMU Monitor Protocol.
+ETEXI
+DEF("qmp", HAS_ARG, QEMU_OPTION_qmp, \
+ "-qmp dev like -monitor but opens in 'control' mode.\n")
+
+DEF("mon", HAS_ARG, QEMU_OPTION_mon, \
+ "-mon chardev=[name][,mode=readline|control][,default]\n")
+STEXI
+@item -mon chardev=[name][,mode=readline|control][,default]
+Setup monitor on chardev @var{name}.
ETEXI
DEF("pidfile", HAS_ARG, QEMU_OPTION_pidfile, \
@@ -1880,6 +1891,11 @@ DEF("incoming", HAS_ARG, QEMU_OPTION_incoming, \
STEXI
ETEXI
+DEF("nodefaults", 0, QEMU_OPTION_nodefaults, \
+ "-nodefaults don't create default devices.\n")
+STEXI
+ETEXI
+
#ifndef _WIN32
DEF("chroot", HAS_ARG, QEMU_OPTION_chroot, \
"-chroot dir Chroot to dir just before starting the VM.\n")
diff --git a/qerror.c b/qerror.c
index eb4ce3331..5f8fc5dec 100644
--- a/qerror.c
+++ b/qerror.c
@@ -41,24 +41,56 @@ static const QType qerror_type = {
*/
static const QErrorStringTable qerror_table[] = {
{
- .error_fmt = QERR_COMMAND_NOT_FOUND,
- .desc = "The command %(name) has not been found",
+ .error_fmt = QERR_COMMAND_NOT_FOUND,
+ .desc = "The command %(name) has not been found",
},
{
- .error_fmt = QERR_DEVICE_NOT_FOUND,
- .desc = "The %(device) device has not been found",
+ .error_fmt = QERR_DEVICE_ENCRYPTED,
+ .desc = "The %(device) is encrypted",
+ },
+ {
+ .error_fmt = QERR_DEVICE_LOCKED,
+ .desc = "Device %(device) is locked",
},
{
.error_fmt = QERR_DEVICE_NOT_ACTIVE,
.desc = "The %(device) device has not been activated by the guest",
},
{
- .error_fmt = QERR_INVALID_PARAMETER_TYPE,
- .desc = "Invalid parameter type, expected: %(expected)",
+ .error_fmt = QERR_DEVICE_NOT_FOUND,
+ .desc = "The %(device) device has not been found",
},
{
- .error_fmt = QERR_INVALID_PASSWORD,
- .desc = "The entered password is invalid",
+ .error_fmt = QERR_DEVICE_NOT_REMOVABLE,
+ .desc = "Device %(device) is not removable",
+ },
+ {
+ .error_fmt = QERR_FD_NOT_FOUND,
+ .desc = "Failed to find file descriptor named %(name)",
+ },
+ {
+ .error_fmt = QERR_FD_NOT_SUPPLIED,
+ .desc = "No file descriptor supplied via SCM_RIGHTS",
+ },
+ {
+ .error_fmt = QERR_INVALID_BLOCK_FORMAT,
+ .desc = "Invalid block format %(name)",
+ },
+ {
+ .error_fmt = QERR_INVALID_PARAMETER,
+ .desc = "Invalid parameter %(name)",
+ },
+ {
+ .error_fmt = QERR_INVALID_PARAMETER_TYPE,
+ .desc = "Invalid parameter type, expected: %(expected)",
+ },
+ {
+ .error_fmt = QERR_INVALID_PASSWORD,
+ .desc = "The entered password is invalid",
+ },
+ {
+ .error_fmt = QERR_JSON_PARSING,
+ .desc = "Invalid JSON syntax",
},
{
.error_fmt = QERR_KVM_MISSING_CAP,
@@ -73,12 +105,20 @@ static const QErrorStringTable qerror_table[] = {
.desc = "Bad QMP input object",
},
{
- .error_fmt = QERR_JSON_PARSING,
- .desc = "Invalid JSON synaxt",
+ .error_fmt = QERR_SET_PASSWD_FAILED,
+ .desc = "Could not set password",
+ },
+ {
+ .error_fmt = QERR_TOO_MANY_FILES,
+ .desc = "Too many open files",
},
{
- .error_fmt = QERR_UNDEFINED_ERROR,
- .desc = "An undefined error has ocurred",
+ .error_fmt = QERR_UNDEFINED_ERROR,
+ .desc = "An undefined error has ocurred",
+ },
+ {
+ .error_fmt = QERR_VNC_SERVER_FAILED,
+ .desc = "Could not start VNC server on %(target)",
},
{}
};
@@ -243,13 +283,11 @@ static const char *append_field(QString *outstr, const QError *qerror,
}
/**
- * qerror_print(): Print QError data
+ * qerror_human(): Format QError data into human-readable string.
*
- * This function will print the member 'desc' of the specified QError object,
- * it uses qemu_error() for this, so that the output is routed to the right
- * place (ie. stderr or Monitor's device).
+ * Formats according to member 'desc' of the specified QError object.
*/
-void qerror_print(const QError *qerror)
+QString *qerror_human(const QError *qerror)
{
const char *p;
QString *qstring;
@@ -269,6 +307,19 @@ void qerror_print(const QError *qerror)
}
}
+ return qstring;
+}
+
+/**
+ * qerror_print(): Print QError data
+ *
+ * This function will print the member 'desc' of the specified QError object,
+ * it uses qemu_error() for this, so that the output is routed to the right
+ * place (ie. stderr or Monitor's device).
+ */
+void qerror_print(const QError *qerror)
+{
+ QString *qstring = qerror_human(qerror);
qemu_error("%s\n", qstring_get_str(qstring));
QDECREF(qstring);
}
diff --git a/qerror.h b/qerror.h
index 5198adf14..9e220d6b4 100644
--- a/qerror.h
+++ b/qerror.h
@@ -13,6 +13,7 @@
#define QERROR_H
#include "qdict.h"
+#include "qstring.h"
#include <stdarg.h>
typedef struct QErrorStringTable {
@@ -32,6 +33,7 @@ typedef struct QError {
QError *qerror_new(void);
QError *qerror_from_info(const char *file, int linenr, const char *func,
const char *fmt, va_list *va);
+QString *qerror_human(const QError *qerror);
void qerror_print(const QError *qerror);
QError *qobject_to_qerror(const QObject *obj);
@@ -39,33 +41,63 @@ QError *qobject_to_qerror(const QObject *obj);
* QError class list
*/
#define QERR_COMMAND_NOT_FOUND \
- "{ 'class': 'CommandNotFound', 'data': { 'name': %s } }"
+ "{ 'class': 'CommandNotFound', 'data': { 'name': %s } }"
-#define QERR_DEVICE_NOT_FOUND \
- "{ 'class': 'DeviceNotFound', 'data': { 'device': %s } }"
+#define QERR_DEVICE_ENCRYPTED \
+ "{ 'class': 'DeviceEncrypted', 'data': { 'device': %s } }"
+
+#define QERR_DEVICE_LOCKED \
+ "{ 'class': 'DeviceLocked', 'data': { 'device': %s } }"
#define QERR_DEVICE_NOT_ACTIVE \
- "{ 'class': 'DeviceNotActive', 'data': { 'device': %s } }"
+ "{ 'class': 'DeviceNotActive', 'data': { 'device': %s } }"
+
+#define QERR_DEVICE_NOT_FOUND \
+ "{ 'class': 'DeviceNotFound', 'data': { 'device': %s } }"
+
+#define QERR_DEVICE_NOT_REMOVABLE \
+ "{ 'class': 'DeviceNotRemovable', 'data': { 'device': %s } }"
+
+#define QERR_FD_NOT_FOUND \
+ "{ 'class': 'FdNotFound', 'data': { 'name': %s } }"
+
+#define QERR_FD_NOT_SUPPLIED \
+ "{ 'class': 'FdNotSupplied', 'data': {} }"
+
+#define QERR_INVALID_BLOCK_FORMAT \
+ "{ 'class': 'InvalidBlockFormat', 'data': { 'name': %s } }"
+
+#define QERR_INVALID_PARAMETER \
+ "{ 'class': 'InvalidParameter', 'data': { 'name': %s } }"
#define QERR_INVALID_PARAMETER_TYPE \
- "{ 'class': 'InvalidParameterType', 'data': { 'name': %s,'expected': %s } }"
+ "{ 'class': 'InvalidParameterType', 'data': { 'name': %s,'expected': %s } }"
#define QERR_INVALID_PASSWORD \
- "{ 'class': 'InvalidPassword', 'data': {} }"
+ "{ 'class': 'InvalidPassword', 'data': {} }"
+
+#define QERR_JSON_PARSING \
+ "{ 'class': 'JSONParsing', 'data': {} }"
#define QERR_KVM_MISSING_CAP \
- "{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }"
+ "{ 'class': 'KVMMissingCap', 'data': { 'capability': %s, 'feature': %s } }"
#define QERR_MISSING_PARAMETER \
- "{ 'class': 'MissingParameter', 'data': { 'name': %s } }"
+ "{ 'class': 'MissingParameter', 'data': { 'name': %s } }"
#define QERR_QMP_BAD_INPUT_OBJECT \
- "{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }"
+ "{ 'class': 'QMPBadInputObject', 'data': { 'expected': %s } }"
-#define QERR_JSON_PARSING \
- "{ 'class': 'JSONParsing', 'data': {} }"
+#define QERR_SET_PASSWD_FAILED \
+ "{ 'class': 'SetPasswdFailed', 'data': {} }"
#define QERR_UNDEFINED_ERROR \
- "{ 'class': 'UndefinedError', 'data': {} }"
+ "{ 'class': 'UndefinedError', 'data': {} }"
+
+#define QERR_TOO_MANY_FILES \
+ "{ 'class': 'TooManyFiles', 'data': {} }"
+
+#define QERR_VNC_SERVER_FAILED \
+ "{ 'class': 'VNCServerFailed', 'data': { 'target': %s } }"
#endif /* QERROR_H */
diff --git a/rules.mak b/rules.mak
index 16713bacd..5d9f684c2 100644
--- a/rules.mak
+++ b/rules.mak
@@ -47,3 +47,6 @@ cc-option = $(if $(shell $(CC) $1 $2 -S -o /dev/null -xc /dev/null \
%.h-timestamp: %.mak
$(call quiet-command, sh $(SRC_PATH)/create_config < $< > $@, " GEN $*.h")
@cmp $@ $*.h >/dev/null 2>&1 || cp $@ $*.h
+
+# will delete the target of a rule if commands exit with a nonzero exit status
+.DELETE_ON_ERROR:
diff --git a/target-i386/machine.c b/target-i386/machine.c
index 402eddc7e..6b10c8702 100644
--- a/target-i386/machine.c
+++ b/target-i386/machine.c
@@ -465,6 +465,7 @@ static const VMStateDescription vmstate_cpu = {
VMSTATE_UINT8_V(nmi_pending, CPUState, 11),
VMSTATE_UINT8_V(has_error_code, CPUState, 11),
VMSTATE_UINT32_V(sipi_vector, CPUState, 11),
+ VMSTATE_INT32_V(exception_index, CPUState, 11),
/* MCE */
VMSTATE_UINT64_V(mcg_cap, CPUState, 10),
VMSTATE_UINT64_V(mcg_status, CPUState, 10),
diff --git a/usb-bsd.c b/usb-bsd.c
index a66364f0d..48567a3ba 100644
--- a/usb-bsd.c
+++ b/usb-bsd.c
@@ -361,7 +361,7 @@ USBDevice *usb_host_device_open(const char *devname)
goto fail;
}
- d = usb_create(NULL /* FIXME */, "USB Host Device");
+ d = usb_create(NULL /* FIXME */, "usb-host");
dev = DO_UPCAST(USBHostDevice, dev, d);
if (dev_info.udi_speed == 1)
@@ -370,10 +370,10 @@ USBDevice *usb_host_device_open(const char *devname)
dev->dev.speed = USB_SPEED_FULL - 1;
if (strncmp(dev_info.udi_product, "product", 7) != 0)
- pstrcpy(dev->dev.devname, sizeof(dev->dev.devname),
+ pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
dev_info.udi_product);
else
- snprintf(dev->dev.devname, sizeof(dev->dev.devname),
+ snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
"host:%s", devname);
pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/");
@@ -393,7 +393,8 @@ fail:
}
static struct USBDeviceInfo usb_host_dev_info = {
- .qdev.name = "USB Host Device",
+ .product_desc = "USB Host Device",
+ .qdev.name = "usb-host",
.qdev.size = sizeof(USBHostDevice),
.init = usb_host_initfn,
.handle_packet = usb_generic_handle_packet,
diff --git a/usb-linux.c b/usb-linux.c
index 285ac227a..105ce88f3 100644
--- a/usb-linux.c
+++ b/usb-linux.c
@@ -933,10 +933,10 @@ static int usb_host_open(USBHostDevice *dev, int bus_num,
dev->dev.speed = USB_SPEED_HIGH;
if (!prod_name || prod_name[0] == '\0')
- snprintf(dev->dev.devname, sizeof(dev->dev.devname),
+ snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
"host:%d.%d", bus_num, addr);
else
- pstrcpy(dev->dev.devname, sizeof(dev->dev.devname),
+ pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
prod_name);
/* USB devio uses 'write' flag to check for async completions */
@@ -979,8 +979,8 @@ static int usb_host_initfn(USBDevice *dev)
}
static struct USBDeviceInfo usb_host_dev_info = {
- .qdev.name = "USB Host Device",
- .qdev.alias = "usb-host",
+ .product_desc = "USB Host Device",
+ .qdev.name = "usb-host",
.qdev.size = sizeof(USBHostDevice),
.init = usb_host_initfn,
.handle_packet = usb_host_handle_packet,
@@ -1010,7 +1010,7 @@ USBDevice *usb_host_device_open(const char *devname)
USBHostDevice *s;
char *p;
- dev = usb_create(NULL /* FIXME */, "USB Host Device");
+ dev = usb_create(NULL /* FIXME */, "usb-host");
s = DO_UPCAST(USBHostDevice, dev, dev);
if (strstr(devname, "auto:")) {
diff --git a/vl.c b/vl.c
index a4d12659c..c7ceb0a06 100644
--- a/vl.c
+++ b/vl.c
@@ -174,9 +174,6 @@ int main(int argc, char **argv)
#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
@@ -196,7 +193,7 @@ int autostart;
static int rtc_utc = 1;
static int rtc_date_offset = -1; /* -1 means no change */
QEMUClock *rtc_clock;
-int vga_interface_type = VGA_CIRRUS;
+int vga_interface_type = VGA_NONE;
#ifdef TARGET_SPARC
int graphic_width = 1024;
int graphic_height = 768;
@@ -285,6 +282,41 @@ uint8_t qemu_uuid[16];
static QEMUBootSetHandler *boot_set_handler;
static void *boot_set_opaque;
+static int default_serial = 1;
+static int default_parallel = 1;
+static int default_virtcon = 1;
+static int default_monitor = 1;
+static int default_vga = 1;
+static int default_drive = 1;
+
+static struct {
+ const char *driver;
+ int *flag;
+} default_list[] = {
+ { .driver = "isa-serial", .flag = &default_serial },
+ { .driver = "isa-parallel", .flag = &default_parallel },
+ { .driver = "virtio-console-pci", .flag = &default_virtcon },
+ { .driver = "virtio-console-s390", .flag = &default_virtcon },
+ { .driver = "VGA", .flag = &default_vga },
+ { .driver = "Cirrus VGA", .flag = &default_vga },
+ { .driver = "QEMUware SVGA", .flag = &default_vga },
+};
+
+static int default_driver_check(QemuOpts *opts, void *opaque)
+{
+ const char *driver = qemu_opt_get(opts, "driver");
+ int i;
+
+ if (!driver)
+ return 0;
+ for (i = 0; i < ARRAY_SIZE(default_list); i++) {
+ if (strcmp(default_list[i].driver, driver) != 0)
+ continue;
+ *(default_list[i].flag) = 0;
+ }
+ return 0;
+}
+
/***********************************************************/
/* x86 ISA bus support */
@@ -4403,6 +4435,7 @@ static void select_vgahw (const char *p)
{
const char *opts;
+ default_vga = 0;
vga_interface_type = VGA_NONE;
if (strstart(p, "std", &opts)) {
vga_interface_type = VGA_STD;
@@ -4644,10 +4677,94 @@ static int device_init_func(QemuOpts *opts, void *opaque)
return 0;
}
+static int chardev_init_func(QemuOpts *opts, void *opaque)
+{
+ CharDriverState *chr;
+
+ chr = qemu_chr_open_opts(opts, NULL);
+ if (!chr)
+ return -1;
+ return 0;
+}
+
+static int mon_init_func(QemuOpts *opts, void *opaque)
+{
+ CharDriverState *chr;
+ const char *chardev;
+ const char *mode;
+ int flags;
+
+ mode = qemu_opt_get(opts, "mode");
+ if (mode == NULL) {
+ mode = "readline";
+ }
+ if (strcmp(mode, "readline") == 0) {
+ flags = MONITOR_USE_READLINE;
+ } else if (strcmp(mode, "control") == 0) {
+ flags = MONITOR_USE_CONTROL;
+ } else {
+ fprintf(stderr, "unknown monitor mode \"%s\"\n", mode);
+ exit(1);
+ }
+
+ if (qemu_opt_get_bool(opts, "default", 0))
+ flags |= MONITOR_IS_DEFAULT;
+
+ chardev = qemu_opt_get(opts, "chardev");
+ chr = qemu_chr_find(chardev);
+ if (chr == NULL) {
+ fprintf(stderr, "chardev \"%s\" not found\n", chardev);
+ exit(1);
+ }
+
+ monitor_init(chr, flags);
+ return 0;
+}
+
+static void monitor_parse(const char *optarg, const char *mode)
+{
+ static int monitor_device_index = 0;
+ QemuOpts *opts;
+ const char *p;
+ char label[32];
+ int def = 0;
+
+ if (strstart(optarg, "chardev:", &p)) {
+ snprintf(label, sizeof(label), "%s", p);
+ } else {
+ if (monitor_device_index) {
+ snprintf(label, sizeof(label), "monitor%d",
+ monitor_device_index);
+ } else {
+ snprintf(label, sizeof(label), "monitor");
+ def = 1;
+ }
+ opts = qemu_chr_parse_compat(label, optarg);
+ if (!opts) {
+ fprintf(stderr, "parse error: %s\n", optarg);
+ exit(1);
+ }
+ }
+
+ opts = qemu_opts_create(&qemu_mon_opts, label, 1);
+ if (!opts) {
+ fprintf(stderr, "duplicate chardev: %s\n", label);
+ exit(1);
+ }
+ qemu_opt_set(opts, "mode", mode);
+ qemu_opt_set(opts, "chardev", label);
+ if (def)
+ qemu_opt_set(opts, "default", "on");
+ monitor_device_index++;
+}
+
struct device_config {
enum {
- DEV_USB, /* -usbdevice */
- DEV_BT, /* -bt */
+ DEV_USB, /* -usbdevice */
+ DEV_BT, /* -bt */
+ DEV_SERIAL, /* -serial */
+ DEV_PARALLEL, /* -parallel */
+ DEV_VIRTCON, /* -virtioconsole */
} type;
const char *cmdline;
QTAILQ_ENTRY(device_config) next;
@@ -4679,6 +4796,72 @@ static int foreach_device_config(int type, int (*func)(const char *cmdline))
return 0;
}
+static int serial_parse(const char *devname)
+{
+ static int index = 0;
+ char label[32];
+
+ if (strcmp(devname, "none") == 0)
+ return 0;
+ if (index == MAX_SERIAL_PORTS) {
+ fprintf(stderr, "qemu: too many serial ports\n");
+ exit(1);
+ }
+ snprintf(label, sizeof(label), "serial%d", index);
+ serial_hds[index] = qemu_chr_open(label, devname, NULL);
+ if (!serial_hds[index]) {
+ fprintf(stderr, "qemu: could not open serial device '%s': %s\n",
+ devname, strerror(errno));
+ return -1;
+ }
+ index++;
+ return 0;
+}
+
+static int parallel_parse(const char *devname)
+{
+ static int index = 0;
+ char label[32];
+
+ if (strcmp(devname, "none") == 0)
+ return 0;
+ if (index == MAX_PARALLEL_PORTS) {
+ fprintf(stderr, "qemu: too many parallel ports\n");
+ exit(1);
+ }
+ snprintf(label, sizeof(label), "parallel%d", index);
+ parallel_hds[index] = qemu_chr_open(label, devname, NULL);
+ if (!parallel_hds[index]) {
+ fprintf(stderr, "qemu: could not open parallel device '%s': %s\n",
+ devname, strerror(errno));
+ return -1;
+ }
+ index++;
+ return 0;
+}
+
+static int virtcon_parse(const char *devname)
+{
+ static int index = 0;
+ char label[32];
+
+ if (strcmp(devname, "none") == 0)
+ return 0;
+ if (index == MAX_VIRTIO_CONSOLES) {
+ fprintf(stderr, "qemu: too many virtio consoles\n");
+ exit(1);
+ }
+ snprintf(label, sizeof(label), "virtcon%d", index);
+ virtcon_hds[index] = qemu_chr_open(label, devname, NULL);
+ if (!virtcon_hds[index]) {
+ fprintf(stderr, "qemu: could not open virtio console '%s': %s\n",
+ devname, strerror(errno));
+ return -1;
+ }
+ index++;
+ return 0;
+}
+
int main(int argc, char **argv, char **envp)
{
const char *gdbstub_dev = NULL;
@@ -4694,16 +4877,6 @@ int main(int argc, char **argv, char **envp)
QemuOpts *hda_opts = NULL, *opts;
int optind;
const char *r, *optarg;
- CharDriverState *monitor_hds[MAX_MONITOR_DEVICES];
- const char *monitor_devices[MAX_MONITOR_DEVICES];
- int monitor_flags[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];
- int parallel_device_index;
- const char *virtio_consoles[MAX_VIRTIO_CONSOLES];
- int virtio_console_index;
const char *loadvm = NULL;
QEMUMachine *machine;
const char *cpu_model;
@@ -4769,43 +4942,6 @@ int main(int argc, char **argv, char **envp)
cyls = heads = secs = 0;
translation = BIOS_ATA_TRANSLATION_AUTO;
-#ifdef TARGET_S390X
- for(i = 0; i < MAX_SERIAL_PORTS; i++)
- serial_devices[i] = NULL;
- serial_device_index = 0;
-
- for(i = 0; i < MAX_PARALLEL_PORTS; i++)
- parallel_devices[i] = NULL;
- parallel_device_index = 0;
-
- virtio_consoles[0] = "mon:stdio";
- for(i = 1; i < MAX_VIRTIO_CONSOLES; i++)
- virtio_consoles[i] = NULL;
- virtio_console_index = 0;
-#else
- serial_devices[0] = "vc:80Cx24C";
- for(i = 1; i < MAX_SERIAL_PORTS; i++)
- serial_devices[i] = NULL;
- serial_device_index = 0;
-
- parallel_devices[0] = "vc:80Cx24C";
- for(i = 1; i < MAX_PARALLEL_PORTS; i++)
- parallel_devices[i] = NULL;
- parallel_device_index = 0;
-
- for(i = 0; i < MAX_VIRTIO_CONSOLES; i++)
- virtio_consoles[i] = NULL;
- virtio_console_index = 0;
-#endif
-
- monitor_devices[0] = "vc:80Cx24C";
- monitor_flags[0] = MONITOR_IS_DEFAULT | MONITOR_USE_READLINE;
- for (i = 1; i < MAX_MONITOR_DEVICES; i++) {
- monitor_devices[i] = NULL;
- monitor_flags[i] = MONITOR_USE_READLINE;
- }
- monitor_device_index = 0;
-
for (i = 0; i < MAX_NODES; i++) {
node_mem[i] = 0;
node_cpumask[i] = 0;
@@ -4911,6 +5047,10 @@ int main(int argc, char **argv, char **envp)
if (qemu_set_option(optarg) != 0)
exit(1);
break;
+ case QEMU_OPTION_global:
+ if (qemu_global_option(optarg) != 0)
+ exit(1);
+ break;
case QEMU_OPTION_mtdblock:
drive_add(optarg, MTD_ALIAS);
break;
@@ -5221,14 +5361,20 @@ int main(int argc, char **argv, char **envp)
break;
}
case QEMU_OPTION_monitor:
- if (monitor_device_index >= MAX_MONITOR_DEVICES) {
- fprintf(stderr, "qemu: too many monitor devices\n");
+ monitor_parse(optarg, "readline");
+ default_monitor = 0;
+ break;
+ case QEMU_OPTION_qmp:
+ monitor_parse(optarg, "control");
+ default_monitor = 0;
+ break;
+ case QEMU_OPTION_mon:
+ opts = qemu_opts_parse(&qemu_mon_opts, optarg, "chardev");
+ if (!opts) {
+ fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
- monitor_devices[monitor_device_index] =
- monitor_cmdline_parse(optarg,
- &monitor_flags[monitor_device_index]);
- monitor_device_index++;
+ default_monitor = 0;
break;
case QEMU_OPTION_chardev:
opts = qemu_opts_parse(&qemu_chardev_opts, optarg, "backend");
@@ -5236,17 +5382,10 @@ int main(int argc, char **argv, char **envp)
fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
- if (qemu_chr_open_opts(opts, NULL) == NULL) {
- exit(1);
- }
break;
case QEMU_OPTION_serial:
- if (serial_device_index >= MAX_SERIAL_PORTS) {
- fprintf(stderr, "qemu: too many serial ports\n");
- exit(1);
- }
- serial_devices[serial_device_index] = optarg;
- serial_device_index++;
+ add_device_config(DEV_SERIAL, optarg);
+ default_serial = 0;
break;
case QEMU_OPTION_watchdog:
if (watchdog) {
@@ -5263,20 +5402,12 @@ int main(int argc, char **argv, char **envp)
}
break;
case QEMU_OPTION_virtiocon:
- if (virtio_console_index >= MAX_VIRTIO_CONSOLES) {
- fprintf(stderr, "qemu: too many virtio consoles\n");
- exit(1);
- }
- virtio_consoles[virtio_console_index] = optarg;
- virtio_console_index++;
+ add_device_config(DEV_VIRTCON, optarg);
+ default_virtcon = 0;
break;
case QEMU_OPTION_parallel:
- if (parallel_device_index >= MAX_PARALLEL_PORTS) {
- fprintf(stderr, "qemu: too many parallel ports\n");
- exit(1);
- }
- parallel_devices[parallel_device_index] = optarg;
- parallel_device_index++;
+ add_device_config(DEV_PARALLEL, optarg);
+ default_parallel = 0;
break;
case QEMU_OPTION_loadvm:
loadvm = optarg;
@@ -5515,6 +5646,15 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_incoming:
incoming = optarg;
break;
+ case QEMU_OPTION_nodefaults:
+ default_serial = 0;
+ default_parallel = 0;
+ default_virtcon = 0;
+ default_monitor = 0;
+ default_vga = 0;
+ default_net = 0;
+ default_drive = 0;
+ break;
#ifndef _WIN32
case QEMU_OPTION_chroot:
chroot_dir = optarg;
@@ -5596,16 +5736,50 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
- if (display_type == DT_NOGRAPHIC) {
- if (serial_device_index == 0)
- serial_devices[0] = "stdio";
- if (parallel_device_index == 0)
- parallel_devices[0] = "null";
- if (strncmp(monitor_devices[0], "vc", 2) == 0) {
- monitor_devices[0] = "stdio";
- }
+ qemu_opts_foreach(&qemu_device_opts, default_driver_check, NULL, 0);
+
+ if (machine->no_serial) {
+ default_serial = 0;
+ }
+ if (machine->no_parallel) {
+ default_parallel = 0;
+ }
+ if (!machine->use_virtcon) {
+ default_virtcon = 0;
+ }
+ if (machine->no_vga) {
+ default_vga = 0;
}
+ if (display_type == DT_NOGRAPHIC) {
+ if (default_parallel)
+ add_device_config(DEV_PARALLEL, "null");
+ if (default_serial && default_monitor) {
+ add_device_config(DEV_SERIAL, "mon:stdio");
+ } else if (default_virtcon && default_monitor) {
+ add_device_config(DEV_VIRTCON, "mon:stdio");
+ } else {
+ if (default_serial)
+ add_device_config(DEV_SERIAL, "stdio");
+ if (default_virtcon)
+ add_device_config(DEV_VIRTCON, "stdio");
+ if (default_monitor)
+ monitor_parse("stdio", "readline");
+ }
+ } else {
+ if (default_serial)
+ add_device_config(DEV_SERIAL, "vc:80Cx24C");
+ if (default_parallel)
+ add_device_config(DEV_PARALLEL, "vc:80Cx24C");
+ if (default_monitor)
+ monitor_parse("vc:80Cx24C", "readline");
+ }
+ if (default_vga)
+ vga_interface_type = VGA_CIRRUS;
+
+ if (qemu_opts_foreach(&qemu_chardev_opts, chardev_init_func, NULL, 1) != 0)
+ exit(1);
+
#ifndef _WIN32
if (daemonize) {
pid_t pid;
@@ -5736,14 +5910,16 @@ int main(int argc, char **argv, char **envp)
blk_mig_init();
- /* we always create the cdrom drive, even if no disk is there */
- drive_add(NULL, CDROM_ALIAS);
+ if (default_drive) {
+ /* we always create the cdrom drive, even if no disk is there */
+ drive_add(NULL, CDROM_ALIAS);
- /* we always create at least one floppy */
- drive_add(NULL, FD_ALIAS, 0);
+ /* we always create at least one floppy */
+ drive_add(NULL, FD_ALIAS, 0);
- /* we always create one sd slot, even if no card is in it */
- drive_add(NULL, SD_ALIAS);
+ /* we always create one sd slot, even if no card is in it */
+ drive_add(NULL, SD_ALIAS);
+ }
/* open the virtual block devices */
if (snapshot)
@@ -5755,32 +5931,6 @@ int main(int argc, char **argv, char **envp)
register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL,
ram_load, NULL);
- /* Maintain compatibility with multiple stdio monitors */
- 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_devices[0] = NULL;
- break;
- } else if (devname && !strcmp(devname,"stdio")) {
- monitor_devices[0] = NULL;
- serial_devices[i] = "mon:stdio";
- break;
- }
- }
- for (i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
- const char *devname = virtio_consoles[i];
- if (devname && !strcmp(devname,"mon:stdio")) {
- monitor_devices[0] = NULL;
- break;
- } else if (devname && !strcmp(devname,"stdio")) {
- monitor_devices[0] = NULL;
- virtio_consoles[i] = "mon:stdio";
- break;
- }
- }
- }
-
if (nb_numa_nodes > 0) {
int i;
@@ -5823,65 +5973,12 @@ int main(int argc, char **argv, char **envp)
}
}
- 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);
- }
- }
- }
-
- for(i = 0; i < MAX_SERIAL_PORTS; i++) {
- const char *devname = serial_devices[i];
- if (devname && strcmp(devname, "none")) {
- char label[32];
- snprintf(label, sizeof(label), "serial%d", i);
- serial_hds[i] = qemu_chr_open(label, devname, NULL);
- if (!serial_hds[i]) {
- fprintf(stderr, "qemu: could not open serial device '%s': %s\n",
- devname, strerror(errno));
- exit(1);
- }
- }
- }
-
- for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
- const char *devname = parallel_devices[i];
- if (devname && strcmp(devname, "none")) {
- char label[32];
- snprintf(label, sizeof(label), "parallel%d", i);
- parallel_hds[i] = qemu_chr_open(label, devname, NULL);
- if (!parallel_hds[i]) {
- fprintf(stderr, "qemu: could not open parallel device '%s': %s\n",
- devname, strerror(errno));
- exit(1);
- }
- }
- }
-
- for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
- const char *devname = virtio_consoles[i];
- if (devname && strcmp(devname, "none")) {
- char label[32];
- snprintf(label, sizeof(label), "virtcon%d", i);
- virtcon_hds[i] = qemu_chr_open(label, devname, NULL);
- if (!virtcon_hds[i]) {
- fprintf(stderr, "qemu: could not open virtio console '%s': %s\n",
- devname, strerror(errno));
- exit(1);
- }
- }
- }
+ if (foreach_device_config(DEV_SERIAL, serial_parse) < 0)
+ exit(1);
+ if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0)
+ exit(1);
+ if (foreach_device_config(DEV_VIRTCON, virtcon_parse) < 0)
+ exit(1);
module_call_init(MODULE_INIT_DEVICE);
@@ -5892,8 +5989,10 @@ int main(int argc, char **argv, char **envp)
}
if (machine->compat_props) {
- qdev_prop_register_compat(machine->compat_props);
+ qdev_prop_register_global_list(machine->compat_props);
}
+ qemu_add_globals();
+
machine->init(ram_size, boot_devices,
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
@@ -5986,35 +6085,8 @@ int main(int argc, char **argv, char **envp)
text_consoles_set_display(display_state);
- for (i = 0; i < MAX_MONITOR_DEVICES; i++) {
- if (monitor_devices[i] && monitor_hds[i]) {
- monitor_init(monitor_hds[i], monitor_flags[i]);
- }
- }
-
- for(i = 0; i < MAX_SERIAL_PORTS; i++) {
- const char *devname = serial_devices[i];
- if (devname && strcmp(devname, "none")) {
- if (strstart(devname, "vc", 0))
- qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
- }
- }
-
- for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
- const char *devname = parallel_devices[i];
- if (devname && strcmp(devname, "none")) {
- if (strstart(devname, "vc", 0))
- qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
- }
- }
-
- for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
- const char *devname = virtio_consoles[i];
- if (virtcon_hds[i] && devname) {
- if (strstart(devname, "vc", 0))
- qemu_chr_printf(virtcon_hds[i], "virtio console%d\r\n", i);
- }
- }
+ if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0)
+ exit(1);
if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
diff --git a/vnc.c b/vnc.c
index 32c467880..39c0d9860 100644
--- a/vnc.c
+++ b/vnc.c
@@ -1506,11 +1506,13 @@ static void do_key_event(VncState *vs, int down, int keycode, int sym)
static void key_event(VncState *vs, int down, uint32_t sym)
{
int keycode;
+ int lsym = sym;
- if (sym >= 'A' && sym <= 'Z' && is_graphic_console())
- sym = sym - 'A' + 'a';
+ if (lsym >= 'A' && lsym <= 'Z' && is_graphic_console()) {
+ lsym = lsym - 'A' + 'a';
+ }
- keycode = keysym2scancode(vs->vd->kbd_layout, sym & 0xFFFF);
+ keycode = keysym2scancode(vs->vd->kbd_layout, lsym & 0xFFFF);
do_key_event(vs, down, keycode, sym);
}