summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--VERSION2
-rw-r--r--backends/cryptodev-builtin.c10
-rw-r--r--block.c9
-rw-r--r--block/file-posix.c5
-rw-r--r--block/replication.c4
-rw-r--r--block/sheepdog.c9
-rw-r--r--block/vhdx.c8
-rw-r--r--blockdev.c16
-rw-r--r--cpus.c50
-rw-r--r--docs/devel/qapi-code-gen.txt4
-rw-r--r--dump/dump.c2
-rw-r--r--hw/arm/virt.c4
-rw-r--r--hw/block/fdc.c1
-rw-r--r--hw/core/machine-hmp-cmds.c2
-rw-r--r--hw/display/bochs-display.c6
-rw-r--r--hw/i2c/smbus_eeprom.c32
-rw-r--r--hw/mips/mips_fulong2e.c10
-rw-r--r--hw/net/virtio-net.c7
-rw-r--r--hw/ppc/ppc4xx_devs.c8
-rw-r--r--hw/ppc/sam460ex.c13
-rw-r--r--hw/riscv/boot.c13
-rw-r--r--hw/riscv/sifive_e.c5
-rw-r--r--hw/riscv/sifive_u.c142
-rw-r--r--hw/riscv/spike.c30
-rw-r--r--hw/riscv/virt.c6
-rw-r--r--hw/scsi/scsi-disk.c2
-rw-r--r--hw/sd/sdhci.c2
-rw-r--r--hw/xen/xen_pt.c12
-rw-r--r--include/hw/i2c/smbus_eeprom.h2
-rw-r--r--include/hw/riscv/boot.h6
-rw-r--r--include/hw/riscv/sifive_u.h3
-rw-r--r--include/qapi/qmp/qdict.h3
-rw-r--r--include/qapi/qmp/qlist.h10
-rw-r--r--include/qapi/visitor-impl.h9
-rw-r--r--include/qapi/visitor.h192
-rw-r--r--include/qemu/option.h1
-rw-r--r--io/channel-socket.c5
-rw-r--r--linux-user/riscv/signal.c3
-rw-r--r--migration/colo.c8
-rw-r--r--monitor/hmp-cmds.c3
-rw-r--r--monitor/qmp.c5
-rw-r--r--pc-bios/opensbi-riscv32-sifive_u-fw_jump.binbin49472 -> 49520 bytes
-rw-r--r--pc-bios/opensbi-riscv32-virt-fw_jump.binbin41280 -> 49504 bytes
-rw-r--r--pc-bios/opensbi-riscv64-sifive_u-fw_jump.binbin53760 -> 57936 bytes
-rw-r--r--pc-bios/opensbi-riscv64-virt-fw_jump.binbin49664 -> 57920 bytes
-rw-r--r--qapi/qapi-dealloc-visitor.c7
-rw-r--r--qapi/qapi-visit-core.c20
-rw-r--r--qapi/qobject-input-visitor.c21
-rw-r--r--qemu-img.c87
-rw-r--r--qga/commands-posix.c3
-rw-r--r--qga/commands-win32.c14
-rw-r--r--qobject/qdict.c19
-rw-r--r--qobject/qjson.c107
-rw-r--r--qobject/qlist.c44
-rw-r--r--qom/object.c4
m---------roms/opensbi0
-rw-r--r--scripts/qapi/commands.py60
-rw-r--r--scripts/qapi/visit.py8
-rw-r--r--softmmu/vl.c10
-rw-r--r--target/i386/cpu.c18
-rw-r--r--target/microblaze/cpu.c14
-rw-r--r--target/ppc/translate_init.inc.c4
-rw-r--r--target/riscv/cpu.c10
-rw-r--r--target/riscv/cpu.h1
-rw-r--r--target/riscv/cpu_helper.c18
-rw-r--r--tests/check-qlist.c37
-rw-r--r--tests/qtest/fuzz/qos_fuzz.c34
-rw-r--r--tests/qtest/libqos/qos_external.c68
-rw-r--r--tests/qtest/libqos/qos_external.h10
-rw-r--r--tests/qtest/qos-test.c29
-rw-r--r--tests/test-logging.c4
-rw-r--r--tests/test-qemu-opts.c46
-rw-r--r--tests/test-qobject-output-visitor.c39
-rw-r--r--tests/test-string-output-visitor.c19
-rw-r--r--util/qemu-option.c245
76 files changed, 813 insertions, 852 deletions
diff --git a/Makefile b/Makefile
index 8a9113e666..34275f57c9 100644
--- a/Makefile
+++ b/Makefile
@@ -582,7 +582,6 @@ $(ROM_DIRS_RULES):
.PHONY: recurse-all recurse-clean recurse-install
recurse-all: $(addsuffix /all, $(TARGET_DIRS) $(ROM_DIRS))
-recurse-fuzz: $(addsuffix /fuzz, $(TARGET_DIRS) $(ROM_DIRS))
recurse-clean: $(addsuffix /clean, $(TARGET_DIRS) $(ROM_DIRS))
recurse-install: $(addsuffix /install, $(TARGET_DIRS))
$(addsuffix /install, $(TARGET_DIRS)): all
diff --git a/VERSION b/VERSION
index 85dd7acf40..a480698ce5 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-4.2.94
+5.0.50
diff --git a/backends/cryptodev-builtin.c b/backends/cryptodev-builtin.c
index c8ae3b9742..14316333fe 100644
--- a/backends/cryptodev-builtin.c
+++ b/backends/cryptodev-builtin.c
@@ -282,12 +282,7 @@ static int cryptodev_builtin_sym_close_session(
CryptoDevBackendBuiltin *builtin =
CRYPTODEV_BACKEND_BUILTIN(backend);
- if (session_id >= MAX_NUM_SESSIONS ||
- builtin->sessions[session_id] == NULL) {
- error_setg(errp, "Cannot find a valid session id: %" PRIu64 "",
- session_id);
- return -1;
- }
+ assert(session_id < MAX_NUM_SESSIONS && builtin->sessions[session_id]);
qcrypto_cipher_free(builtin->sessions[session_id]->cipher);
g_free(builtin->sessions[session_id]);
@@ -356,8 +351,7 @@ static void cryptodev_builtin_cleanup(
for (i = 0; i < MAX_NUM_SESSIONS; i++) {
if (builtin->sessions[i] != NULL) {
- cryptodev_builtin_sym_close_session(
- backend, i, 0, errp);
+ cryptodev_builtin_sym_close_session(backend, i, 0, &error_abort);
}
}
diff --git a/block.c b/block.c
index 2e3905c99e..c11385ae05 100644
--- a/block.c
+++ b/block.c
@@ -2982,7 +2982,6 @@ BdrvChild *bdrv_open_child(const char *filename,
BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
{
BlockDriverState *bs = NULL;
- Error *local_err = NULL;
QObject *obj = NULL;
QDict *qdict = NULL;
const char *reference = NULL;
@@ -2995,11 +2994,7 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
assert(ref->type == QTYPE_QDICT);
v = qobject_output_visitor_new(&obj);
- visit_type_BlockdevOptions(v, NULL, &options, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- goto fail;
- }
+ visit_type_BlockdevOptions(v, NULL, &options, &error_abort);
visit_complete(v, &obj);
qdict = qobject_to(QDict, obj);
@@ -3017,8 +3012,6 @@ BlockDriverState *bdrv_open_blockdev_ref(BlockdevRef *ref, Error **errp)
bs = bdrv_open_inherit(NULL, reference, qdict, 0, NULL, NULL, errp);
obj = NULL;
-
-fail:
qobject_unref(obj);
visit_free(v);
return bs;
diff --git a/block/file-posix.c b/block/file-posix.c
index 7e19bbff5f..094e3b0212 100644
--- a/block/file-posix.c
+++ b/block/file-posix.c
@@ -2691,10 +2691,13 @@ static void check_cache_dropped(BlockDriverState *bs, Error **errp)
vec_end = DIV_ROUND_UP(length, page_size);
for (i = 0; i < vec_end; i++) {
if (vec[i] & 0x1) {
- error_setg(errp, "page cache still in use!");
break;
}
}
+ if (i < vec_end) {
+ error_setg(errp, "page cache still in use!");
+ break;
+ }
}
if (window) {
diff --git a/block/replication.c b/block/replication.c
index da013c2041..971f0fe266 100644
--- a/block/replication.c
+++ b/block/replication.c
@@ -172,8 +172,8 @@ static void replication_child_perm(BlockDriverState *bs, BdrvChild *c,
if ((bs->open_flags & (BDRV_O_INACTIVE | BDRV_O_RDWR)) == BDRV_O_RDWR) {
*nperm |= BLK_PERM_WRITE;
}
- *nshared = BLK_PERM_CONSISTENT_READ \
- | BLK_PERM_WRITE \
+ *nshared = BLK_PERM_CONSISTENT_READ
+ | BLK_PERM_WRITE
| BLK_PERM_WRITE_UNCHANGED;
return;
}
diff --git a/block/sheepdog.c b/block/sheepdog.c
index 59f7ebb171..5f3aead038 100644
--- a/block/sheepdog.c
+++ b/block/sheepdog.c
@@ -1854,19 +1854,12 @@ static int sd_create_prealloc(BlockdevOptionsSheepdog *location, int64_t size,
Visitor *v;
QObject *obj = NULL;
QDict *qdict;
- Error *local_err = NULL;
int ret;
v = qobject_output_visitor_new(&obj);
- visit_type_BlockdevOptionsSheepdog(v, NULL, &location, &local_err);
+ visit_type_BlockdevOptionsSheepdog(v, NULL, &location, &error_abort);
visit_free(v);
- if (local_err) {
- error_propagate(errp, local_err);
- qobject_unref(obj);
- return -EINVAL;
- }
-
qdict = qobject_to(QDict, obj);
qdict_flatten(qdict);
diff --git a/block/vhdx.c b/block/vhdx.c
index 33e57cd656..e16fdc2f2d 100644
--- a/block/vhdx.c
+++ b/block/vhdx.c
@@ -2206,20 +2206,20 @@ static QemuOptsList vhdx_create_opts = {
.name = VHDX_BLOCK_OPT_BLOCK_SIZE,
.type = QEMU_OPT_SIZE,
.def_value_str = stringify(0),
- .help = "Block Size; min 1MB, max 256MB. " \
+ .help = "Block Size; min 1MB, max 256MB. "
"0 means auto-calculate based on image size."
},
{
.name = BLOCK_OPT_SUBFMT,
.type = QEMU_OPT_STRING,
- .help = "VHDX format type, can be either 'dynamic' or 'fixed'. "\
+ .help = "VHDX format type, can be either 'dynamic' or 'fixed'. "
"Default is 'dynamic'."
},
{
.name = VHDX_BLOCK_OPT_ZERO,
.type = QEMU_OPT_BOOL,
- .help = "Force use of payload blocks of type 'ZERO'. "\
- "Non-standard, but default. Do not set to 'off' when "\
+ .help = "Force use of payload blocks of type 'ZERO'. "
+ "Non-standard, but default. Do not set to 'off' when "
"using 'qemu-img convert' with subformat=dynamic."
},
{ NULL }
diff --git a/blockdev.c b/blockdev.c
index 5faddaa705..9da960b1e7 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -3725,14 +3725,8 @@ void qmp_blockdev_add(BlockdevOptions *options, Error **errp)
QObject *obj;
Visitor *v = qobject_output_visitor_new(&obj);
QDict *qdict;
- Error *local_err = NULL;
-
- visit_type_BlockdevOptions(v, NULL, &options, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- goto fail;
- }
+ visit_type_BlockdevOptions(v, NULL, &options, &error_abort);
visit_complete(v, &obj);
qdict = qobject_to(QDict, obj);
@@ -3760,7 +3754,6 @@ void qmp_x_blockdev_reopen(BlockdevOptions *options, Error **errp)
AioContext *ctx;
QObject *obj;
Visitor *v = qobject_output_visitor_new(&obj);
- Error *local_err = NULL;
BlockReopenQueue *queue;
QDict *qdict;
@@ -3777,12 +3770,7 @@ void qmp_x_blockdev_reopen(BlockdevOptions *options, Error **errp)
}
/* Put all options in a QDict and flatten it */
- visit_type_BlockdevOptions(v, NULL, &options, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- goto fail;
- }
-
+ visit_type_BlockdevOptions(v, NULL, &options, &error_abort);
visit_complete(v, &obj);
qdict = qobject_to(QDict, obj);
diff --git a/cpus.c b/cpus.c
index ef441bdf62..5670c96bcf 100644
--- a/cpus.c
+++ b/cpus.c
@@ -25,6 +25,7 @@
#include "qemu/osdep.h"
#include "qemu-common.h"
#include "qemu/config-file.h"
+#include "qemu/cutils.h"
#include "migration/vmstate.h"
#include "monitor/monitor.h"
#include "qapi/error.h"
@@ -797,40 +798,47 @@ void cpu_ticks_init(void)
void configure_icount(QemuOpts *opts, Error **errp)
{
- const char *option;
- char *rem_str = NULL;
+ const char *option = qemu_opt_get(opts, "shift");
+ bool sleep = qemu_opt_get_bool(opts, "sleep", true);
+ bool align = qemu_opt_get_bool(opts, "align", false);
+ long time_shift = -1;
- option = qemu_opt_get(opts, "shift");
- if (!option) {
- if (qemu_opt_get(opts, "align") != NULL) {
- error_setg(errp, "Please specify shift option when using align");
- }
+ if (!option && qemu_opt_get(opts, "align")) {
+ error_setg(errp, "Please specify shift option when using align");
return;
}
- icount_sleep = qemu_opt_get_bool(opts, "sleep", true);
- if (icount_sleep) {
- timers_state.icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
- icount_timer_cb, NULL);
- }
-
- icount_align_option = qemu_opt_get_bool(opts, "align", false);
-
- if (icount_align_option && !icount_sleep) {
+ if (align && !sleep) {
error_setg(errp, "align=on and sleep=off are incompatible");
+ return;
}
+
if (strcmp(option, "auto") != 0) {
- errno = 0;
- timers_state.icount_time_shift = strtol(option, &rem_str, 0);
- if (errno != 0 || *rem_str != '\0' || !strlen(option)) {
+ if (qemu_strtol(option, NULL, 0, &time_shift) < 0
+ || time_shift < 0 || time_shift > MAX_ICOUNT_SHIFT) {
error_setg(errp, "icount: Invalid shift value");
+ return;
}
- use_icount = 1;
- return;
} else if (icount_align_option) {
error_setg(errp, "shift=auto and align=on are incompatible");
+ return;
} else if (!icount_sleep) {
error_setg(errp, "shift=auto and sleep=off are incompatible");
+ return;
+ }
+
+ icount_sleep = sleep;
+ if (icount_sleep) {
+ timers_state.icount_warp_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL_RT,
+ icount_timer_cb, NULL);
+ }
+
+ icount_align_option = align;
+
+ if (time_shift >= 0) {
+ timers_state.icount_time_shift = time_shift;
+ use_icount = 1;
+ return;
}
use_icount = 2;
diff --git a/docs/devel/qapi-code-gen.txt b/docs/devel/qapi-code-gen.txt
index 1967adfa92..a7794ef658 100644
--- a/docs/devel/qapi-code-gen.txt
+++ b/docs/devel/qapi-code-gen.txt
@@ -1446,6 +1446,8 @@ Example:
goto out;
}
if (!*obj) {
+ /* incomplete */
+ assert(visit_is_dealloc(v));
goto out_obj;
}
visit_type_UserDefOne_members(v, *obj, &err);
@@ -1577,8 +1579,8 @@ Example:
void qmp_marshal_my_command(QDict *args, QObject **ret, Error **errp)
{
Error *err = NULL;
- UserDefOne *retval;
Visitor *v;
+ UserDefOne *retval;
q_obj_my_command_arg arg = {0};
v = qobject_input_visitor_new(QOBJECT(args));
diff --git a/dump/dump.c b/dump/dump.c
index 22ed1d3b0d..248ea06370 100644
--- a/dump/dump.c
+++ b/dump/dump.c
@@ -1892,7 +1892,7 @@ static void dump_process(DumpState *s, Error **errp)
result = qmp_query_dump(NULL);
/* should never fail */
assert(result);
- qapi_event_send_dump_completed(result, !!local_err, (local_err ? \
+ qapi_event_send_dump_completed(result, !!local_err, (local_err ?
error_get_pretty(local_err) : NULL));
qapi_free_DumpQueryResult(result);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 7dc96abf72..cca5316256 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -1186,7 +1186,7 @@ static void create_smmu(const VirtMachineState *vms,
g_free(node);
}
-static void create_virtio_iommu_dt_bindings(VirtMachineState *vms, Error **errp)
+static void create_virtio_iommu_dt_bindings(VirtMachineState *vms)
{
const char compat[] = "virtio,pci-iommu";
uint16_t bdf = vms->virtio_iommu_bdf;
@@ -2118,7 +2118,7 @@ static void virt_machine_device_plug_cb(HotplugHandler *hotplug_dev,
vms->iommu = VIRT_IOMMU_VIRTIO;
vms->virtio_iommu_bdf = pci_get_bdf(pdev);
- create_virtio_iommu_dt_bindings(vms, errp);
+ create_virtio_iommu_dt_bindings(vms);
}
}
diff --git a/hw/block/fdc.c b/hw/block/fdc.c
index 33bc9e2f92..9628cc171e 100644
--- a/hw/block/fdc.c
+++ b/hw/block/fdc.c
@@ -2615,6 +2615,7 @@ static void fdctrl_realize_common(DeviceState *dev, FDCtrl *fdctrl,
if (fdctrl->fallback == FLOPPY_DRIVE_TYPE_AUTO) {
error_setg(errp, "Cannot choose a fallback FDrive type of 'auto'");
+ return;
}
/* Fill 'command_to_handler' lookup table */
diff --git a/hw/core/machine-hmp-cmds.c b/hw/core/machine-hmp-cmds.c
index b76f7223af..39999c47c5 100644
--- a/hw/core/machine-hmp-cmds.c
+++ b/hw/core/machine-hmp-cmds.c
@@ -113,7 +113,7 @@ void hmp_info_memdev(Monitor *mon, const QDict *qdict)
while (m) {
v = string_output_visitor_new(false, &str);
- visit_type_uint16List(v, NULL, &m->value->host_nodes, NULL);
+ visit_type_uint16List(v, NULL, &m->value->host_nodes, &error_abort);
monitor_printf(mon, "memory backend: %s\n", m->value->id);
monitor_printf(mon, " size: %" PRId64 "\n", m->value->size);
monitor_printf(mon, " merge: %s\n",
diff --git a/hw/display/bochs-display.c b/hw/display/bochs-display.c
index 70eb619ef4..e763a0a72d 100644
--- a/hw/display/bochs-display.c
+++ b/hw/display/bochs-display.c
@@ -267,16 +267,18 @@ static void bochs_display_realize(PCIDevice *dev, Error **errp)
Object *obj = OBJECT(dev);
int ret;
- s->con = graphic_console_init(DEVICE(dev), 0, &bochs_display_gfx_ops, s);
-
if (s->vgamem < 4 * MiB) {
error_setg(errp, "bochs-display: video memory too small");
+ return;
}
if (s->vgamem > 256 * MiB) {
error_setg(errp, "bochs-display: video memory too big");
+ return;
}
s->vgamem = pow2ceil(s->vgamem);
+ s->con = graphic_console_init(DEVICE(dev), 0, &bochs_display_gfx_ops, s);
+
memory_region_init_ram(&s->vram, obj, "bochs-display-vram", s->vgamem,
&error_fatal);
memory_region_init_io(&s->vbe, obj, &bochs_display_vbe_ops, s,
diff --git a/hw/i2c/smbus_eeprom.c b/hw/i2c/smbus_eeprom.c
index 5adf3b15b5..e199fc8678 100644
--- a/hw/i2c/smbus_eeprom.c
+++ b/hw/i2c/smbus_eeprom.c
@@ -195,8 +195,7 @@ void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom,
}
/* Generate SDRAM SPD EEPROM data describing a module of type and size */
-uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size,
- Error **errp)
+uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size)
{
uint8_t *spd;
uint8_t nbanks;
@@ -222,39 +221,18 @@ uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size,
g_assert_not_reached();
}
size = ram_size >> 20; /* work in terms of megabytes */
- if (size < 4) {
- error_setg(errp, "SDRAM size is too small");
- return NULL;
- }
sz_log2 = 31 - clz32(size);
size = 1U << sz_log2;
- if (ram_size > size * MiB) {
- error_setg(errp, "SDRAM size 0x"RAM_ADDR_FMT" is not a power of 2, "
- "truncating to %u MB", ram_size, size);
- }
- if (sz_log2 < min_log2) {
- error_setg(errp,
- "Memory size is too small for SDRAM type, adjusting type");
- if (size >= 32) {
- type = DDR;
- min_log2 = 5;
- max_log2 = 12;
- } else {
- type = SDR;
- min_log2 = 2;
- max_log2 = 9;
- }
- }
+ assert(ram_size == size * MiB);
+ assert(sz_log2 >= min_log2);
nbanks = 1;
while (sz_log2 > max_log2 && nbanks < 8) {
sz_log2--;
- nbanks++;
+ nbanks *= 2;
}
- if (size > (1ULL << sz_log2) * nbanks) {
- error_setg(errp, "Memory size is too big for SDRAM, truncating");
- }
+ assert(size == (1ULL << sz_log2) * nbanks);
/* split to 2 banks if possible to avoid a bug in MIPS Malta firmware */
if (nbanks == 1 && sz_log2 > min_log2) {
diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c
index 5040afd581..ef02d54b33 100644
--- a/hw/mips/mips_fulong2e.c
+++ b/hw/mips/mips_fulong2e.c
@@ -297,7 +297,6 @@ static void mips_fulong2e_init(MachineState *machine)
MemoryRegion *bios = g_new(MemoryRegion, 1);
long bios_size;
uint8_t *spd_data;
- Error *err = NULL;
int64_t kernel_entry;
PCIBus *pci_bus;
ISABus *isa_bus;
@@ -377,13 +376,8 @@ static void mips_fulong2e_init(MachineState *machine)
}
/* Populate SPD eeprom data */
- spd_data = spd_data_generate(DDR, machine->ram_size, &err);
- if (err) {
- warn_report_err(err);
- }
- if (spd_data) {
- smbus_eeprom_init_one(smbus, 0x50, spd_data);
- }
+ spd_data = spd_data_generate(DDR, machine->ram_size);
+ smbus_eeprom_init_one(smbus, 0x50, spd_data);
mc146818_rtc_init(isa_bus, 2000, NULL);
diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index e85d902588..3301869d4f 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1526,7 +1526,7 @@ static void virtio_net_rsc_extract_unit6(VirtioNetRscChain *chain,
+ sizeof(struct eth_header));
unit->ip = ip6;
unit->ip_plen = &(ip6->ip6_ctlun.ip6_un1.ip6_un1_plen);
- unit->tcp = (struct tcp_header *)(((uint8_t *)unit->ip)\
+ unit->tcp = (struct tcp_header *)(((uint8_t *)unit->ip)
+ sizeof(struct ip6_header));
unit->tcp_hdrlen = (htons(unit->tcp->th_offset_flags) & 0xF000) >> 10;
@@ -2947,6 +2947,7 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
n->net_conf.duplex = DUPLEX_FULL;
} else {
error_setg(errp, "'duplex' must be 'half' or 'full'");
+ return;
}
n->host_features |= (1ULL << VIRTIO_NET_F_SPEED_DUPLEX);
} else {
@@ -2955,7 +2956,9 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp)
if (n->net_conf.speed < SPEED_UNKNOWN) {
error_setg(errp, "'speed' must be between 0 and INT_MAX");
- } else if (n->net_conf.speed >= 0) {
+ return;
+ }
+ if (n->net_conf.speed >= 0) {
n->host_features |= (1ULL << VIRTIO_NET_F_SPEED_DUPLEX);
}
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 3376c43ff5..f1651e04d9 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -716,11 +716,11 @@ void ppc4xx_sdram_banks(MemoryRegion *ram, int nr_banks,
for (i = 0; sdram_bank_sizes[i]; i++) {
g_string_append_printf(s, "%" PRIi64 "%s",
sdram_bank_sizes[i] / MiB,
- sdram_bank_sizes[i + 1] ? " ," : "");
+ sdram_bank_sizes[i + 1] ? ", " : "");
}
- error_report("Max %d banks of %s MB DIMM/bank supported",
- nr_banks, s->str);
- error_report("Possible valid RAM size: %" PRIi64,
+ error_report("at most %d bank%s of %s MiB each supported",
+ nr_banks, nr_banks == 1 ? "" : "s", s->str);
+ error_printf("Possible valid RAM size: %" PRIi64 " MiB \n",
used_size ? used_size / MiB : sdram_bank_sizes[i - 1] / MiB);
g_string_free(s, true);
diff --git a/hw/ppc/sam460ex.c b/hw/ppc/sam460ex.c
index 898453cf30..42a8c9fb7f 100644
--- a/hw/ppc/sam460ex.c
+++ b/hw/ppc/sam460ex.c
@@ -292,7 +292,6 @@ static void sam460ex_init(MachineState *machine)
SysBusDevice *sbdev;
struct boot_info *boot_info;
uint8_t *spd_data;
- Error *err = NULL;
int success;
cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
@@ -335,14 +334,10 @@ static void sam460ex_init(MachineState *machine)
dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]);
i2c = PPC4xx_I2C(dev)->bus;
/* SPD EEPROM on RAM module */
- spd_data = spd_data_generate(DDR2, ram_sizes[0], &err);
- if (err) {
- warn_report_err(err);
- }
- if (spd_data) {
- spd_data[20] = 4; /* SO-DIMM module */
- smbus_eeprom_init_one(i2c, 0x50, spd_data);
- }
+ spd_data = spd_data_generate(ram_sizes[0] < 128 * MiB ? DDR : DDR2,
+ ram_sizes[0]);
+ spd_data[20] = 4; /* SO-DIMM module */
+ smbus_eeprom_init_one(i2c, 0x50, spd_data);
/* RTC */
i2c_create_slave(i2c, "m41t80", 0x68);
diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
index b8e765277d..726300a171 100644
--- a/hw/riscv/boot.c
+++ b/hw/riscv/boot.c
@@ -36,7 +36,8 @@
void riscv_find_and_load_firmware(MachineState *machine,
const char *default_machine_firmware,
- hwaddr firmware_load_addr)
+ hwaddr firmware_load_addr,
+ symbol_fn_t sym_cb)
{
char *firmware_filename = NULL;
@@ -76,7 +77,7 @@ void riscv_find_and_load_firmware(MachineState *machine,
if (firmware_filename) {
/* If not "none" load the firmware */
- riscv_load_firmware(firmware_filename, firmware_load_addr);
+ riscv_load_firmware(firmware_filename, firmware_load_addr, sym_cb);
g_free(firmware_filename);
}
}
@@ -96,12 +97,14 @@ char *riscv_find_firmware(const char *firmware_filename)
}
target_ulong riscv_load_firmware(const char *firmware_filename,
- hwaddr firmware_load_addr)
+ hwaddr firmware_load_addr,
+ symbol_fn_t sym_cb)
{
uint64_t firmware_entry, firmware_start, firmware_end;
- if (load_elf(firmware_filename, NULL, NULL, NULL, &firmware_entry,
- &firmware_start, &firmware_end, NULL, 0, EM_RISCV, 1, 0) > 0) {
+ if (load_elf_ram_sym(firmware_filename, NULL, NULL, NULL,
+ &firmware_entry, &firmware_start, &firmware_end, NULL,
+ 0, EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) {
return firmware_entry;
}
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 646553a7c3..b53109521e 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -123,8 +123,6 @@ static void riscv_sifive_e_soc_init(Object *obj)
object_initialize_child(obj, "cpus", &s->cpus,
sizeof(s->cpus), TYPE_RISCV_HART_ARRAY,
&error_abort, NULL);
- object_property_set_str(OBJECT(&s->cpus), SIFIVE_E_CPU, "cpu-type",
- &error_abort);
object_property_set_int(OBJECT(&s->cpus), ms->smp.cpus, "num-harts",
&error_abort);
sysbus_init_child_obj(obj, "riscv.sifive.e.gpio0",
@@ -141,6 +139,8 @@ static void riscv_sifive_e_soc_realize(DeviceState *dev, Error **errp)
SiFiveESoCState *s = RISCV_E_SOC(dev);
MemoryRegion *sys_mem = get_system_memory();
+ object_property_set_str(OBJECT(&s->cpus), ms->cpu_type, "cpu-type",
+ &error_abort);
object_property_set_bool(OBJECT(&s->cpus), true, "realized",
&error_abort);
@@ -219,6 +219,7 @@ static void riscv_sifive_e_machine_init(MachineClass *mc)
mc->desc = "RISC-V Board compatible with SiFive E SDK";
mc->init = riscv_sifive_e_init;
mc->max_cpus = 1;
+ mc->default_cpu_type = SIFIVE_E_CPU;
}
DEFINE_MACHINE("sifive_e", riscv_sifive_e_machine_init)
diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
index 56351c4faa..bed10fcfa8 100644
--- a/hw/riscv/sifive_u.c
+++ b/hw/riscv/sifive_u.c
@@ -34,6 +34,7 @@
#include "qemu/log.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
+#include "qapi/visitor.h"
#include "hw/boards.h"
#include "hw/loader.h"
#include "hw/sysbus.h"
@@ -159,7 +160,11 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
qemu_fdt_add_subnode(fdt, nodename);
/* cpu 0 is the management hart that does not have mmu */
if (cpu != 0) {
+#if defined(TARGET_RISCV32)
+ qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32");
+#else
qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
+#endif
isa = riscv_isa_string(&s->soc.u_cpus.harts[cpu - 1]);
} else {
isa = riscv_isa_string(&s->soc.e_cpus.harts[0]);
@@ -312,7 +317,7 @@ static void create_fdt(SiFiveUState *s, const struct MemmapEntry *memmap,
g_free(nodename);
}
-static void riscv_sifive_u_init(MachineState *machine)
+static void sifive_u_machine_init(MachineState *machine)
{
const struct MemmapEntry *memmap = sifive_u_memmap;
SiFiveUState *s = RISCV_U_MACHINE(machine);
@@ -326,6 +331,8 @@ static void riscv_sifive_u_init(MachineState *machine)
object_initialize_child(OBJECT(machine), "soc", &s->soc,
sizeof(s->soc), TYPE_RISCV_U_SOC,
&error_abort, NULL);
+ object_property_set_uint(OBJECT(&s->soc), s->serial, "serial",
+ &error_abort);
object_property_set_bool(OBJECT(&s->soc), true, "realized",
&error_abort);
@@ -345,7 +352,7 @@ static void riscv_sifive_u_init(MachineState *machine)
create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline);
riscv_find_and_load_firmware(machine, BIOS_FILENAME,
- memmap[SIFIVE_U_DRAM].base);
+ memmap[SIFIVE_U_DRAM].base, NULL);
if (machine->kernel_filename) {
uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename,
@@ -403,6 +410,76 @@ static void riscv_sifive_u_init(MachineState *machine)
&address_space_memory);
}
+static bool sifive_u_machine_get_start_in_flash(Object *obj, Error **errp)
+{
+ SiFiveUState *s = RISCV_U_MACHINE(obj);
+
+ return s->start_in_flash;
+}
+
+static void sifive_u_machine_set_start_in_flash(Object *obj, bool value, Error **errp)
+{
+ SiFiveUState *s = RISCV_U_MACHINE(obj);
+
+ s->start_in_flash = value;
+}
+
+static void sifive_u_machine_get_serial(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ visit_type_uint32(v, name, (uint32_t *)opaque, errp);
+}
+
+static void sifive_u_machine_set_serial(Object *obj, Visitor *v, const char *name,
+ void *opaque, Error **errp)
+{
+ visit_type_uint32(v, name, (uint32_t *)opaque, errp);
+}
+
+static void sifive_u_machine_instance_init(Object *obj)
+{
+ SiFiveUState *s = RISCV_U_MACHINE(obj);
+
+ s->start_in_flash = false;
+ object_property_add_bool(obj, "start-in-flash", sifive_u_machine_get_start_in_flash,
+ sifive_u_machine_set_start_in_flash, NULL);
+ object_property_set_description(obj, "start-in-flash",
+ "Set on to tell QEMU's ROM to jump to "
+ "flash. Otherwise QEMU will jump to DRAM",
+ NULL);
+
+ s->serial = OTP_SERIAL;
+ object_property_add(obj, "serial", "uint32", sifive_u_machine_get_serial,
+ sifive_u_machine_set_serial, NULL, &s->serial, NULL);
+ object_property_set_description(obj, "serial", "Board serial number", NULL);
+}
+
+static void sifive_u_machine_class_init(ObjectClass *oc, void *data)
+{
+ MachineClass *mc = MACHINE_CLASS(oc);
+
+ mc->desc = "RISC-V Board compatible with SiFive U SDK";
+ mc->init = sifive_u_machine_init;
+ mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT;
+ mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1;
+ mc->default_cpus = mc->min_cpus;
+}
+
+static const TypeInfo sifive_u_machine_typeinfo = {
+ .name = MACHINE_TYPE_NAME("sifive_u"),
+ .parent = TYPE_MACHINE,
+ .class_init = sifive_u_machine_class_init,
+ .instance_init = sifive_u_machine_instance_init,
+ .instance_size = sizeof(SiFiveUState),
+};
+
+static void sifive_u_machine_init_register_types(void)
+{
+ type_register_static(&sifive_u_machine_typeinfo);
+}
+
+type_init(sifive_u_machine_init_register_types)
+
static void riscv_sifive_u_soc_init(Object *obj)
{
MachineState *ms = MACHINE(qdev_get_machine());
@@ -438,38 +515,10 @@ static void riscv_sifive_u_soc_init(Object *obj)
TYPE_SIFIVE_U_PRCI);
sysbus_init_child_obj(obj, "otp", &s->otp, sizeof(s->otp),
TYPE_SIFIVE_U_OTP);
- qdev_prop_set_uint32(DEVICE(&s->otp), "serial", OTP_SERIAL);
sysbus_init_child_obj(obj, "gem", &s->gem, sizeof(s->gem),
TYPE_CADENCE_GEM);
}
-static bool sifive_u_get_start_in_flash(Object *obj, Error **errp)
-{
- SiFiveUState *s = RISCV_U_MACHINE(obj);
-
- return s->start_in_flash;
-}
-
-static void sifive_u_set_start_in_flash(Object *obj, bool value, Error **errp)
-{
- SiFiveUState *s = RISCV_U_MACHINE(obj);
-
- s->start_in_flash = value;
-}
-
-static void riscv_sifive_u_machine_instance_init(Object *obj)
-{
- SiFiveUState *s = RISCV_U_MACHINE(obj);
-
- s->start_in_flash = false;
- object_property_add_bool(obj, "start-in-flash", sifive_u_get_start_in_flash,
- sifive_u_set_start_in_flash, NULL);
- object_property_set_description(obj, "start-in-flash",
- "Set on to tell QEMU's ROM to jump to " \
- "flash. Otherwise QEMU will jump to DRAM",
- NULL);
-}
-
static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
{
MachineState *ms = MACHINE(qdev_get_machine());
@@ -558,6 +607,7 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
object_property_set_bool(OBJECT(&s->prci), true, "realized", &err);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->prci), 0, memmap[SIFIVE_U_PRCI].base);
+ qdev_prop_set_uint32(DEVICE(&s->otp), "serial", s->serial);
object_property_set_bool(OBJECT(&s->otp), true, "realized", &err);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->otp), 0, memmap[SIFIVE_U_OTP].base);
@@ -584,10 +634,16 @@ static void riscv_sifive_u_soc_realize(DeviceState *dev, Error **errp)
memmap[SIFIVE_U_GEM_MGMT].base, memmap[SIFIVE_U_GEM_MGMT].size);
}
+static Property riscv_sifive_u_soc_props[] = {
+ DEFINE_PROP_UINT32("serial", SiFiveUSoCState, serial, OTP_SERIAL),
+ DEFINE_PROP_END_OF_LIST()
+};
+
static void riscv_sifive_u_soc_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
+ device_class_set_props(dc, riscv_sifive_u_soc_props);
dc->realize = riscv_sifive_u_soc_realize;
/* Reason: Uses serial_hds in realize function, thus can't be used twice */
dc->user_creatable = false;
@@ -607,29 +663,3 @@ static void riscv_sifive_u_soc_register_types(void)
}
type_init(riscv_sifive_u_soc_register_types)
-
-static void riscv_sifive_u_machine_class_init(ObjectClass *oc, void *data)
-{
- MachineClass *mc = MACHINE_CLASS(oc);
-
- mc->desc = "RISC-V Board compatible with SiFive U SDK";
- mc->init = riscv_sifive_u_init;
- mc->max_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + SIFIVE_U_COMPUTE_CPU_COUNT;
- mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1;
- mc->default_cpus = mc->min_cpus;
-}
-
-static const TypeInfo riscv_sifive_u_machine_typeinfo = {
- .name = MACHINE_TYPE_NAME("sifive_u"),
- .parent = TYPE_MACHINE,
- .class_init = riscv_sifive_u_machine_class_init,
- .instance_init = riscv_sifive_u_machine_instance_init,
- .instance_size = sizeof(SiFiveUState),
-};
-
-static void riscv_sifive_u_machine_init_register_types(void)
-{
- type_register_static(&riscv_sifive_u_machine_typeinfo);
-}
-
-type_init(riscv_sifive_u_machine_init_register_types)
diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c
index 5053fe4590..d0c4843712 100644
--- a/hw/riscv/spike.c
+++ b/hw/riscv/spike.c
@@ -45,6 +45,12 @@
#include <libfdt.h>
+#if defined(TARGET_RISCV32)
+# define BIOS_FILENAME "opensbi-riscv32-spike-fw_jump.elf"
+#else
+# define BIOS_FILENAME "opensbi-riscv64-spike-fw_jump.elf"
+#endif
+
static const struct MemmapEntry {
hwaddr base;
hwaddr size;
@@ -102,7 +108,11 @@ static void create_fdt(SpikeState *s, const struct MemmapEntry *memmap,
char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu);
char *isa = riscv_isa_string(&s->soc.harts[cpu]);
qemu_fdt_add_subnode(fdt, nodename);
+#if defined(TARGET_RISCV32)
+ qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32");
+#else
qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
+#endif
qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa);
qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv");
qemu_fdt_setprop_string(fdt, nodename, "status", "okay");
@@ -183,8 +193,24 @@ static void spike_board_init(MachineState *machine)
memory_region_add_subregion(system_memory, memmap[SPIKE_MROM].base,
mask_rom);
+ riscv_find_and_load_firmware(machine, BIOS_FILENAME,
+ memmap[SPIKE_DRAM].base,
+ htif_symbol_callback);
+
if (machine->kernel_filename) {
- riscv_load_kernel(machine->kernel_filename, htif_symbol_callback);
+ uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename,
+ htif_symbol_callback);
+
+ if (machine->initrd_filename) {
+ hwaddr start;
+ hwaddr end = riscv_load_initrd(machine->initrd_filename,
+ machine->ram_size, kernel_entry,
+ &start);
+ qemu_fdt_setprop_cell(s->fdt, "/chosen",
+ "linux,initrd-start", start);
+ qemu_fdt_setprop_cell(s->fdt, "/chosen", "linux,initrd-end",
+ end);
+ }
}
/* reset vector */
@@ -450,7 +476,7 @@ static void spike_machine_init(MachineClass *mc)
{
mc->desc = "RISC-V Spike Board";
mc->init = spike_board_init;
- mc->max_cpus = 1;
+ mc->max_cpus = 8;
mc->is_default = true;
mc->default_cpu_type = SPIKE_V1_10_0_CPU;
}
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 85ec9e22aa..daae3ebdbb 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -229,7 +229,11 @@ static void create_fdt(RISCVVirtState *s, const struct MemmapEntry *memmap,
char *intc = g_strdup_printf("/cpus/cpu@%d/interrupt-controller", cpu);
char *isa = riscv_isa_string(&s->soc.harts[cpu]);
qemu_fdt_add_subnode(fdt, nodename);
+#if defined(TARGET_RISCV32)
+ qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32");
+#else
qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48");
+#endif
qemu_fdt_setprop_string(fdt, nodename, "riscv,isa", isa);
qemu_fdt_setprop_string(fdt, nodename, "compatible", "riscv");
qemu_fdt_setprop_string(fdt, nodename, "status", "okay");
@@ -507,7 +511,7 @@ static void riscv_virt_board_init(MachineState *machine)
mask_rom);
riscv_find_and_load_firmware(machine, BIOS_FILENAME,
- memmap[VIRT_DRAM].base);
+ memmap[VIRT_DRAM].base, NULL);
if (machine->kernel_filename) {
uint64_t kernel_entry = riscv_load_kernel(machine->kernel_filename,
diff --git a/hw/scsi/scsi-disk.c b/hw/scsi/scsi-disk.c
index 1c0cb63a6f..e5bcd0baf8 100644
--- a/hw/scsi/scsi-disk.c
+++ b/hw/scsi/scsi-disk.c
@@ -3078,7 +3078,7 @@ static const TypeInfo scsi_cd_info = {
#ifdef __linux__
static Property scsi_block_properties[] = {
- DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf), \
+ DEFINE_BLOCK_ERROR_PROPERTIES(SCSIDiskState, qdev.conf),
DEFINE_PROP_DRIVE("drive", SCSIDiskState, qdev.conf.blk),
DEFINE_PROP_BOOL("share-rw", SCSIDiskState, qdev.conf.share_rw, false),
DEFINE_PROP_UINT16("rotation_rate", SCSIDiskState, rotation_rate, 0),
diff --git a/hw/sd/sdhci.c b/hw/sd/sdhci.c
index de63ffb037..70531ad360 100644
--- a/hw/sd/sdhci.c
+++ b/hw/sd/sdhci.c
@@ -1130,7 +1130,7 @@ sdhci_write(void *opaque, hwaddr offset, uint64_t val, unsigned size)
/* Limit block size to the maximum buffer size */
if (extract32(s->blksize, 0, 12) > s->buf_maxsz) {
- qemu_log_mask(LOG_GUEST_ERROR, "%s: Size 0x%x is larger than " \
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: Size 0x%x is larger than "
"the maximum buffer 0x%x", __func__, s->blksize,
s->buf_maxsz);
diff --git a/hw/xen/xen_pt.c b/hw/xen/xen_pt.c
index b91082cb8b..81d5ad8da7 100644
--- a/hw/xen/xen_pt.c
+++ b/hw/xen/xen_pt.c
@@ -858,8 +858,8 @@ static void xen_pt_realize(PCIDevice *d, Error **errp)
rc = xc_physdev_map_pirq(xen_xc, xen_domid, machine_irq, &pirq);
if (rc < 0) {
- error_setg_errno(errp, errno, "Mapping machine irq %u to"
- " pirq %i failed", machine_irq, pirq);
+ XEN_PT_ERR(d, "Mapping machine irq %u to pirq %i failed, (err: %d)\n",
+ machine_irq, pirq, errno);
/* Disable PCI intx assertion (turn on bit10 of devctl) */
cmd |= PCI_COMMAND_INTX_DISABLE;
@@ -880,8 +880,8 @@ static void xen_pt_realize(PCIDevice *d, Error **errp)
PCI_SLOT(d->devfn),
e_intx);
if (rc < 0) {
- error_setg_errno(errp, errno, "Binding of interrupt %u failed",
- e_intx);
+ XEN_PT_ERR(d, "Binding of interrupt %i failed! (err: %d)\n",
+ e_intx, errno);
/* Disable PCI intx assertion (turn on bit10 of devctl) */
cmd |= PCI_COMMAND_INTX_DISABLE;
@@ -889,8 +889,8 @@ static void xen_pt_realize(PCIDevice *d, Error **errp)
if (xen_pt_mapped_machine_irq[machine_irq] == 0) {
if (xc_physdev_unmap_pirq(xen_xc, xen_domid, machine_irq)) {
- error_setg_errno(errp, errno, "Unmapping of machine"
- " interrupt %u failed", machine_irq);
+ XEN_PT_ERR(d, "Unmapping of machine interrupt %i failed!"
+ " (err: %d)\n", machine_irq, errno);
}
}
s->machine_irq = 0;
diff --git a/include/hw/i2c/smbus_eeprom.h b/include/hw/i2c/smbus_eeprom.h
index 15e2151b50..68b0063ab6 100644
--- a/include/hw/i2c/smbus_eeprom.h
+++ b/include/hw/i2c/smbus_eeprom.h
@@ -31,6 +31,6 @@ void smbus_eeprom_init(I2CBus *bus, int nb_eeprom,
const uint8_t *eeprom_spd, int size);
enum sdram_type { SDR = 0x4, DDR = 0x7, DDR2 = 0x8 };
-uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t size, Error **errp);
+uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t size);
#endif
diff --git a/include/hw/riscv/boot.h b/include/hw/riscv/boot.h
index df80051fbc..474a940ad5 100644
--- a/include/hw/riscv/boot.h
+++ b/include/hw/riscv/boot.h
@@ -24,10 +24,12 @@
void riscv_find_and_load_firmware(MachineState *machine,
const char *default_machine_firmware,
- hwaddr firmware_load_addr);
+ hwaddr firmware_load_addr,
+ symbol_fn_t sym_cb);
char *riscv_find_firmware(const char *firmware_filename);
target_ulong riscv_load_firmware(const char *firmware_filename,
- hwaddr firmware_load_addr);
+ hwaddr firmware_load_addr,
+ symbol_fn_t sym_cb);
target_ulong riscv_load_kernel(const char *kernel_filename,
symbol_fn_t sym_cb);
hwaddr riscv_load_initrd(const char *filename, uint64_t mem_size,
diff --git a/include/hw/riscv/sifive_u.h b/include/hw/riscv/sifive_u.h
index 82667b5746..16c297ec5f 100644
--- a/include/hw/riscv/sifive_u.h
+++ b/include/hw/riscv/sifive_u.h
@@ -42,6 +42,8 @@ typedef struct SiFiveUSoCState {
SiFiveUPRCIState prci;
SiFiveUOTPState otp;
CadenceGEMState gem;
+
+ uint32_t serial;
} SiFiveUSoCState;
#define TYPE_RISCV_U_MACHINE MACHINE_TYPE_NAME("sifive_u")
@@ -59,6 +61,7 @@ typedef struct SiFiveUState {
int fdt_size;
bool start_in_flash;
+ uint32_t serial;
} SiFiveUState;
enum {
diff --git a/include/qapi/qmp/qdict.h b/include/qapi/qmp/qdict.h
index 7f3ec10a10..da942347a7 100644
--- a/include/qapi/qmp/qdict.h
+++ b/include/qapi/qmp/qdict.h
@@ -40,9 +40,6 @@ void qdict_del(QDict *qdict, const char *key);
int qdict_haskey(const QDict *qdict, const char *key);
QObject *qdict_get(const QDict *qdict, const char *key);
bool qdict_is_equal(const QObject *x, const QObject *y);
-void qdict_iter(const QDict *qdict,
- void (*iter)(const char *key, QObject *obj, void *opaque),
- void *opaque);
const QDictEntry *qdict_first(const QDict *qdict);
const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry);
void qdict_destroy_obj(QObject *obj);
diff --git a/include/qapi/qmp/qlist.h b/include/qapi/qmp/qlist.h
index 8d2c32ca28..595b7943e1 100644
--- a/include/qapi/qmp/qlist.h
+++ b/include/qapi/qmp/qlist.h
@@ -34,10 +34,10 @@ void qlist_append_int(QList *qlist, int64_t value);
void qlist_append_null(QList *qlist);
void qlist_append_str(QList *qlist, const char *value);
-#define QLIST_FOREACH_ENTRY(qlist, var) \
- for ((var) = ((qlist)->head.tqh_first); \
- (var); \
- (var) = ((var)->next.tqe_next))
+#define QLIST_FOREACH_ENTRY(qlist, var) \
+ for ((var) = QTAILQ_FIRST(&(qlist)->head); \
+ (var); \
+ (var) = QTAILQ_NEXT((var), next))
static inline QObject *qlist_entry_obj(const QListEntry *entry)
{
@@ -47,8 +47,6 @@ static inline QObject *qlist_entry_obj(const QListEntry *entry)
QList *qlist_new(void);
QList *qlist_copy(QList *src);
void qlist_append_obj(QList *qlist, QObject *obj);
-void qlist_iter(const QList *qlist,
- void (*iter)(QObject *obj, void *opaque), void *opaque);
QObject *qlist_pop(QList *qlist);
QObject *qlist_peek(QList *qlist);
int qlist_empty(const QList *qlist);
diff --git a/include/qapi/visitor-impl.h b/include/qapi/visitor-impl.h
index 8ccb3b6c20..98dc533d39 100644
--- a/include/qapi/visitor-impl.h
+++ b/include/qapi/visitor-impl.h
@@ -43,6 +43,10 @@ typedef enum VisitorType {
struct Visitor
{
+ /*
+ * Only input visitors may fail!
+ */
+
/* Must be set to visit structs */
void (*start_struct)(Visitor *v, const char *name, void **obj,
size_t size, Error **errp);
@@ -67,13 +71,12 @@ struct Visitor
/* Must be set */
void (*end_list)(Visitor *v, void **list);
- /* Must be set by input and dealloc visitors to visit alternates;
- * optional for output visitors. */
+ /* Must be set by input and clone visitors to visit alternates */
void (*start_alternate)(Visitor *v, const char *name,
GenericAlternate **obj, size_t size,
Error **errp);
- /* Optional, needed for dealloc visitor */
+ /* Optional */
void (*end_alternate)(Visitor *v, void **obj);
/* Must be set */
diff --git a/include/qapi/visitor.h b/include/qapi/visitor.h
index c5b23851a1..5573906966 100644
--- a/include/qapi/visitor.h
+++ b/include/qapi/visitor.h
@@ -25,19 +25,21 @@
* for doing work at each node of a QAPI graph; it can also be used
* for a virtual walk, where there is no actual QAPI C struct.
*
- * There are four kinds of visitor classes: input visitors (QObject,
- * string, and QemuOpts) parse an external representation and build
- * the corresponding QAPI graph, output visitors (QObject and string) take
- * a completed QAPI graph and generate an external representation, the
- * dealloc visitor can take a QAPI graph (possibly partially
- * constructed) and recursively free its resources, and the clone
- * visitor performs a deep clone of one QAPI object to another. While
- * the dealloc and QObject input/output visitors are general, the string,
- * QemuOpts, and clone visitors have some implementation limitations;
- * see the documentation for each visitor for more details on what it
- * supports. Also, see visitor-impl.h for the callback contracts
- * implemented by each visitor, and docs/devel/qapi-code-gen.txt for more
- * about the QAPI code generator.
+ * There are four kinds of visitors: input visitors (QObject, string,
+ * and QemuOpts) parse an external representation and build the
+ * corresponding QAPI object, output visitors (QObject and string)
+ * take a QAPI object and generate an external representation, the
+ * dealloc visitor takes a QAPI object (possibly partially
+ * constructed) and recursively frees it, and the clone visitor
+ * performs a deep clone of a QAPI object.
+ *
+ * While the dealloc and QObject input/output visitors are general,
+ * the string, QemuOpts, and clone visitors have some implementation
+ * limitations; see the documentation for each visitor for more
+ * details on what it supports. Also, see visitor-impl.h for the
+ * callback contracts implemented by each visitor, and
+ * docs/devel/qapi-code-gen.txt for more about the QAPI code
+ * generator.
*
* All of the visitors are created via:
*
@@ -45,11 +47,15 @@
*
* A visitor should be used for exactly one top-level visit_type_FOO()
* or virtual walk; if that is successful, the caller can optionally
- * call visit_complete() (for now, useful only for output visits, but
- * safe to call on all visits). Then, regardless of success or
- * failure, the user should call visit_free() to clean up resources.
- * It is okay to free the visitor without completing the visit, if
- * some other error is detected in the meantime.
+ * call visit_complete() (useful only for output visits, but safe to
+ * call on all visits). Then, regardless of success or failure, the
+ * user should call visit_free() to clean up resources. It is okay to
+ * free the visitor without completing the visit, if some other error
+ * is detected in the meantime.
+ *
+ * The clone and dealloc visitor should not be used directly outside
+ * of QAPI code. Use the qapi_free_FOO() and QAPI_CLONE() instead,
+ * described below.
*
* All QAPI types have a corresponding function with a signature
* roughly compatible with this:
@@ -58,7 +64,7 @@
*
* where T is FOO for scalar types, and FOO * otherwise. The scalar
* visitors are declared here; the remaining visitors are generated in
- * qapi-visit.h.
+ * qapi-visit-MODULE.h.
*
* The @name parameter of visit_type_FOO() describes the relation
* between this QAPI value and its parent container. When visiting
@@ -68,55 +74,56 @@
* alternate, @name should equal the name used for visiting the
* alternate.
*
- * The visit_type_FOO() functions expect a non-null @obj argument;
- * they allocate *@obj during input visits, leave it unchanged on
- * output visits, and recursively free any resources during a dealloc
- * visit. Each function also takes the customary @errp argument (see
+ * The visit_type_FOO() functions take a non-null @obj argument; they
+ * allocate *@obj during input visits, leave it unchanged during
+ * output and clone visits, and free it (recursively) during a dealloc
+ * visit.
+ *
+ * Each function also takes the customary @errp argument (see
* qapi/error.h for details), for reporting any errors (such as if a
* member @name is not present, or is present but not the specified
- * type).
+ * type). Only input visitors can fail.
*
* If an error is detected during visit_type_FOO() with an input
- * visitor, then *@obj will be NULL for pointer types, and left
- * unchanged for scalar types. Using an output or clone visitor with
- * an incomplete object has undefined behavior (other than a special
- * case for visit_type_str() treating NULL like ""), while the dealloc
- * visitor safely handles incomplete objects. Since input visitors
- * never produce an incomplete object, such an object is possible only
- * by manual construction.
+ * visitor, then *@obj will be set to NULL for pointer types, and left
+ * unchanged for scalar types.
+ *
+ * Using an output or clone visitor with an incomplete object has
+ * undefined behavior (other than a special case for visit_type_str()
+ * treating NULL like ""), while the dealloc visitor safely handles
+ * incomplete objects. Since input visitors never produce an
+ * incomplete object, such an object is possible only by manual
+ * construction.
*
* For the QAPI object types (structs, unions, and alternates), there
- * is an additional generated function in qapi-visit.h compatible
- * with:
+ * is an additional generated function in qapi-visit-MODULE.h
+ * compatible with:
*
* void visit_type_FOO_members(Visitor *v, FOO *obj, Error **errp);
*
* for visiting the members of a type without also allocating the QAPI
* struct.
*
- * Additionally, in qapi-types.h, all QAPI pointer types (structs,
- * unions, alternates, and lists) have a generated function compatible
+ * Additionally, QAPI pointer types (structs, unions, alternates, and
+ * lists) have a generated function in qapi-types-MODULE.h compatible
* with:
*
* void qapi_free_FOO(FOO *obj);
*
- * where behaves like free() in that @obj may be NULL. Such objects
- * may also be used with the following macro, provided alongside the
- * clone visitor:
+ * Does nothing when @obj is NULL.
+ *
+ * Such objects may also be used with macro
*
* Type *QAPI_CLONE(Type, src);
*
- * in order to perform a deep clone of @src. Because of the generated
- * qapi_free functions and the QAPI_CLONE() macro, the clone and
- * dealloc visitor should not be used directly outside of QAPI code.
+ * in order to perform a deep clone of @src.
*
- * QAPI types can also inherit from a base class; when this happens, a
- * function is generated for easily going from the derived type to the
- * base type:
+ * For QAPI types can that inherit from a base type, a function is
+ * generated for going from the derived type to the base type:
*
* BASE *qapi_CHILD_base(CHILD *obj);
*
- * For a real QAPI struct, typical input usage involves:
+ * Typical input visitor usage involves:
*
* <example>
* Foo *f;
@@ -153,36 +160,22 @@
* qapi_free_FooList(l);
* </example>
*
- * Similarly, typical output usage is:
+ * Typical output visitor usage:
*
* <example>
* Foo *f = ...obtain populated object...
- * Error *err = NULL;
* Visitor *v;
* Type *result;
*
* v = FOO_visitor_new(..., &result);
- * visit_type_Foo(v, NULL, &f, &err);
- * if (err) {
- * ...handle error...
- * } else {
- * visit_complete(v, &result);
- * ...use result...
- * }
+ * visit_type_Foo(v, NULL, &f, &error_abort);
+ * visit_complete(v, &result);
* visit_free(v);
+ * ...use result...
* </example>
*
- * When visiting a real QAPI struct, this file provides several
- * helpers that rely on in-tree information to control the walk:
- * visit_optional() for the 'has_member' field associated with
- * optional 'member' in the C struct; and visit_next_list() for
- * advancing through a FooList linked list. Similarly, the
- * visit_is_input() helper makes it possible to write code that is
- * visitor-agnostic everywhere except for cleanup. Only the generated
- * visit_type functions need to use these helpers.
- *
* It is also possible to use the visitors to do a virtual walk, where
- * no actual QAPI struct is present. In this situation, decisions
+ * no actual QAPI object is present. In this situation, decisions
* about what needs to be walked are made by the calling code, and
* structured visits are split between pairs of start and end methods
* (where the end method must be called if the start function
@@ -215,6 +208,9 @@
* goto outlist;
* }
* outlist:
+ * if (!err) {
+ * visit_check_list(v, &err);
+ * }
* visit_end_list(v, NULL);
* if (!err) {
* visit_check_struct(v, &err);
@@ -222,9 +218,14 @@
* outobj:
* visit_end_struct(v, NULL);
* out:
- * error_propagate(errp, err);
* visit_free(v);
* </example>
+ *
+ * This file provides helpers for use by the generated
+ * visit_type_FOO(): visit_optional() for the 'has_member' field
+ * associated with optional 'member' in the C struct,
+ * visit_next_list() for advancing through a FooList linked list, and
+ * visit_is_input() for cleaning up on failure.
*/
/*** Useful types ***/
@@ -282,9 +283,8 @@ void visit_free(Visitor *v);
* into *@obj. @obj may also be NULL for a virtual walk, in which
* case @size is ignored.
*
- * @errp obeys typical error usage, and reports failures such as a
- * member @name is not present, or present but not an object. On
- * error, input visitors set *@obj to NULL.
+ * On failure, set *@obj to NULL and store an error through @errp.
+ * Can happen only when @v is an input visitor.
*
* After visit_start_struct() succeeds, the caller may visit its
* members one after the other, passing the member's name and address
@@ -301,8 +301,8 @@ void visit_start_struct(Visitor *v, const char *name, void **obj,
/*
* Prepare for completing an object visit.
*
- * @errp obeys typical error usage, and reports failures such as
- * unparsed keys remaining in the input stream.
+ * On failure, store an error through @errp. Can happen only when @v
+ * is an input visitor.
*
* Should be called prior to visit_end_struct() if all other
* intermediate visit steps were successful, to allow the visitor one
@@ -338,14 +338,13 @@ void visit_end_struct(Visitor *v, void **obj);
* allow @list to be NULL for a virtual walk, in which case @size is
* ignored.
*
- * @errp obeys typical error usage, and reports failures such as a
- * member @name is not present, or present but not a list. On error,
- * input visitors set *@list to NULL.
+ * On failure, set *@list to NULL and store an error through @errp.
+ * Can happen only when @v is an input visitor.
*
* After visit_start_list() succeeds, the caller may visit its members
- * one after the other. A real visit (where @obj is non-NULL) uses
+ * one after the other. A real visit (where @list is non-NULL) uses
* visit_next_list() for traversing the linked list, while a virtual
- * visit (where @obj is NULL) uses other means. For each list
+ * visit (where @list is NULL) uses other means. For each list
* element, call the appropriate visit_type_FOO() with name set to
* NULL and obj set to the address of the value member of the list
* element. Finally, visit_end_list() needs to be called with the
@@ -374,8 +373,8 @@ GenericList *visit_next_list(Visitor *v, GenericList *tail, size_t size);
/*
* Prepare for completing a list visit.
*
- * @errp obeys typical error usage, and reports failures such as
- * unvisited list tail remaining in the input stream.
+ * On failure, store an error through @errp. Can happen only when @v
+ * is an input visitor.
*
* Should be called prior to visit_end_list() if all other
* intermediate visit steps were successful, to allow the visitor one
@@ -407,8 +406,11 @@ void visit_end_list(Visitor *v, void **list);
*
* @obj must not be NULL. Input and clone visitors use @size to
* determine how much memory to allocate into *@obj, then determine
- * the qtype of the next thing to be visited, stored in (*@obj)->type.
- * Other visitors will leave @obj unchanged.
+ * the qtype of the next thing to be visited, and store it in
+ * (*@obj)->type. Other visitors leave @obj unchanged.
+ *
+ * On failure, set *@obj to NULL and store an error through @errp.
+ * Can happen only when @v is an input visitor.
*
* If successful, this must be paired with visit_end_alternate() with
* the same @obj to clean up, even if visiting the contents of the
@@ -461,12 +463,15 @@ bool visit_optional(Visitor *v, const char *name, bool *present);
*
* Currently, all input visitors parse text input, and all output
* visitors produce text output. The mapping between enumeration
- * values and strings is done by the visitor core, using @strings; it
- * should be the ENUM_lookup array from visit-types.h.
+ * values and strings is done by the visitor core, using @lookup.
+ *
+ * On failure, store an error through @errp. Can happen only when @v
+ * is an input visitor.
*
* May call visit_type_str() under the hood, and the enum visit may
* fail even if the corresponding string visit succeeded; this implies
- * that visit_type_str() must have no unwelcome side effects.
+ * that an input visitor's visit_type_str() must have no unwelcome
+ * side effects.
*/
void visit_type_enum(Visitor *v, const char *name, int *obj,
const QEnumLookup *lookup, Error **errp);
@@ -476,6 +481,11 @@ void visit_type_enum(Visitor *v, const char *name, int *obj,
*/
bool visit_is_input(Visitor *v);
+/*
+ * Check if visitor is a dealloc visitor.
+ */
+bool visit_is_dealloc(Visitor *v);
+
/*** Visiting built-in types ***/
/*
@@ -486,6 +496,9 @@ bool visit_is_input(Visitor *v);
*
* @obj must be non-NULL. Input visitors set *@obj to the value;
* other visitors will leave *@obj unchanged.
+ *
+ * On failure, store an error through @errp. Can happen only when @v
+ * is an input visitor.
*/
void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp);
@@ -562,6 +575,9 @@ void visit_type_size(Visitor *v, const char *name, uint64_t *obj,
*
* @obj must be non-NULL. Input visitors set *@obj to the value;
* other visitors will leave *@obj unchanged.
+ *
+ * On failure, store an error through @errp. Can happen only when @v
+ * is an input visitor.
*/
void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp);
@@ -579,6 +595,9 @@ void visit_type_bool(Visitor *v, const char *name, bool *obj, Error **errp);
* It is safe to cast away const when preparing a (const char *) value
* into @obj for use by an output visitor.
*
+ * On failure, set *@obj to NULL and store an error through @errp.
+ * Can happen only when @v is an input visitor.
+ *
* FIXME: Callers that try to output NULL *obj should not be allowed.
*/
void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp);
@@ -592,6 +611,9 @@ void visit_type_str(Visitor *v, const char *name, char **obj, Error **errp);
* @obj must be non-NULL. Input visitors set *@obj to the value;
* other visitors will leave *@obj unchanged. Visitors should
* document if infinity or NaN are not permitted.
+ *
+ * On failure, store an error through @errp. Can happen only when @v
+ * is an input visitor.
*/
void visit_type_number(Visitor *v, const char *name, double *obj,
Error **errp);
@@ -606,6 +628,9 @@ void visit_type_number(Visitor *v, const char *name, double *obj,
* other visitors will leave *@obj unchanged. *@obj must be non-NULL
* for output visitors.
*
+ * On failure, set *@obj to NULL and store an error through @errp.
+ * Can happen only when @v is an input visitor.
+ *
* Note that some kinds of input can't express arbitrary QObject.
* E.g. the visitor returned by qobject_input_visitor_new_keyval()
* can't create numbers or booleans, only strings.
@@ -620,6 +645,9 @@ void visit_type_any(Visitor *v, const char *name, QObject **obj, Error **errp);
*
* @obj must be non-NULL. Input visitors set *@obj to the value;
* other visitors ignore *@obj.
+ *
+ * On failure, set *@obj to NULL and store an error through @errp.
+ * Can happen only when @v is an input visitor.
*/
void visit_type_null(Visitor *v, const char *name, QNull **obj,
Error **errp);
diff --git a/include/qemu/option.h b/include/qemu/option.h
index 844587cab3..eb4097889d 100644
--- a/include/qemu/option.h
+++ b/include/qemu/option.h
@@ -33,7 +33,6 @@ const char *get_opt_value(const char *p, char **value);
void parse_option_size(const char *name, const char *value,
uint64_t *ret, Error **errp);
bool has_help_option(const char *param);
-bool is_valid_option_list(const char *param);
enum QemuOptType {
QEMU_OPT_STRING = 0, /* no parsing (use string as-is) */
diff --git a/io/channel-socket.c b/io/channel-socket.c
index b74f5b92a0..e1b4667087 100644
--- a/io/channel-socket.c
+++ b/io/channel-socket.c
@@ -704,6 +704,7 @@ qio_channel_socket_close(QIOChannel *ioc,
{
QIOChannelSocket *sioc = QIO_CHANNEL_SOCKET(ioc);
int rc = 0;
+ Error *err = NULL;
if (sioc->fd != -1) {
#ifdef WIN32
@@ -715,8 +716,8 @@ qio_channel_socket_close(QIOChannel *ioc,
if (closesocket(sioc->fd) < 0) {
sioc->fd = -1;
- error_setg_errno(errp, errno,
- "Unable to close socket");
+ error_setg_errno(&err, errno, "Unable to close socket");
+ error_propagate(errp, err);
return -1;
}
sioc->fd = -1;
diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c
index 83ecc6f799..67a95dbc7b 100644
--- a/linux-user/riscv/signal.c
+++ b/linux-user/riscv/signal.c
@@ -40,8 +40,9 @@ struct target_ucontext {
unsigned long uc_flags;
struct target_ucontext *uc_link;
target_stack_t uc_stack;
- struct target_sigcontext uc_mcontext;
target_sigset_t uc_sigmask;
+ uint8_t __unused[1024 / 8 - sizeof(target_sigset_t)];
+ struct target_sigcontext uc_mcontext QEMU_ALIGNED(16);
};
struct target_rt_sigframe {
diff --git a/migration/colo.c b/migration/colo.c
index a54ac84f41..1b3493729b 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -263,7 +263,13 @@ ReplicationStatus *qmp_query_xen_replication_status(Error **errp)
void qmp_xen_colo_do_checkpoint(Error **errp)
{
- replication_do_checkpoint_all(errp);
+ Error *err = NULL;
+
+ replication_do_checkpoint_all(&err);
+ if (err) {
+ error_propagate(errp, err);
+ return;
+ }
/* Notify all filters of all NIC to do checkpoint */
colo_notify_filters_event(COLO_EVENT_CHECKPOINT, errp);
}
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index 9b94e67879..7f6e982dc8 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -334,7 +334,8 @@ void hmp_info_migrate(Monitor *mon, const QDict *qdict)
Visitor *v;
char *str;
v = string_output_visitor_new(false, &str);
- visit_type_uint32List(v, NULL, &info->postcopy_vcpu_blocktime, NULL);
+ visit_type_uint32List(v, NULL, &info->postcopy_vcpu_blocktime,
+ &error_abort);
visit_complete(v, &str);
monitor_printf(mon, "postcopy vcpu blocktime: %s\n", str);
g_free(str);
diff --git a/monitor/qmp.c b/monitor/qmp.c
index f89e7daf27..d433ceae5b 100644
--- a/monitor/qmp.c
+++ b/monitor/qmp.c
@@ -322,9 +322,12 @@ static QDict *qmp_greeting(MonitorQMP *mon)
{
QList *cap_list = qlist_new();
QObject *ver = NULL;
+ QDict *args;
QMPCapability cap;
- qmp_marshal_query_version(NULL, &ver, NULL);
+ args = qdict_new();
+ qmp_marshal_query_version(args, &ver, NULL);
+ qobject_unref(args);
for (cap = 0; cap < QMP_CAPABILITY__MAX; cap++) {
if (mon->capab_offered[cap]) {
diff --git a/pc-bios/opensbi-riscv32-sifive_u-fw_jump.bin b/pc-bios/opensbi-riscv32-sifive_u-fw_jump.bin
index bab13f597a..3e0da54080 100644
--- a/pc-bios/opensbi-riscv32-sifive_u-fw_jump.bin
+++ b/pc-bios/opensbi-riscv32-sifive_u-fw_jump.bin
Binary files differ
diff --git a/pc-bios/opensbi-riscv32-virt-fw_jump.bin b/pc-bios/opensbi-riscv32-virt-fw_jump.bin
index c9654e7047..bc56ed61fd 100644
--- a/pc-bios/opensbi-riscv32-virt-fw_jump.bin
+++ b/pc-bios/opensbi-riscv32-virt-fw_jump.bin
Binary files differ
diff --git a/pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin b/pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin
index 77f4dc8f83..1acee86dc7 100644
--- a/pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin
+++ b/pc-bios/opensbi-riscv64-sifive_u-fw_jump.bin
Binary files differ
diff --git a/pc-bios/opensbi-riscv64-virt-fw_jump.bin b/pc-bios/opensbi-riscv64-virt-fw_jump.bin
index 31e74d12ea..c62f2b449b 100644
--- a/pc-bios/opensbi-riscv64-virt-fw_jump.bin
+++ b/pc-bios/opensbi-riscv64-virt-fw_jump.bin
Binary files differ
diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
index d192724b13..2239fc6417 100644
--- a/qapi/qapi-dealloc-visitor.c
+++ b/qapi/qapi-dealloc-visitor.c
@@ -34,12 +34,6 @@ static void qapi_dealloc_end_struct(Visitor *v, void **obj)
}
}
-static void qapi_dealloc_start_alternate(Visitor *v, const char *name,
- GenericAlternate **obj, size_t size,
- Error **errp)
-{
-}
-
static void qapi_dealloc_end_alternate(Visitor *v, void **obj)
{
if (obj) {
@@ -123,7 +117,6 @@ Visitor *qapi_dealloc_visitor_new(void)
v->visitor.type = VISITOR_DEALLOC;
v->visitor.start_struct = qapi_dealloc_start_struct;
v->visitor.end_struct = qapi_dealloc_end_struct;
- v->visitor.start_alternate = qapi_dealloc_start_alternate;
v->visitor.end_alternate = qapi_dealloc_end_alternate;
v->visitor.start_list = qapi_dealloc_start_list;
v->visitor.next_list = qapi_dealloc_next_list;
diff --git a/qapi/qapi-visit-core.c b/qapi/qapi-visit-core.c
index 5365561b07..74aa9c04bd 100644
--- a/qapi/qapi-visit-core.c
+++ b/qapi/qapi-visit-core.c
@@ -142,6 +142,11 @@ bool visit_is_input(Visitor *v)
return v->type == VISITOR_INPUT;
}
+bool visit_is_dealloc(Visitor *v)
+{
+ return v->type == VISITOR_DEALLOC;
+}
+
void visit_type_int(Visitor *v, const char *name, int64_t *obj, Error **errp)
{
assert(obj);
@@ -155,10 +160,13 @@ static void visit_type_uintN(Visitor *v, uint64_t *obj, const char *name,
Error *err = NULL;
uint64_t value = *obj;
+ assert(v->type == VISITOR_INPUT || value <= max);
+
v->type_uint64(v, name, &value, &err);
if (err) {
error_propagate(errp, err);
} else if (value > max) {
+ assert(v->type == VISITOR_INPUT);
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
name ? name : "null", type);
} else {
@@ -214,10 +222,13 @@ static void visit_type_intN(Visitor *v, int64_t *obj, const char *name,
Error *err = NULL;
int64_t value = *obj;
+ assert(v->type == VISITOR_INPUT || (value >= min && value <= max));
+
v->type_int64(v, name, &value, &err);
if (err) {
error_propagate(errp, err);
} else if (value < min || value > max) {
+ assert(v->type == VISITOR_INPUT);
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
name ? name : "null", type);
} else {
@@ -336,15 +347,6 @@ static void output_type_enum(Visitor *v, const char *name, int *obj,
int value = *obj;
char *enum_str;
- /*
- * TODO why is this an error, not an assertion? If assertion:
- * delete, and rely on qapi_enum_lookup()
- */
- if (value < 0 || value >= lookup->size) {
- error_setg(errp, QERR_INVALID_PARAMETER, name ? name : "null");
- return;
- }
-
enum_str = (char *)qapi_enum_lookup(lookup, value);
visit_type_str(v, name, &enum_str, errp);
}
diff --git a/qapi/qobject-input-visitor.c b/qapi/qobject-input-visitor.c
index 32236cbcb1..5ce3ec2e5f 100644
--- a/qapi/qobject-input-visitor.c
+++ b/qapi/qobject-input-visitor.c
@@ -203,31 +203,32 @@ static const char *qobject_input_get_keyval(QObjectInputVisitor *qiv,
return qstring_get_str(qstr);
}
-static void qdict_add_key(const char *key, QObject *obj, void *opaque)
-{
- GHashTable *h = opaque;
- g_hash_table_insert(h, (gpointer) key, NULL);
-}
-
static const QListEntry *qobject_input_push(QObjectInputVisitor *qiv,
const char *name,
QObject *obj, void *qapi)
{
GHashTable *h;
StackObject *tos = g_new0(StackObject, 1);
+ QDict *qdict = qobject_to(QDict, obj);
+ QList *qlist = qobject_to(QList, obj);
+ const QDictEntry *entry;
assert(obj);
tos->name = name;
tos->obj = obj;
tos->qapi = qapi;
- if (qobject_type(obj) == QTYPE_QDICT) {
+ if (qdict) {
h = g_hash_table_new(g_str_hash, g_str_equal);
- qdict_iter(qobject_to(QDict, obj), qdict_add_key, h);
+ for (entry = qdict_first(qdict);
+ entry;
+ entry = qdict_next(qdict, entry)) {
+ g_hash_table_insert(h, (void *)qdict_entry_key(entry), NULL);
+ }
tos->h = h;
} else {
- assert(qobject_type(obj) == QTYPE_QLIST);
- tos->entry = qlist_first(qobject_to(QList, obj));
+ assert(qlist);
+ tos->entry = qlist_first(qlist);
tos->index = -1;
}
diff --git a/qemu-img.c b/qemu-img.c
index 821cbf610e..a2369766f0 100644
--- a/qemu-img.c
+++ b/qemu-img.c
@@ -223,6 +223,53 @@ static bool qemu_img_object_print_help(const char *type, QemuOpts *opts)
return true;
}
+/*
+ * Is @optarg safe for accumulate_options()?
+ * It is when multiple of them can be joined together separated by ','.
+ * To make that work, @optarg must not start with ',' (or else a
+ * separating ',' preceding it gets escaped), and it must not end with
+ * an odd number of ',' (or else a separating ',' following it gets
+ * escaped), or be empty (or else a separating ',' preceding it can
+ * escape a separating ',' following it).
+ *
+ */
+static bool is_valid_option_list(const char *optarg)
+{
+ size_t len = strlen(optarg);
+ size_t i;
+
+ if (!optarg[0] || optarg[0] == ',') {
+ return false;
+ }
+
+ for (i = len; i > 0 && optarg[i - 1] == ','; i--) {
+ }
+ if ((len - i) % 2) {
+ return false;
+ }
+
+ return true;
+}
+
+static int accumulate_options(char **options, char *optarg)
+{
+ char *new_options;
+
+ if (!is_valid_option_list(optarg)) {
+ error_report("Invalid option list: %s", optarg);
+ return -1;
+ }
+
+ if (!*options) {
+ *options = g_strdup(optarg);
+ } else {
+ new_options = g_strdup_printf("%s,%s", *options, optarg);
+ g_free(*options);
+ *options = new_options;
+ }
+ return 0;
+}
+
static QemuOptsList qemu_source_opts = {
.name = "source",
.implied_opt_name = "file",
@@ -482,17 +529,9 @@ static int img_create(int argc, char **argv)
fmt = optarg;
break;
case 'o':
- if (!is_valid_option_list(optarg)) {
- error_report("Invalid option list: %s", optarg);
+ if (accumulate_options(&options, optarg) < 0) {
goto fail;
}
- if (!options) {
- options = g_strdup(optarg);
- } else {
- char *old_options = options;
- options = g_strdup_printf("%s,%s", options, optarg);
- g_free(old_options);
- }
break;
case 'q':
quiet = true;
@@ -2127,17 +2166,9 @@ static int img_convert(int argc, char **argv)
s.compressed = true;
break;
case 'o':
- if (!is_valid_option_list(optarg)) {
- error_report("Invalid option list: %s", optarg);
+ if (accumulate_options(&options, optarg) < 0) {
goto fail_getopt;
}
- if (!options) {
- options = g_strdup(optarg);
- } else {
- char *old_options = options;
- options = g_strdup_printf("%s,%s", options, optarg);
- g_free(old_options);
- }
break;
case 'l':
if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
@@ -3953,18 +3984,10 @@ static int img_amend(int argc, char **argv)
help();
break;
case 'o':
- if (!is_valid_option_list(optarg)) {
- error_report("Invalid option list: %s", optarg);
+ if (accumulate_options(&options, optarg) < 0) {
ret = -1;
goto out_no_progress;
}
- if (!options) {
- options = g_strdup(optarg);
- } else {
- char *old_options = options;
- options = g_strdup_printf("%s,%s", options, optarg);
- g_free(old_options);
- }
break;
case 'f':
fmt = optarg;
@@ -4855,17 +4878,9 @@ static int img_measure(int argc, char **argv)
out_fmt = optarg;
break;
case 'o':
- if (!is_valid_option_list(optarg)) {
- error_report("Invalid option list: %s", optarg);
+ if (accumulate_options(&options, optarg) < 0) {
goto out;
}
- if (!options) {
- options = g_strdup(optarg);
- } else {
- char *old_options = options;
- options = g_strdup_printf("%s,%s", options, optarg);
- g_free(old_options);
- }
break;
case 'l':
if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) {
diff --git a/qga/commands-posix.c b/qga/commands-posix.c
index a52af0315f..ae1348dc8f 100644
--- a/qga/commands-posix.c
+++ b/qga/commands-posix.c
@@ -2518,6 +2518,9 @@ GuestMemoryBlockList *qmp_guest_get_memory_blocks(Error **errp)
mem_blk->phys_index = strtoul(&de->d_name[6], NULL, 10);
mem_blk->has_can_offline = true; /* lolspeak ftw */
transfer_memory_block(mem_blk, true, NULL, &local_err);
+ if (local_err) {
+ break;
+ }
entry = g_malloc0(sizeof *entry);
entry->value = mem_blk;
diff --git a/qga/commands-win32.c b/qga/commands-win32.c
index 9717a8d52d..5ba56327dd 100644
--- a/qga/commands-win32.c
+++ b/qga/commands-win32.c
@@ -1322,9 +1322,16 @@ void qmp_guest_suspend_disk(Error **errp)
*mode = GUEST_SUSPEND_MODE_DISK;
check_suspend_mode(*mode, &local_err);
+ if (local_err) {
+ goto out;
+ }
acquire_privilege(SE_SHUTDOWN_NAME, &local_err);
+ if (local_err) {
+ goto out;
+ }
execute_async(do_suspend, mode, &local_err);
+out:
if (local_err) {
error_propagate(errp, local_err);
g_free(mode);
@@ -1338,9 +1345,16 @@ void qmp_guest_suspend_ram(Error **errp)
*mode = GUEST_SUSPEND_MODE_RAM;
check_suspend_mode(*mode, &local_err);
+ if (local_err) {
+ goto out;
+ }
acquire_privilege(SE_SHUTDOWN_NAME, &local_err);
+ if (local_err) {
+ goto out;
+ }
execute_async(do_suspend, mode, &local_err);
+out:
if (local_err) {
error_propagate(errp, local_err);
g_free(mode);
diff --git a/qobject/qdict.c b/qobject/qdict.c
index 3d8c2f7bbc..526de54ceb 100644
--- a/qobject/qdict.c
+++ b/qobject/qdict.c
@@ -298,25 +298,6 @@ const char *qdict_get_try_str(const QDict *qdict, const char *key)
return qstr ? qstring_get_str(qstr) : NULL;
}
-/**
- * qdict_iter(): Iterate over all the dictionary's stored values.
- *
- * This function allows the user to provide an iterator, which will be
- * called for each stored value in the dictionary.
- */
-void qdict_iter(const QDict *qdict,
- void (*iter)(const char *key, QObject *obj, void *opaque),
- void *opaque)
-{
- int i;
- QDictEntry *entry;
-
- for (i = 0; i < QDICT_BUCKET_MAX; i++) {
- QLIST_FOREACH(entry, &qdict->table[i], next)
- iter(entry->key, entry->value, opaque);
- }
-}
-
static QDictEntry *qdict_next_entry(const QDict *qdict, int first_bucket)
{
int i;
diff --git a/qobject/qjson.c b/qobject/qjson.c
index db36101f3b..f1f2c69704 100644
--- a/qobject/qjson.c
+++ b/qobject/qjson.c
@@ -149,58 +149,18 @@ QDict *qdict_from_jsonf_nofail(const char *string, ...)
return qdict;
}
-typedef struct ToJsonIterState
-{
- int indent;
- int pretty;
- int count;
- QString *str;
-} ToJsonIterState;
-
static void to_json(const QObject *obj, QString *str, int pretty, int indent);
-static void to_json_dict_iter(const char *key, QObject *obj, void *opaque)
-{
- ToJsonIterState *s = opaque;
- QString *qkey;
- int j;
-
- if (s->count) {
- qstring_append(s->str, s->pretty ? "," : ", ");
- }
-
- if (s->pretty) {
- qstring_append(s->str, "\n");
- for (j = 0 ; j < s->indent ; j++)
- qstring_append(s->str, " ");
- }
-
- qkey = qstring_from_str(key);
- to_json(QOBJECT(qkey), s->str, s->pretty, s->indent);
- qobject_unref(qkey);
-
- qstring_append(s->str, ": ");
- to_json(obj, s->str, s->pretty, s->indent);
- s->count++;
-}
-
-static void to_json_list_iter(QObject *obj, void *opaque)
+static void json_pretty_newline(QString *str, bool pretty, int indent)
{
- ToJsonIterState *s = opaque;
- int j;
+ int i;
- if (s->count) {
- qstring_append(s->str, s->pretty ? "," : ", ");
- }
-
- if (s->pretty) {
- qstring_append(s->str, "\n");
- for (j = 0 ; j < s->indent ; j++)
- qstring_append(s->str, " ");
+ if (pretty) {
+ qstring_append(str, "\n");
+ for (i = 0; i < indent; i++) {
+ qstring_append(str, " ");
+ }
}
-
- to_json(obj, s->str, s->pretty, s->indent);
- s->count++;
}
static void to_json(const QObject *obj, QString *str, int pretty, int indent)
@@ -273,40 +233,49 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent)
break;
}
case QTYPE_QDICT: {
- ToJsonIterState s;
QDict *val = qobject_to(QDict, obj);
+ const char *comma = pretty ? "," : ", ";
+ const char *sep = "";
+ const QDictEntry *entry;
+ QString *qkey;
- s.count = 0;
- s.str = str;
- s.indent = indent + 1;
- s.pretty = pretty;
qstring_append(str, "{");
- qdict_iter(val, to_json_dict_iter, &s);
- if (pretty) {
- int j;
- qstring_append(str, "\n");
- for (j = 0 ; j < indent ; j++)
- qstring_append(str, " ");
+
+ for (entry = qdict_first(val);
+ entry;
+ entry = qdict_next(val, entry)) {
+ qstring_append(str, sep);
+ json_pretty_newline(str, pretty, indent + 1);
+
+ qkey = qstring_from_str(qdict_entry_key(entry));
+ to_json(QOBJECT(qkey), str, pretty, indent + 1);
+ qobject_unref(qkey);
+
+ qstring_append(str, ": ");
+ to_json(qdict_entry_value(entry), str, pretty, indent + 1);
+ sep = comma;
}
+
+ json_pretty_newline(str, pretty, indent);
qstring_append(str, "}");
break;
}
case QTYPE_QLIST: {
- ToJsonIterState s;
QList *val = qobject_to(QList, obj);
+ const char *comma = pretty ? "," : ", ";
+ const char *sep = "";
+ QListEntry *entry;
- s.count = 0;
- s.str = str;
- s.indent = indent + 1;
- s.pretty = pretty;
qstring_append(str, "[");
- qlist_iter(val, (void *)to_json_list_iter, &s);
- if (pretty) {
- int j;
- qstring_append(str, "\n");
- for (j = 0 ; j < indent ; j++)
- qstring_append(str, " ");
+
+ QLIST_FOREACH_ENTRY(val, entry) {
+ qstring_append(str, sep);
+ json_pretty_newline(str, pretty, indent + 1);
+ to_json(qlist_entry_obj(entry), str, pretty, indent + 1);
+ sep = comma;
}
+
+ json_pretty_newline(str, pretty, indent);
qstring_append(str, "]");
break;
}
diff --git a/qobject/qlist.c b/qobject/qlist.c
index b3274af88b..1be95367d1 100644
--- a/qobject/qlist.c
+++ b/qobject/qlist.c
@@ -34,20 +34,17 @@ QList *qlist_new(void)
return qlist;
}
-static void qlist_copy_elem(QObject *obj, void *opaque)
-{
- QList *dst = opaque;
-
- qobject_ref(obj);
- qlist_append_obj(dst, obj);
-}
-
QList *qlist_copy(QList *src)
{
QList *dst = qlist_new();
+ QListEntry *entry;
+ QObject *elt;
- qlist_iter(src, qlist_copy_elem, dst);
-
+ QLIST_FOREACH_ENTRY(src, entry) {
+ elt = qlist_entry_obj(entry);
+ qobject_ref(elt);
+ qlist_append_obj(dst, elt);
+ }
return dst;
}
@@ -86,21 +83,6 @@ void qlist_append_null(QList *qlist)
qlist_append(qlist, qnull());
}
-/**
- * qlist_iter(): Iterate over all the list's stored values.
- *
- * This function allows the user to provide an iterator, which will be
- * called for each stored value in the list.
- */
-void qlist_iter(const QList *qlist,
- void (*iter)(QObject *obj, void *opaque), void *opaque)
-{
- QListEntry *entry;
-
- QTAILQ_FOREACH(entry, &qlist->head, next)
- iter(entry->value, opaque);
-}
-
QObject *qlist_pop(QList *qlist)
{
QListEntry *entry;
@@ -137,16 +119,14 @@ int qlist_empty(const QList *qlist)
return QTAILQ_EMPTY(&qlist->head);
}
-static void qlist_size_iter(QObject *obj, void *opaque)
-{
- size_t *count = opaque;
- (*count)++;
-}
-
size_t qlist_size(const QList *qlist)
{
size_t count = 0;
- qlist_iter(qlist, qlist_size_iter, &count);
+ QListEntry *entry;
+
+ QLIST_FOREACH_ENTRY(qlist, entry) {
+ count++;
+ }
return count;
}
diff --git a/qom/object.c b/qom/object.c
index 1812f79224..be700e831f 100644
--- a/qom/object.c
+++ b/qom/object.c
@@ -1550,11 +1550,9 @@ int object_property_get_enum(Object *obj, const char *name,
}
visit_complete(v, &str);
visit_free(v);
- v = string_input_visitor_new(str);
- visit_type_enum(v, name, &ret, enumprop->lookup, errp);
+ ret = qapi_enum_parse(enumprop->lookup, str, -1, errp);
g_free(str);
- visit_free(v);
return ret;
}
diff --git a/roms/opensbi b/roms/opensbi
-Subproject ac5e821d50be631f26274765a59bc1b444ffd86
+Subproject 9f1b72ce66d659e91013b358939e832fb27223f
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index bc30876c88..6809b0fb6e 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -104,6 +104,7 @@ def gen_marshal(name, arg_type, boxed, ret_type):
%(proto)s
{
Error *err = NULL;
+ Visitor *v;
''',
proto=build_marshal_proto(name))
@@ -114,44 +115,38 @@ def gen_marshal(name, arg_type, boxed, ret_type):
c_type=ret_type.c_type())
if have_args:
- visit_members = ('visit_type_%s_members(v, &arg, &err);'
- % arg_type.c_name())
ret += mcgen('''
- Visitor *v;
%(c_name)s arg = {0};
-
''',
c_name=arg_type.c_name())
- else:
- visit_members = ''
- ret += mcgen('''
- Visitor *v = NULL;
-
- if (args) {
-''')
- push_indent()
ret += mcgen('''
+
v = qobject_input_visitor_new(QOBJECT(args));
visit_start_struct(v, NULL, NULL, 0, &err);
if (err) {
goto out;
}
- %(visit_members)s
+''')
+
+ if have_args:
+ ret += mcgen('''
+ visit_type_%(c_arg_type)s_members(v, &arg, &err);
if (!err) {
visit_check_struct(v, &err);
}
+''',
+ c_arg_type=arg_type.c_name())
+ else:
+ ret += mcgen('''
+ visit_check_struct(v, &err);
+''')
+
+ ret += mcgen('''
visit_end_struct(v, NULL);
if (err) {
goto out;
}
-''',
- visit_members=visit_members)
-
- if not have_args:
- pop_indent()
- ret += mcgen('''
- }
''')
ret += gen_call(name, arg_type, boxed, ret_type)
@@ -163,29 +158,20 @@ out:
visit_free(v);
''')
+ ret += mcgen('''
+ v = qapi_dealloc_visitor_new();
+ visit_start_struct(v, NULL, NULL, 0, NULL);
+''')
+
if have_args:
- visit_members = ('visit_type_%s_members(v, &arg, NULL);'
- % arg_type.c_name())
- else:
- visit_members = ''
ret += mcgen('''
- if (args) {
-''')
- push_indent()
+ visit_type_%(c_arg_type)s_members(v, &arg, NULL);
+''',
+ c_arg_type=arg_type.c_name())
ret += mcgen('''
- v = qapi_dealloc_visitor_new();
- visit_start_struct(v, NULL, NULL, 0, NULL);
- %(visit_members)s
visit_end_struct(v, NULL);
visit_free(v);
-''',
- visit_members=visit_members)
-
- if not have_args:
- pop_indent()
- ret += mcgen('''
- }
''')
ret += mcgen('''
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index 23d9194aa4..d5d7a1031f 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -189,6 +189,8 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
goto out;
}
if (!*obj) {
+ /* incomplete */
+ assert(visit_is_dealloc(v));
goto out_obj;
}
switch ((*obj)->type) {
@@ -230,8 +232,12 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
case QTYPE_NONE:
abort();
default:
+ assert(visit_is_input(v));
error_setg(&err, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
"%(name)s");
+ /* Avoid passing invalid *obj to qapi_free_%(c_name)s() */
+ g_free(*obj);
+ *obj = NULL;
}
out_obj:
visit_end_alternate(v, (void **)obj);
@@ -260,6 +266,8 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
goto out;
}
if (!*obj) {
+ /* incomplete */
+ assert(visit_is_dealloc(v));
goto out_obj;
}
visit_type_%(c_name)s_members(v, *obj, &err);
diff --git a/softmmu/vl.c b/softmmu/vl.c
index 32c0047889..afd2615fb3 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -3059,19 +3059,19 @@ void qemu_init(int argc, char **argv, char **envp)
}
break;
case QEMU_OPTION_kernel:
- qemu_opts_set(qemu_find_opts("machine"), 0, "kernel", optarg,
+ qemu_opts_set(qemu_find_opts("machine"), NULL, "kernel", optarg,
&error_abort);
break;
case QEMU_OPTION_initrd:
- qemu_opts_set(qemu_find_opts("machine"), 0, "initrd", optarg,
+ qemu_opts_set(qemu_find_opts("machine"), NULL, "initrd", optarg,
&error_abort);
break;
case QEMU_OPTION_append:
- qemu_opts_set(qemu_find_opts("machine"), 0, "append", optarg,
+ qemu_opts_set(qemu_find_opts("machine"), NULL, "append", optarg,
&error_abort);
break;
case QEMU_OPTION_dtb:
- qemu_opts_set(qemu_find_opts("machine"), 0, "dtb", optarg,
+ qemu_opts_set(qemu_find_opts("machine"), NULL, "dtb", optarg,
&error_abort);
break;
case QEMU_OPTION_cdrom:
@@ -3182,7 +3182,7 @@ void qemu_init(int argc, char **argv, char **envp)
}
break;
case QEMU_OPTION_bios:
- qemu_opts_set(qemu_find_opts("machine"), 0, "firmware", optarg,
+ qemu_opts_set(qemu_find_opts("machine"), NULL, "firmware", optarg,
&error_abort);
break;
case QEMU_OPTION_singlestep:
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 90ffc5f3b1..9c256ab159 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -5784,9 +5784,9 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
host_cpuid(index, 0, eax, ebx, ecx, edx);
break;
}
- *eax = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) | \
+ *eax = (L1_DTLB_2M_ASSOC << 24) | (L1_DTLB_2M_ENTRIES << 16) |
(L1_ITLB_2M_ASSOC << 8) | (L1_ITLB_2M_ENTRIES);
- *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) | \
+ *ebx = (L1_DTLB_4K_ASSOC << 24) | (L1_DTLB_4K_ENTRIES << 16) |
(L1_ITLB_4K_ASSOC << 8) | (L1_ITLB_4K_ENTRIES);
*ecx = encode_cache_cpuid80000005(env->cache_info_amd.l1d_cache);
*edx = encode_cache_cpuid80000005(env->cache_info_amd.l1i_cache);
@@ -5797,13 +5797,13 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
host_cpuid(index, 0, eax, ebx, ecx, edx);
break;
}
- *eax = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) | \
- (L2_DTLB_2M_ENTRIES << 16) | \
- (AMD_ENC_ASSOC(L2_ITLB_2M_ASSOC) << 12) | \
+ *eax = (AMD_ENC_ASSOC(L2_DTLB_2M_ASSOC) << 28) |
+ (L2_DTLB_2M_ENTRIES << 16) |
+ (AMD_ENC_ASSOC(L2_ITLB_2M_ASSOC) << 12) |
(L2_ITLB_2M_ENTRIES);
- *ebx = (AMD_ENC_ASSOC(L2_DTLB_4K_ASSOC) << 28) | \
- (L2_DTLB_4K_ENTRIES << 16) | \
- (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) | \
+ *ebx = (AMD_ENC_ASSOC(L2_DTLB_4K_ASSOC) << 28) |
+ (L2_DTLB_4K_ENTRIES << 16) |
+ (AMD_ENC_ASSOC(L2_ITLB_4K_ASSOC) << 12) |
(L2_ITLB_4K_ENTRIES);
encode_cache_cpuid80000006(env->cache_info_amd.l2_cache,
cpu->enable_l3_cache ?
@@ -6326,7 +6326,7 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp)
*/
env->features[w] |=
x86_cpu_get_supported_feature_word(w, cpu->migratable) &
- ~env->user_features[w] & \
+ ~env->user_features[w] &
~feature_word_info[w].no_autoenable_flags;
}
}
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
index a2c2f271df..c9cf2364ca 100644
--- a/target/microblaze/cpu.c
+++ b/target/microblaze/cpu.c
@@ -163,14 +163,14 @@ static void mb_cpu_realizefn(DeviceState *dev, Error **errp)
qemu_init_vcpu(cs);
- env->pvr.regs[0] = PVR0_USE_EXC_MASK \
- | PVR0_USE_ICACHE_MASK \
+ env->pvr.regs[0] = PVR0_USE_EXC_MASK
+ | PVR0_USE_ICACHE_MASK
| PVR0_USE_DCACHE_MASK;
- env->pvr.regs[2] = PVR2_D_OPB_MASK \
- | PVR2_D_LMB_MASK \
- | PVR2_I_OPB_MASK \
- | PVR2_I_LMB_MASK \
- | PVR2_FPU_EXC_MASK \
+ env->pvr.regs[2] = PVR2_D_OPB_MASK
+ | PVR2_D_LMB_MASK
+ | PVR2_I_OPB_MASK
+ | PVR2_I_LMB_MASK
+ | PVR2_FPU_EXC_MASK
| 0;
version = cpu->cfg.version ? cpu->cfg.version : DEFAULT_CPU_VERSION;
diff --git a/target/ppc/translate_init.inc.c b/target/ppc/translate_init.inc.c
index e853164a86..fd763e588e 100644
--- a/target/ppc/translate_init.inc.c
+++ b/target/ppc/translate_init.inc.c
@@ -5210,7 +5210,7 @@ POWERPC_FAMILY(e5500)(ObjectClass *oc, void *data)
PPC_FLOAT_STFIWX | PPC_WAIT |
PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC |
PPC_64B | PPC_POPCNTB | PPC_POPCNTWD;
- pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_PERM_ISA206 | \
+ pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_PERM_ISA206 |
PPC2_FP_CVT_S64;
pcc->msr_mask = (1ull << MSR_CM) |
(1ull << MSR_GS) |
@@ -5258,7 +5258,7 @@ POWERPC_FAMILY(e6500)(ObjectClass *oc, void *data)
PPC_FLOAT_STFIWX | PPC_WAIT |
PPC_MEM_TLBSYNC | PPC_TLBIVAX | PPC_MEM_SYNC |
PPC_64B | PPC_POPCNTB | PPC_POPCNTWD | PPC_ALTIVEC;
- pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_PERM_ISA206 | \
+ pcc->insns_flags2 = PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_PERM_ISA206 |
PPC2_FP_CVT_S64 | PPC2_ATOMIC_ISA206;
pcc->msr_mask = (1ull << MSR_CM) |
(1ull << MSR_GS) |
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 4e578239d3..059d71f2c7 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -164,6 +164,15 @@ static void rv32imacu_nommu_cpu_init(Object *obj)
set_feature(env, RISCV_FEATURE_PMP);
}
+static void rv32imafcu_nommu_cpu_init(Object *obj)
+{
+ CPURISCVState *env = &RISCV_CPU(obj)->env;
+ set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVC | RVU);
+ set_priv_version(env, PRIV_VERSION_1_10_0);
+ set_resetvec(env, DEFAULT_RSTVEC);
+ set_feature(env, RISCV_FEATURE_PMP);
+}
+
#elif defined(TARGET_RISCV64)
static void riscv_base64_cpu_init(Object *obj)
@@ -610,6 +619,7 @@ static const TypeInfo riscv_cpu_type_infos[] = {
#if defined(TARGET_RISCV32)
DEFINE_CPU(TYPE_RISCV_CPU_BASE32, riscv_base32_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32imacu_nommu_cpu_init),
+ DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32imafcu_nommu_cpu_init),
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32gcsu_priv1_10_0_cpu_init),
/* Depreacted */
DEFINE_CPU(TYPE_RISCV_CPU_RV32IMACU_NOMMU, rv32imacu_nommu_cpu_init),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 7d21addbab..d0e7f5b9c5 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -36,6 +36,7 @@
#define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32")
#define TYPE_RISCV_CPU_BASE64 RISCV_CPU_TYPE_NAME("rv64")
#define TYPE_RISCV_CPU_SIFIVE_E31 RISCV_CPU_TYPE_NAME("sifive-e31")
+#define TYPE_RISCV_CPU_SIFIVE_E34 RISCV_CPU_TYPE_NAME("sifive-e34")
#define TYPE_RISCV_CPU_SIFIVE_E51 RISCV_CPU_TYPE_NAME("sifive-e51")
#define TYPE_RISCV_CPU_SIFIVE_U34 RISCV_CPU_TYPE_NAME("sifive-u34")
#define TYPE_RISCV_CPU_SIFIVE_U54 RISCV_CPU_TYPE_NAME("sifive-u54")
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index d3ba9efb02..bc80aa87cf 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -452,10 +452,11 @@ restart:
hwaddr pte_addr;
if (two_stage && first_stage) {
+ int vbase_prot;
hwaddr vbase;
/* Do the second stage translation on the base PTE address. */
- get_physical_address(env, &vbase, prot, base, access_type,
+ get_physical_address(env, &vbase, &vbase_prot, base, access_type,
mmu_idx, false, true);
pte_addr = vbase + idx * ptesize;
@@ -558,12 +559,7 @@ restart:
/* for superpage mappings, make a fake leaf PTE for the TLB's
benefit. */
target_ulong vpn = addr >> PGSHIFT;
- if (i == 0) {
- *physical = (ppn | (vpn & ((1L << (ptshift + widened)) - 1))) <<
- PGSHIFT;
- } else {
- *physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT;
- }
+ *physical = (ppn | (vpn & ((1L << ptshift) - 1))) << PGSHIFT;
/* set permissions on the TLB entry */
if ((pte & PTE_R) || ((pte & PTE_X) && mxr)) {
@@ -706,7 +702,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
#ifndef CONFIG_USER_ONLY
vaddr im_address;
hwaddr pa = 0;
- int prot;
+ int prot, prot2;
bool pmp_violation = false;
bool m_mode_two_stage = false;
bool hs_mode_two_stage = false;
@@ -756,13 +752,15 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
/* Second stage lookup */
im_address = pa;
- ret = get_physical_address(env, &pa, &prot, im_address,
+ ret = get_physical_address(env, &pa, &prot2, im_address,
access_type, mmu_idx, false, true);
qemu_log_mask(CPU_LOG_MMU,
"%s 2nd-stage address=%" VADDR_PRIx " ret %d physical "
TARGET_FMT_plx " prot %d\n",
- __func__, im_address, ret, pa, prot);
+ __func__, im_address, ret, pa, prot2);
+
+ prot &= prot2;
if (riscv_feature(env, RISCV_FEATURE_PMP) &&
(ret == TRANSLATE_SUCCESS) &&
diff --git a/tests/check-qlist.c b/tests/check-qlist.c
index ece83e293d..3cd0ccbf19 100644
--- a/tests/check-qlist.c
+++ b/tests/check-qlist.c
@@ -61,40 +61,31 @@ static void qobject_to_qlist_test(void)
qobject_unref(qlist);
}
-static int iter_called;
-static const int iter_max = 42;
-
-static void iter_func(QObject *obj, void *opaque)
-{
- QNum *qi;
- int64_t val;
-
- g_assert(opaque == NULL);
-
- qi = qobject_to(QNum, obj);
- g_assert(qi != NULL);
-
- g_assert(qnum_get_try_int(qi, &val));
- g_assert_cmpint(val, >=, 0);
- g_assert_cmpint(val, <=, iter_max);
-
- iter_called++;
-}
-
static void qlist_iter_test(void)
{
+ const int iter_max = 42;
int i;
QList *qlist;
+ QListEntry *entry;
+ QNum *qi;
+ int64_t val;
qlist = qlist_new();
for (i = 0; i < iter_max; i++)
qlist_append_int(qlist, i);
- iter_called = 0;
- qlist_iter(qlist, iter_func, NULL);
+ i = 0;
+ QLIST_FOREACH_ENTRY(qlist, entry) {
+ qi = qobject_to(QNum, qlist_entry_obj(entry));
+ g_assert(qi != NULL);
+
+ g_assert(qnum_get_try_int(qi, &val));
+ g_assert_cmpint(val, ==, i);
+ i++;
+ }
- g_assert(iter_called == iter_max);
+ g_assert(i == iter_max);
qobject_unref(qlist);
}
diff --git a/tests/qtest/fuzz/qos_fuzz.c b/tests/qtest/fuzz/qos_fuzz.c
index af28c92866..87eadb0889 100644
--- a/tests/qtest/fuzz/qos_fuzz.c
+++ b/tests/qtest/fuzz/qos_fuzz.c
@@ -36,7 +36,6 @@
#include "qapi/qapi-commands-machine.h"
#include "qapi/qapi-commands-qom.h"
-#include "qapi/qmp/qlist.h"
void *fuzz_qos_obj;
@@ -45,34 +44,19 @@ QGuestAllocator *fuzz_qos_alloc;
static const char *fuzz_target_name;
static char **fuzz_path_vec;
-/*
- * Replaced the qmp commands with direct qmp_marshal calls.
- * Probably there is a better way to do this
- */
static void qos_set_machines_devices_available(void)
{
- QDict *req = qdict_new();
- QObject *response;
- QDict *args = qdict_new();
- QList *lst;
-
- qmp_marshal_query_machines(NULL, &response, &error_abort);
- lst = qobject_to(QList, response);
- apply_to_qlist(lst, true);
-
- qobject_unref(response);
-
+ MachineInfoList *mach_info;
+ ObjectTypeInfoList *type_info;
- qdict_put_str(req, "execute", "qom-list-types");
- qdict_put_str(args, "implements", "device");
- qdict_put_bool(args, "abstract", true);
- qdict_put_obj(req, "arguments", (QObject *) args);
+ mach_info = qmp_query_machines(&error_abort);
+ machines_apply_to_node(mach_info);
+ qapi_free_MachineInfoList(mach_info);
- qmp_marshal_qom_list_types(args, &response, &error_abort);
- lst = qobject_to(QList, response);
- apply_to_qlist(lst, false);
- qobject_unref(response);
- qobject_unref(req);
+ type_info = qmp_qom_list_types(true, "device", true, true,
+ &error_abort);
+ types_apply_to_node(type_info);
+ qapi_free_ObjectTypeInfoList(type_info);
}
static char **current_path;
diff --git a/tests/qtest/libqos/qos_external.c b/tests/qtest/libqos/qos_external.c
index 398556dde0..9f5180e18d 100644
--- a/tests/qtest/libqos/qos_external.c
+++ b/tests/qtest/libqos/qos_external.c
@@ -29,66 +29,44 @@
#include "libqos/qgraph_internal.h"
#include "libqos/qos_external.h"
+static void machine_apply_to_node(const char *name)
+{
+ char *machine_name = g_strconcat(qtest_get_arch(), "/", name, NULL);
+ qos_graph_node_set_availability(machine_name, true);
+ g_free(machine_name);
+}
-void apply_to_node(const char *name, bool is_machine, bool is_abstract)
+void machines_apply_to_node(MachineInfoList *mach_info)
{
- char *machine_name = NULL;
- if (is_machine) {
- const char *arch = qtest_get_arch();
- machine_name = g_strconcat(arch, "/", name, NULL);
- name = machine_name;
+ MachineInfoList *tail;
+
+ for (tail = mach_info; tail; tail = tail->next) {
+ machine_apply_to_node(tail->value->name);
+ if (tail->value->alias) {
+ machine_apply_to_node(tail->value->alias);
+ }
}
+}
+
+static void type_apply_to_node(const char *name, bool is_abstract)
+{
qos_graph_node_set_availability(name, true);
if (is_abstract) {
qos_delete_cmd_line(name);
}
- g_free(machine_name);
}
-/**
- * apply_to_qlist(): using QMP queries QEMU for a list of
- * machines and devices available, and sets the respective node
- * as true. If a node is found, also all its produced and contained
- * child are marked available.
- *
- * See qos_graph_node_set_availability() for more info
- */
-void apply_to_qlist(QList *list, bool is_machine)
+void types_apply_to_node(ObjectTypeInfoList *type_info)
{
- const QListEntry *p;
- const char *name;
- bool abstract;
- QDict *minfo;
- QObject *qobj;
- QString *qstr;
- QBool *qbool;
-
- for (p = qlist_first(list); p; p = qlist_next(p)) {
- minfo = qobject_to(QDict, qlist_entry_obj(p));
- qobj = qdict_get(minfo, "name");
- qstr = qobject_to(QString, qobj);
- name = qstring_get_str(qstr);
-
- qobj = qdict_get(minfo, "abstract");
- if (qobj) {
- qbool = qobject_to(QBool, qobj);
- abstract = qbool_get_bool(qbool);
- } else {
- abstract = false;
- }
+ ObjectTypeInfoList *tail;
- apply_to_node(name, is_machine, abstract);
- qobj = qdict_get(minfo, "alias");
- if (qobj) {
- qstr = qobject_to(QString, qobj);
- name = qstring_get_str(qstr);
- apply_to_node(name, is_machine, abstract);
- }
+ for (tail = type_info; tail; tail = tail->next) {
+ type_apply_to_node(tail->value->name, tail->value->abstract);
}
}
-QGuestAllocator *get_machine_allocator(QOSGraphObject *obj)
+static QGuestAllocator *get_machine_allocator(QOSGraphObject *obj)
{
return obj->get_driver(obj, "memory");
}
diff --git a/tests/qtest/libqos/qos_external.h b/tests/qtest/libqos/qos_external.h
index 7b44930c55..72d7f91707 100644
--- a/tests/qtest/libqos/qos_external.h
+++ b/tests/qtest/libqos/qos_external.h
@@ -18,11 +18,13 @@
#ifndef QOS_EXTERNAL_H
#define QOS_EXTERNAL_H
-#include "libqos/qgraph.h"
-void apply_to_node(const char *name, bool is_machine, bool is_abstract);
-void apply_to_qlist(QList *list, bool is_machine);
-QGuestAllocator *get_machine_allocator(QOSGraphObject *obj);
+#include "libqos/malloc.h"
+#include "qapi/qapi-types-machine.h"
+#include "qapi/qapi-types-qom.h"
+
+void machines_apply_to_node(MachineInfoList *mach_info);
+void types_apply_to_node(ObjectTypeInfoList *type_info);
void *allocate_objects(QTestState *qts, char **path, QGuestAllocator **p_alloc);
#endif
diff --git a/tests/qtest/qos-test.c b/tests/qtest/qos-test.c
index ad193f43a5..3062a13557 100644
--- a/tests/qtest/qos-test.c
+++ b/tests/qtest/qos-test.c
@@ -19,11 +19,12 @@
#include "qemu/osdep.h"
#include <getopt.h>
#include "libqtest-single.h"
+#include "qapi/error.h"
#include "qapi/qmp/qdict.h"
-#include "qapi/qmp/qbool.h"
-#include "qapi/qmp/qstring.h"
#include "qemu/module.h"
-#include "qapi/qmp/qlist.h"
+#include "qapi/qobject-input-visitor.h"
+#include "qapi/qapi-visit-machine.h"
+#include "qapi/qapi-visit-qom.h"
#include "libqos/malloc.h"
#include "libqos/qgraph.h"
#include "libqos/qgraph_internal.h"
@@ -51,13 +52,20 @@ static void qos_set_machines_devices_available(void)
{
QDict *response;
QDict *args = qdict_new();
- QList *list;
+ QObject *ret;
+ Visitor *v;
+ MachineInfoList *mach_info;
+ ObjectTypeInfoList *type_info;
qtest_start("-machine none");
response = qmp("{ 'execute': 'query-machines' }");
- list = qdict_get_qlist(response, "return");
+ ret = qdict_get(response, "return");
- apply_to_qlist(list, true);
+ v = qobject_input_visitor_new(ret);
+ visit_type_MachineInfoList(v, NULL, &mach_info, &error_abort);
+ visit_free(v);
+ machines_apply_to_node(mach_info);
+ qapi_free_MachineInfoList(mach_info);
qobject_unref(response);
@@ -66,10 +74,13 @@ static void qos_set_machines_devices_available(void)
response = qmp("{'execute': 'qom-list-types',"
" 'arguments': %p }", args);
- g_assert(qdict_haskey(response, "return"));
- list = qdict_get_qlist(response, "return");
+ ret = qdict_get(response, "return");
- apply_to_qlist(list, false);
+ v = qobject_input_visitor_new(ret);
+ visit_type_ObjectTypeInfoList(v, NULL, &type_info, &error_abort);
+ visit_free(v);
+ types_apply_to_node(type_info);
+ qapi_free_ObjectTypeInfoList(type_info);
qtest_end();
qobject_unref(response);
diff --git a/tests/test-logging.c b/tests/test-logging.c
index 6387e4933f..8580b82420 100644
--- a/tests/test-logging.c
+++ b/tests/test-logging.c
@@ -73,10 +73,10 @@ static void test_parse_range(void)
g_assert(qemu_log_in_addr_range(UINT64_MAX));
g_assert_false(qemu_log_in_addr_range(UINT64_MAX - 1));
- qemu_set_dfilter_ranges("0..0xffffffffffffffff", &err);
+ qemu_set_dfilter_ranges("0..0xffffffffffffffff", &error_abort);
g_assert(qemu_log_in_addr_range(0));
g_assert(qemu_log_in_addr_range(UINT64_MAX));
-
+
qemu_set_dfilter_ranges("2..1", &err);
error_free_or_abort(&err);
diff --git a/tests/test-qemu-opts.c b/tests/test-qemu-opts.c
index ef96e84aed..2a0f42a09b 100644
--- a/tests/test-qemu-opts.c
+++ b/tests/test-qemu-opts.c
@@ -500,10 +500,10 @@ static void test_opts_parse(void)
g_assert(!opts);
/* TODO Cover .merge_lists = true */
- /* Buggy ID recognition */
+ /* Buggy ID recognition (fixed) */
opts = qemu_opts_parse(&opts_list_03, "x=,,id=bar", false, &error_abort);
g_assert_cmpuint(opts_count(opts), ==, 1);
- g_assert_cmpstr(qemu_opts_id(opts), ==, "bar"); /* BUG */
+ g_assert(!qemu_opts_id(opts));
g_assert_cmpstr(qemu_opt_get(opts, "x"), ==, ",id=bar");
/* Anti-social ID */
@@ -728,6 +728,47 @@ static void test_opts_parse_size(void)
qemu_opts_reset(&opts_list_02);
}
+static void test_has_help_option(void)
+{
+ static const struct {
+ const char *params;
+ /* expected value of qemu_opt_has_help_opt() with implied=false */
+ bool expect;
+ /* expected value of qemu_opt_has_help_opt() with implied=true */
+ bool expect_implied;
+ } test[] = {
+ { "help", true, false },
+ { "?", true, false },
+ { "helpme", false, false },
+ { "?me", false, false },
+ { "a,help", true, true },
+ { "a,?", true, true },
+ { "a=0,help,b", true, true },
+ { "a=0,?,b", true, true },
+ { "help,b=1", true, false },
+ { "?,b=1", true, false },
+ { "a,b,,help", true, true },
+ { "a,b,,?", true, true },
+ };
+ int i;
+ QemuOpts *opts;
+
+ for (i = 0; i < ARRAY_SIZE(test); i++) {
+ g_assert_cmpint(has_help_option(test[i].params),
+ ==, test[i].expect);
+ opts = qemu_opts_parse(&opts_list_03, test[i].params, false,
+ &error_abort);
+ g_assert_cmpint(qemu_opt_has_help_opt(opts),
+ ==, test[i].expect);
+ qemu_opts_del(opts);
+ opts = qemu_opts_parse(&opts_list_03, test[i].params, true,
+ &error_abort);
+ g_assert_cmpint(qemu_opt_has_help_opt(opts),
+ ==, test[i].expect_implied);
+ qemu_opts_del(opts);
+ }
+}
+
static void append_verify_list_01(QemuOptDesc *desc, bool with_overlapping)
{
int i = 0;
@@ -990,6 +1031,7 @@ int main(int argc, char *argv[])
g_test_add_func("/qemu-opts/opts_parse/bool", test_opts_parse_bool);
g_test_add_func("/qemu-opts/opts_parse/number", test_opts_parse_number);
g_test_add_func("/qemu-opts/opts_parse/size", test_opts_parse_size);
+ g_test_add_func("/qemu-opts/has_help_option", test_has_help_option);
g_test_add_func("/qemu-opts/append_to_null", test_opts_append_to_null);
g_test_add_func("/qemu-opts/append", test_opts_append);
g_test_add_func("/qemu-opts/to_qdict/basic", test_opts_to_qdict_basic);
diff --git a/tests/test-qobject-output-visitor.c b/tests/test-qobject-output-visitor.c
index d7761ebf84..1c856d9bd2 100644
--- a/tests/test-qobject-output-visitor.c
+++ b/tests/test-qobject-output-visitor.c
@@ -141,21 +141,6 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
}
}
-static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
- const void *unused)
-{
- EnumOne i, bad_values[] = { ENUM_ONE__MAX, -1 };
-
- for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
- Error *err = NULL;
-
- visit_type_EnumOne(data->ov, "unused", &bad_values[i], &err);
- error_free_or_abort(&err);
- visitor_reset(data);
- }
-}
-
-
static void test_visitor_out_struct(TestOutputVisitorData *data,
const void *unused)
{
@@ -234,26 +219,6 @@ static void test_visitor_out_struct_nested(TestOutputVisitorData *data,
qapi_free_UserDefTwo(ud2);
}
-static void test_visitor_out_struct_errors(TestOutputVisitorData *data,
- const void *unused)
-{
- EnumOne bad_values[] = { ENUM_ONE__MAX, -1 };
- UserDefOne u = {0};
- UserDefOne *pu = &u;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
- Error *err = NULL;
-
- u.has_enum1 = true;
- u.enum1 = bad_values[i];
- visit_type_UserDefOne(data->ov, "unused", &pu, &err);
- error_free_or_abort(&err);
- visitor_reset(data);
- }
-}
-
-
static void test_visitor_out_list(TestOutputVisitorData *data,
const void *unused)
{
@@ -821,14 +786,10 @@ int main(int argc, char **argv)
&out_visitor_data, test_visitor_out_no_string);
output_visitor_test_add("/visitor/output/enum",
&out_visitor_data, test_visitor_out_enum);
- output_visitor_test_add("/visitor/output/enum-errors",
- &out_visitor_data, test_visitor_out_enum_errors);
output_visitor_test_add("/visitor/output/struct",
&out_visitor_data, test_visitor_out_struct);
output_visitor_test_add("/visitor/output/struct-nested",
&out_visitor_data, test_visitor_out_struct_nested);
- output_visitor_test_add("/visitor/output/struct-errors",
- &out_visitor_data, test_visitor_out_struct_errors);
output_visitor_test_add("/visitor/output/list",
&out_visitor_data, test_visitor_out_list);
output_visitor_test_add("/visitor/output/any",
diff --git a/tests/test-string-output-visitor.c b/tests/test-string-output-visitor.c
index 1be1540767..3bd732222c 100644
--- a/tests/test-string-output-visitor.c
+++ b/tests/test-string-output-visitor.c
@@ -203,19 +203,6 @@ static void test_visitor_out_enum(TestOutputVisitorData *data,
}
}
-static void test_visitor_out_enum_errors(TestOutputVisitorData *data,
- const void *unused)
-{
- EnumOne i, bad_values[] = { ENUM_ONE__MAX, -1 };
-
- for (i = 0; i < ARRAY_SIZE(bad_values) ; i++) {
- Error *err = NULL;
-
- visit_type_EnumOne(data->ov, "unused", &bad_values[i], &err);
- error_free_or_abort(&err);
- }
-}
-
static void
output_visitor_test_add(const char *testpath,
TestOutputVisitorData *data,
@@ -260,12 +247,6 @@ int main(int argc, char **argv)
&out_visitor_data, test_visitor_out_enum, false);
output_visitor_test_add("/string-visitor/output/enum-human",
&out_visitor_data, test_visitor_out_enum, true);
- output_visitor_test_add("/string-visitor/output/enum-errors",
- &out_visitor_data, test_visitor_out_enum_errors,
- false);
- output_visitor_test_add("/string-visitor/output/enum-errors-human",
- &out_visitor_data, test_visitor_out_enum_errors,
- true);
output_visitor_test_add("/string-visitor/output/intList",
&out_visitor_data, test_visitor_out_intList, false);
output_visitor_test_add("/string-visitor/output/intList-human",
diff --git a/util/qemu-option.c b/util/qemu-option.c
index 97172b5eaa..0ebfd97a98 100644
--- a/util/qemu-option.c
+++ b/util/qemu-option.c
@@ -165,48 +165,6 @@ void parse_option_size(const char *name, const char *value,
*ret = size;
}
-bool has_help_option(const char *param)
-{
- const char *p = param;
- bool result = false;
-
- while (*p && !result) {
- char *value;
-
- p = get_opt_value(p, &value);
- if (*p) {
- p++;
- }
-
- result = is_help_option(value);
- g_free(value);
- }
-
- return result;
-}
-
-bool is_valid_option_list(const char *p)
-{
- char *value = NULL;
- bool result = false;
-
- while (*p) {
- p = get_opt_value(p, &value);
- if ((*p && !*++p) ||
- (!*value || *value == ',')) {
- goto out;
- }
-
- g_free(value);
- value = NULL;
- }
-
- result = true;
-out:
- g_free(value);
- return result;
-}
-
static const char *opt_type_to_string(enum QemuOptType type)
{
switch (type) {
@@ -539,7 +497,7 @@ int qemu_opt_unset(QemuOpts *opts, const char *name)
}
static void opt_set(QemuOpts *opts, const char *name, char *value,
- bool prepend, bool *invalidp, Error **errp)
+ bool prepend, bool *help_wanted, Error **errp)
{
QemuOpt *opt;
const QemuOptDesc *desc;
@@ -549,8 +507,8 @@ static void opt_set(QemuOpts *opts, const char *name, char *value,
if (!desc && !opts_accepts_any(opts)) {
g_free(value);
error_setg(errp, QERR_INVALID_PARAMETER, name);
- if (invalidp) {
- *invalidp = true;
+ if (help_wanted && is_help_option(name)) {
+ *help_wanted = true;
}
return;
}
@@ -805,61 +763,108 @@ void qemu_opts_print(QemuOpts *opts, const char *separator)
}
}
+static const char *get_opt_name_value(const char *params,
+ const char *firstname,
+ char **name, char **value)
+{
+ const char *p, *pe, *pc;
+
+ pe = strchr(params, '=');
+ pc = strchr(params, ',');
+
+ if (!pe || (pc && pc < pe)) {
+ /* found "foo,more" */
+ if (firstname) {
+ /* implicitly named first option */
+ *name = g_strdup(firstname);
+ p = get_opt_value(params, value);
+ } else {
+ /* option without value, must be a flag */
+ p = get_opt_name(params, name, ',');
+ if (strncmp(*name, "no", 2) == 0) {
+ memmove(*name, *name + 2, strlen(*name + 2) + 1);
+ *value = g_strdup("off");
+ } else {
+ *value = g_strdup("on");
+ }
+ }
+ } else {
+ /* found "foo=bar,more" */
+ p = get_opt_name(params, name, '=');
+ assert(*p == '=');
+ p++;
+ p = get_opt_value(p, value);
+ }
+
+ assert(!*p || *p == ',');
+ if (*p == ',') {
+ p++;
+ }
+ return p;
+}
+
static void opts_do_parse(QemuOpts *opts, const char *params,
const char *firstname, bool prepend,
- bool *invalidp, Error **errp)
+ bool *help_wanted, Error **errp)
{
- char *option = NULL;
- char *value = NULL;
- const char *p,*pe,*pc;
Error *local_err = NULL;
+ char *option, *value;
+ const char *p;
- for (p = params; *p != '\0'; p++) {
- pe = strchr(p, '=');
- pc = strchr(p, ',');
- if (!pe || (pc && pc < pe)) {
- /* found "foo,more" */
- if (p == params && firstname) {
- /* implicitly named first option */
- option = g_strdup(firstname);
- p = get_opt_value(p, &value);
- } else {
- /* option without value, probably a flag */
- p = get_opt_name(p, &option, ',');
- if (strncmp(option, "no", 2) == 0) {
- memmove(option, option+2, strlen(option+2)+1);
- value = g_strdup("off");
- } else {
- value = g_strdup("on");
- }
- }
- } else {
- /* found "foo=bar,more" */
- p = get_opt_name(p, &option, '=');
- assert(*p == '=');
- p++;
- p = get_opt_value(p, &value);
+ for (p = params; *p;) {
+ p = get_opt_name_value(p, firstname, &option, &value);
+ firstname = NULL;
+
+ if (!strcmp(option, "id")) {
+ g_free(option);
+ g_free(value);
+ continue;
}
- if (strcmp(option, "id") != 0) {
- /* store and parse */
- opt_set(opts, option, value, prepend, invalidp, &local_err);
- value = NULL;
- if (local_err) {
- error_propagate(errp, local_err);
- goto cleanup;
- }
+
+ opt_set(opts, option, value, prepend, help_wanted, &local_err);
+ g_free(option);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
}
- if (*p != ',') {
- break;
+ }
+}
+
+static char *opts_parse_id(const char *params)
+{
+ const char *p;
+ char *name, *value;
+
+ for (p = params; *p;) {
+ p = get_opt_name_value(p, NULL, &name, &value);
+ if (!strcmp(name, "id")) {
+ g_free(name);
+ return value;
}
- g_free(option);
+ g_free(name);
+ g_free(value);
+ }
+
+ return NULL;
+}
+
+bool has_help_option(const char *params)
+{
+ const char *p;
+ char *name, *value;
+ bool ret;
+
+ for (p = params; *p;) {
+ p = get_opt_name_value(p, NULL, &name, &value);
+ ret = is_help_option(name);
+ g_free(name);
g_free(value);
- option = value = NULL;
+ if (ret) {
+ return true;
+ }
}
- cleanup:
- g_free(option);
- g_free(value);
+ return false;
}
/**
@@ -876,23 +881,16 @@ void qemu_opts_do_parse(QemuOpts *opts, const char *params,
static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
bool permit_abbrev, bool defaults,
- bool *invalidp, Error **errp)
+ bool *help_wanted, Error **errp)
{
const char *firstname;
- char *id = NULL;
- const char *p;
+ char *id = opts_parse_id(params);
QemuOpts *opts;
Error *local_err = NULL;
assert(!permit_abbrev || list->implied_opt_name);
firstname = permit_abbrev ? list->implied_opt_name : NULL;
- if (strncmp(params, "id=", 3) == 0) {
- get_opt_value(params + 3, &id);
- } else if ((p = strstr(params, ",id=")) != NULL) {
- get_opt_value(p + 4, &id);
- }
-
/*
* This code doesn't work for defaults && !list->merge_lists: when
* params has no id=, and list has an element with !opts->id, it
@@ -908,7 +906,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
return NULL;
}
- opts_do_parse(opts, params, firstname, defaults, invalidp, &local_err);
+ opts_do_parse(opts, params, firstname, defaults, help_wanted, &local_err);
if (local_err) {
error_propagate(errp, local_err);
qemu_opts_del(opts);
@@ -944,11 +942,11 @@ QemuOpts *qemu_opts_parse_noisily(QemuOptsList *list, const char *params,
{
Error *err = NULL;
QemuOpts *opts;
- bool invalidp = false;
+ bool help_wanted = false;
- opts = opts_parse(list, params, permit_abbrev, false, &invalidp, &err);
+ opts = opts_parse(list, params, permit_abbrev, false, &help_wanted, &err);
if (err) {
- if (invalidp && has_help_option(params)) {
+ if (help_wanted) {
qemu_opts_print_help(list, true);
error_free(err);
} else {
@@ -967,18 +965,16 @@ void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
assert(opts);
}
-typedef struct OptsFromQDictState {
- QemuOpts *opts;
- Error **errp;
-} OptsFromQDictState;
-
-static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
+static void qemu_opts_from_qdict_entry(QemuOpts *opts,
+ const QDictEntry *entry,
+ Error **errp)
{
- OptsFromQDictState *state = opaque;
+ const char *key = qdict_entry_key(entry);
+ QObject *obj = qdict_entry_value(entry);
char buf[32], *tmp = NULL;
const char *value;
- if (!strcmp(key, "id") || *state->errp) {
+ if (!strcmp(key, "id")) {
return;
}
@@ -999,7 +995,7 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
return;
}
- qemu_opt_set(state->opts, key, value, state->errp);
+ qemu_opt_set(opts, key, value, errp);
g_free(tmp);
}
@@ -1012,9 +1008,9 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
Error **errp)
{
- OptsFromQDictState state;
Error *local_err = NULL;
QemuOpts *opts;
+ const QDictEntry *entry;
opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
&local_err);
@@ -1025,13 +1021,15 @@ QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
assert(opts != NULL);
- state.errp = &local_err;
- state.opts = opts;
- qdict_iter(qdict, qemu_opts_from_qdict_1, &state);
- if (local_err) {
- error_propagate(errp, local_err);
- qemu_opts_del(opts);
- return NULL;
+ for (entry = qdict_first(qdict);
+ entry;
+ entry = qdict_next(qdict, entry)) {
+ qemu_opts_from_qdict_entry(opts, entry, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ qemu_opts_del(opts);
+ return NULL;
+ }
}
return opts;
@@ -1050,21 +1048,16 @@ void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp)
while (entry != NULL) {
Error *local_err = NULL;
- OptsFromQDictState state = {
- .errp = &local_err,
- .opts = opts,
- };
next = qdict_next(qdict, entry);
if (find_desc_by_name(opts->list->desc, entry->key)) {
- qemu_opts_from_qdict_1(entry->key, entry->value, &state);
+ qemu_opts_from_qdict_entry(opts, entry, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
- } else {
- qdict_del(qdict, entry->key);
}
+ qdict_del(qdict, entry->key);
}
entry = next;