Miscellaneous patches for 2020-04-29
-----BEGIN PGP SIGNATURE----- iQJGBAABCAAwFiEENUvIs9frKmtoZ05fOHC0AOuRhlMFAl6pIewSHGFybWJydUBy ZWRoYXQuY29tAAoJEDhwtADrkYZTY+wP/jN6QXjmqY3hOXWw90pOsroVPNcBqlIN dtMWMQ48TZ5kL87UZHvm8OZmmwM/UaFbtmTMkWWfZNzNhIUQfgWqIIWYX+gPu9M3 5XSvzT8rqJGrZQ51JwXV7WXWi44MzXuEDlK3ghRxt9lE2QLacC0g/ZSp1eBR07RG +dDIFbQhU7ZkYN4CWCwUcq9vA/U9ZHCRlgx4Mi7FRdEPis4dtbvBxucK/c2gh5OR /GWfQ2okx7ybKlob9mK7VllR99nzybYR5GtYb/aVAR7iqtrWQbaCGnqWYae2ZbI2 0YgjxzjRKBLWmfODVf2ER/DcEbwrrxjPDjHBk6t4JFMnUsZtJBTCo9MXiTfjmgpv WRl/3TjArVUCp/bIp5IRdIuV7ld1Vz08IFo39FaZCMiz2izbte9jQOTJaMVw8ZY2 Ehl/ei8/+Qf+NBW0uGuH++qQFHol9YJpjq7cAlt3fYL/bW0nkIOQnfIPSL561rTU qUSIyQMjupuGgKhTSoZlpFn+03j6QSNdkFqvK4bRR2dGnRKrt//kkyNgLQRqnAoF 4CAFBTiG5i6JjH3QZwvcbgsmo6QuRsEsi58fQawNzz/JSY1VUgmbWXpsXDGJ1uRF i8ADz35FCxjCOyxbTNnkPzMpr3EJFBoReOsaH0zn6XYqxxROJ94M418VanEGl48G SsEarm+K5mP3 =zCqZ -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-misc-2020-04-29' into staging Miscellaneous patches for 2020-04-29 # gpg: Signature made Wed 29 Apr 2020 07:42:52 BST # gpg: using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653 # gpg: issuer "armbru@redhat.com" # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full] # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" [full] # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-misc-2020-04-29: (32 commits) qemu-option: pass NULL rather than 0 to the id of qemu_opts_set() libqos: Give get_machine_allocator() internal linkage fuzz: Simplify how we compute available machines and types Makefile: Drop unused, broken target recurse-fuzz smbus: Fix spd_data_generate() for number of banks > 2 bamboo, sam460ex: Tidy up error message for unsupported RAM size smbus: Fix spd_data_generate() error API violation sam460ex: Suppress useless warning on -m 32 and -m 64 qga: Fix qmp_guest_suspend_{disk, ram}() error handling qga: Fix qmp_guest_get_memory_blocks() error handling tests/test-logging: Fix test for -dfilter 0..0xffffffffffffffff migration/colo: Fix qmp_xen_colo_do_checkpoint() error handling io: Fix qio_channel_socket_close() error handling xen/pt: Fix flawed conversion to realize() virtio-net: Fix duplex=... and speed=... error handling bochs-display: Fix vgamem=SIZE error handling fdc: Fix fallback=auto error handling arm/virt: Fix virt_machine_device_plug_cb() error API violation cpus: Proper range-checking for -icount shift=N cpus: Fix configure_icount() error API violation ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
648db19685
1
Makefile
1
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
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 }
|
||||
|
52
cpus.c
52
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 (align && !sleep) {
|
||||
error_setg(errp, "align=on and sleep=off are incompatible");
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcmp(option, "auto") != 0) {
|
||||
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;
|
||||
}
|
||||
} 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 = qemu_opt_get_bool(opts, "align", false);
|
||||
icount_align_option = align;
|
||||
|
||||
if (icount_align_option && !icount_sleep) {
|
||||
error_setg(errp, "align=on and sleep=off are incompatible");
|
||||
}
|
||||
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)) {
|
||||
error_setg(errp, "icount: Invalid shift value");
|
||||
}
|
||||
if (time_shift >= 0) {
|
||||
timers_state.icount_time_shift = time_shift;
|
||||
use_icount = 1;
|
||||
return;
|
||||
} else if (icount_align_option) {
|
||||
error_setg(errp, "shift=auto and align=on are incompatible");
|
||||
} else if (!icount_sleep) {
|
||||
error_setg(errp, "shift=auto and sleep=off are incompatible");
|
||||
}
|
||||
|
||||
use_icount = 2;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -465,7 +465,7 @@ static void riscv_sifive_u_machine_instance_init(Object *obj)
|
||||
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 " \
|
||||
"Set on to tell QEMU's ROM to jump to "
|
||||
"flash. Otherwise QEMU will jump to DRAM",
|
||||
NULL);
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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) */
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
87
qemu-img.c
87
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)) {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
10
softmmu/vl.c
10
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:
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) |
|
||||
|
@ -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;
|
||||
MachineInfoList *mach_info;
|
||||
ObjectTypeInfoList *type_info;
|
||||
|
||||
qmp_marshal_query_machines(NULL, &response, &error_abort);
|
||||
lst = qobject_to(QList, response);
|
||||
apply_to_qlist(lst, true);
|
||||
mach_info = qmp_query_machines(&error_abort);
|
||||
machines_apply_to_node(mach_info);
|
||||
qapi_free_MachineInfoList(mach_info);
|
||||
|
||||
qobject_unref(response);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
@ -29,66 +29,44 @@
|
||||
#include "libqos/qgraph_internal.h"
|
||||
#include "libqos/qos_external.h"
|
||||
|
||||
|
||||
|
||||
void apply_to_node(const char *name, bool is_machine, bool is_abstract)
|
||||
static void machine_apply_to_node(const char *name)
|
||||
{
|
||||
char *machine_name = NULL;
|
||||
if (is_machine) {
|
||||
const char *arch = qtest_get_arch();
|
||||
machine_name = g_strconcat(arch, "/", name, NULL);
|
||||
name = machine_name;
|
||||
char *machine_name = g_strconcat(qtest_get_arch(), "/", name, NULL);
|
||||
|
||||
qos_graph_node_set_availability(machine_name, true);
|
||||
g_free(machine_name);
|
||||
}
|
||||
|
||||
void machines_apply_to_node(MachineInfoList *mach_info)
|
||||
{
|
||||
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;
|
||||
ObjectTypeInfoList *tail;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 void opts_do_parse(QemuOpts *opts, const char *params,
|
||||
const char *firstname, bool prepend,
|
||||
bool *invalidp, Error **errp)
|
||||
static const char *get_opt_name_value(const char *params,
|
||||
const char *firstname,
|
||||
char **name, char **value)
|
||||
{
|
||||
char *option = NULL;
|
||||
char *value = NULL;
|
||||
const char *p,*pe,*pc;
|
||||
Error *local_err = NULL;
|
||||
const char *p, *pe, *pc;
|
||||
|
||||
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");
|
||||
}
|
||||
}
|
||||
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 {
|
||||
/* found "foo=bar,more" */
|
||||
p = get_opt_name(p, &option, '=');
|
||||
assert(*p == '=');
|
||||
p++;
|
||||
p = get_opt_value(p, &value);
|
||||
}
|
||||
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;
|
||||
/* 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");
|
||||
}
|
||||
}
|
||||
if (*p != ',') {
|
||||
break;
|
||||
}
|
||||
g_free(option);
|
||||
g_free(value);
|
||||
option = value = NULL;
|
||||
} else {
|
||||
/* found "foo=bar,more" */
|
||||
p = get_opt_name(params, name, '=');
|
||||
assert(*p == '=');
|
||||
p++;
|
||||
p = get_opt_value(p, value);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
g_free(option);
|
||||
g_free(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 *help_wanted, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
char *option, *value;
|
||||
const char *p;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
opt_set(opts, option, value, prepend, help_wanted, &local_err);
|
||||
g_free(option);
|
||||
if (local_err) {
|
||||
error_propagate(errp, local_err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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(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);
|
||||
if (ret) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
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 {
|
||||
|
Loading…
Reference in New Issue
Block a user