summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--MAINTAINERS9
-rw-r--r--Makefile1
-rw-r--r--Makefile.objs6
-rw-r--r--Makefile.target2
-rw-r--r--QMP/qmp.py6
-rwxr-xr-xQMP/qom-get67
-rwxr-xr-xQMP/qom-list64
-rwxr-xr-xQMP/qom-set64
-rw-r--r--blockdev.c3
-rw-r--r--console.c26
-rw-r--r--console.h2
-rw-r--r--default-configs/i386-softmmu.mak1
-rw-r--r--default-configs/mips-softmmu.mak1
-rw-r--r--default-configs/mips64-softmmu.mak1
-rw-r--r--default-configs/mips64el-softmmu.mak1
-rw-r--r--default-configs/mipsel-softmmu.mak1
-rw-r--r--default-configs/x86_64-softmmu.mak1
-rw-r--r--hw/baum.c7
-rw-r--r--hw/baum.h2
-rw-r--r--hw/boards.h1
-rw-r--r--hw/jazz_led.c177
-rw-r--r--hw/mips.h3
-rw-r--r--hw/mips_jazz.c2
-rw-r--r--hw/msmouse.c5
-rw-r--r--hw/msmouse.h2
-rw-r--r--hw/pc.c56
-rw-r--r--hw/pc.h3
-rw-r--r--hw/pc_piix.c62
-rw-r--r--hw/pc_sysfw.c254
-rw-r--r--hw/pci.c15
-rw-r--r--hw/pci.h61
-rw-r--r--hw/pflash_cfi01.c44
-rw-r--r--hw/pflash_cfi02.c83
-rw-r--r--hw/qdev-properties.c186
-rw-r--r--hw/qxl-render.c12
-rw-r--r--hw/qxl.c109
-rw-r--r--hw/qxl.h4
-rw-r--r--include/qemu/object.h28
-rw-r--r--monitor.c9
-rw-r--r--qapi/qapi-visit-core.c51
-rw-r--r--qapi/qapi-visit-impl.h23
-rw-r--r--qapi/qmp-input-visitor.c39
-rw-r--r--qapi/qmp-output-visitor.c22
-rw-r--r--qapi/string-input-visitor.c138
-rw-r--r--qapi/string-input-visitor.h25
-rw-r--r--qapi/string-output-visitor.c89
-rw-r--r--qapi/string-output-visitor.h26
-rw-r--r--qemu-char.c140
-rw-r--r--qemu-config.c12
-rw-r--r--qemu-sockets.c55
-rw-r--r--qmp-commands.hx6
-rw-r--r--qom/object.c38
-rw-r--r--spice-qemu-char.c9
-rw-r--r--sysconfigs/target/target-x86_64.conf52
-rw-r--r--target-i386/cpuid.c72
-rw-r--r--test-string-input-visitor.c195
-rw-r--r--test-string-output-visitor.c188
-rw-r--r--tests/Makefile12
-rw-r--r--trace-events4
-rw-r--r--ui/qemu-spice.h9
-rw-r--r--ui/spice-core.c50
-rw-r--r--vl.c40
63 files changed, 1974 insertions, 704 deletions
diff --git a/.gitignore b/.gitignore
index f5aab2cb07..c72955aad1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -44,6 +44,8 @@ QMP/qmp-commands.txt
test-coroutine
test-qmp-input-visitor
test-qmp-output-visitor
+test-string-input-visitor
+test-string-output-visitor
fsdev/virtfs-proxy-helper.1
fsdev/virtfs-proxy-helper.pod
.gdbinit
diff --git a/MAINTAINERS b/MAINTAINERS
index 647c41363d..0b3b3d8dc6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -420,11 +420,16 @@ F: hw/pci*
F: hw/piix*
SCSI
+M: Paolo Bonzini <pbonzini@redhat.com>
+S: Supported
+F: hw/virtio-scsi.*
+F: hw/scsi*
+T: git://github.com/bonzini/qemu.git scsi-next
+
+LSI53C895A
M: Paul Brook <paul@codesourcery.com>
-M: Kevin Wolf <kwolf@redhat.com>
S: Odd Fixes
F: hw/lsi53c895a.c
-F: hw/scsi*
USB
M: Gerd Hoffmann <kraxel@redhat.com>
diff --git a/Makefile b/Makefile
index e66e885d1b..c67493e184 100644
--- a/Makefile
+++ b/Makefile
@@ -159,6 +159,7 @@ qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
qemu-bridge-helper$(EXESUF): qemu-bridge-helper.o
+qemu-bridge-helper.o: $(GENERATED_HEADERS)
fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y)
fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
diff --git a/Makefile.objs b/Makefile.objs
index 391e524525..67ee3df828 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -250,6 +250,7 @@ hw-obj-$(CONFIG_PPCE500_PCI) += ppce500_pci.o
# MIPS devices
hw-obj-$(CONFIG_PIIX4) += piix4.o
hw-obj-$(CONFIG_G364FB) += g364fb.o
+hw-obj-$(CONFIG_JAZZ_LED) += jazz_led.o
# PCI watchdog devices
hw-obj-$(CONFIG_PCI) += wdt_i6300esb.o
@@ -412,8 +413,9 @@ libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o
######################################################################
# qapi
-qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-dealloc-visitor.o
-qapi-nested-y += qmp-registry.o qmp-dispatch.o
+qapi-nested-y = qapi-visit-core.o qapi-dealloc-visitor.o qmp-input-visitor.o
+qapi-nested-y += qmp-output-visitor.o qmp-registry.o qmp-dispatch.o
+qapi-nested-y += string-input-visitor.o string-output-visitor.o
qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y))
common-obj-y += qmp-marshal.o qapi-visit.o qapi-types.o $(qapi-obj-y)
diff --git a/Makefile.target b/Makefile.target
index eef4accb27..68a5641183 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -242,6 +242,7 @@ obj-i386-y += vmport.o
obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
obj-i386-y += debugcon.o multiboot.o
obj-i386-y += pc_piix.o
+obj-i386-y += pc_sysfw.o
obj-i386-$(CONFIG_KVM) += kvm/clock.o kvm/apic.o kvm/i8259.o kvm/ioapic.o
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
@@ -300,7 +301,6 @@ obj-lm32-y += framebuffer.o
obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
obj-mips-y += mips_addr.o mips_timer.o mips_int.o
-obj-mips-y += jazz_led.o
obj-mips-y += gt64xxx.o mc146818rtc.o
obj-mips-$(CONFIG_FULONG) += bonito.o vt82c686.o mips_fulong2e.o
diff --git a/QMP/qmp.py b/QMP/qmp.py
index c7dbea076d..36ecc1dfae 100644
--- a/QMP/qmp.py
+++ b/QMP/qmp.py
@@ -128,6 +128,12 @@ class QEMUMonitorProtocol:
qmp_cmd['id'] = id
return self.cmd_obj(qmp_cmd)
+ def command(self, cmd, **kwds):
+ ret = self.cmd(cmd, kwds)
+ if ret.has_key('error'):
+ raise Exception(ret['error']['desc'])
+ return ret['return']
+
def get_events(self, wait=False):
"""
Get a list of available QMP events.
diff --git a/QMP/qom-get b/QMP/qom-get
new file mode 100755
index 0000000000..0172c69441
--- /dev/null
+++ b/QMP/qom-get
@@ -0,0 +1,67 @@
+#!/usr/bin/python
+##
+# QEMU Object Model test tools
+#
+# Copyright IBM, Corp. 2011
+#
+# Authors:
+# Anthony Liguori <aliguori@us.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later. See
+# the COPYING file in the top-level directory.
+##
+
+import sys
+import os
+from qmp import QEMUMonitorProtocol
+
+cmd, args = sys.argv[0], sys.argv[1:]
+socket_path = None
+path = None
+prop = None
+
+def usage():
+ return '''environment variables:
+ QMP_SOCKET=<path | addr:port>
+usage:
+ %s [-h] [-s <QMP socket path | addr:port>] <path>.<property>
+''' % cmd
+
+def usage_error(error_msg = "unspecified error"):
+ sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg))
+ exit(1)
+
+if len(args) > 0:
+ if args[0] == "-h":
+ print usage()
+ exit(0);
+ elif args[0] == "-s":
+ try:
+ socket_path = args[1]
+ except:
+ usage_error("missing argument: QMP socket path or address");
+ args = args[2:]
+
+if not socket_path:
+ if os.environ.has_key('QMP_SOCKET'):
+ socket_path = os.environ['QMP_SOCKET']
+ else:
+ usage_error("no QMP socket path or address given");
+
+if len(args) > 0:
+ try:
+ path, prop = args[0].rsplit('.', 1)
+ except:
+ usage_error("invalid format for path/property/value")
+else:
+ usage_error("not enough arguments")
+
+srv = QEMUMonitorProtocol(socket_path)
+srv.connect()
+
+rsp = srv.command('qom-get', path=path, property=prop)
+if type(rsp) == dict:
+ for i in rsp.keys():
+ print '%s: %s' % (i, rsp[i])
+else:
+ print rsp
diff --git a/QMP/qom-list b/QMP/qom-list
new file mode 100755
index 0000000000..1e7cc6cb2d
--- /dev/null
+++ b/QMP/qom-list
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+##
+# QEMU Object Model test tools
+#
+# Copyright IBM, Corp. 2011
+#
+# Authors:
+# Anthony Liguori <aliguori@us.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later. See
+# the COPYING file in the top-level directory.
+##
+
+import sys
+import os
+from qmp import QEMUMonitorProtocol
+
+cmd, args = sys.argv[0], sys.argv[1:]
+socket_path = None
+path = None
+prop = None
+
+def usage():
+ return '''environment variables:
+ QMP_SOCKET=<path | addr:port>
+usage:
+ %s [-h] [-s <QMP socket path | addr:port>] [<path>]
+''' % cmd
+
+def usage_error(error_msg = "unspecified error"):
+ sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg))
+ exit(1)
+
+if len(args) > 0:
+ if args[0] == "-h":
+ print usage()
+ exit(0);
+ elif args[0] == "-s":
+ try:
+ socket_path = args[1]
+ except:
+ usage_error("missing argument: QMP socket path or address");
+ args = args[2:]
+
+if not socket_path:
+ if os.environ.has_key('QMP_SOCKET'):
+ socket_path = os.environ['QMP_SOCKET']
+ else:
+ usage_error("no QMP socket path or address given");
+
+srv = QEMUMonitorProtocol(socket_path)
+srv.connect()
+
+if len(args) == 0:
+ print '/'
+ sys.exit(0)
+
+for item in srv.command('qom-list', path=args[0]):
+ if item['type'].startswith('child<'):
+ print '%s/' % item['name']
+ elif item['type'].startswith('link<'):
+ print '@%s/' % item['name']
+ else:
+ print '%s' % item['name']
diff --git a/QMP/qom-set b/QMP/qom-set
new file mode 100755
index 0000000000..54ecfecc53
--- /dev/null
+++ b/QMP/qom-set
@@ -0,0 +1,64 @@
+#!/usr/bin/python
+##
+# QEMU Object Model test tools
+#
+# Copyright IBM, Corp. 2011
+#
+# Authors:
+# Anthony Liguori <aliguori@us.ibm.com>
+#
+# This work is licensed under the terms of the GNU GPL, version 2 or later. See
+# the COPYING file in the top-level directory.
+##
+
+import sys
+import os
+from qmp import QEMUMonitorProtocol
+
+cmd, args = sys.argv[0], sys.argv[1:]
+socket_path = None
+path = None
+prop = None
+value = None
+
+def usage():
+ return '''environment variables:
+ QMP_SOCKET=<path | addr:port>
+usage:
+ %s [-h] [-s <QMP socket path | addr:port>] <path>.<property> <value>
+''' % cmd
+
+def usage_error(error_msg = "unspecified error"):
+ sys.stderr.write('%s\nERROR: %s\n' % (usage(), error_msg))
+ exit(1)
+
+if len(args) > 0:
+ if args[0] == "-h":
+ print usage()
+ exit(0);
+ elif args[0] == "-s":
+ try:
+ socket_path = args[1]
+ except:
+ usage_error("missing argument: QMP socket path or address");
+ args = args[2:]
+
+if not socket_path:
+ if os.environ.has_key('QMP_SOCKET'):
+ socket_path = os.environ['QMP_SOCKET']
+ else:
+ usage_error("no QMP socket path or address given");
+
+if len(args) > 1:
+ try:
+ path, prop = args[0].rsplit('.', 1)
+ except:
+ usage_error("invalid format for path/property/value")
+ value = args[1]
+else:
+ usage_error("not enough arguments")
+
+srv = QEMUMonitorProtocol(socket_path)
+srv.connect()
+
+print srv.command('qom-set', path=path, property=prop, value=sys.argv[2])
diff --git a/blockdev.c b/blockdev.c
index 7a6613a2d2..2c132a308b 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -595,7 +595,8 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
/* CDROM is fine for any interface, don't check. */
ro = 1;
} else if (ro == 1) {
- if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
+ if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY &&
+ type != IF_NONE && type != IF_PFLASH) {
error_report("readonly not supported by this bus type");
goto err;
}
diff --git a/console.c b/console.c
index 135394f6f6..744ef2d810 100644
--- a/console.c
+++ b/console.c
@@ -1441,9 +1441,6 @@ void console_color_init(DisplayState *ds)
}
}
-static int n_text_consoles;
-static CharDriverState *text_consoles[128];
-
static void text_console_set_echo(CharDriverState *chr, bool echo)
{
TextConsole *s = chr->opaque;
@@ -1510,7 +1507,7 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
chr->init(chr);
}
-int text_console_init(QemuOpts *opts, CharDriverState **_chr)
+CharDriverState *text_console_init(QemuOpts *opts)
{
CharDriverState *chr;
TextConsole *s;
@@ -1519,13 +1516,6 @@ int text_console_init(QemuOpts *opts, CharDriverState **_chr)
chr = g_malloc0(sizeof(CharDriverState));
- if (n_text_consoles == 128) {
- fprintf(stderr, "Too many text consoles\n");
- exit(1);
- }
- text_consoles[n_text_consoles] = chr;
- n_text_consoles++;
-
width = qemu_opt_get_number(opts, "width", 0);
if (width == 0)
width = qemu_opt_get_number(opts, "cols", 0) * FONT_WIDTH;
@@ -1542,7 +1532,7 @@ int text_console_init(QemuOpts *opts, CharDriverState **_chr)
if (!s) {
g_free(chr);
- return -EBUSY;
+ return NULL;
}
s->chr = chr;
@@ -1550,20 +1540,18 @@ int text_console_init(QemuOpts *opts, CharDriverState **_chr)
s->g_height = height;
chr->opaque = s;
chr->chr_set_echo = text_console_set_echo;
-
- *_chr = chr;
- return 0;
+ return chr;
}
void text_consoles_set_display(DisplayState *ds)
{
int i;
- for (i = 0; i < n_text_consoles; i++) {
- text_console_do_init(text_consoles[i], ds);
+ for (i = 0; i < nb_consoles; i++) {
+ if (consoles[i]->console_type != GRAPHIC_CONSOLE) {
+ text_console_do_init(consoles[i]->chr, ds);
+ }
}
-
- n_text_consoles = 0;
}
void qemu_console_resize(DisplayState *ds, int width, int height)
diff --git a/console.h b/console.h
index 6ba0d5ddf3..c33ffe0007 100644
--- a/console.h
+++ b/console.h
@@ -356,7 +356,7 @@ void vga_hw_text_update(console_ch_t *chardata);
int is_graphic_console(void);
int is_fixedsize_console(void);
-int text_console_init(QemuOpts *opts, CharDriverState **_chr);
+CharDriverState *text_console_init(QemuOpts *opts);
void text_consoles_set_display(DisplayState *ds);
void console_select(unsigned int index);
void console_color_init(DisplayState *ds);
diff --git a/default-configs/i386-softmmu.mak b/default-configs/i386-softmmu.mak
index 662348ef11..2c78175ae7 100644
--- a/default-configs/i386-softmmu.mak
+++ b/default-configs/i386-softmmu.mak
@@ -24,3 +24,4 @@ CONFIG_SOUND=y
CONFIG_HPET=y
CONFIG_APPLESMC=y
CONFIG_I8259=y
+CONFIG_PFLASH_CFI01=y
diff --git a/default-configs/mips-softmmu.mak b/default-configs/mips-softmmu.mak
index 308d04aeab..a271b1c6da 100644
--- a/default-configs/mips-softmmu.mak
+++ b/default-configs/mips-softmmu.mak
@@ -30,3 +30,4 @@ CONFIG_MIPSNET=y
CONFIG_PFLASH_CFI01=y
CONFIG_G364FB=y
CONFIG_I8259=y
+CONFIG_JAZZ_LED=y
diff --git a/default-configs/mips64-softmmu.mak b/default-configs/mips64-softmmu.mak
index f1b92da8a3..0510bb6a53 100644
--- a/default-configs/mips64-softmmu.mak
+++ b/default-configs/mips64-softmmu.mak
@@ -30,3 +30,4 @@ CONFIG_MIPSNET=y
CONFIG_PFLASH_CFI01=y
CONFIG_G364FB=y
CONFIG_I8259=y
+CONFIG_JAZZ_LED=y
diff --git a/default-configs/mips64el-softmmu.mak b/default-configs/mips64el-softmmu.mak
index 567396c84f..ed3bed3b8d 100644
--- a/default-configs/mips64el-softmmu.mak
+++ b/default-configs/mips64el-softmmu.mak
@@ -32,3 +32,4 @@ CONFIG_PFLASH_CFI01=y
CONFIG_FULONG=y
CONFIG_G364FB=y
CONFIG_I8259=y
+CONFIG_JAZZ_LED=y
diff --git a/default-configs/mipsel-softmmu.mak b/default-configs/mipsel-softmmu.mak
index a8e421b151..fa3a2cacdd 100644
--- a/default-configs/mipsel-softmmu.mak
+++ b/default-configs/mipsel-softmmu.mak
@@ -30,3 +30,4 @@ CONFIG_MIPSNET=y
CONFIG_PFLASH_CFI01=y
CONFIG_G364FB=y
CONFIG_I8259=y
+CONFIG_JAZZ_LED=y
diff --git a/default-configs/x86_64-softmmu.mak b/default-configs/x86_64-softmmu.mak
index b445be2059..233a8564eb 100644
--- a/default-configs/x86_64-softmmu.mak
+++ b/default-configs/x86_64-softmmu.mak
@@ -24,3 +24,4 @@ CONFIG_SOUND=y
CONFIG_HPET=y
CONFIG_APPLESMC=y
CONFIG_I8259=y
+CONFIG_PFLASH_CFI01=y
diff --git a/hw/baum.c b/hw/baum.c
index 86d780a617..3e94f84e51 100644
--- a/hw/baum.c
+++ b/hw/baum.c
@@ -562,7 +562,7 @@ static void baum_close(struct CharDriverState *chr)
g_free(baum);
}
-int chr_baum_init(QemuOpts *opts, CharDriverState **_chr)
+CharDriverState *chr_baum_init(QemuOpts *opts)
{
BaumDriverState *baum;
CharDriverState *chr;
@@ -614,8 +614,7 @@ int chr_baum_init(QemuOpts *opts, CharDriverState **_chr)
qemu_chr_generic_open(chr);
- *_chr = chr;
- return 0;
+ return chr;
fail:
qemu_free_timer(baum->cellCount_timer);
@@ -624,5 +623,5 @@ fail_handle:
g_free(handle);
g_free(chr);
g_free(baum);
- return -EIO;
+ return NULL;
}
diff --git a/hw/baum.h b/hw/baum.h
index 3f28cc339a..8af710fa21 100644
--- a/hw/baum.h
+++ b/hw/baum.h
@@ -23,4 +23,4 @@
*/
/* char device */
-int chr_baum_init(QemuOpts *opts, CharDriverState **_chr);
+CharDriverState *chr_baum_init(QemuOpts *opts);
diff --git a/hw/boards.h b/hw/boards.h
index f6d3784cf1..667177d76d 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -32,6 +32,7 @@ typedef struct QEMUMachine {
} QEMUMachine;
int qemu_register_machine(QEMUMachine *m);
+QEMUMachine *find_default_machine(void);
extern QEMUMachine *current_machine;
diff --git a/hw/jazz_led.c b/hw/jazz_led.c
index f8a218252c..5d8040be30 100644
--- a/hw/jazz_led.c
+++ b/hw/jazz_led.c
@@ -1,7 +1,7 @@
/*
* QEMU JAZZ LED emulator.
*
- * Copyright (c) 2007 Hervé Poussineau
+ * Copyright (c) 2007-2012 Herve Poussineau
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@@ -22,131 +22,53 @@
* THE SOFTWARE.
*/
-#include "hw.h"
-#include "mips.h"
#include "console.h"
#include "pixel_ops.h"
-
-//#define DEBUG_LED
-
-#ifdef DEBUG_LED
-#define DPRINTF(fmt, ...) \
-do { printf("jazz led: " fmt , ## __VA_ARGS__); } while (0)
-#else
-#define DPRINTF(fmt, ...) do {} while (0)
-#endif
-#define BADF(fmt, ...) \
-do { fprintf(stderr, "jazz led ERROR: " fmt , ## __VA_ARGS__);} while (0)
+#include "trace.h"
+#include "sysbus.h"
typedef enum {
REDRAW_NONE = 0, REDRAW_SEGMENTS = 1, REDRAW_BACKGROUND = 2,
} screen_state_t;
typedef struct LedState {
+ SysBusDevice busdev;
MemoryRegion iomem;
uint8_t segments;
DisplayState *ds;
screen_state_t state;
} LedState;
-static uint32_t led_readb(void *opaque, target_phys_addr_t addr)
+static uint64_t jazz_led_read(void *opaque, target_phys_addr_t addr,
+ unsigned int size)
{
LedState *s = opaque;
- uint32_t val;
-
- switch (addr) {
- case 0:
- val = s->segments;
- break;
- default:
- BADF("invalid read at [" TARGET_FMT_plx "]\n", addr);
- val = 0;
- }
+ uint8_t val;
- DPRINTF("read addr=" TARGET_FMT_plx " val=0x%02x\n", addr, val);
+ val = s->segments;
+ trace_jazz_led_read(addr, val);
return val;
}
-static uint32_t led_readw(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = led_readb(opaque, addr) << 8;
- v |= led_readb(opaque, addr + 1);
-#else
- v = led_readb(opaque, addr);
- v |= led_readb(opaque, addr + 1) << 8;
-#endif
- return v;
-}
-
-static uint32_t led_readl(void *opaque, target_phys_addr_t addr)
-{
- uint32_t v;
-#ifdef TARGET_WORDS_BIGENDIAN
- v = led_readb(opaque, addr) << 24;
- v |= led_readb(opaque, addr + 1) << 16;
- v |= led_readb(opaque, addr + 2) << 8;
- v |= led_readb(opaque, addr + 3);
-#else
- v = led_readb(opaque, addr);
- v |= led_readb(opaque, addr + 1) << 8;
- v |= led_readb(opaque, addr + 2) << 16;
- v |= led_readb(opaque, addr + 3) << 24;
-#endif
- return v;
-}
-
-static void led_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+static void jazz_led_write(void *opaque, target_phys_addr_t addr,
+ uint64_t val, unsigned int size)
{
LedState *s = opaque;
+ uint8_t new_val = val & 0xff;
- DPRINTF("write addr=" TARGET_FMT_plx " val=0x%02x\n", addr, val);
+ trace_jazz_led_write(addr, new_val);
- switch (addr) {
- case 0:
- s->segments = val;
- s->state |= REDRAW_SEGMENTS;
- break;
- default:
- BADF("invalid write of 0x%08x at [" TARGET_FMT_plx "]\n", val, addr);
- break;
- }
-}
-
-static void led_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- led_writeb(opaque, addr, (val >> 8) & 0xff);
- led_writeb(opaque, addr + 1, val & 0xff);
-#else
- led_writeb(opaque, addr, val & 0xff);
- led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
-#endif
-}
-
-static void led_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
-{
-#ifdef TARGET_WORDS_BIGENDIAN
- led_writeb(opaque, addr, (val >> 24) & 0xff);
- led_writeb(opaque, addr + 1, (val >> 16) & 0xff);
- led_writeb(opaque, addr + 2, (val >> 8) & 0xff);
- led_writeb(opaque, addr + 3, val & 0xff);
-#else
- led_writeb(opaque, addr, val & 0xff);
- led_writeb(opaque, addr + 1, (val >> 8) & 0xff);
- led_writeb(opaque, addr + 2, (val >> 16) & 0xff);
- led_writeb(opaque, addr + 3, (val >> 24) & 0xff);
-#endif
+ s->segments = new_val;
+ s->state |= REDRAW_SEGMENTS;
}
static const MemoryRegionOps led_ops = {
- .old_mmio = {
- .read = { led_readb, led_readw, led_readl, },
- .write = { led_writeb, led_writew, led_writel, },
- },
+ .read = jazz_led_read,
+ .write = jazz_led_write,
.endianness = DEVICE_NATIVE_ENDIAN,
+ .impl.min_access_size = 1,
+ .impl.max_access_size = 1,
};
/***********************************************************/
@@ -304,20 +226,71 @@ static void jazz_led_text_update(void *opaque, console_ch_t *chardata)
dpy_update(s->ds, 0, 0, 2, 1);
}
-void jazz_led_init(MemoryRegion *address_space, target_phys_addr_t base)
+static int jazz_led_post_load(void *opaque, int version_id)
{
- LedState *s;
+ /* force refresh */
+ jazz_led_invalidate_display(opaque);
+
+ return 0;
+}
- s = g_malloc0(sizeof(LedState));
+static const VMStateDescription vmstate_jazz_led = {
+ .name = "jazz-led",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .minimum_version_id_old = 0,
+ .post_load = jazz_led_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT8(segments, LedState),
+ VMSTATE_END_OF_LIST()
+ }
+};
- s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
+static int jazz_led_init(SysBusDevice *dev)
+{
+ LedState *s = FROM_SYSBUS(LedState, dev);
memory_region_init_io(&s->iomem, &led_ops, s, "led", 1);
- memory_region_add_subregion(address_space, base, &s->iomem);
+ sysbus_init_mmio(dev, &s->iomem);
s->ds = graphic_console_init(jazz_led_update_display,
jazz_led_invalidate_display,
jazz_led_screen_dump,
jazz_led_text_update, s);
+
+ return 0;
+}
+
+static void jazz_led_reset(DeviceState *d)
+{
+ LedState *s = DO_UPCAST(LedState, busdev.qdev, d);
+
+ s->segments = 0;
+ s->state = REDRAW_SEGMENTS | REDRAW_BACKGROUND;
qemu_console_resize(s->ds, 60, 80);
}
+
+static void jazz_led_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+
+ k->init = jazz_led_init;
+ dc->desc = "Jazz LED display",
+ dc->vmsd = &vmstate_jazz_led;
+ dc->reset = jazz_led_reset;
+}
+
+static TypeInfo jazz_led_info = {
+ .name = "jazz-led",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(LedState),
+ .class_init = jazz_led_class_init,
+};
+
+static void jazz_led_register(void)
+{
+ type_register_static(&jazz_led_info);
+}
+
+type_init(jazz_led_register);
diff --git a/hw/mips.h b/hw/mips.h
index 22156fce53..a7e6d4cc62 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -10,9 +10,6 @@ PCIBus *gt64120_register(qemu_irq *pic);
/* bonito.c */
PCIBus *bonito_init(qemu_irq *pic);
-/* jazz_led.c */
-void jazz_led_init(MemoryRegion *address_space, target_phys_addr_t base);
-
/* rc4030.c */
typedef struct rc4030DMAState *rc4030_dma;
void rc4030_dma_memory_rw(void *opaque, target_phys_addr_t addr, uint8_t *buf, int len, int is_write);
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 65608dc644..2b4678e170 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -295,7 +295,7 @@ static void mips_jazz_init(MemoryRegion *address_space,
sysbus_mmio_map(sysbus, 0, 0x80009000);
/* LED indicator */
- jazz_led_init(address_space, 0x8000f000);
+ sysbus_create_simple("jazz-led", 0x8000f000, NULL);
}
static
diff --git a/hw/msmouse.c b/hw/msmouse.c
index c3b57ea31c..9c492a4637 100644
--- a/hw/msmouse.c
+++ b/hw/msmouse.c
@@ -64,7 +64,7 @@ static void msmouse_chr_close (struct CharDriverState *chr)
g_free (chr);
}
-int qemu_chr_open_msmouse(QemuOpts *opts, CharDriverState **_chr)
+CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts)
{
CharDriverState *chr;
@@ -74,6 +74,5 @@ int qemu_chr_open_msmouse(QemuOpts *opts, CharDriverState **_chr)
qemu_add_mouse_event_handler(msmouse_event, chr, 0, "QEMU Microsoft Mouse");
- *_chr = chr;
- return 0;
+ return chr;
}
diff --git a/hw/msmouse.h b/hw/msmouse.h
index 8b853b35bf..456cb21424 100644
--- a/hw/msmouse.h
+++ b/hw/msmouse.h
@@ -1,2 +1,2 @@
/* msmouse.c */
-int qemu_chr_open_msmouse(QemuOpts *opts, CharDriverState **_chr);
+CharDriverState *qemu_chr_open_msmouse(QemuOpts *opts);
diff --git a/hw/pc.c b/hw/pc.c
index 57461291ef..b9f4bc72d7 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -60,10 +60,6 @@
#define DPRINTF(fmt, ...)
#endif
-#define BIOS_FILENAME "bios.bin"
-
-#define PC_MAX_BIOS_SIZE (4 * 1024 * 1024)
-
/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */
#define ACPI_DATA_SIZE 0x10000
#define BIOS_CFG_IOPORT 0x510
@@ -990,11 +986,9 @@ void pc_memory_init(MemoryRegion *system_memory,
MemoryRegion *rom_memory,
MemoryRegion **ram_memory)
{
- char *filename;
- int ret, linux_boot, i;
- MemoryRegion *ram, *bios, *isa_bios, *option_rom_mr;
+ int linux_boot, i;
+ MemoryRegion *ram, *option_rom_mr;
MemoryRegion *ram_below_4g, *ram_above_4g;
- int bios_size, isa_bios_size;
void *fw_cfg;
linux_boot = (kernel_filename != NULL);
@@ -1020,44 +1014,9 @@ void pc_memory_init(MemoryRegion *system_memory,
ram_above_4g);
}
- /* BIOS load */
- if (bios_name == NULL)
- bios_name = BIOS_FILENAME;
- filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
- if (filename) {
- bios_size = get_image_size(filename);
- } else {
- bios_size = -1;
- }
- if (bios_size <= 0 ||
- (bios_size % 65536) != 0) {
- goto bios_error;
- }
- bios = g_malloc(sizeof(*bios));
- memory_region_init_ram(bios, "pc.bios", bios_size);
- vmstate_register_ram_global(bios);
- memory_region_set_readonly(bios, true);
- ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
- if (ret != 0) {
- bios_error:
- fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name);
- exit(1);
- }
- if (filename) {
- g_free(filename);
- }
- /* map the last 128KB of the BIOS in ISA space */
- isa_bios_size = bios_size;
- if (isa_bios_size > (128 * 1024))
- isa_bios_size = 128 * 1024;
- isa_bios = g_malloc(sizeof(*isa_bios));
- memory_region_init_alias(isa_bios, "isa-bios", bios,
- bios_size - isa_bios_size, isa_bios_size);
- memory_region_add_subregion_overlap(rom_memory,
- 0x100000 - isa_bios_size,
- isa_bios,
- 1);
- memory_region_set_readonly(isa_bios, true);
+
+ /* Initialize PC system firmware */
+ pc_system_firmware_init(rom_memory);
option_rom_mr = g_malloc(sizeof(*option_rom_mr));
memory_region_init_ram(option_rom_mr, "pc.rom", PC_ROM_SIZE);
@@ -1067,11 +1026,6 @@ void pc_memory_init(MemoryRegion *system_memory,
option_rom_mr,
1);
- /* map all the bios at the top of memory */
- memory_region_add_subregion(rom_memory,
- (uint32_t)(-bios_size),
- bios);
-
fw_cfg = bochs_bios_init();
rom_set_fw(fw_cfg);
diff --git a/hw/pc.h b/hw/pc.h
index 1b47bbdb0e..71f7df30aa 100644
--- a/hw/pc.h
+++ b/hw/pc.h
@@ -216,6 +216,9 @@ static inline bool isa_ne2000_init(ISABus *bus, int base, int irq, NICInfo *nd)
return true;
}
+/* pc_sysfw.c */
+void pc_system_firmware_init(MemoryRegion *rom_memory);
+
/* e820 types */
#define E820_RAM 1
#define E820_RESERVED 2
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 17f8d5d593..fe7a729472 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -371,8 +371,8 @@ static void pc_xen_hvm_init(ram_addr_t ram_size,
}
#endif
-static QEMUMachine pc_machine_v1_0 = {
- .name = "pc-1.0",
+static QEMUMachine pc_machine_v1_1 = {
+ .name = "pc-1.1",
.alias = "pc",
.desc = "Standard PC",
.init = pc_init_pci,
@@ -380,12 +380,34 @@ static QEMUMachine pc_machine_v1_0 = {
.is_default = 1,
};
+static QEMUMachine pc_machine_v1_0 = {
+ .name = "pc-1.0",
+ .desc = "Standard PC",
+ .init = pc_init_pci,
+ .max_cpus = 255,
+ .compat_props = (GlobalProperty[]) {
+ {
+ .driver = "pc-sysfw",
+ .property = "rom_only",
+ .value = stringify(1),
+ },
+ { /* end of list */ }
+ },
+};
+
static QEMUMachine pc_machine_v0_15 = {
.name = "pc-0.15",
.desc = "Standard PC",
.init = pc_init_pci,
.max_cpus = 255,
- .is_default = 1,
+ .compat_props = (GlobalProperty[]) {
+ {
+ .driver = "pc-sysfw",
+ .property = "rom_only",
+ .value = stringify(1),
+ },
+ { /* end of list */ }
+ },
};
static QEMUMachine pc_machine_v0_14 = {
@@ -419,6 +441,11 @@ static QEMUMachine pc_machine_v0_14 = {
.property = "event_idx",
.value = "off",
},
+ {
+ .driver = "pc-sysfw",
+ .property = "rom_only",
+ .value = stringify(1),
+ },
{ /* end of list */ }
},
};
@@ -466,6 +493,11 @@ static QEMUMachine pc_machine_v0_13 = {
.property = "use_broken_id",
.value = stringify(1),
},
+ {
+ .driver = "pc-sysfw",
+ .property = "rom_only",
+ .value = stringify(1),
+ },
{ /* end of list */ }
},
};
@@ -517,6 +549,11 @@ static QEMUMachine pc_machine_v0_12 = {
.property = "use_broken_id",
.value = stringify(1),
},
+ {
+ .driver = "pc-sysfw",
+ .property = "rom_only",
+ .value = stringify(1),
+ },
{ /* end of list */ }
}
};
@@ -576,6 +613,11 @@ static QEMUMachine pc_machine_v0_11 = {
.property = "use_broken_id",
.value = stringify(1),
},
+ {
+ .driver = "pc-sysfw",
+ .property = "rom_only",
+ .value = stringify(1),
+ },
{ /* end of list */ }
}
};
@@ -647,6 +689,11 @@ static QEMUMachine pc_machine_v0_10 = {
.property = "use_broken_id",
.value = stringify(1),
},
+ {
+ .driver = "pc-sysfw",
+ .property = "rom_only",
+ .value = stringify(1),
+ },
{ /* end of list */ }
},
};
@@ -656,6 +703,14 @@ static QEMUMachine isapc_machine = {
.desc = "ISA-only PC",
.init = pc_init_isa,
.max_cpus = 1,
+ .compat_props = (GlobalProperty[]) {
+ {
+ .driver = "pc-sysfw",
+ .property = "rom_only",
+ .value = stringify(1),
+ },
+ { /* end of list */ }
+ },
};
#ifdef CONFIG_XEN
@@ -670,6 +725,7 @@ static QEMUMachine xenfv_machine = {
static void pc_machine_init(void)
{
+ qemu_register_machine(&pc_machine_v1_1);
qemu_register_machine(&pc_machine_v1_0);
qemu_register_machine(&pc_machine_v0_15);
qemu_register_machine(&pc_machine_v0_14);
diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c
new file mode 100644
index 0000000000..abf9004182
--- /dev/null
+++ b/hw/pc_sysfw.c
@@ -0,0 +1,254 @@
+/*
+ * QEMU PC System Firmware
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2011-2012 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "hw.h"
+#include "pc.h"
+#include "hw/boards.h"
+#include "loader.h"
+#include "sysemu.h"
+#include "flash.h"
+#include "kvm.h"
+
+#define BIOS_FILENAME "bios.bin"
+
+typedef struct PcSysFwDevice {
+ SysBusDevice busdev;
+ uint8_t rom_only;
+} PcSysFwDevice;
+
+static void pc_isa_bios_init(MemoryRegion *rom_memory,
+ MemoryRegion *flash_mem,
+ int ram_size)
+{
+ int isa_bios_size;
+ MemoryRegion *isa_bios;
+ uint64_t flash_size;
+ void *flash_ptr, *isa_bios_ptr;
+
+ flash_size = memory_region_size(flash_mem);
+
+ /* map the last 128KB of the BIOS in ISA space */
+ isa_bios_size = flash_size;
+ if (isa_bios_size > (128 * 1024)) {
+ isa_bios_size = 128 * 1024;
+ }
+ isa_bios = g_malloc(sizeof(*isa_bios));
+ memory_region_init_ram(isa_bios, "isa-bios", isa_bios_size);
+ vmstate_register_ram_global(isa_bios);
+ memory_region_add_subregion_overlap(rom_memory,
+ 0x100000 - isa_bios_size,
+ isa_bios,
+ 1);
+
+ /* copy ISA rom image from top of flash memory */
+ flash_ptr = memory_region_get_ram_ptr(flash_mem);
+ isa_bios_ptr = memory_region_get_ram_ptr(isa_bios);
+ memcpy(isa_bios_ptr,
+ ((uint8_t*)flash_ptr) + (flash_size - isa_bios_size),
+ isa_bios_size);
+
+ memory_region_set_readonly(isa_bios, true);
+}
+
+static void pc_fw_add_pflash_drv(void)
+{
+ QemuOpts *opts;
+ QEMUMachine *machine;
+ char *filename;
+
+ if (bios_name == NULL) {
+ bios_name = BIOS_FILENAME;
+ }
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+
+ opts = drive_add(IF_PFLASH, -1, filename, "readonly=on");
+ if (opts == NULL) {
+ return;
+ }
+
+ machine = find_default_machine();
+ if (machine == NULL) {
+ return;
+ }
+
+ drive_init(opts, machine->use_scsi);
+}
+
+static void pc_system_flash_init(MemoryRegion *rom_memory,
+ DriveInfo *pflash_drv)
+{
+ BlockDriverState *bdrv;
+ int64_t size;
+ target_phys_addr_t phys_addr;
+ int sector_bits, sector_size;
+ pflash_t *system_flash;
+ MemoryRegion *flash_mem;
+
+ bdrv = pflash_drv->bdrv;
+ size = bdrv_getlength(pflash_drv->bdrv);
+ sector_bits = 12;
+ sector_size = 1 << sector_bits;
+
+ if ((size % sector_size) != 0) {
+ fprintf(stderr,
+ "qemu: PC system firmware (pflash) must be a multiple of 0x%x\n",
+ sector_size);
+ exit(1);
+ }
+
+ phys_addr = 0x100000000ULL - size;
+ system_flash = pflash_cfi01_register(phys_addr, NULL, "system.flash", size,
+ bdrv, sector_size, size >> sector_bits,
+ 1, 0x0000, 0x0000, 0x0000, 0x0000, 0);
+ flash_mem = pflash_cfi01_get_memory(system_flash);
+
+ pc_isa_bios_init(rom_memory, flash_mem, size);
+}
+
+static void old_pc_system_rom_init(MemoryRegion *rom_memory)
+{
+ char *filename;
+ MemoryRegion *bios, *isa_bios;
+ int bios_size, isa_bios_size;
+ int ret;
+
+ /* BIOS load */
+ if (bios_name == NULL) {
+ bios_name = BIOS_FILENAME;
+ }
+ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+ if (filename) {
+ bios_size = get_image_size(filename);
+ } else {
+ bios_size = -1;
+ }
+ if (bios_size <= 0 ||
+ (bios_size % 65536) != 0) {
+ goto bios_error;
+ }
+ bios = g_malloc(sizeof(*bios));
+ memory_region_init_ram(bios, "pc.bios", bios_size);
+ vmstate_register_ram_global(bios);
+ memory_region_set_readonly(bios, true);
+ ret = rom_add_file_fixed(bios_name, (uint32_t)(-bios_size), -1);
+ if (ret != 0) {
+ bios_error:
+ fprintf(stderr, "qemu: could not load PC BIOS '%s'\n", bios_name);
+ exit(1);
+ }
+ if (filename) {
+ g_free(filename);
+ }
+
+ /* map the last 128KB of the BIOS in ISA space */
+ isa_bios_size = bios_size;
+ if (isa_bios_size > (128 * 1024)) {
+ isa_bios_size = 128 * 1024;
+ }
+ isa_bios = g_malloc(sizeof(*isa_bios));
+ memory_region_init_alias(isa_bios, "isa-bios", bios,
+ bios_size - isa_bios_size, isa_bios_size);
+ memory_region_add_subregion_overlap(rom_memory,
+ 0x100000 - isa_bios_size,
+ isa_bios,
+ 1);
+ memory_region_set_readonly(isa_bios, true);
+
+ /* map all the bios at the top of memory */
+ memory_region_add_subregion(rom_memory,
+ (uint32_t)(-bios_size),
+ bios);
+}
+
+void pc_system_firmware_init(MemoryRegion *rom_memory)
+{
+ DriveInfo *pflash_drv;
+ PcSysFwDevice *sysfw_dev;
+
+ sysfw_dev = (PcSysFwDevice*) qdev_create(NULL, "pc-sysfw");
+
+ if (sysfw_dev->rom_only) {
+ old_pc_system_rom_init(rom_memory);
+ return;
+ }
+
+ pflash_drv = drive_get(IF_PFLASH, 0, 0);
+
+ /* Currently KVM cannot execute from device memory.
+ Use old rom based firmware initialization for KVM. */
+ if (kvm_enabled()) {
+ if (pflash_drv != NULL) {
+ fprintf(stderr, "qemu: pflash cannot be used with kvm enabled\n");
+ exit(1);
+ } else {
+ sysfw_dev->rom_only = 1;
+ old_pc_system_rom_init(rom_memory);
+ return;
+ }
+ }
+
+ /* If a pflash drive is not found, then create one using
+ the bios filename. */
+ if (pflash_drv == NULL) {
+ pc_fw_add_pflash_drv();
+ pflash_drv = drive_get(IF_PFLASH, 0, 0);
+ }
+
+ if (pflash_drv != NULL) {
+ pc_system_flash_init(rom_memory, pflash_drv);
+ } else {
+ fprintf(stderr, "qemu: PC system firmware (pflash) not available\n");
+ exit(1);
+ }
+}
+
+static Property pcsysfw_properties[] = {
+ DEFINE_PROP_UINT8("rom_only", PcSysFwDevice, rom_only, 0),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void pcsysfw_class_init (ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS (klass);
+
+ dc->desc = "PC System Firmware";
+ dc->props = pcsysfw_properties;
+}
+
+static TypeInfo pcsysfw_info = {
+ .name = "pc-sysfw",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof (PcSysFwDevice),
+ .class_init = pcsysfw_class_init,
+};
+
+static void pcsysfw_register (void)
+{
+ type_register_static (&pcsysfw_info);
+}
+
+type_init (pcsysfw_register);
+
diff --git a/hw/pci.c b/hw/pci.c
index 678a8c1117..bf046bfcad 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -614,7 +614,7 @@ static void pci_init_w1cmask(PCIDevice *dev)
PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY);
}
-static void pci_init_wmask_bridge(PCIDevice *d)
+static void pci_init_mask_bridge(PCIDevice *d)
{
/* PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS and
PCI_SEC_LETENCY_TIMER */
@@ -635,6 +635,14 @@ static void pci_init_wmask_bridge(PCIDevice *d)
/* PCI_PREF_BASE_UPPER32 and PCI_PREF_LIMIT_UPPER32 */
memset(d->wmask + PCI_PREF_BASE_UPPER32, 0xff, 8);
+ /* Supported memory and i/o types */
+ d->config[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_32;
+ d->config[PCI_IO_LIMIT] |= PCI_IO_RANGE_TYPE_32;
+ pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_BASE,
+ PCI_PREF_RANGE_TYPE_64);
+ pci_word_test_and_set_mask(d->config + PCI_PREF_MEMORY_LIMIT,
+ PCI_PREF_RANGE_TYPE_64);
+
/* TODO: add this define to pci_regs.h in linux and then in qemu. */
#define PCI_BRIDGE_CTL_VGA_16BIT 0x10 /* VGA 16-bit decode */
#define PCI_BRIDGE_CTL_DISCARD 0x100 /* Primary discard timer */
@@ -657,6 +665,9 @@ static void pci_init_wmask_bridge(PCIDevice *d)
* completeness. */
pci_set_word(d->w1cmask + PCI_BRIDGE_CONTROL,
PCI_BRIDGE_CTL_DISCARD_STATUS);
+ d->cmask[PCI_IO_BASE] |= PCI_IO_RANGE_TYPE_MASK;
+ pci_word_test_and_set_mask(d->cmask + PCI_PREF_MEMORY_BASE,
+ PCI_PREF_RANGE_TYPE_MASK);
}
static int pci_init_multifunction(PCIBus *bus, PCIDevice *dev)
@@ -778,7 +789,7 @@ static PCIDevice *do_pci_register_device(PCIDevice *pci_dev, PCIBus *bus,
pci_init_wmask(pci_dev);
pci_init_w1cmask(pci_dev);
if (pc->is_bridge) {
- pci_init_wmask_bridge(pci_dev);
+ pci_init_mask_bridge(pci_dev);
}
if (pci_init_multifunction(bus, pci_dev)) {
pci_config_free(pci_dev);
diff --git a/hw/pci.h b/hw/pci.h
index ff4c12d452..4f19fdbd89 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -465,6 +465,67 @@ pci_quad_test_and_set_mask(uint8_t *config, uint64_t mask)
return val & mask;
}
+/* Access a register specified by a mask */
+static inline void
+pci_set_byte_by_mask(uint8_t *config, uint8_t mask, uint8_t reg)
+{
+ uint8_t val = pci_get_byte(config);
+ uint8_t rval = reg << (ffs(mask) - 1);
+ pci_set_byte(config, (~mask & val) | (mask & rval));
+}
+
+static inline uint8_t
+pci_get_byte_by_mask(uint8_t *config, uint8_t mask)
+{
+ uint8_t val = pci_get_byte(config);
+ return (val & mask) >> (ffs(mask) - 1);
+}
+
+static inline void
+pci_set_word_by_mask(uint8_t *config, uint16_t mask, uint16_t reg)
+{
+ uint16_t val = pci_get_word(config);
+ uint16_t rval = reg << (ffs(mask) - 1);
+ pci_set_word(config, (~mask & val) | (mask & rval));
+}
+
+static inline uint16_t
+pci_get_word_by_mask(uint8_t *config, uint16_t mask)
+{
+ uint16_t val = pci_get_word(config);
+ return (val & mask) >> (ffs(mask) - 1);
+}
+
+static inline void
+pci_set_long_by_mask(uint8_t *config, uint32_t mask, uint32_t reg)
+{
+ uint32_t val = pci_get_long(config);
+ uint32_t rval = reg << (ffs(mask) - 1);
+ pci_set_long(config, (~mask & val) | (mask & rval));
+}
+
+static inline uint32_t
+pci_get_long_by_mask(uint8_t *config, uint32_t mask)
+{
+ uint32_t val = pci_get_long(config);
+ return (val & mask) >> (ffs(mask) - 1);
+}
+
+static inline void
+pci_set_quad_by_mask(uint8_t *config, uint64_t mask, uint64_t reg)
+{
+ uint64_t val = pci_get_quad(config);
+ uint64_t rval = reg << (ffs(mask) - 1);
+ pci_set_quad(config, (~mask & val) | (mask & rval));
+}
+
+static inline uint64_t
+pci_get_quad_by_mask(uint8_t *config, uint64_t mask)
+{
+ uint64_t val = pci_get_quad(config);
+ return (val & mask) >> (ffs(mask) - 1);
+}
+
PCIDevice *pci_create_multifunction(PCIBus *bus, int devfn, bool multifunction,
const char *name);
PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn,
diff --git a/hw/pflash_cfi01.c b/hw/pflash_cfi01.c
index ee0c3baab1..b03f623cb1 100644
--- a/hw/pflash_cfi01.c
+++ b/hw/pflash_cfi01.c
@@ -283,8 +283,12 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
TARGET_FMT_plx "\n",
__func__, offset, pfl->sector_len);
- memset(p + offset, 0xff, pfl->sector_len);
- pflash_update(pfl, offset, pfl->sector_len);
+ if (!pfl->ro) {
+ memset(p + offset, 0xff, pfl->sector_len);
+ pflash_update(pfl, offset, pfl->sector_len);
+ } else {
+ pfl->status |= 0x20; /* Block erase error */
+ }
pfl->status |= 0x80; /* Ready! */
break;
case 0x50: /* Clear status bits */
@@ -323,8 +327,12 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
case 0x10: /* Single Byte Program */
case 0x40: /* Single Byte Program */
DPRINTF("%s: Single Byte Program\n", __func__);
- pflash_data_write(pfl, offset, value, width, be);
- pflash_update(pfl, offset, width);
+ if (!pfl->ro) {
+ pflash_data_write(pfl, offset, value, width, be);
+ pflash_update(pfl, offset, width);
+ } else {
+ pfl->status |= 0x10; /* Programming error */
+ }
pfl->status |= 0x80; /* Ready! */
pfl->wcycle = 0;
break;
@@ -372,7 +380,11 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
case 2:
switch (pfl->cmd) {
case 0xe8: /* Block write */
- pflash_data_write(pfl, offset, value, width, be);
+ if (!pfl->ro) {
+ pflash_data_write(pfl, offset, value, width, be);
+ } else {
+ pfl->status |= 0x10; /* Programming error */
+ }
pfl->status |= 0x80;
@@ -382,8 +394,12 @@ static void pflash_write(pflash_t *pfl, target_phys_addr_t offset,
DPRINTF("%s: block write finished\n", __func__);
pfl->wcycle++;
- /* Flush the entire write buffer onto backing storage. */
- pflash_update(pfl, offset & mask, pfl->writeblock_size);
+ if (!pfl->ro) {
+ /* Flush the entire write buffer onto backing storage. */
+ pflash_update(pfl, offset & mask, pfl->writeblock_size);
+ } else {
+ pfl->status |= 0x10; /* Programming error */
+ }
}
pfl->counter--;
@@ -607,13 +623,13 @@ pflash_t *pflash_cfi01_register(target_phys_addr_t base,
}
bdrv_attach_dev_nofail(pfl->bs, pfl);
}
-#if 0 /* XXX: there should be a bit to set up read-only,
- * the same way the hardware does (with WP pin).
- */
- pfl->ro = 1;
-#else
- pfl->ro = 0;
-#endif
+
+ if (pfl->bs) {
+ pfl->ro = bdrv_is_read_only(pfl->bs);
+ } else {
+ pfl->ro = 0;
+ }
+
pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl);
pfl->base = base;
pfl->sector_len = sector_len;
diff --git a/hw/pflash_cfi02.c b/hw/pflash_cfi02.c
index 2ca0fd4560..3e2002e4b3 100644
--- a/hw/pflash_cfi02.c
+++ b/hw/pflash_cfi02.c
@@ -330,35 +330,37 @@ static void pflash_write (pflash_t *pfl, target_phys_addr_t offset,
DPRINTF("%s: write data offset " TARGET_FMT_plx " %08x %d\n",
__func__, offset, value, width);
p = pfl->storage;
- switch (width) {
- case 1:
- p[offset] &= value;
- pflash_update(pfl, offset, 1);
- break;
- case 2:
- if (be) {
- p[offset] &= value >> 8;
- p[offset + 1] &= value;
- } else {
+ if (!pfl->ro) {
+ switch (width) {
+ case 1:
p[offset] &= value;
- p[offset + 1] &= value >> 8;
+ pflash_update(pfl, offset, 1);
+ break;
+ case 2:
+ if (be) {
+ p[offset] &= value >> 8;
+ p[offset + 1] &= value;
+ } else {
+ p[offset] &= value;
+ p[offset + 1] &= value >> 8;
+ }
+ pflash_update(pfl, offset, 2);
+ break;
+ case 4:
+ if (be) {
+ p[offset] &= value >> 24;
+ p[offset + 1] &= value >> 16;
+ p[offset + 2] &= value >> 8;
+ p[offset + 3] &= value;
+ } else {
+ p[offset] &= value;
+ p[offset + 1] &= value >> 8;
+ p[offset + 2] &= value >> 16;
+ p[offset + 3] &= value >> 24;
+ }
+ pflash_update(pfl, offset, 4);
+ break;
}
- pflash_update(pfl, offset, 2);
- break;
- case 4:
- if (be) {
- p[offset] &= value >> 24;
- p[offset + 1] &= value >> 16;
- p[offset + 2] &= value >> 8;
- p[offset + 3] &= value;
- } else {
- p[offset] &= value;
- p[offset + 1] &= value >> 8;
- p[offset + 2] &= value >> 16;
- p[offset + 3] &= value >> 24;
- }
- pflash_update(pfl, offset, 4);
- break;
}
pfl->status = 0x00 | ~(value & 0x80);
/* Let's pretend write is immediate */
@@ -404,9 +406,11 @@ static void pflash_write (pflash_t *pfl, target_phys_addr_t offset,
}
/* Chip erase */
DPRINTF("%s: start chip erase\n", __func__);
- memset(pfl->storage, 0xFF, pfl->chip_len);
+ if (!pfl->ro) {
+ memset(pfl->storage, 0xFF, pfl->chip_len);
+ pflash_update(pfl, 0, pfl->chip_len);
+ }
pfl->status = 0x00;
- pflash_update(pfl, 0, pfl->chip_len);
/* Let's wait 5 seconds before chip erase is done */
qemu_mod_timer(pfl->timer,
qemu_get_clock_ns(vm_clock) + (get_ticks_per_sec() * 5));
@@ -417,8 +421,10 @@ static void pflash_write (pflash_t *pfl, target_phys_addr_t offset,
offset &= ~(pfl->sector_len - 1);
DPRINTF("%s: start sector erase at " TARGET_FMT_plx "\n", __func__,
offset);
- memset(p + offset, 0xFF, pfl->sector_len);
- pflash_update(pfl, offset, pfl->sector_len);
+ if (!pfl->ro) {
+ memset(p + offset, 0xFF, pfl->sector_len);
+ pflash_update(pfl, offset, pfl->sector_len);
+ }
pfl->status = 0x00;
/* Let's wait 1/2 second before sector erase is done */
qemu_mod_timer(pfl->timer,
@@ -645,16 +651,17 @@ pflash_t *pflash_cfi02_register(target_phys_addr_t base,
}
bdrv_attach_dev_nofail(pfl->bs, pfl);
}
+
pflash_setup_mappings(pfl);
pfl->rom_mode = 1;
memory_region_add_subregion(get_system_memory(), pfl->base, &pfl->mem);
-#if 0 /* XXX: there should be a bit to set up read-only,
- * the same way the hardware does (with WP pin).
- */
- pfl->ro = 1;
-#else
- pfl->ro = 0;
-#endif
+
+ if (pfl->bs) {
+ pfl->ro = bdrv_is_read_only(pfl->bs);
+ } else {
+ pfl->ro = 0;
+ }
+
pfl->timer = qemu_new_timer_ns(vm_clock, pflash_timer, pfl);
pfl->sector_len = sector_len;
pfl->width = width;
diff --git a/hw/qdev-properties.c b/hw/qdev-properties.c
index 7b74dd5beb..0423af1c31 100644
--- a/hw/qdev-properties.c
+++ b/hw/qdev-properties.c
@@ -27,16 +27,6 @@ static void bit_prop_set(DeviceState *dev, Property *props, bool val)
}
/* Bit */
-static int parse_bit(DeviceState *dev, Property *prop, const char *str)
-{
- if (!strcasecmp(str, "on"))
- bit_prop_set(dev, prop, true);
- else if (!strcasecmp(str, "off"))
- bit_prop_set(dev, prop, false);
- else
- return -EINVAL;
- return 0;
-}
static int print_bit(DeviceState *dev, Property *prop, char *dest, size_t len)
{
@@ -79,7 +69,6 @@ static void set_bit(Object *obj, Visitor *v, void *opaque,
PropertyInfo qdev_prop_bit = {
.name = "boolean",
.legacy_name = "on/off",
- .parse = parse_bit,
.print = print_bit,
.get = get_bit,
.set = set_bit,
@@ -87,26 +76,6 @@ PropertyInfo qdev_prop_bit = {
/* --- 8bit integer --- */
-static int parse_uint8(DeviceState *dev, Property *prop, const char *str)
-{
- uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
- char *end;
-
- /* accept both hex and decimal */
- *ptr = strtoul(str, &end, 0);
- if ((*end != '\0') || (end == str)) {
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int print_uint8(DeviceState *dev, Property *prop, char *dest, size_t len)
-{
- uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
- return snprintf(dest, len, "%" PRIu8, *ptr);
-}
-
static void get_int8(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
@@ -149,8 +118,6 @@ static void set_int8(Object *obj, Visitor *v, void *opaque,
PropertyInfo qdev_prop_uint8 = {
.name = "uint8",
- .parse = parse_uint8,
- .print = print_uint8,
.get = get_int8,
.set = set_int8,
.min = 0,
@@ -164,6 +131,10 @@ static int parse_hex8(DeviceState *dev, Property *prop, const char *str)
uint8_t *ptr = qdev_get_prop_ptr(dev, prop);
char *end;
+ if (str[0] != '0' || str[1] != 'x') {
+ return -EINVAL;
+ }
+
*ptr = strtoul(str, &end, 16);
if ((*end != '\0') || (end == str)) {
return -EINVAL;
@@ -191,26 +162,6 @@ PropertyInfo qdev_prop_hex8 = {
/* --- 16bit integer --- */
-static int parse_uint16(DeviceState *dev, Property *prop, const char *str)
-{
- uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
- char *end;
-
- /* accept both hex and decimal */
- *ptr = strtoul(str, &end, 0);
- if ((*end != '\0') || (end == str)) {
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int print_uint16(DeviceState *dev, Property *prop, char *dest, size_t len)
-{
- uint16_t *ptr = qdev_get_prop_ptr(dev, prop);
- return snprintf(dest, len, "%" PRIu16, *ptr);
-}
-
static void get_int16(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
@@ -253,8 +204,6 @@ static void set_int16(Object *obj, Visitor *v, void *opaque,
PropertyInfo qdev_prop_uint16 = {
.name = "uint16",
- .parse = parse_uint16,
- .print = print_uint16,
.get = get_int16,
.set = set_int16,
.min = 0,
@@ -263,26 +212,6 @@ PropertyInfo qdev_prop_uint16 = {
/* --- 32bit integer --- */
-static int parse_uint32(DeviceState *dev, Property *prop, const char *str)
-{
- uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
- char *end;
-
- /* accept both hex and decimal */
- *ptr = strtoul(str, &end, 0);
- if ((*end != '\0') || (end == str)) {
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int print_uint32(DeviceState *dev, Property *prop, char *dest, size_t len)
-{
- uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
- return snprintf(dest, len, "%" PRIu32, *ptr);
-}
-
static void get_int32(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
@@ -325,37 +254,14 @@ static void set_int32(Object *obj, Visitor *v, void *opaque,
PropertyInfo qdev_prop_uint32 = {
.name = "uint32",
- .parse = parse_uint32,
- .print = print_uint32,
.get = get_int32,
.set = set_int32,
.min = 0,
.max = 0xFFFFFFFFULL,
};
-static int parse_int32(DeviceState *dev, Property *prop, const char *str)
-{
- int32_t *ptr = qdev_get_prop_ptr(dev, prop);
- char *end;
-
- *ptr = strtol(str, &end, 10);
- if ((*end != '\0') || (end == str)) {
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int print_int32(DeviceState *dev, Property *prop, char *dest, size_t len)
-{
- int32_t *ptr = qdev_get_prop_ptr(dev, prop);
- return snprintf(dest, len, "%" PRId32, *ptr);
-}
-
PropertyInfo qdev_prop_int32 = {
.name = "int32",
- .parse = parse_int32,
- .print = print_int32,
.get = get_int32,
.set = set_int32,
.min = -0x80000000LL,
@@ -369,6 +275,10 @@ static int parse_hex32(DeviceState *dev, Property *prop, const char *str)
uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
char *end;
+ if (str[0] != '0' || str[1] != 'x') {
+ return -EINVAL;
+ }
+
*ptr = strtoul(str, &end, 16);
if ((*end != '\0') || (end == str)) {
return -EINVAL;
@@ -396,26 +306,6 @@ PropertyInfo qdev_prop_hex32 = {
/* --- 64bit integer --- */
-static int parse_uint64(DeviceState *dev, Property *prop, const char *str)
-{
- uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
- char *end;
-
- /* accept both hex and decimal */
- *ptr = strtoull(str, &end, 0);
- if ((*end != '\0') || (end == str)) {
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int print_uint64(DeviceState *dev, Property *prop, char *dest, size_t len)
-{
- uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
- return snprintf(dest, len, "%" PRIu64, *ptr);
-}
-
static void get_int64(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
@@ -443,8 +333,6 @@ static void set_int64(Object *obj, Visitor *v, void *opaque,
PropertyInfo qdev_prop_uint64 = {
.name = "uint64",
- .parse = parse_uint64,
- .print = print_uint64,
.get = get_int64,
.set = set_int64,
};
@@ -456,6 +344,10 @@ static int parse_hex64(DeviceState *dev, Property *prop, const char *str)
uint64_t *ptr = qdev_get_prop_ptr(dev, prop);
char *end;
+ if (str[0] != '0' || str[1] != 'x') {
+ return -EINVAL;
+ }
+
*ptr = strtoull(str, &end, 16);
if ((*end != '\0') || (end == str)) {
return -EINVAL;
@@ -737,19 +629,6 @@ PropertyInfo qdev_prop_netdev = {
/* --- vlan --- */
-static int parse_vlan(DeviceState *dev, Property *prop, const char *str)
-{
- VLANState **ptr = qdev_get_prop_ptr(dev, prop);
- int id;
-
- if (sscanf(str, "%d", &id) != 1)
- return -EINVAL;
- *ptr = qemu_find_vlan(id, 1);
- if (*ptr == NULL)
- return -ENOENT;
- return 0;
-}
-
static int print_vlan(DeviceState *dev, Property *prop, char *dest, size_t len)
{
VLANState **ptr = qdev_get_prop_ptr(dev, prop);
@@ -808,7 +687,6 @@ static void set_vlan(Object *obj, Visitor *v, void *opaque,
PropertyInfo qdev_prop_vlan = {
.name = "vlan",
- .parse = parse_vlan,
.print = print_vlan,
.get = get_vlan,
.set = set_vlan,
@@ -943,25 +821,40 @@ PropertyInfo qdev_prop_losttickpolicy = {
/*
* bus-local address, i.e. "$slot" or "$slot.$fn"
*/
-static int parse_pci_devfn(DeviceState *dev, Property *prop, const char *str)
+static void set_pci_devfn(Object *obj, Visitor *v, void *opaque,
+ const char *name, Error **errp)
{
+ DeviceState *dev = DEVICE(obj);
+ Property *prop = opaque;
uint32_t *ptr = qdev_get_prop_ptr(dev, prop);
unsigned int slot, fn, n;
+ Error *local_err = NULL;
+ char *str = (char *)"";
+
+ if (dev->state != DEV_STATE_CREATED) {
+ error_set(errp, QERR_PERMISSION_DENIED);
+ return;
+ }
+
+ visit_type_str(v, &str, name, &local_err);
+ if (local_err) {
+ return set_int32(obj, v, opaque, name, errp);
+ }
if (sscanf(str, "%x.%x%n", &slot, &fn, &n) != 2) {
fn = 0;
if (sscanf(str, "%x%n", &slot, &n) != 1) {
- return -EINVAL;
+ goto invalid;
}
}
- if (str[n] != '\0')
- return -EINVAL;
- if (fn > 7)
- return -EINVAL;
- if (slot > 31)
- return -EINVAL;
+ if (str[n] != '\0' || fn > 7 || slot > 31) {
+ goto invalid;
+ }
*ptr = slot << 3 | fn;
- return 0;
+ return;
+
+invalid:
+ error_set_from_qdev_prop_error(errp, EINVAL, dev, prop, str);
}
static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t len)
@@ -978,10 +871,9 @@ static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest, size_t
PropertyInfo qdev_prop_pci_devfn = {
.name = "int32",
.legacy_name = "pci-devfn",
- .parse = parse_pci_devfn,
.print = print_pci_devfn,
.get = get_int32,
- .set = set_int32,
+ .set = set_pci_devfn,
/* FIXME: this should be -1...255, but the address is stored
* into an uint32_t rather than int32_t.
*/
@@ -1054,9 +946,9 @@ int qdev_prop_parse(DeviceState *dev, const char *name, const char *value)
legacy_name = g_strdup_printf("legacy-%s", name);
if (object_property_get_type(OBJECT(dev), legacy_name, NULL)) {
- object_property_set_str(OBJECT(dev), value, legacy_name, &err);
+ object_property_parse(OBJECT(dev), value, legacy_name, &err);
} else {
- object_property_set_str(OBJECT(dev), value, name, &err);
+ object_property_parse(OBJECT(dev), value, name, &err);
}
g_free(legacy_name);
diff --git a/hw/qxl-render.c b/hw/qxl-render.c
index 133d09324c..708414376e 100644
--- a/hw/qxl-render.c
+++ b/hw/qxl-render.c
@@ -121,19 +121,17 @@ void qxl_render_update(PCIQXLDevice *qxl)
dpy_resize(vga->ds);
}
- if (!qxl->guest_primary.commands) {
- return;
- }
- qxl->guest_primary.commands = 0;
-
update.left = 0;
update.right = qxl->guest_primary.surface.width;
update.top = 0;
update.bottom = qxl->guest_primary.surface.height;
memset(dirty, 0, sizeof(dirty));
- qxl_spice_update_area(qxl, 0, &update,
- dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
+ if (runstate_is_running() && qxl->guest_primary.commands) {
+ qxl->guest_primary.commands = 0;
+ qxl_spice_update_area(qxl, 0, &update,
+ dirty, ARRAY_SIZE(dirty), 1, QXL_SYNC);
+ }
if (redraw) {
memset(dirty, 0, sizeof(dirty));
dirty[0] = update;
diff --git a/hw/qxl.c b/hw/qxl.c
index ac69125f27..87ad49ad8b 100644
--- a/hw/qxl.c
+++ b/hw/qxl.c
@@ -625,7 +625,7 @@ static void interface_release_resource(QXLInstance *sin,
if (ext.group_id == MEMSLOT_GROUP_HOST) {
/* host group -> vga mode update request */
- qemu_spice_destroy_update(&qxl->ssd, (void*)ext.info->id);
+ qemu_spice_destroy_update(&qxl->ssd, (void *)(intptr_t)ext.info->id);
return;
}
@@ -748,7 +748,8 @@ static void interface_async_complete(QXLInstance *sin, uint64_t cookie)
qxl->current_async = QXL_UNDEFINED_IO;
qemu_mutex_unlock(&qxl->async_lock);
- dprint(qxl, 2, "async_complete: %d (%ld) done\n", current_async, cookie);
+ dprint(qxl, 2, "async_complete: %d (%" PRId64 ") done\n",
+ current_async, cookie);
switch (current_async) {
case QXL_IO_CREATE_PRIMARY_ASYNC:
qxl_create_guest_primary_complete(qxl);
@@ -1006,7 +1007,7 @@ static void qxl_reset_surfaces(PCIQXLDevice *d)
qxl_spice_destroy_surfaces(d, QXL_SYNC);
}
-/* called from spice server thread context only */
+/* can be also called from spice server thread context */
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
{
uint64_t phys = le64_to_cpu(pqxl);
@@ -1015,7 +1016,7 @@ void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL pqxl, int group_id)
switch (group_id) {
case MEMSLOT_GROUP_HOST:
- return (void*)offset;
+ return (void *)(intptr_t)offset;
case MEMSLOT_GROUP_GUEST:
PANIC_ON(slot >= NUM_MEMSLOTS);
PANIC_ON(!qxl->guest_slots[slot].active);
@@ -1465,6 +1466,46 @@ static void qxl_hw_text_update(void *opaque, console_ch_t *chardata)
}
}
+static void qxl_dirty_surfaces(PCIQXLDevice *qxl)
+{
+ intptr_t vram_start;
+ int i;
+
+ if (qxl->mode != QXL_MODE_NATIVE && qxl->mode != QXL_MODE_COMPAT) {
+ return;
+ }
+
+ /* dirty the primary surface */
+ qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
+ qxl->shadow_rom.surface0_area_size);
+
+ vram_start = (intptr_t)memory_region_get_ram_ptr(&qxl->vram_bar);
+
+ /* dirty the off-screen surfaces */
+ for (i = 0; i < NUM_SURFACES; i++) {
+ QXLSurfaceCmd *cmd;
+ intptr_t surface_offset;
+ int surface_size;
+
+ if (qxl->guest_surfaces.cmds[i] == 0) {
+ continue;
+ }
+
+ cmd = qxl_phys2virt(qxl, qxl->guest_surfaces.cmds[i],
+ MEMSLOT_GROUP_GUEST);
+ assert(cmd->type == QXL_SURFACE_CMD_CREATE);
+ surface_offset = (intptr_t)qxl_phys2virt(qxl,
+ cmd->u.surface_create.data,
+ MEMSLOT_GROUP_GUEST);
+ surface_offset -= vram_start;
+ surface_size = cmd->u.surface_create.height *
+ abs(cmd->u.surface_create.stride);
+ dprint(qxl, 3, "%s: dirty surface %d, offset %d, size %d\n", __func__,
+ i, (int)surface_offset, surface_size);
+ qxl_set_dirty(&qxl->vram_bar, surface_offset, surface_size);
+ }
+}
+
static void qxl_vm_change_state_handler(void *opaque, int running,
RunState state)
{
@@ -1478,14 +1519,9 @@ static void qxl_vm_change_state_handler(void *opaque, int running,
* called
*/
qxl_update_irq(qxl);
- } else if (qxl->mode == QXL_MODE_NATIVE) {
- /* dirty all vram (which holds surfaces) and devram (primary surface)
- * to make sure they are saved */
- /* FIXME #1: should go out during "live" stage */
- /* FIXME #2: we only need to save the areas which are actually used */
- qxl_set_dirty(&qxl->vram_bar, 0, qxl->vram_size);
- qxl_set_dirty(&qxl->vga.vram, qxl->shadow_rom.draw_area_offset,
- qxl->shadow_rom.surface0_area_size);
+ } else {
+ /* make sure surfaces are saved before migration */
+ qxl_dirty_surfaces(qxl);
}
}
@@ -1518,6 +1554,31 @@ static DisplayChangeListener display_listener = {
.dpy_refresh = display_refresh,
};
+static void qxl_init_ramsize(PCIQXLDevice *qxl, uint32_t ram_min_mb)
+{
+ /* vga ram (bar 0) */
+ if (qxl->ram_size_mb != -1) {
+ qxl->vga.vram_size = qxl->ram_size_mb * 1024 * 1024;
+ }
+ if (qxl->vga.vram_size < ram_min_mb * 1024 * 1024) {
+ qxl->vga.vram_size = ram_min_mb * 1024 * 1024;
+ }
+
+ /* vram (surfaces, bar 1) */
+ if (qxl->vram_size_mb != -1) {
+ qxl->vram_size = qxl->vram_size_mb * 1024 * 1024;
+ }
+ if (qxl->vram_size < 4096) {
+ qxl->vram_size = 4096;
+ }
+ if (qxl->revision == 1) {
+ qxl->vram_size = 4096;
+ }
+
+ qxl->vga.vram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
+ qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
+}
+
static int qxl_init_common(PCIQXLDevice *qxl)
{
uint8_t* config = qxl->pci.config;
@@ -1556,13 +1617,6 @@ static int qxl_init_common(PCIQXLDevice *qxl)
init_qxl_rom(qxl);
init_qxl_ram(qxl);
- if (qxl->vram_size < 16 * 1024 * 1024) {
- qxl->vram_size = 16 * 1024 * 1024;
- }
- if (qxl->revision == 1) {
- qxl->vram_size = 4096;
- }
- qxl->vram_size = msb_mask(qxl->vram_size * 2 - 1);
memory_region_init_ram(&qxl->vram_bar, "qxl.vram", qxl->vram_size);
vmstate_register_ram(&qxl->vram_bar, &qxl->pci.qdev);
@@ -1605,15 +1659,11 @@ static int qxl_init_primary(PCIDevice *dev)
{
PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
VGACommonState *vga = &qxl->vga;
- ram_addr_t ram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
PortioList *qxl_vga_port_list = g_new(PortioList, 1);
qxl->id = 0;
-
- if (ram_size < 32 * 1024 * 1024) {
- ram_size = 32 * 1024 * 1024;
- }
- vga_common_init(vga, ram_size);
+ qxl_init_ramsize(qxl, 32);
+ vga_common_init(vga, qxl->vga.vram_size);
vga_init(vga, pci_address_space(dev), pci_address_space_io(dev), false);
portio_list_init(qxl_vga_port_list, qxl_vga_portio_list, vga, "vga");
portio_list_add(qxl_vga_port_list, pci_address_space_io(dev), 0x3b0);
@@ -1632,14 +1682,9 @@ static int qxl_init_secondary(PCIDevice *dev)
{
static int device_id = 1;
PCIQXLDevice *qxl = DO_UPCAST(PCIQXLDevice, pci, dev);
- ram_addr_t ram_size = msb_mask(qxl->vga.vram_size * 2 - 1);
qxl->id = device_id++;
-
- if (ram_size < 16 * 1024 * 1024) {
- ram_size = 16 * 1024 * 1024;
- }
- qxl->vga.vram_size = ram_size;
+ qxl_init_ramsize(qxl, 16);
memory_region_init_ram(&qxl->vga.vram, "qxl.vgavram", qxl->vga.vram_size);
vmstate_register_ram(&qxl->vga.vram, &qxl->pci.qdev);
qxl->vga.vram_ptr = memory_region_get_ram_ptr(&qxl->vga.vram);
@@ -1821,6 +1866,8 @@ static Property qxl_properties[] = {
DEFINE_PROP_UINT32("debug", PCIQXLDevice, debug, 0),
DEFINE_PROP_UINT32("guestdebug", PCIQXLDevice, guestdebug, 0),
DEFINE_PROP_UINT32("cmdlog", PCIQXLDevice, cmdlog, 0),
+ DEFINE_PROP_UINT32("ram_size_mb", PCIQXLDevice, ram_size_mb, -1),
+ DEFINE_PROP_UINT32("vram_size_mb", PCIQXLDevice, vram_size_mb, -1),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/qxl.h b/hw/qxl.h
index 766aa6d68e..d0629916ad 100644
--- a/hw/qxl.h
+++ b/hw/qxl.h
@@ -89,6 +89,10 @@ typedef struct PCIQXLDevice {
/* io bar */
MemoryRegion io_bar;
+
+ /* user-friendly properties (in megabytes) */
+ uint32_t ram_size_mb;
+ uint32_t vram_size_mb;
} PCIQXLDevice;
#define PANIC_ON(x) if ((x)) { \
diff --git a/include/qemu/object.h b/include/qemu/object.h
index 5179c0cf5a..69e4b7b282 100644
--- a/include/qemu/object.h
+++ b/include/qemu/object.h
@@ -730,6 +730,30 @@ void object_property_set(Object *obj, struct Visitor *v, const char *name,
struct Error **errp);
/**
+ * object_property_parse:
+ * @obj: the object
+ * @string: the string that will be used to parse the property value.
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Parses a string and writes the result into a property of an object.
+ */
+void object_property_parse(Object *obj, const char *string,
+ const char *name, struct Error **errp);
+
+/**
+ * object_property_print:
+ * @obj: the object
+ * @name: the name of the property
+ * @errp: returns an error if this function fails
+ *
+ * Returns a string representation of the value of the property. The
+ * caller shall free the string.
+ */
+char *object_property_print(Object *obj, const char *name,
+ struct Error **errp);
+
+/**
* object_property_get_type:
* @obj: the object
* @name: the name of the property
@@ -813,6 +837,10 @@ Object *object_resolve_path_type(const char *path, const char *typename,
*
* There is no way for a child to determine what its parent is. It is not
* a bidirectional relationship. This is by design.
+ *
+ * The value of a child property as a C string will be the child object's
+ * canonical path. It can be retrieved using object_property_get_str().
+ * The child object itself can be retrieved using object_property_get_link().
*/
void object_property_add_child(Object *obj, const char *name,
Object *child, struct Error **errp);
diff --git a/monitor.c b/monitor.c
index aadbdcbf33..0d4daadf42 100644
--- a/monitor.c
+++ b/monitor.c
@@ -823,13 +823,18 @@ static int add_graphics_client(Monitor *mon, const QDict *qdict, QObject **ret_d
CharDriverState *s;
if (strcmp(protocol, "spice") == 0) {
+ int fd = monitor_get_fd(mon, fdname);
+ int skipauth = qdict_get_try_bool(qdict, "skipauth", 0);
+ int tls = qdict_get_try_bool(qdict, "tls", 0);
if (!using_spice) {
/* correct one? spice isn't a device ,,, */
qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
return -1;
}
- qerror_report(QERR_ADD_CLIENT_FAILED);
- return -1;
+ if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) {
+ close(fd);
+ }
+ return 0;
#ifdef CONFIG_VNC
} else if (strcmp(protocol, "vnc") == 0) {
int fd = monitor_get_fd(mon, fdname);
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index ddef3eda12..a4e088c9fc 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -12,6 +12,7 @@
*/
#include "qapi/qapi-visit-core.h"
+#include "qapi/qapi-visit-impl.h"
void visit_start_handle(Visitor *v, void **obj, const char *kind,
const char *name, Error **errp)
@@ -116,3 +117,53 @@ void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp)
v->type_number(v, obj, name, errp);
}
}
+
+void output_type_enum(Visitor *v, int *obj, const char *strings[],
+ const char *kind, const char *name,
+ Error **errp)
+{
+ int i = 0;
+ int value = *obj;
+ char *enum_str;
+
+ assert(strings);
+ while (strings[i++] != NULL);
+ if (value < 0 || value >= i - 1) {
+ error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
+ return;
+ }
+
+ enum_str = (char *)strings[value];
+ visit_type_str(v, &enum_str, name, errp);
+}
+
+void input_type_enum(Visitor *v, int *obj, const char *strings[],
+ const char *kind, const char *name,
+ Error **errp)
+{
+ int64_t value = 0;
+ char *enum_str;
+
+ assert(strings);
+
+ visit_type_str(v, &enum_str, name, errp);
+ if (error_is_set(errp)) {
+ return;
+ }
+
+ while (strings[value] != NULL) {
+ if (strcmp(strings[value], enum_str) == 0) {
+ break;
+ }
+ value++;
+ }
+
+ if (strings[value] == NULL) {
+ error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
+ g_free(enum_str);
+ return;
+ }
+
+ g_free(enum_str);
+ *obj = value;
+}
diff --git a/qapi/qapi-visit-impl.h b/qapi/qapi-visit-impl.h
new file mode 100644
index 0000000000..0f3a1898fe
--- /dev/null
+++ b/qapi/qapi-visit-impl.h
@@ -0,0 +1,23 @@
+/*
+ * Core Definitions for QAPI Visitor implementations
+ *
+ * Copyright (C) 2012 Red Hat, Inc.
+ *
+ * Author: Paolo Bonizni <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+#ifndef QAPI_VISITOR_IMPL_H
+#define QAPI_VISITOR_IMPL_H
+
+#include "qapi/qapi-types-core.h"
+#include "qapi/qapi-visit-core.h"
+
+void input_type_enum(Visitor *v, int *obj, const char *strings[],
+ const char *kind, const char *name, Error **errp);
+void output_type_enum(Visitor *v, int *obj, const char *strings[],
+ const char *kind, const char *name, Error **errp);
+
+#endif
diff --git a/qapi/qmp-input-visitor.c b/qapi/qmp-input-visitor.c
index c78022bb87..e6b6152e08 100644
--- a/qapi/qmp-input-visitor.c
+++ b/qapi/qmp-input-visitor.c
@@ -12,6 +12,7 @@
*/
#include "qmp-input-visitor.h"
+#include "qapi/qapi-visit-impl.h"
#include "qemu-queue.h"
#include "qemu-common.h"
#include "qemu-objects.h"
@@ -217,37 +218,6 @@ static void qmp_input_type_number(Visitor *v, double *obj, const char *name,
*obj = qfloat_get_double(qobject_to_qfloat(qobj));
}
-static void qmp_input_type_enum(Visitor *v, int *obj, const char *strings[],
- const char *kind, const char *name,
- Error **errp)
-{
- int64_t value = 0;
- char *enum_str;
-
- assert(strings);
-
- qmp_input_type_str(v, &enum_str, name, errp);
- if (error_is_set(errp)) {
- return;
- }
-
- while (strings[value] != NULL) {
- if (strcmp(strings[value], enum_str) == 0) {
- break;
- }
- value++;
- }
-
- if (strings[value] == NULL) {
- error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
- g_free(enum_str);
- return;
- }
-
- g_free(enum_str);
- *obj = value;
-}
-
static void qmp_input_start_optional(Visitor *v, bool *present,
const char *name, Error **errp)
{
@@ -262,10 +232,6 @@ static void qmp_input_start_optional(Visitor *v, bool *present,
*present = true;
}
-static void qmp_input_end_optional(Visitor *v, Error **errp)
-{
-}
-
Visitor *qmp_input_get_visitor(QmpInputVisitor *v)
{
return &v->visitor;
@@ -288,13 +254,12 @@ QmpInputVisitor *qmp_input_visitor_new(QObject *obj)
v->visitor.start_list = qmp_input_start_list;
v->visitor.next_list = qmp_input_next_list;
v->visitor.end_list = qmp_input_end_list;
- v->visitor.type_enum = qmp_input_type_enum;
+ v->visitor.type_enum = input_type_enum;
v->visitor.type_int = qmp_input_type_int;
v->visitor.type_bool = qmp_input_type_bool;
v->visitor.type_str = qmp_input_type_str;
v->visitor.type_number = qmp_input_type_number;
v->visitor.start_optional = qmp_input_start_optional;
- v->visitor.end_optional = qmp_input_end_optional;
v->obj = obj;
qobject_incref(v->obj);
diff --git a/qapi/qmp-output-visitor.c b/qapi/qmp-output-visitor.c
index f76d0159cd..e0697b0d0f 100644
--- a/qapi/qmp-output-visitor.c
+++ b/qapi/qmp-output-visitor.c
@@ -12,6 +12,7 @@
*/
#include "qmp-output-visitor.h"
+#include "qapi/qapi-visit-impl.h"
#include "qemu-queue.h"
#include "qemu-common.h"
#include "qemu-objects.h"
@@ -180,25 +181,6 @@ static void qmp_output_type_number(Visitor *v, double *obj, const char *name,
qmp_output_add(qov, name, qfloat_from_double(*obj));
}
-static void qmp_output_type_enum(Visitor *v, int *obj, const char *strings[],
- const char *kind, const char *name,
- Error **errp)
-{
- int i = 0;
- int value = *obj;
- char *enum_str;
-
- assert(strings);
- while (strings[i++] != NULL);
- if (value < 0 || value >= i - 1) {
- error_set(errp, QERR_INVALID_PARAMETER, name ? name : "null");
- return;
- }
-
- enum_str = (char *)strings[value];
- qmp_output_type_str(v, &enum_str, name, errp);
-}
-
QObject *qmp_output_get_qobject(QmpOutputVisitor *qov)
{
QObject *obj = qmp_output_first(qov);
@@ -239,7 +221,7 @@ QmpOutputVisitor *qmp_output_visitor_new(void)
v->visitor.start_list = qmp_output_start_list;
v->visitor.next_list = qmp_output_next_list;
v->visitor.end_list = qmp_output_end_list;
- v->visitor.type_enum = qmp_output_type_enum;
+ v->visitor.type_enum = output_type_enum;
v->visitor.type_int = qmp_output_type_int;
v->visitor.type_bool = qmp_output_type_bool;
v->visitor.type_str = qmp_output_type_str;
diff --git a/qapi/string-input-visitor.c b/qapi/string-input-visitor.c
new file mode 100644
index 0000000000..497eb9a60a
--- /dev/null
+++ b/qapi/string-input-visitor.c
@@ -0,0 +1,138 @@
+/*
+ * String parsing visitor
+ *
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Author: Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "string-input-visitor.h"
+#include "qapi/qapi-visit-impl.h"
+#include "qerror.h"
+
+struct StringInputVisitor
+{
+ Visitor visitor;
+ const char *string;
+};
+
+static void parse_type_int(Visitor *v, int64_t *obj, const char *name,
+ Error **errp)
+{
+ StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ char *endp = (char *) siv->string;
+ long long val;
+
+ errno = 0;
+ if (siv->string) {
+ val = strtoll(siv->string, &endp, 0);
+ }
+ if (!siv->string || errno || endp == siv->string || *endp) {
+ error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "integer");
+ return;
+ }
+
+ *obj = val;
+}
+
+static void parse_type_bool(Visitor *v, bool *obj, const char *name,
+ Error **errp)
+{
+ StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+
+ if (siv->string) {
+ if (!strcasecmp(siv->string, "on") ||
+ !strcasecmp(siv->string, "yes") ||
+ !strcasecmp(siv->string, "true")) {
+ *obj = true;
+ return;
+ }
+ if (!strcasecmp(siv->string, "off") ||
+ !strcasecmp(siv->string, "no") ||
+ !strcasecmp(siv->string, "false")) {
+ *obj = false;
+ return;
+ }
+ }
+
+ error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "boolean");
+}
+
+static void parse_type_str(Visitor *v, char **obj, const char *name,
+ Error **errp)
+{
+ StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ if (siv->string) {
+ *obj = g_strdup(siv->string);
+ } else {
+ error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "string");
+ }
+}
+
+static void parse_type_number(Visitor *v, double *obj, const char *name,
+ Error **errp)
+{
+ StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+ char *endp = (char *) siv->string;
+ double val;
+
+ errno = 0;
+ if (siv->string) {
+ val = strtod(siv->string, &endp);
+ }
+ if (!siv->string || errno || endp == siv->string || *endp) {
+ error_set(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
+ "number");
+ return;
+ }
+
+ *obj = val;
+}
+
+static void parse_start_optional(Visitor *v, bool *present,
+ const char *name, Error **errp)
+{
+ StringInputVisitor *siv = DO_UPCAST(StringInputVisitor, visitor, v);
+
+ if (!siv->string) {
+ *present = false;
+ return;
+ }
+
+ *present = true;
+}
+
+Visitor *string_input_get_visitor(StringInputVisitor *v)
+{
+ return &v->visitor;
+}
+
+void string_input_visitor_cleanup(StringInputVisitor *v)
+{
+ g_free(v);
+}
+
+StringInputVisitor *string_input_visitor_new(const char *str)
+{
+ StringInputVisitor *v;
+
+ v = g_malloc0(sizeof(*v));
+
+ v->visitor.type_enum = input_type_enum;
+ v->visitor.type_int = parse_type_int;
+ v->visitor.type_bool = parse_type_bool;
+ v->visitor.type_str = parse_type_str;
+ v->visitor.type_number = parse_type_number;
+ v->visitor.start_optional = parse_start_optional;
+
+ v->string = str;
+ return v;
+}
diff --git a/qapi/string-input-visitor.h b/qapi/string-input-visitor.h
new file mode 100644
index 0000000000..d269d42cef
--- /dev/null
+++ b/qapi/string-input-visitor.h
@@ -0,0 +1,25 @@
+/*
+ * String parsing Visitor
+ *
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Author: Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef STRING_INPUT_VISITOR_H
+#define STRING_INPUT_VISITOR_H
+
+#include "qapi-visit-core.h"
+
+typedef struct StringInputVisitor StringInputVisitor;
+
+StringInputVisitor *string_input_visitor_new(const char *str);
+void string_input_visitor_cleanup(StringInputVisitor *v);
+
+Visitor *string_input_get_visitor(StringInputVisitor *v);
+
+#endif
diff --git a/qapi/string-output-visitor.c b/qapi/string-output-visitor.c
new file mode 100644
index 0000000000..92b0305212
--- /dev/null
+++ b/qapi/string-output-visitor.c
@@ -0,0 +1,89 @@
+/*
+ * String printing Visitor
+ *
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Author: Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include "string-output-visitor.h"
+#include "qapi/qapi-visit-impl.h"
+#include "qerror.h"
+
+struct StringOutputVisitor
+{
+ Visitor visitor;
+ char *string;
+};
+
+static void string_output_set(StringOutputVisitor *sov, char *string)
+{
+ g_free(sov->string);
+ sov->string = string;
+}
+
+static void print_type_int(Visitor *v, int64_t *obj, const char *name,
+ Error **errp)
+{
+ StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ string_output_set(sov, g_strdup_printf("%lld", (long long) *obj));
+}
+
+static void print_type_bool(Visitor *v, bool *obj, const char *name,
+ Error **errp)
+{
+ StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ string_output_set(sov, g_strdup(*obj ? "true" : "false"));
+}
+
+static void print_type_str(Visitor *v, char **obj, const char *name,
+ Error **errp)
+{
+ StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ string_output_set(sov, g_strdup(*obj ? *obj : ""));
+}
+
+static void print_type_number(Visitor *v, double *obj, const char *name,
+ Error **errp)
+{
+ StringOutputVisitor *sov = DO_UPCAST(StringOutputVisitor, visitor, v);
+ string_output_set(sov, g_strdup_printf("%g", *obj));
+}
+
+char *string_output_get_string(StringOutputVisitor *sov)
+{
+ char *string = sov->string;
+ sov->string = NULL;
+ return string;
+}
+
+Visitor *string_output_get_visitor(StringOutputVisitor *sov)
+{
+ return &sov->visitor;
+}
+
+void string_output_visitor_cleanup(StringOutputVisitor *sov)
+{
+ g_free(sov->string);
+ g_free(sov);
+}
+
+StringOutputVisitor *string_output_visitor_new(void)
+{
+ StringOutputVisitor *v;
+
+ v = g_malloc0(sizeof(*v));
+
+ v->visitor.type_enum = output_type_enum;
+ v->visitor.type_int = print_type_int;
+ v->visitor.type_bool = print_type_bool;
+ v->visitor.type_str = print_type_str;
+ v->visitor.type_number = print_type_number;
+
+ return v;
+}
diff --git a/qapi/string-output-visitor.h b/qapi/string-output-visitor.h
new file mode 100644
index 0000000000..8868454110
--- /dev/null
+++ b/qapi/string-output-visitor.h
@@ -0,0 +1,26 @@
+/*
+ * String printing Visitor
+ *
+ * Copyright Red Hat, Inc. 2012
+ *
+ * Author: Paolo Bonzini <pbonzini@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING.LIB file in the top-level directory.
+ *
+ */
+
+#ifndef STRING_OUTPUT_VISITOR_H
+#define STRING_OUTPUT_VISITOR_H
+
+#include "qapi-visit-core.h"
+
+typedef struct StringOutputVisitor StringOutputVisitor;
+
+StringOutputVisitor *string_output_visitor_new(void);
+void string_output_visitor_cleanup(StringOutputVisitor *v);
+
+char *string_output_get_string(StringOutputVisitor *v);
+Visitor *string_output_get_visitor(StringOutputVisitor *v);
+
+#endif
diff --git a/qemu-char.c b/qemu-char.c
index b1d80dd24e..bb9e3f50a8 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -218,15 +218,13 @@ static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
return len;
}
-static int qemu_chr_open_null(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_null(QemuOpts *opts)
{
CharDriverState *chr;
chr = g_malloc0(sizeof(CharDriverState));
chr->chr_write = null_chr_write;
-
- *_chr= chr;
- return 0;
+ return chr;
}
/* MUX driver for serial I/O splitting */
@@ -636,21 +634,19 @@ static CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
return chr;
}
-static int qemu_chr_open_file_out(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_file_out(QemuOpts *opts)
{
int fd_out;
TFR(fd_out = qemu_open(qemu_opt_get(opts, "path"),
O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666));
if (fd_out < 0) {
- return -errno;
+ return NULL;
}
-
- *_chr = qemu_chr_open_fd(-1, fd_out);
- return 0;
+ return qemu_chr_open_fd(-1, fd_out);
}
-static int qemu_chr_open_pipe(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_pipe(QemuOpts *opts)
{
int fd_in, fd_out;
char filename_in[256], filename_out[256];
@@ -658,7 +654,7 @@ static int qemu_chr_open_pipe(QemuOpts *opts, CharDriverState **_chr)
if (filename == NULL) {
fprintf(stderr, "chardev: pipe: no filename given\n");
- return -EINVAL;
+ return NULL;
}
snprintf(filename_in, 256, "%s.in", filename);
@@ -672,12 +668,10 @@ static int qemu_chr_open_pipe(QemuOpts *opts, CharDriverState **_chr)
close(fd_out);
TFR(fd_in = fd_out = qemu_open(filename, O_RDWR | O_BINARY));
if (fd_in < 0) {
- return -errno;
+ return NULL;
}
}
-
- *_chr = qemu_chr_open_fd(fd_in, fd_out);
- return 0;
+ return qemu_chr_open_fd(fd_in, fd_out);
}
@@ -768,14 +762,13 @@ static void qemu_chr_close_stdio(struct CharDriverState *chr)
fd_chr_close(chr);
}
-static int qemu_chr_open_stdio(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_stdio(QemuOpts *opts)
{
CharDriverState *chr;
if (stdio_nb_clients >= STDIO_MAX_CLIENTS) {
- return -EBUSY;
+ return NULL;
}
-
if (stdio_nb_clients == 0) {
old_fd0_flags = fcntl(0, F_GETFL);
tcgetattr (0, &oldtty);
@@ -792,8 +785,7 @@ static int qemu_chr_open_stdio(QemuOpts *opts, CharDriverState **_chr)
display_type != DT_NOGRAPHIC);
qemu_chr_fe_set_echo(chr, false);
- *_chr = chr;
- return 0;
+ return chr;
}
#ifdef __sun__
@@ -980,7 +972,7 @@ static void pty_chr_close(struct CharDriverState *chr)
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
-static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
{
CharDriverState *chr;
PtyCharDriver *s;
@@ -995,7 +987,7 @@ static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr)
#endif
if (openpty(&master_fd, &slave_fd, pty_name, NULL, NULL) < 0) {
- return -errno;
+ return NULL;
}
/* Set raw attributes on the pty. */
@@ -1021,8 +1013,7 @@ static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr)
s->fd = master_fd;
s->timer = qemu_new_timer_ms(rt_clock, pty_chr_timer, chr);
- *_chr = chr;
- return 0;
+ return chr;
}
static void tty_serial_init(int fd, int speed,
@@ -1223,7 +1214,7 @@ static void qemu_chr_close_tty(CharDriverState *chr)
}
}
-static int qemu_chr_open_tty(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_tty(QemuOpts *opts)
{
const char *filename = qemu_opt_get(opts, "path");
CharDriverState *chr;
@@ -1231,20 +1222,18 @@ static int qemu_chr_open_tty(QemuOpts *opts, CharDriverState **_chr)
TFR(fd = qemu_open(filename, O_RDWR | O_NONBLOCK));
if (fd < 0) {
- return -errno;
+ return NULL;
}
tty_serial_init(fd, 115200, 'N', 8, 1);
chr = qemu_chr_open_fd(fd, fd);
chr->chr_ioctl = tty_serial_ioctl;
chr->chr_close = qemu_chr_close_tty;
-
- *_chr = chr;
- return 0;
+ return chr;
}
#else /* ! __linux__ && ! __sun__ */
-static int qemu_chr_open_pty(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_pty(QemuOpts *opts)
{
- return -ENOTSUP;
+ return NULL;
}
#endif /* __linux__ || __sun__ */
@@ -1358,21 +1347,21 @@ static void pp_close(CharDriverState *chr)
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
-static int qemu_chr_open_pp(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
{
const char *filename = qemu_opt_get(opts, "path");
CharDriverState *chr;
ParallelCharDriver *drv;
int fd;
- TFR(fd = open(filename, O_RDWR));
+ TFR(fd = qemu_open(filename, O_RDWR));
if (fd < 0) {
- return -errno;
+ return NULL;
}
if (ioctl(fd, PPCLAIM) < 0) {
close(fd);
- return -errno;
+ return NULL;
}
drv = g_malloc0(sizeof(ParallelCharDriver));
@@ -1387,8 +1376,7 @@ static int qemu_chr_open_pp(QemuOpts *opts, CharDriverState **_chr)
qemu_chr_generic_open(chr);
- *_chr = chr;
- return 0;
+ return chr;
}
#endif /* __linux__ */
@@ -1430,7 +1418,7 @@ static int pp_ioctl(CharDriverState *chr, int cmd, void *arg)
return 0;
}
-static int qemu_chr_open_pp(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_pp(QemuOpts *opts)
{
const char *filename = qemu_opt_get(opts, "path");
CharDriverState *chr;
@@ -1438,16 +1426,14 @@ static int qemu_chr_open_pp(QemuOpts *opts, CharDriverState **_chr)
fd = qemu_open(filename, O_RDWR);
if (fd < 0) {
- return -errno;
+ return NULL;
}
chr = g_malloc0(sizeof(CharDriverState));
chr->opaque = (void *)(intptr_t)fd;
chr->chr_write = null_chr_write;
chr->chr_ioctl = pp_ioctl;
-
- *_chr = chr;
- return 0;
+ return chr;
}
#endif
@@ -1663,7 +1649,7 @@ static int win_chr_poll(void *opaque)
return 0;
}
-static int qemu_chr_open_win(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_win(QemuOpts *opts)
{
const char *filename = qemu_opt_get(opts, "path");
CharDriverState *chr;
@@ -1678,12 +1664,10 @@ static int qemu_chr_open_win(QemuOpts *opts, CharDriverState **_chr)
if (win_chr_init(chr, filename) < 0) {
g_free(s);
g_free(chr);
- return -EIO;
+ return NULL;
}
qemu_chr_generic_open(chr);
-
- *_chr = chr;
- return 0;
+ return chr;
}
static int win_chr_pipe_poll(void *opaque)
@@ -1765,7 +1749,7 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename)
}
-static int qemu_chr_open_win_pipe(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_win_pipe(QemuOpts *opts)
{
const char *filename = qemu_opt_get(opts, "path");
CharDriverState *chr;
@@ -1780,15 +1764,13 @@ static int qemu_chr_open_win_pipe(QemuOpts *opts, CharDriverState **_chr)
if (win_chr_pipe_init(chr, filename) < 0) {
g_free(s);
g_free(chr);
- return -EIO;
+ return NULL;
}
qemu_chr_generic_open(chr);
-
- *_chr = chr;
- return 0;
+ return chr;
}
-static int qemu_chr_open_win_file(HANDLE fd_out, CharDriverState **pchr)
+static CharDriverState *qemu_chr_open_win_file(HANDLE fd_out)
{
CharDriverState *chr;
WinCharState *s;
@@ -1799,16 +1781,15 @@ static int qemu_chr_open_win_file(HANDLE fd_out, CharDriverState **pchr)
chr->opaque = s;
chr->chr_write = win_chr_write;
qemu_chr_generic_open(chr);
- *pchr = chr;
- return 0;
+ return chr;
}
-static int qemu_chr_open_win_con(QemuOpts *opts, CharDriverState **chr)
+static CharDriverState *qemu_chr_open_win_con(QemuOpts *opts)
{
- return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE), chr);
+ return qemu_chr_open_win_file(GetStdHandle(STD_OUTPUT_HANDLE));
}
-static int qemu_chr_open_win_file_out(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_win_file_out(QemuOpts *opts)
{
const char *file_out = qemu_opt_get(opts, "path");
HANDLE fd_out;
@@ -1816,10 +1797,10 @@ static int qemu_chr_open_win_file_out(QemuOpts *opts, CharDriverState **_chr)
fd_out = CreateFile(file_out, GENERIC_WRITE, FILE_SHARE_READ, NULL,
OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (fd_out == INVALID_HANDLE_VALUE) {
- return -EIO;
+ return NULL;
}
- return qemu_chr_open_win_file(fd_out, _chr);
+ return qemu_chr_open_win_file(fd_out);
}
static int win_stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
@@ -1960,7 +1941,7 @@ static void win_stdio_close(CharDriverState *chr)
stdio_nb_clients--;
}
-static int qemu_chr_open_win_stdio(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_win_stdio(QemuOpts *opts)
{
CharDriverState *chr;
WinStdioCharState *stdio;
@@ -1969,7 +1950,7 @@ static int qemu_chr_open_win_stdio(QemuOpts *opts, CharDriverState **_chr)
if (stdio_nb_clients >= STDIO_MAX_CLIENTS
|| ((display_type != DT_NOGRAPHIC) && (stdio_nb_clients != 0))) {
- return -EIO;
+ return NULL;
}
chr = g_malloc0(sizeof(CharDriverState));
@@ -2028,9 +2009,7 @@ static int qemu_chr_open_win_stdio(QemuOpts *opts, CharDriverState **_chr)
chr->chr_set_echo = qemu_chr_set_echo_win_stdio;
qemu_chr_fe_set_echo(chr, false);
- *_chr = chr;
-
- return 0;
+ return chr;
}
#endif /* !_WIN32 */
@@ -2111,12 +2090,11 @@ static void udp_chr_close(CharDriverState *chr)
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
-static int qemu_chr_open_udp(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_udp(QemuOpts *opts)
{
CharDriverState *chr = NULL;
NetCharDriver *s = NULL;
int fd = -1;
- int ret;
chr = g_malloc0(sizeof(CharDriverState));
s = g_malloc0(sizeof(NetCharDriver));
@@ -2124,7 +2102,6 @@ static int qemu_chr_open_udp(QemuOpts *opts, CharDriverState **_chr)
fd = inet_dgram_opts(opts);
if (fd < 0) {
fprintf(stderr, "inet_dgram_opts failed\n");
- ret = -errno;
goto return_err;
}
@@ -2135,9 +2112,7 @@ static int qemu_chr_open_udp(QemuOpts *opts, CharDriverState **_chr)
chr->chr_write = udp_chr_write;
chr->chr_update_read_handler = udp_chr_update_read_handler;
chr->chr_close = udp_chr_close;
-
- *_chr = chr;
- return 0;
+ return chr;
return_err:
g_free(chr);
@@ -2145,7 +2120,7 @@ return_err:
if (fd >= 0) {
closesocket(fd);
}
- return ret;
+ return NULL;
}
/***********************************************************/
@@ -2436,7 +2411,7 @@ static void tcp_chr_close(CharDriverState *chr)
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
}
-static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
+static CharDriverState *qemu_chr_open_socket(QemuOpts *opts)
{
CharDriverState *chr = NULL;
TCPCharDriver *s = NULL;
@@ -2446,7 +2421,6 @@ static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
int do_nodelay;
int is_unix;
int is_telnet;
- int ret;
is_listen = qemu_opt_get_bool(opts, "server", 0);
is_waitconnect = qemu_opt_get_bool(opts, "wait", 1);
@@ -2473,7 +2447,6 @@ static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
}
}
if (fd < 0) {
- ret = -errno;
goto fail;
}
@@ -2528,16 +2501,14 @@ static int qemu_chr_open_socket(QemuOpts *opts, CharDriverState **_chr)
tcp_chr_accept(chr);
socket_set_nonblock(s->listen_fd);
}
-
- *_chr = chr;
- return 0;
+ return chr;
fail:
if (fd >= 0)
closesocket(fd);
g_free(s);
g_free(chr);
- return ret;
+ return NULL;
}
/***********************************************************/
@@ -2730,7 +2701,7 @@ fail:
static const struct {
const char *name;
- int (*open)(QemuOpts *opts, CharDriverState **chr);
+ CharDriverState *(*open)(QemuOpts *opts);
} backend_table[] = {
{ .name = "null", .open = qemu_chr_open_null },
{ .name = "socket", .open = qemu_chr_open_socket },
@@ -2771,7 +2742,6 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
{
CharDriverState *chr;
int i;
- int ret;
if (qemu_opts_id(opts) == NULL) {
fprintf(stderr, "chardev: no id specified\n");
@@ -2793,10 +2763,10 @@ CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
return NULL;
}
- ret = backend_table[i].open(opts, &chr);
- if (ret < 0) {
- fprintf(stderr, "chardev: opening backend \"%s\" failed: %s\n",
- qemu_opt_get(opts, "backend"), strerror(-ret));
+ chr = backend_table[i].open(opts);
+ if (!chr) {
+ fprintf(stderr, "chardev: opening backend \"%s\" failed\n",
+ qemu_opt_get(opts, "backend"));
return NULL;
}
diff --git a/qemu-config.c b/qemu-config.c
index c9763e0b93..7d9da787c7 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -566,6 +566,18 @@ static QemuOptsList qemu_machine_opts = {
.name = "kvm_shadow_mem",
.type = QEMU_OPT_SIZE,
.help = "KVM shadow MMU size",
+ }, {
+ .name = "kernel",
+ .type = QEMU_OPT_STRING,
+ .help = "Linux kernel image file",
+ }, {
+ .name = "initrd",
+ .type = QEMU_OPT_STRING,
+ .help = "Linux initial ramdisk file",
+ }, {
+ .name = "append",
+ .type = QEMU_OPT_STRING,
+ .help = "Linux kernel command line",
},
{ /* End of list */ }
},
diff --git a/qemu-sockets.c b/qemu-sockets.c
index 61b2247077..6bcb8e3e0f 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -26,7 +26,6 @@
# define AI_ADDRCONFIG 0
#endif
-static int sockets_debug = 0;
static const int on=1, off=0;
/* used temporarely until all users are converted to QemuOpts */
@@ -101,21 +100,6 @@ const char *inet_strfamily(int family)
return "unknown";
}
-static void inet_print_addrinfo(const char *tag, struct addrinfo *res)
-{
- struct addrinfo *e;
- char uaddr[INET6_ADDRSTRLEN+1];
- char uport[33];
-
- for (e = res; e != NULL; e = e->ai_next) {
- getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
- uaddr,INET6_ADDRSTRLEN,uport,32,
- NI_NUMERICHOST | NI_NUMERICSERV);
- fprintf(stderr,"%s: getaddrinfo: family %s, host %s, port %s\n",
- tag, inet_strfamily(e->ai_family), uaddr, uport);
- }
-}
-
int inet_listen_opts(QemuOpts *opts, int port_offset)
{
struct addrinfo ai,*res,*e;
@@ -123,7 +107,7 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
char port[33];
char uaddr[INET6_ADDRSTRLEN+1];
char uport[33];
- int slisten,rc,to,try_next;
+ int slisten, rc, to, port_min, port_max, p;
memset(&ai,0, sizeof(ai));
ai.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
@@ -153,8 +137,6 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
gai_strerror(rc));
return -1;
}
- if (sockets_debug)
- inet_print_addrinfo(__FUNCTION__, res);
/* create socket + bind */
for (e = res; e != NULL; e = e->ai_next) {
@@ -177,23 +159,18 @@ int inet_listen_opts(QemuOpts *opts, int port_offset)
}
#endif
- for (;;) {
+ port_min = inet_getport(e);
+ port_max = to ? to + port_offset : port_min;
+ for (p = port_min; p <= port_max; p++) {
+ inet_setport(e, p);
if (bind(slisten, e->ai_addr, e->ai_addrlen) == 0) {
- if (sockets_debug)
- fprintf(stderr,"%s: bind(%s,%s,%d): OK\n", __FUNCTION__,
- inet_strfamily(e->ai_family), uaddr, inet_getport(e));
goto listen;
}
- try_next = to && (inet_getport(e) <= to + port_offset);
- if (!try_next || sockets_debug)
+ if (p == port_max) {
fprintf(stderr,"%s: bind(%s,%s,%d): %s\n", __FUNCTION__,
inet_strfamily(e->ai_family), uaddr, inet_getport(e),
strerror(errno));
- if (try_next) {
- inet_setport(e, inet_getport(e) + 1);
- continue;
}
- break;
}
closesocket(slisten);
}
@@ -249,8 +226,6 @@ int inet_connect_opts(QemuOpts *opts)
gai_strerror(rc));
return -1;
}
- if (sockets_debug)
- inet_print_addrinfo(__FUNCTION__, res);
for (e = res; e != NULL; e = e->ai_next) {
if (getnameinfo((struct sockaddr*)e->ai_addr,e->ai_addrlen,
@@ -269,17 +244,13 @@ int inet_connect_opts(QemuOpts *opts)
/* connect to peer */
if (connect(sock,e->ai_addr,e->ai_addrlen) < 0) {
- if (sockets_debug || NULL == e->ai_next)
+ if (NULL == e->ai_next)
fprintf(stderr, "%s: connect(%s,%s,%s,%s): %s\n", __FUNCTION__,
inet_strfamily(e->ai_family),
e->ai_canonname, uaddr, uport, strerror(errno));
closesocket(sock);
continue;
}
- if (sockets_debug)
- fprintf(stderr, "%s: connect(%s,%s,%s,%s): OK\n", __FUNCTION__,
- inet_strfamily(e->ai_family),
- e->ai_canonname, uaddr, uport);
freeaddrinfo(res);
return sock;
}
@@ -322,10 +293,6 @@ int inet_dgram_opts(QemuOpts *opts)
gai_strerror(rc));
return -1;
}
- if (sockets_debug) {
- fprintf(stderr, "%s: peer (%s:%s)\n", __FUNCTION__, addr, port);
- inet_print_addrinfo(__FUNCTION__, peer);
- }
/* lookup local addr */
memset(&ai,0, sizeof(ai));
@@ -346,10 +313,6 @@ int inet_dgram_opts(QemuOpts *opts)
gai_strerror(rc));
return -1;
}
- if (sockets_debug) {
- fprintf(stderr, "%s: local (%s:%s)\n", __FUNCTION__, addr, port);
- inet_print_addrinfo(__FUNCTION__, local);
- }
/* create socket */
sock = qemu_socket(peer->ai_family, peer->ai_socktype, peer->ai_protocol);
@@ -541,8 +504,6 @@ int unix_listen_opts(QemuOpts *opts)
goto err;
}
- if (sockets_debug)
- fprintf(stderr, "bind(unix:%s): OK\n", un.sun_path);
return sock;
err:
@@ -576,8 +537,6 @@ int unix_connect_opts(QemuOpts *opts)
return -1;
}
- if (sockets_debug)
- fprintf(stderr, "connect(unix:%s): OK\n", path);
return sock;
}
diff --git a/qmp-commands.hx b/qmp-commands.hx
index b5e2ab8574..dee95f1d67 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -910,8 +910,8 @@ EQMP
{
.name = "add_client",
- .args_type = "protocol:s,fdname:s,skipauth:b?",
- .params = "protocol fdname skipauth",
+ .args_type = "protocol:s,fdname:s,skipauth:b?,tls:b?",
+ .params = "protocol fdname skipauth tls",
.help = "add a graphics client",
.user_print = monitor_user_noop,
.mhandler.cmd_new = add_graphics_client,
@@ -927,6 +927,8 @@ Arguments:
- "protocol": protocol name (json-string)
- "fdname": file descriptor name (json-string)
+- "skipauth": whether to skip authentication (json-bool, optional)
+- "tls": whether to perform TLS (json-bool, optional)
Example:
diff --git a/qom/object.c b/qom/object.c
index 0cbd9bb004..aa037d299f 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -13,6 +13,8 @@
#include "qemu/object.h"
#include "qemu-common.h"
#include "qapi/qapi-visit-core.h"
+#include "qapi/string-input-visitor.h"
+#include "qapi/string-output-visitor.h"
/* TODO: replace QObject with a simpler visitor to avoid a dependency
* of the QOM core on QObject? */
@@ -262,7 +264,7 @@ void object_initialize_with_type(void *data, TypeImpl *type)
Object *obj = data;
g_assert(type != NULL);
- g_assert(type->instance_size >= sizeof(ObjectClass));
+ g_assert(type->instance_size >= sizeof(Object));
type_class_init(type);
g_assert(type->abstract == false);
@@ -782,6 +784,29 @@ int64_t object_property_get_int(Object *obj, const char *name,
return retval;
}
+void object_property_parse(Object *obj, const char *string,
+ const char *name, Error **errp)
+{
+ StringInputVisitor *mi;
+ mi = string_input_visitor_new(string);
+ object_property_set(obj, string_input_get_visitor(mi), name, errp);
+
+ string_input_visitor_cleanup(mi);
+}
+
+char *object_property_print(Object *obj, const char *name,
+ Error **errp)
+{
+ StringOutputVisitor *mo;
+ char *string;
+
+ mo = string_output_visitor_new();
+ object_property_get(obj, string_output_get_visitor(mo), name, NULL);
+ string = string_output_get_string(mo);
+ string_output_visitor_cleanup(mo);
+ return string;
+}
+
const char *object_property_get_type(Object *obj, const char *name, Error **errp)
{
ObjectProperty *prop = object_property_find(obj, name);
@@ -867,6 +892,7 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
Object **child = opaque;
+ Object *old_target;
bool ambiguous = false;
const char *type;
char *path;
@@ -876,10 +902,8 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
visit_type_str(v, &path, name, errp);
- if (*child) {
- object_unref(*child);
- *child = NULL;
- }
+ old_target = *child;
+ *child = NULL;
if (strcmp(path, "") != 0) {
Object *target;
@@ -905,6 +929,10 @@ static void object_set_link_property(Object *obj, Visitor *v, void *opaque,
}
g_free(path);
+
+ if (old_target != NULL) {
+ object_unref(old_target);
+ }
}
void object_property_add_link(Object *obj, const char *name,
diff --git a/spice-qemu-char.c b/spice-qemu-char.c
index 7e8eaa9fd8..1e735ffd09 100644
--- a/spice-qemu-char.c
+++ b/spice-qemu-char.c
@@ -188,7 +188,7 @@ static void print_allowed_subtypes(void)
fprintf(stderr, "\n");
}
-int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr)
+CharDriverState *qemu_chr_open_spice(QemuOpts *opts)
{
CharDriverState *chr;
SpiceCharDriver *s;
@@ -200,7 +200,7 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr)
if (name == NULL) {
fprintf(stderr, "spice-qemu-char: missing name parameter\n");
print_allowed_subtypes();
- return -EINVAL;
+ return NULL;
}
for(;*psubtype != NULL; ++psubtype) {
if (strcmp(name, *psubtype) == 0) {
@@ -211,7 +211,7 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr)
if (subtype == NULL) {
fprintf(stderr, "spice-qemu-char: unsupported name\n");
print_allowed_subtypes();
- return -EINVAL;
+ return NULL;
}
chr = g_malloc0(sizeof(CharDriverState));
@@ -233,6 +233,5 @@ int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr)
}
#endif
- *_chr = chr;
- return 0;
+ return chr;
}
diff --git a/sysconfigs/target/target-x86_64.conf b/sysconfigs/target/target-x86_64.conf
index 43ad282b5c..d0503804c2 100644
--- a/sysconfigs/target/target-x86_64.conf
+++ b/sysconfigs/target/target-x86_64.conf
@@ -7,9 +7,9 @@
family = "6"
model = "2"
stepping = "3"
- feature_edx = "sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36"
- feature_ecx = "sse3 ssse3"
- extfeature_edx = "fxsr mmx pat cmov pge apic cx8 mce pae msr tsc pse de fpu lm syscall nx"
+ feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu"
+ feature_ecx = "ssse3 sse3"
+ extfeature_edx = "i64 xd syscall"
extfeature_ecx = "lahf_lm"
xlevel = "0x8000000A"
model_id = "Intel Celeron_4x0 (Conroe/Merom Class Core 2)"
@@ -21,9 +21,9 @@
family = "6"
model = "2"
stepping = "3"
- feature_edx = "sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36"
- feature_ecx = "sse3 cx16 ssse3 sse4.1"
- extfeature_edx = "fxsr mmx pat cmov pge apic cx8 mce pae msr tsc pse de fpu lm syscall nx"
+ feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu"
+ feature_ecx = "sse4.1 cx16 ssse3 sse3"
+ extfeature_edx = "i64 xd syscall"
extfeature_ecx = "lahf_lm"
xlevel = "0x8000000A"
model_id = "Intel Core 2 Duo P9xxx (Penryn Class Core 2)"
@@ -35,24 +35,38 @@
family = "6"
model = "2"
stepping = "3"
- feature_edx = "sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36"
- feature_ecx = "sse3 cx16 ssse3 sse4.1 sse4.2 popcnt"
- extfeature_edx = "fxsr mmx pat cmov pge apic cx8 mce pae msr tsc pse de fpu lm syscall nx"
+ feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu"
+ feature_ecx = "popcnt sse4.2 sse4.1 cx16 ssse3 sse3"
+ extfeature_edx = "i64 syscall xd"
extfeature_ecx = "lahf_lm"
xlevel = "0x8000000A"
model_id = "Intel Core i7 9xx (Nehalem Class Core i7)"
[cpudef]
+ name = "Westmere"
+ level = "11"
+ vendor = "GenuineIntel"
+ family = "6"
+ model = "44"
+ stepping = "1"
+ feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu"
+ feature_ecx = "aes popcnt sse4.2 sse4.1 cx16 ssse3 sse3"
+ extfeature_edx = "i64 syscall xd"
+ extfeature_ecx = "lahf_lm"
+ xlevel = "0x8000000A"
+ model_id = "Westmere E56xx/L56xx/X56xx (Nehalem-C)"
+
+[cpudef]
name = "Opteron_G1"
level = "5"
vendor = "AuthenticAMD"
family = "15"
model = "6"
stepping = "1"
- feature_edx = "sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36"
+ feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu"
feature_ecx = "sse3"
- extfeature_edx = "fxsr mmx pat cmov pge apic cx8 mce pae msr tsc pse de fpu lm syscall nx"
-# extfeature_ecx = ""
+ extfeature_edx = "lm fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu"
+ extfeature_ecx = " "
xlevel = "0x80000008"
model_id = "AMD Opteron 240 (Gen 1 Class Opteron)"
@@ -63,9 +77,9 @@
family = "15"
model = "6"
stepping = "1"
- feature_edx = "sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36"
- feature_ecx = "sse3 cx16"
- extfeature_edx = "fxsr mmx pat cmov pge apic cx8 mce pae msr tsc pse de fpu lm syscall nx rdtscp"
+ feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu"
+ feature_ecx = "cx16 sse3"
+ extfeature_edx = "lm rdtscp fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu"
extfeature_ecx = "svm lahf_lm"
xlevel = "0x80000008"
model_id = "AMD Opteron 22xx (Gen 2 Class Opteron)"
@@ -77,10 +91,10 @@
family = "15"
model = "6"
stepping = "1"
- feature_edx = "sse2 sse fxsr mmx pat cmov pge sep apic cx8 mce pae msr tsc pse de fpu mtrr clflush mca pse36"
- feature_ecx = "sse3 cx16 monitor popcnt"
- extfeature_edx = "fxsr mmx pat cmov pge apic cx8 mce pae msr tsc pse de fpu lm syscall nx rdtscp"
- extfeature_ecx = "svm sse4a abm misalignsse lahf_lm"
+ feature_edx = "sse2 sse fxsr mmx clflush pse36 pat cmov mca pge mtrr sep apic cx8 mce pae msr tsc pse de fpu"
+ feature_ecx = "popcnt cx16 monitor sse3"
+ extfeature_edx = "lm rdtscp fxsr mmx nx pse36 pat cmov mca pge mtrr syscall apic cx8 mce pae msr tsc pse de fpu"
+ extfeature_ecx = "misalignsse sse4a abm svm lahf_lm"
xlevel = "0x80000008"
model_id = "AMD Opteron 23xx (Gen 3 Class Opteron)"
diff --git a/target-i386/cpuid.c b/target-i386/cpuid.c
index b9bfeaff70..c2edb646fe 100644
--- a/target-i386/cpuid.c
+++ b/target-i386/cpuid.c
@@ -44,7 +44,7 @@ static const char *feature_name[] = {
"ht" /* Intel htt */, "tm", "ia64", "pbe",
};
static const char *ext_feature_name[] = {
- "pni|sse3" /* Intel,AMD sse3 */, "pclmuldq", "dtes64", "monitor",
+ "pni|sse3" /* Intel,AMD sse3 */, "pclmulqdq|pclmuldq", "dtes64", "monitor",
"ds_cpl", "vmx", "smx", "est",
"tm2", "ssse3", "cid", NULL,
"fma", "cx16", "xtpr", "pdcm",
@@ -59,9 +59,9 @@ static const char *ext2_feature_name[] = {
"cx8" /* AMD CMPXCHG8B */, "apic", NULL, "syscall",
"mtrr", "pge", "mca", "cmov",
"pat", "pse36", NULL, NULL /* Linux mp */,
- "nx" /* Intel xd */, NULL, "mmxext", "mmx",
- "fxsr", "fxsr_opt" /* AMD ffxsr */, "pdpe1gb" /* AMD Page1GB */, "rdtscp",
- NULL, "lm" /* Intel 64 */, "3dnowext", "3dnow",
+ "nx|xd", NULL, "mmxext", "mmx",
+ "fxsr", "fxsr_opt|ffxsr", "pdpe1gb" /* AMD Page1GB */, "rdtscp",
+ NULL, "lm|i64", "3dnowext", "3dnow",
};
static const char *ext3_feature_name[] = {
"lahf_lm" /* AMD LahfSahf */, "cmp_legacy", "svm", "extapic" /* AMD ExtApicSpace */,
@@ -597,6 +597,46 @@ static int check_features_against_host(x86_def_t *guest_def)
return rv;
}
+static void x86_cpuid_version_set_family(CPUX86State *env, int family)
+{
+ env->cpuid_version &= ~0xff00f00;
+ if (family > 0x0f) {
+ env->cpuid_version |= 0xf00 | ((family - 0x0f) << 20);
+ } else {
+ env->cpuid_version |= family << 8;
+ }
+}
+
+static void x86_cpuid_version_set_model(CPUX86State *env, int model)
+{
+ env->cpuid_version &= ~0xf00f0;
+ env->cpuid_version |= ((model & 0xf) << 4) | ((model >> 4) << 16);
+}
+
+static void x86_cpuid_version_set_stepping(CPUX86State *env, int stepping)
+{
+ env->cpuid_version &= ~0xf;
+ env->cpuid_version |= stepping & 0xf;
+}
+
+static void x86_cpuid_set_model_id(CPUX86State *env, const char *model_id)
+{
+ int c, len, i;
+
+ if (model_id == NULL) {
+ model_id = "";
+ }
+ len = strlen(model_id);
+ for (i = 0; i < 48; i++) {
+ if (i >= len) {
+ c = '\0';
+ } else {
+ c = (uint8_t)model_id[i];
+ }
+ env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
+ }
+}
+
static int cpu_x86_find_by_name(x86_def_t *x86_cpu_def, const char *cpu_model)
{
unsigned int i;
@@ -883,12 +923,9 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
}
env->cpuid_vendor_override = def->vendor_override;
env->cpuid_level = def->level;
- if (def->family > 0x0f)
- env->cpuid_version = 0xf00 | ((def->family - 0x0f) << 20);
- else
- env->cpuid_version = def->family << 8;
- env->cpuid_version |= ((def->model & 0xf) << 4) | ((def->model >> 4) << 16);
- env->cpuid_version |= def->stepping;
+ x86_cpuid_version_set_family(env, def->family);
+ x86_cpuid_version_set_model(env, def->model);
+ x86_cpuid_version_set_stepping(env, def->stepping);
env->cpuid_features = def->features;
env->cpuid_ext_features = def->ext_features;
env->cpuid_ext2_features = def->ext2_features;
@@ -910,20 +947,7 @@ int cpu_x86_register (CPUX86State *env, const char *cpu_model)
env->cpuid_ext3_features &= TCG_EXT3_FEATURES;
env->cpuid_svm_features &= TCG_SVM_FEATURES;
}
- {
- const char *model_id = def->model_id;
- int c, len, i;
- if (!model_id)
- model_id = "";
- len = strlen(model_id);
- for(i = 0; i < 48; i++) {
- if (i >= len)
- c = '\0';
- else
- c = (uint8_t)model_id[i];
- env->cpuid_model[i >> 2] |= c << (8 * (i & 3));
- }
- }
+ x86_cpuid_set_model_id(env, def->model_id);
return 0;
}
diff --git a/test-string-input-visitor.c b/test-string-input-visitor.c
new file mode 100644
index 0000000000..5370e32041
--- /dev/null
+++ b/test-string-input-visitor.c
@@ -0,0 +1,195 @@
+/*
+ * String Input Visitor unit-tests.
+ *
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * Authors:
+ * Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-input-visitor)
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+#include <stdarg.h>
+
+#include "qapi/string-input-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestInputVisitorData {
+ StringInputVisitor *siv;
+} TestInputVisitorData;
+
+static void visitor_input_teardown(TestInputVisitorData *data,
+ const void *unused)
+{
+ if (data->siv) {
+ string_input_visitor_cleanup(data->siv);
+ data->siv = NULL;
+ }
+}
+
+/* This is provided instead of a test setup function so that the JSON
+ string used by the tests are kept in the test functions (and not
+ int main()) */
+static
+Visitor *visitor_input_test_init(TestInputVisitorData *data,
+ const char *string)
+{
+ Visitor *v;
+
+ data->siv = string_input_visitor_new(string);
+ g_assert(data->siv != NULL);
+
+ v = string_input_get_visitor(data->siv);
+ g_assert(v != NULL);
+
+ return v;
+}
+
+static void test_visitor_in_int(TestInputVisitorData *data,
+ const void *unused)
+{
+ int64_t res = 0, value = -42;
+ Error *errp = NULL;
+ Visitor *v;
+
+ v = visitor_input_test_init(data, "-42");
+
+ visit_type_int(v, &res, NULL, &errp);
+ g_assert(!error_is_set(&errp));
+ g_assert_cmpint(res, ==, value);
+}
+
+static void test_visitor_in_bool(TestInputVisitorData *data,
+ const void *unused)
+{
+ Error *errp = NULL;
+ bool res = false;
+ Visitor *v;
+
+ v = visitor_input_test_init(data, "true");
+
+ visit_type_bool(v, &res, NULL, &errp);
+ g_assert(!error_is_set(&errp));
+ g_assert_cmpint(res, ==, true);
+ visitor_input_teardown(data, unused);
+
+ v = visitor_input_test_init(data, "yes");
+
+ visit_type_bool(v, &res, NULL, &errp);
+ g_assert(!error_is_set(&errp));
+ g_assert_cmpint(res, ==, true);
+ visitor_input_teardown(data, unused);
+
+ v = visitor_input_test_init(data, "on");
+
+ visit_type_bool(v, &res, NULL, &errp);
+ g_assert(!error_is_set(&errp));
+ g_assert_cmpint(res, ==, true);
+ visitor_input_teardown(data, unused);
+
+ v = visitor_input_test_init(data, "false");
+
+ visit_type_bool(v, &res, NULL, &errp);
+ g_assert(!error_is_set(&errp));
+ g_assert_cmpint(res, ==, false);
+ visitor_input_teardown(data, unused);
+
+ v = visitor_input_test_init(data, "no");
+
+ visit_type_bool(v, &res, NULL, &errp);
+ g_assert(!error_is_set(&errp));
+ g_assert_cmpint(res, ==, false);
+ visitor_input_teardown(data, unused);
+
+ v = visitor_input_test_init(data, "off");
+
+ visit_type_bool(v, &res, NULL, &errp);
+ g_assert(!error_is_set(&errp));
+ g_assert_cmpint(res, ==, false);
+}
+
+static void test_visitor_in_number(TestInputVisitorData *data,
+ const void *unused)
+{
+ double res = 0, value = 3.14;
+ Error *errp = NULL;
+ Visitor *v;
+
+ v = visitor_input_test_init(data, "3.14");
+
+ visit_type_number(v, &res, NULL, &errp);
+ g_assert(!error_is_set(&errp));
+ g_assert_cmpfloat(res, ==, value);
+}
+
+static void test_visitor_in_string(TestInputVisitorData *data,
+ const void *unused)
+{
+ char *res = NULL, *value = (char *) "Q E M U";
+ Error *errp = NULL;
+ Visitor *v;
+
+ v = visitor_input_test_init(data, value);
+
+ visit_type_str(v, &res, NULL, &errp);
+ g_assert(!error_is_set(&errp));
+ g_assert_cmpstr(res, ==, value);
+
+ g_free(res);
+}
+
+static void test_visitor_in_enum(TestInputVisitorData *data,
+ const void *unused)
+{
+ Error *errp = NULL;
+ Visitor *v;
+ EnumOne i;
+
+ for (i = 0; EnumOne_lookup[i]; i++) {
+ EnumOne res = -1;
+
+ v = visitor_input_test_init(data, EnumOne_lookup[i]);
+
+ visit_type_EnumOne(v, &res, NULL, &errp);
+ g_assert(!error_is_set(&errp));
+ g_assert_cmpint(i, ==, res);
+
+ visitor_input_teardown(data, NULL);
+ }
+
+ data->siv = NULL;
+}
+
+static void input_visitor_test_add(const char *testpath,
+ TestInputVisitorData *data,
+ void (*test_func)(TestInputVisitorData *data, const void *user_data))
+{
+ g_test_add(testpath, TestInputVisitorData, data, NULL, test_func,
+ visitor_input_teardown);
+}
+
+int main(int argc, char **argv)
+{
+ TestInputVisitorData in_visitor_data;
+
+ g_test_init(&argc, &argv, NULL);
+
+ input_visitor_test_add("/string-visitor/input/int",
+ &in_visitor_data, test_visitor_in_int);
+ input_visitor_test_add("/string-visitor/input/bool",
+ &in_visitor_data, test_visitor_in_bool);
+ input_visitor_test_add("/string-visitor/input/number",
+ &in_visitor_data, test_visitor_in_number);
+ input_visitor_test_add("/string-visitor/input/string",
+ &in_visitor_data, test_visitor_in_string);
+ input_visitor_test_add("/string-visitor/input/enum",
+ &in_visitor_data, test_visitor_in_enum);
+
+ g_test_run();
+
+ return 0;
+}
diff --git a/test-string-output-visitor.c b/test-string-output-visitor.c
new file mode 100644
index 0000000000..22909b84ef
--- /dev/null
+++ b/test-string-output-visitor.c
@@ -0,0 +1,188 @@
+/*
+ * String Output Visitor unit-tests.
+ *
+ * Copyright (C) 2012 Red Hat Inc.
+ *
+ * Authors:
+ * Paolo Bonzini <pbonzini@redhat.com> (based on test-qmp-output-visitor)
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include <glib.h>
+
+#include "qapi/string-output-visitor.h"
+#include "test-qapi-types.h"
+#include "test-qapi-visit.h"
+#include "qemu-objects.h"
+
+typedef struct TestOutputVisitorData {
+ StringOutputVisitor *sov;
+ Visitor *ov;
+} TestOutputVisitorData;
+
+static void visitor_output_setup(TestOutputVisitorData *data,
+ const void *unused)
+{
+ data->sov = string_output_visitor_new();
+ g_assert(data->sov != NULL);
+
+ data->ov = string_output_get_visitor(data->sov);
+ g_assert(data->ov != NULL);
+}
+
+static void visitor_output_teardown(TestOutputVisitorData *data,
+ const void *unused)
+{
+ string_output_visitor_cleanup(data->sov);
+ data->sov = NULL;
+ data->ov = NULL;
+}
+
+static void test_visitor_out_int(TestOutputVisitorData *data,
+ const void *unused)
+{
+ int64_t value = -42;
+ Error *errp = NULL;
+ char *str;
+
+ visit_type_int(data->ov, &value, NULL, &errp);
+ g_assert(error_is_set(&errp) == 0);
+
+ str = string_output_get_string(data->sov);
+ g_assert(str != NULL);
+ g_assert_cmpstr(str, ==, "-42");
+ g_free(str);
+}
+
+static void test_visitor_out_bool(TestOutputVisitorData *data,
+ const void *unused)
+{
+ Error *errp = NULL;
+ bool value = true;
+ char *str;
+
+ visit_type_bool(data->ov, &value, NULL, &errp);
+ g_assert(error_is_set(&errp) == 0);
+
+ str = string_output_get_string(data->sov);
+ g_assert(str != NULL);
+ g_assert_cmpstr(str, ==, "true");
+ g_free(str);
+}
+
+static void test_visitor_out_number(TestOutputVisitorData *data,
+ const void *unused)
+{
+ double value = 3.14;
+ Error *errp = NULL;
+ char *str;
+
+ visit_type_number(data->ov, &value, NULL, &errp);
+ g_assert(error_is_set(&errp) == 0);
+
+ str = string_output_get_string(data->sov);
+ g_assert(str != NULL);
+ g_assert_cmpstr(str, ==, "3.14");
+ g_free(str);
+}
+
+static void test_visitor_out_string(TestOutputVisitorData *data,
+ const void *unused)
+{
+ char *string = (char *) "Q E M U";
+ Error *errp = NULL;
+ char *str;
+
+ visit_type_str(data->ov, &string, NULL, &errp);
+ g_assert(error_is_set(&errp) == 0);
+
+ str = string_output_get_string(data->sov);
+ g_assert(str != NULL);
+ g_assert_cmpstr(str, ==, string);
+ g_free(str);
+}
+
+static void test_visitor_out_no_string(TestOutputVisitorData *data,
+ const void *unused)
+{
+ char *string = NULL;
+ Error *errp = NULL;
+ char *str;
+
+ /* A null string should return "" */
+ visit_type_str(data->ov, &string, NULL, &errp);
+ g_assert(error_is_set(&errp) == 0);
+
+ str = string_output_get_string(data->sov);
+ g_assert(str != NULL);
+ g_assert_cmpstr(str, ==, "");
+ g_free(str);
+}
+
+static void test_visitor_out_enum(TestOutputVisitorData *data,
+ const void *unused)
+{
+ Error *errp = NULL;
+ char *str;
+ EnumOne i;
+
+ for (i = 0; i < ENUM_ONE_MAX; i++) {
+ visit_type_EnumOne(data->ov, &i, "unused", &errp);
+ g_assert(!error_is_set(&errp));
+
+ str = string_output_get_string(data->sov);
+ g_assert(str != NULL);
+ g_assert_cmpstr(str, ==, EnumOne_lookup[i]);
+ g_free(str);
+ }
+}
+
+static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
+ const void *unused)
+{
+ EnumOne i, bad_values[] = { ENUM_ONE_MAX, -1 };
+ Error *errp;
+
+ for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
+ errp = NULL;
+ visit_type_EnumOne(data->ov, &bad_values[i], "unused", &errp);
+ g_assert(error_is_set(&errp) == true);
+ error_free(errp);
+ }
+}
+
+static void output_visitor_test_add(const char *testpath,
+ TestOutputVisitorData *data,
+ void (*test_func)(TestOutputVisitorData *data, const void *user_data))
+{
+ g_test_add(testpath, TestOutputVisitorData, data, visitor_output_setup,
+ test_func, visitor_output_teardown);
+}
+
+int main(int argc, char **argv)
+{
+ TestOutputVisitorData out_visitor_data;
+
+ g_test_init(&argc, &argv, NULL);
+
+ output_visitor_test_add("/string-visitor/output/int",
+ &out_visitor_data, test_visitor_out_int);
+ output_visitor_test_add("/string-visitor/output/bool",
+ &out_visitor_data, test_visitor_out_bool);
+ output_visitor_test_add("/string-visitor/output/number",
+ &out_visitor_data, test_visitor_out_number);
+ output_visitor_test_add("/string-visitor/output/string",
+ &out_visitor_data, test_visitor_out_string);
+ output_visitor_test_add("/string-visitor/output/no-string",
+ &out_visitor_data, test_visitor_out_no_string);
+ output_visitor_test_add("/string-visitor/output/enum",
+ &out_visitor_data, test_visitor_out_enum);
+ output_visitor_test_add("/string-visitor/output/enum-errors",
+ &out_visitor_data, test_visitor_out_enum_errors);
+
+ g_test_run();
+
+ return 0;
+}
diff --git a/tests/Makefile b/tests/Makefile
index 55e8eb0ad5..74b29dc076 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -1,6 +1,6 @@
CHECKS = check-qdict check-qfloat check-qint check-qstring check-qlist
CHECKS += check-qjson test-qmp-output-visitor test-qmp-input-visitor
-CHECKS += test-coroutine
+CHECKS += test-string-input-visitor test-string-output-visitor test-coroutine
check-qint.o check-qstring.o check-qdict.o check-qlist.o check-qfloat.o check-qjson.o test-coroutine.o: $(GENERATED_HEADERS)
@@ -12,7 +12,9 @@ check-qfloat: check-qfloat.o qfloat.o $(tools-obj-y)
check-qjson: check-qjson.o $(qobject-obj-y) $(tools-obj-y)
test-coroutine: test-coroutine.o qemu-timer-common.o async.o $(coroutine-obj-y) $(tools-obj-y)
-test-qmp-input-visitor.o test-qmp-output-visitor.o test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
+test-qmp-input-visitor.o test-qmp-output-visitor.o \
+test-string-input-visitor.o test-string-output-visitor.o \
+ test-qmp-commands.o qemu-ga$(EXESUF): QEMU_CFLAGS += -I $(qapi-dir)
$(qapi-dir)/test-qapi-types.c $(qapi-dir)/test-qapi-types.h :\
$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
@@ -25,6 +27,12 @@ $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o "$(qapi-dir)" -p "test-" < $<, " GEN $@")
+test-string-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
+test-string-output-visitor: test-string-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+
+test-string-input-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
+test-string-input-visitor: test-string-input-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
+
test-qmp-output-visitor.o: $(addprefix $(qapi-dir)/, test-qapi-types.c test-qapi-types.h test-qapi-visit.c test-qapi-visit.h) $(qapi-obj-y)
test-qmp-output-visitor: test-qmp-output-visitor.o $(qobject-obj-y) $(qapi-obj-y) $(tools-obj-y) $(qapi-dir)/test-qapi-visit.o $(qapi-dir)/test-qapi-types.o
diff --git a/trace-events b/trace-events
index 9b26ce2304..e918ff61fd 100644
--- a/trace-events
+++ b/trace-events
@@ -141,6 +141,10 @@ ecc_mem_readl_ecr1(uint32_t ret) "Read event count 2 %08x"
ecc_diag_mem_writeb(uint64_t addr, uint32_t val) "Write diagnostic %"PRId64" = %02x"
ecc_diag_mem_readb(uint64_t addr, uint32_t ret) "Read diagnostic %"PRId64"= %02x"
+# hw/jazz-led.c
+jazz_led_read(uint64_t addr, uint8_t val) "read addr=0x%"PRIx64": 0x%x"
+jazz_led_write(uint64_t addr, uint8_t new) "write addr=0x%"PRIx64": 0x%x"
+
# hw/lance.c
lance_mem_readw(uint64_t addr, uint32_t ret) "addr=%"PRIx64"val=0x%04x"
lance_mem_writew(uint64_t addr, uint32_t val) "addr=%"PRIx64"val=0x%04x"
diff --git a/ui/qemu-spice.h b/ui/qemu-spice.h
index c35b29c1f6..3299da87d6 100644
--- a/ui/qemu-spice.h
+++ b/ui/qemu-spice.h
@@ -33,6 +33,7 @@ void qemu_spice_init(void);
void qemu_spice_input_init(void);
void qemu_spice_audio_init(void);
void qemu_spice_display_init(DisplayState *ds);
+int qemu_spice_display_add_client(int csock, int skipauth, int tls);
int qemu_spice_add_interface(SpiceBaseInstance *sin);
int qemu_spice_set_passwd(const char *passwd,
bool fail_if_connected, bool disconnect_if_connected);
@@ -44,7 +45,7 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
void do_info_spice_print(Monitor *mon, const QObject *data);
void do_info_spice(Monitor *mon, QObject **ret_data);
-int qemu_chr_open_spice(QemuOpts *opts, CharDriverState **_chr);
+CharDriverState *qemu_chr_open_spice(QemuOpts *opts);
#else /* CONFIG_SPICE */
#include "monitor.h"
@@ -68,6 +69,12 @@ static inline int qemu_spice_migrate_info(const char *h, int p, int t,
return -1;
}
+static inline int qemu_spice_display_add_client(int csock, int skipauth,
+ int tls)
+{
+ return -1;
+}
+
#endif /* CONFIG_SPICE */
#endif /* QEMU_SPICE_H */
diff --git a/ui/spice-core.c b/ui/spice-core.c
index b4629f895b..1308a3d886 100644
--- a/ui/spice-core.c
+++ b/ui/spice-core.c
@@ -220,10 +220,23 @@ static void channel_event(int event, SpiceChannelEventInfo *info)
}
client = qdict_new();
- add_addr_info(client, &info->paddr, info->plen);
-
server = qdict_new();
- add_addr_info(server, &info->laddr, info->llen);
+
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
+ if (info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
+ add_addr_info(client, (struct sockaddr *)&info->paddr_ext,
+ info->plen_ext);
+ add_addr_info(server, (struct sockaddr *)&info->laddr_ext,
+ info->llen_ext);
+ } else {
+ fprintf(stderr, "spice: %s, extended address is expected\n",
+ __func__);
+#endif
+ add_addr_info(client, &info->paddr, info->plen);
+ add_addr_info(server, &info->laddr, info->llen);
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
+ }
+#endif
if (event == SPICE_CHANNEL_EVENT_INITIALIZED) {
qdict_put(server, "auth", qstring_from_str(auth));
@@ -376,16 +389,30 @@ static SpiceChannelList *qmp_query_spice_channels(void)
QTAILQ_FOREACH(item, &channel_list, link) {
SpiceChannelList *chan;
char host[NI_MAXHOST], port[NI_MAXSERV];
+ struct sockaddr *paddr;
+ socklen_t plen;
chan = g_malloc0(sizeof(*chan));
chan->value = g_malloc0(sizeof(*chan->value));
- getnameinfo(&item->info->paddr, item->info->plen,
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
+ if (item->info->flags & SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT) {
+ paddr = (struct sockaddr *)&item->info->paddr_ext;
+ plen = item->info->plen_ext;
+ } else {
+#endif
+ paddr = &item->info->paddr;
+ plen = item->info->plen;
+#ifdef SPICE_CHANNEL_EVENT_FLAG_ADDR_EXT
+ }
+#endif
+
+ getnameinfo(paddr, plen,
host, sizeof(host), port, sizeof(port),
NI_NUMERICHOST | NI_NUMERICSERV);
chan->value->host = g_strdup(host);
chan->value->port = g_strdup(port);
- chan->value->family = g_strdup(inet_strfamily(item->info->paddr.sa_family));
+ chan->value->family = g_strdup(inet_strfamily(paddr->sa_family));
chan->value->connection_id = item->info->connection_id;
chan->value->channel_type = item->info->type;
@@ -747,6 +774,19 @@ int qemu_spice_set_pw_expire(time_t expires)
return qemu_spice_set_ticket(false, false);
}
+int qemu_spice_display_add_client(int csock, int skipauth, int tls)
+{
+#if SPICE_SERVER_VERSION >= 0x000a01
+ if (tls) {
+ return spice_server_add_ssl_client(spice_server, csock, skipauth);
+ } else {
+ return spice_server_add_client(spice_server, csock, skipauth);
+ }
+#else
+ return -1;
+#endif
+}
+
static void spice_register_config(void)
{
qemu_add_opts(&qemu_spice_opts);
diff --git a/vl.c b/vl.c
index d8a521afe2..641df593cb 100644
--- a/vl.c
+++ b/vl.c
@@ -1187,7 +1187,7 @@ static QEMUMachine *find_machine(const char *name)
return NULL;
}
-static QEMUMachine *find_default_machine(void)
+QEMUMachine *find_default_machine(void)
{
QEMUMachine *m;
@@ -1857,8 +1857,10 @@ struct device_config {
DEV_PARALLEL, /* -parallel */
DEV_VIRTCON, /* -virtioconsole */
DEV_DEBUGCON, /* -debugcon */
+ DEV_GDB, /* -gdb, -s */
} type;
const char *cmdline;
+ Location loc;
QTAILQ_ENTRY(device_config) next;
};
QTAILQ_HEAD(, device_config) device_configs = QTAILQ_HEAD_INITIALIZER(device_configs);
@@ -1870,6 +1872,7 @@ static void add_device_config(int type, const char *cmdline)
conf = g_malloc0(sizeof(*conf));
conf->type = type;
conf->cmdline = cmdline;
+ loc_save(&conf->loc);
QTAILQ_INSERT_TAIL(&device_configs, conf, next);
}
@@ -1881,7 +1884,9 @@ static int foreach_device_config(int type, int (*func)(const char *cmdline))
QTAILQ_FOREACH(conf, &device_configs, next) {
if (conf->type != type)
continue;
+ loc_push_restore(&conf->loc);
rc = func(conf->cmdline);
+ loc_pop(&conf->loc);
if (0 != rc)
return rc;
}
@@ -2178,7 +2183,6 @@ int qemu_init_main_loop(void)
int main(int argc, char **argv, char **envp)
{
- const char *gdbstub_dev = NULL;
int i;
int snapshot, linux_boot;
const char *icount_option = NULL;
@@ -2238,11 +2242,8 @@ int main(int argc, char **argv, char **envp)
module_call_init(MODULE_INIT_MACHINE);
machine = find_default_machine();
cpu_model = NULL;
- initrd_filename = NULL;
ram_size = 0;
snapshot = 0;
- kernel_filename = NULL;
- kernel_cmdline = "";
cyls = heads = secs = 0;
translation = BIOS_ATA_TRANSLATION_AUTO;
@@ -2318,9 +2319,6 @@ int main(int argc, char **argv, char **envp)
cpu_model = optarg;
}
break;
- case QEMU_OPTION_initrd:
- initrd_filename = optarg;
- break;
case QEMU_OPTION_hda:
{
char buf[256];
@@ -2451,10 +2449,13 @@ int main(int argc, char **argv, char **envp)
}
break;
case QEMU_OPTION_kernel:
- kernel_filename = optarg;
+ qemu_opts_set(qemu_find_opts("machine"), 0, "kernel", optarg);
+ break;
+ case QEMU_OPTION_initrd:
+ qemu_opts_set(qemu_find_opts("machine"), 0, "initrd", optarg);
break;
case QEMU_OPTION_append:
- kernel_cmdline = optarg;
+ qemu_opts_set(qemu_find_opts("machine"), 0, "append", optarg);
break;
case QEMU_OPTION_cdrom:
drive_add(IF_DEFAULT, 2, optarg, CDROM_OPTS);
@@ -2606,10 +2607,10 @@ int main(int argc, char **argv, char **envp)
log_file = optarg;
break;
case QEMU_OPTION_s:
- gdbstub_dev = "tcp::" DEFAULT_GDBSTUB_PORT;
+ add_device_config(DEV_GDB, "tcp::" DEFAULT_GDBSTUB_PORT);
break;
case QEMU_OPTION_gdb:
- gdbstub_dev = optarg;
+ add_device_config(DEV_GDB, optarg);
break;
case QEMU_OPTION_L:
data_dir = optarg;
@@ -3249,6 +3250,17 @@ int main(int argc, char **argv, char **envp)
fprintf(stderr, "qemu_init_main_loop failed\n");
exit(1);
}
+
+ kernel_filename = qemu_opt_get(qemu_opts_find(qemu_find_opts("machine"),
+ 0), "kernel");
+ initrd_filename = qemu_opt_get(qemu_opts_find(qemu_find_opts("machine"),
+ 0), "initrd");
+ kernel_cmdline = qemu_opt_get(qemu_opts_find(qemu_find_opts("machine"),
+ 0), "append");
+ if (!kernel_cmdline) {
+ kernel_cmdline = "";
+ }
+
linux_boot = (kernel_filename != NULL);
if (!linux_boot && *kernel_cmdline != '\0') {
@@ -3488,9 +3500,7 @@ int main(int argc, char **argv, char **envp)
}
text_consoles_set_display(ds);
- if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
- fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
- gdbstub_dev);
+ if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) {
exit(1);
}