diff options
44 files changed, 501 insertions, 328 deletions
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml index 6c05c46..7173749 100644 --- a/.gitlab-ci.d/buildtest.yml +++ b/.gitlab-ci.d/buildtest.yml @@ -327,6 +327,7 @@ clang-user: extends: .native_build_job_template needs: job: amd64-debian-user-cross-container + timeout: 70m variables: IMAGE: debian-all-test-cross CONFIGURE_ARGS: --cc=clang --cxx=clang++ --disable-system diff --git a/accel/accel-softmmu.c b/accel/accel-softmmu.c index 67276e4..f9cdafb 100644 --- a/accel/accel-softmmu.c +++ b/accel/accel-softmmu.c @@ -66,6 +66,7 @@ void accel_init_ops_interfaces(AccelClass *ac) { const char *ac_name; char *ops_name; + ObjectClass *oc; AccelOpsClass *ops; ac_name = object_class_get_name(OBJECT_CLASS(ac)); @@ -73,8 +74,13 @@ void accel_init_ops_interfaces(AccelClass *ac) ops_name = g_strdup_printf("%s" ACCEL_OPS_SUFFIX, ac_name); ops = ACCEL_OPS_CLASS(module_object_class_by_name(ops_name)); + oc = module_object_class_by_name(ops_name); + if (!oc) { + error_report("fatal: could not load module for type '%s'", ops_name); + exit(1); + } g_free(ops_name); - + ops = ACCEL_OPS_CLASS(oc); /* * all accelerators need to define ops, providing at least a mandatory * non-NULL create_vcpu_thread operation. diff --git a/audio/audio.c b/audio/audio.c index cc66427..065602c 100644 --- a/audio/audio.c +++ b/audio/audio.c @@ -73,20 +73,24 @@ void audio_driver_register(audio_driver *drv) audio_driver *audio_driver_lookup(const char *name) { struct audio_driver *d; + Error *local_err = NULL; + int rv; QLIST_FOREACH(d, &audio_drivers, next) { if (strcmp(name, d->name) == 0) { return d; } } - - audio_module_load_one(name); - QLIST_FOREACH(d, &audio_drivers, next) { - if (strcmp(name, d->name) == 0) { - return d; + rv = audio_module_load(name, &local_err); + if (rv > 0) { + QLIST_FOREACH(d, &audio_drivers, next) { + if (strcmp(name, d->name) == 0) { + return d; + } } + } else if (rv < 0) { + error_report_err(local_err); } - return NULL; } @@ -464,12 +464,18 @@ BlockDriver *bdrv_find_format(const char *format_name) /* The driver isn't registered, maybe we need to load a module */ for (i = 0; i < (int)ARRAY_SIZE(block_driver_modules); ++i) { if (!strcmp(block_driver_modules[i].format_name, format_name)) { - block_module_load_one(block_driver_modules[i].library_name); + Error *local_err = NULL; + int rv = block_module_load(block_driver_modules[i].library_name, + &local_err); + if (rv > 0) { + return bdrv_do_find_format(format_name); + } else if (rv < 0) { + error_report_err(local_err); + } break; } } - - return bdrv_do_find_format(format_name); + return NULL; } static int bdrv_format_is_whitelisted(const char *format_name, bool read_only) @@ -981,12 +987,16 @@ BlockDriver *bdrv_find_protocol(const char *filename, for (i = 0; i < (int)ARRAY_SIZE(block_driver_modules); ++i) { if (block_driver_modules[i].protocol_name && !strcmp(block_driver_modules[i].protocol_name, protocol)) { - block_module_load_one(block_driver_modules[i].library_name); + int rv = block_module_load(block_driver_modules[i].library_name, errp); + if (rv > 0) { + drv1 = bdrv_do_find_protocol(protocol); + } else if (rv < 0) { + return NULL; + } break; } } - drv1 = bdrv_do_find_protocol(protocol); if (!drv1) { error_setg(errp, "Unknown protocol '%s'", protocol); } diff --git a/block/dmg.c b/block/dmg.c index 4221362..675e840 100644 --- a/block/dmg.c +++ b/block/dmg.c @@ -254,6 +254,25 @@ static int dmg_read_mish_block(BDRVDMGState *s, DmgHeaderState *ds, for (i = s->n_chunks; i < s->n_chunks + chunk_count; i++) { s->types[i] = buff_read_uint32(buffer, offset); if (!dmg_is_known_block_type(s->types[i])) { + switch (s->types[i]) { + case UDBZ: + warn_report_once("dmg-bzip2 module is missing, accessing bzip2 " + "compressed blocks will result in I/O errors"); + break; + case ULFO: + warn_report_once("dmg-lzfse module is missing, accessing lzfse " + "compressed blocks will result in I/O errors"); + break; + case UDCM: + case UDLE: + /* Comments and last entry can be ignored without problems */ + break; + default: + warn_report_once("Image contains chunks of unknown type %x, " + "accessing them will result in I/O errors", + s->types[i]); + break; + } chunk_count--; i--; offset += 40; @@ -444,9 +463,17 @@ static int dmg_open(BlockDriverState *bs, QDict *options, int flags, if (ret < 0) { return ret; } - - block_module_load_one("dmg-bz2"); - block_module_load_one("dmg-lzfse"); + /* + * NB: if uncompress submodules are absent, + * ie block_module_load return value == 0, the function pointers + * dmg_uncompress_bz2 and dmg_uncompress_lzfse will be NULL. + */ + if (block_module_load("dmg-bz2", errp) < 0) { + return -EINVAL; + } + if (block_module_load("dmg-lzfse", errp) < 0) { + return -EINVAL; + } s->n_chunks = 0; s->offsets = s->lengths = s->sectors = s->sectorcounts = NULL; @@ -1258,7 +1258,7 @@ if test "$stack_protector" != "no"; then cat > $TMPC << EOF int main(int argc, char *argv[]) { - char arr[64], *p = arr, *c = argv[0]; + char arr[64], *p = arr, *c = argv[argc - 1]; while (*c) { *p++ = *c++; } @@ -1607,7 +1607,7 @@ fi if test "$safe_stack" = "yes"; then cat > $TMPC << EOF -int main(int argc, char *argv[]) +int main(void) { #if ! __has_feature(safe_stack) #error SafeStack Disabled @@ -1629,7 +1629,7 @@ EOF fi else cat > $TMPC << EOF -int main(int argc, char *argv[]) +int main(void) { #if defined(__has_feature) #if __has_feature(safe_stack) @@ -1675,7 +1675,7 @@ static const int Z = 1; #define TAUT(X) ((X) == Z) #define PAREN(X, Y) (X == Y) #define ID(X) (X) -int main(int argc, char *argv[]) +int main(void) { int x = 0, y = 0; x = ID(x); diff --git a/docs/devel/testing.rst b/docs/devel/testing.rst index fbb98fa..e10c47b 100644 --- a/docs/devel/testing.rst +++ b/docs/devel/testing.rst @@ -99,7 +99,7 @@ successfully on various hosts. The following list shows some best practices: * If your test cases uses the blkdebug feature, use relative path to pass the config and image file paths in the command line as Windows absolute path contains the delimiter ":" which will confuse the blkdebug parser. -* Use double quotes in your extra QEMU commmand line in your test cases +* Use double quotes in your extra QEMU command line in your test cases instead of single quotes, as Windows does not drop single quotes when passing the command line to QEMU. * Windows opens a file in text mode by default, while a POSIX compliant diff --git a/docs/system/arm/cpu-features.rst b/docs/system/arm/cpu-features.rst index c2c01ec..00c4440 100644 --- a/docs/system/arm/cpu-features.rst +++ b/docs/system/arm/cpu-features.rst @@ -433,7 +433,7 @@ additional constraints on the set of vector lengths supported by SME. SME User-mode Default Vector Length Property -------------------------------------------- -For qemu-aarch64, the cpu propery ``sme-default-vector-length=N`` is +For qemu-aarch64, the cpu property ``sme-default-vector-length=N`` is defined to mirror the Linux kernel parameter file ``/proc/sys/abi/sme_default_vector_length``. The default length, ``N``, is in units of bytes and must be between 16 and 8192. diff --git a/docs/system/loongarch/loongson3.rst b/docs/system/loongarch/loongson3.rst index 1bdab44..489ea20 100644 --- a/docs/system/loongarch/loongson3.rst +++ b/docs/system/loongarch/loongson3.rst @@ -41,7 +41,7 @@ can be accessed by following steps. $ qemu-system-loongarch64 -machine virt -m 4G -cpu la464-loongarch-cpu \ -smp 1 -bios QEMU_EFI.fd -kernel vmlinuz.efi -initrd initrd.img \ - -append "root=/dev/ram rdinit=/sbin/init consol e=ttyS0,115200" \ + -append "root=/dev/ram rdinit=/sbin/init console=ttyS0,115200" \ --nographic Note: The running speed may be a little slow, as the performance of our diff --git a/docs/tools/virtiofsd.rst b/docs/tools/virtiofsd.rst index 5f5ac9d..995a754 100644 --- a/docs/tools/virtiofsd.rst +++ b/docs/tools/virtiofsd.rst @@ -232,7 +232,7 @@ e.g.: ``:ok:server::security.:`` - will pass 'securty.' xattr's in listxattr from the server + will pass 'security.' xattr's in listxattr from the server and ignore following rules. ``:ok:all:::`` diff --git a/gdb-xml/i386-32bit.xml b/gdb-xml/i386-32bit.xml index 872fcea..7a66a02 100644 --- a/gdb-xml/i386-32bit.xml +++ b/gdb-xml/i386-32bit.xml @@ -110,7 +110,7 @@ <field name="PKE" start="22" end="22"/> </flags> - <flags id="i386_efer" size="8"> + <flags id="i386_efer" size="4"> <field name="TCE" start="15" end="15"/> <field name="FFXSR" start="14" end="14"/> <field name="LMSLE" start="13" end="13"/> diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 0806d8f..0145501 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -147,8 +147,21 @@ bool qdev_set_parent_bus(DeviceState *dev, BusState *bus, Error **errp) DeviceState *qdev_new(const char *name) { - if (!object_class_by_name(name)) { - module_load_qom_one(name); + ObjectClass *oc = object_class_by_name(name); +#ifdef CONFIG_MODULES + if (!oc) { + int rv = module_load_qom(name, &error_fatal); + if (rv > 0) { + oc = object_class_by_name(name); + } else { + error_report("could not find a module for type '%s'", name); + exit(1); + } + } +#endif + if (!oc) { + error_report("unknown type '%s'", name); + abort(); } return DEVICE(object_new(name)); } diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 7d9523f..95d1b3a 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -1522,21 +1522,37 @@ IOInstEnding css_do_xsch(SubchDev *sch) IOInstEnding css_do_csch(SubchDev *sch) { SCHIB *schib = &sch->curr_status; + uint16_t old_scsw_ctrl; + IOInstEnding ccode; if (~(schib->pmcw.flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) { return IOINST_CC_NOT_OPERATIONAL; } + /* + * Save the current scsw.ctrl in case CSCH fails and we need + * to revert the scsw to the status quo ante. + */ + old_scsw_ctrl = schib->scsw.ctrl; + /* Trigger the clear function. */ schib->scsw.ctrl &= ~(SCSW_CTRL_MASK_FCTL | SCSW_CTRL_MASK_ACTL); schib->scsw.ctrl |= SCSW_FCTL_CLEAR_FUNC | SCSW_ACTL_CLEAR_PEND; - return do_subchannel_work(sch); + ccode = do_subchannel_work(sch); + + if (ccode != IOINST_CC_EXPECTED) { + schib->scsw.ctrl = old_scsw_ctrl; + } + + return ccode; } IOInstEnding css_do_hsch(SubchDev *sch) { SCHIB *schib = &sch->curr_status; + uint16_t old_scsw_ctrl; + IOInstEnding ccode; if (~(schib->pmcw.flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) { return IOINST_CC_NOT_OPERATIONAL; @@ -1553,6 +1569,12 @@ IOInstEnding css_do_hsch(SubchDev *sch) return IOINST_CC_BUSY; } + /* + * Save the current scsw.ctrl in case HSCH fails and we need + * to revert the scsw to the status quo ante. + */ + old_scsw_ctrl = schib->scsw.ctrl; + /* Trigger the halt function. */ schib->scsw.ctrl |= SCSW_FCTL_HALT_FUNC; schib->scsw.ctrl &= ~SCSW_FCTL_START_FUNC; @@ -1564,7 +1586,13 @@ IOInstEnding css_do_hsch(SubchDev *sch) } schib->scsw.ctrl |= SCSW_ACTL_HALT_PEND; - return do_subchannel_work(sch); + ccode = do_subchannel_work(sch); + + if (ccode != IOINST_CC_EXPECTED) { + schib->scsw.ctrl = old_scsw_ctrl; + } + + return ccode; } static void css_update_chnmon(SubchDev *sch) @@ -1605,6 +1633,8 @@ static void css_update_chnmon(SubchDev *sch) IOInstEnding css_do_ssch(SubchDev *sch, ORB *orb) { SCHIB *schib = &sch->curr_status; + uint16_t old_scsw_ctrl, old_scsw_flags; + IOInstEnding ccode; if (~(schib->pmcw.flags) & (PMCW_FLAGS_MASK_DNV | PMCW_FLAGS_MASK_ENA)) { return IOINST_CC_NOT_OPERATIONAL; @@ -1626,11 +1656,26 @@ IOInstEnding css_do_ssch(SubchDev *sch, ORB *orb) } sch->orb = *orb; sch->channel_prog = orb->cpa; + + /* + * Save the current scsw.ctrl and scsw.flags in case SSCH fails and we need + * to revert the scsw to the status quo ante. + */ + old_scsw_ctrl = schib->scsw.ctrl; + old_scsw_flags = schib->scsw.flags; + /* Trigger the start function. */ schib->scsw.ctrl |= (SCSW_FCTL_START_FUNC | SCSW_ACTL_START_PEND); schib->scsw.flags &= ~SCSW_FLAGS_MASK_PNO; - return do_subchannel_work(sch); + ccode = do_subchannel_work(sch); + + if (ccode != IOINST_CC_EXPECTED) { + schib->scsw.ctrl = old_scsw_ctrl; + schib->scsw.flags = old_scsw_flags; + } + + return ccode; } static void copy_irb_to_guest(IRB *dest, const IRB *src, const PMCW *pmcw, diff --git a/hw/s390x/s390-pci-inst.c b/hw/s390x/s390-pci-inst.c index 20a9bcc..7cc4bcf 100644 --- a/hw/s390x/s390-pci-inst.c +++ b/hw/s390x/s390-pci-inst.c @@ -677,8 +677,9 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) S390PCIBusDevice *pbdev; S390PCIIOMMU *iommu; S390IOTLBEntry entry; - hwaddr start, end; + hwaddr start, end, sstart; uint32_t dma_avail; + bool again; if (env->psw.mask & PSW_MASK_PSTATE) { s390_program_interrupt(env, PGM_PRIVILEGED, ra); @@ -691,7 +692,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) } fh = env->regs[r1] >> 32; - start = env->regs[r2]; + sstart = start = env->regs[r2]; end = start + env->regs[r2 + 1]; pbdev = s390_pci_find_dev_by_fh(s390_get_phb(), fh); @@ -732,6 +733,9 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) goto err; } + retry: + start = sstart; + again = false; while (start < end) { error = s390_guest_io_table_walk(iommu->g_iota, start, &entry); if (error) { @@ -739,13 +743,24 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2, uintptr_t ra) } start += entry.len; - while (entry.iova < start && entry.iova < end && - (dma_avail > 0 || entry.perm == IOMMU_NONE)) { - dma_avail = s390_pci_update_iotlb(iommu, &entry); - entry.iova += TARGET_PAGE_SIZE; - entry.translated_addr += TARGET_PAGE_SIZE; + while (entry.iova < start && entry.iova < end) { + if (dma_avail > 0 || entry.perm == IOMMU_NONE) { + dma_avail = s390_pci_update_iotlb(iommu, &entry); + entry.iova += TARGET_PAGE_SIZE; + entry.translated_addr += TARGET_PAGE_SIZE; + } else { + /* + * We are unable to make a new mapping at this time, continue + * on and hopefully free up more space. Then attempt another + * pass. + */ + again = true; + break; + } } } + if (again && dma_avail > 0) + goto retry; err: if (error) { pbdev->state = ZPCI_FS_ERROR; diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index 806de32..560ddbb 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -43,6 +43,7 @@ #include "sysemu/sysemu.h" #include "hw/s390x/pv.h" #include "migration/blocker.h" +#include "qapi/visitor.h" static Error *pv_mig_blocker; @@ -84,8 +85,15 @@ out: static void s390_init_cpus(MachineState *machine) { MachineClass *mc = MACHINE_GET_CLASS(machine); + S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc); int i; + if (machine->smp.threads > s390mc->max_threads) { + error_report("S390 does not support more than %d threads.", + s390mc->max_threads); + exit(1); + } + /* initialize possible_cpus */ mc->possible_cpu_arch_ids(machine); @@ -589,38 +597,6 @@ static ram_addr_t s390_fixup_ram_size(ram_addr_t sz) return newsz; } -static void ccw_machine_class_init(ObjectClass *oc, void *data) -{ - MachineClass *mc = MACHINE_CLASS(oc); - NMIClass *nc = NMI_CLASS(oc); - HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); - S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc); - - s390mc->ri_allowed = true; - s390mc->cpu_model_allowed = true; - s390mc->css_migration_enabled = true; - s390mc->hpage_1m_allowed = true; - mc->init = ccw_init; - mc->reset = s390_machine_reset; - mc->block_default_type = IF_VIRTIO; - mc->no_cdrom = 1; - mc->no_floppy = 1; - mc->no_parallel = 1; - mc->no_sdcard = 1; - mc->max_cpus = S390_MAX_CPUS; - mc->has_hotpluggable_cpus = true; - assert(!mc->get_hotplug_handler); - mc->get_hotplug_handler = s390_get_hotplug_handler; - mc->cpu_index_to_instance_props = s390_cpu_index_to_props; - mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids; - /* it is overridden with 'host' cpu *in kvm_arch_init* */ - mc->default_cpu_type = S390_CPU_TYPE_NAME("qemu"); - hc->plug = s390_machine_device_plug; - hc->unplug_request = s390_machine_device_unplug_request; - nc->nmi_monitor_handler = s390_nmi; - mc->default_ram_id = "s390.ram"; -} - static inline bool machine_get_aes_key_wrap(Object *obj, Error **errp) { S390CcwMachineState *ms = S390_CCW_MACHINE(obj); @@ -710,19 +686,29 @@ bool hpage_1m_allowed(void) return get_machine_class()->hpage_1m_allowed; } -static char *machine_get_loadparm(Object *obj, Error **errp) +static void machine_get_loadparm(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) { S390CcwMachineState *ms = S390_CCW_MACHINE(obj); + char *str = g_strndup((char *) ms->loadparm, sizeof(ms->loadparm)); - /* make a NUL-terminated string */ - return g_strndup((char *) ms->loadparm, sizeof(ms->loadparm)); + visit_type_str(v, name, &str, errp); + g_free(str); } -static void machine_set_loadparm(Object *obj, const char *val, Error **errp) +static void machine_set_loadparm(Object *obj, Visitor *v, + const char *name, void *opaque, + Error **errp) { S390CcwMachineState *ms = S390_CCW_MACHINE(obj); + char *val; int i; + if (!visit_type_str(v, name, &val, errp)) { + return; + } + for (i = 0; i < sizeof(ms->loadparm) && val[i]; i++) { uint8_t c = qemu_toupper(val[i]); /* mimic HMC */ @@ -740,34 +726,73 @@ static void machine_set_loadparm(Object *obj, const char *val, Error **errp) ms->loadparm[i] = ' '; /* pad right with spaces */ } } -static inline void s390_machine_initfn(Object *obj) + +static void ccw_machine_class_init(ObjectClass *oc, void *data) { - object_property_add_bool(obj, "aes-key-wrap", - machine_get_aes_key_wrap, - machine_set_aes_key_wrap); - object_property_set_description(obj, "aes-key-wrap", + MachineClass *mc = MACHINE_CLASS(oc); + NMIClass *nc = NMI_CLASS(oc); + HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc); + S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc); + + s390mc->ri_allowed = true; + s390mc->cpu_model_allowed = true; + s390mc->css_migration_enabled = true; + s390mc->hpage_1m_allowed = true; + s390mc->max_threads = 1; + mc->init = ccw_init; + mc->reset = s390_machine_reset; + mc->block_default_type = IF_VIRTIO; + mc->no_cdrom = 1; + mc->no_floppy = 1; + mc->no_parallel = 1; + mc->no_sdcard = 1; + mc->max_cpus = S390_MAX_CPUS; + mc->has_hotpluggable_cpus = true; + assert(!mc->get_hotplug_handler); + mc->get_hotplug_handler = s390_get_hotplug_handler; + mc->cpu_index_to_instance_props = s390_cpu_index_to_props; + mc->possible_cpu_arch_ids = s390_possible_cpu_arch_ids; + /* it is overridden with 'host' cpu *in kvm_arch_init* */ + mc->default_cpu_type = S390_CPU_TYPE_NAME("qemu"); + hc->plug = s390_machine_device_plug; + hc->unplug_request = s390_machine_device_unplug_request; + nc->nmi_monitor_handler = s390_nmi; + mc->default_ram_id = "s390.ram"; + + object_class_property_add_bool(oc, "aes-key-wrap", + machine_get_aes_key_wrap, + machine_set_aes_key_wrap); + object_class_property_set_description(oc, "aes-key-wrap", "enable/disable AES key wrapping using the CPACF wrapping key"); - object_property_set_bool(obj, "aes-key-wrap", true, NULL); - object_property_add_bool(obj, "dea-key-wrap", - machine_get_dea_key_wrap, - machine_set_dea_key_wrap); - object_property_set_description(obj, "dea-key-wrap", + object_class_property_add_bool(oc, "dea-key-wrap", + machine_get_dea_key_wrap, + machine_set_dea_key_wrap); + object_class_property_set_description(oc, "dea-key-wrap", "enable/disable DEA key wrapping using the CPACF wrapping key"); - object_property_set_bool(obj, "dea-key-wrap", true, NULL); - object_property_add_str(obj, "loadparm", - machine_get_loadparm, machine_set_loadparm); - object_property_set_description(obj, "loadparm", + + object_class_property_add(oc, "loadparm", "loadparm", + machine_get_loadparm, machine_set_loadparm, + NULL, NULL); + object_class_property_set_description(oc, "loadparm", "Up to 8 chars in set of [A-Za-z0-9. ] (lower case chars converted" " to upper case) to pass to machine loader, boot manager," " and guest kernel"); - object_property_add_bool(obj, "zpcii-disable", - machine_get_zpcii_disable, - machine_set_zpcii_disable); - object_property_set_description(obj, "zpcii-disable", + object_class_property_add_bool(oc, "zpcii-disable", + machine_get_zpcii_disable, + machine_set_zpcii_disable); + object_class_property_set_description(oc, "zpcii-disable", "disable zPCI interpretation facilties"); - object_property_set_bool(obj, "zpcii-disable", false, NULL); +} + +static inline void s390_machine_initfn(Object *obj) +{ + S390CcwMachineState *ms = S390_CCW_MACHINE(obj); + + ms->aes_key_wrap = true; + ms->dea_key_wrap = true; + ms->zpcii_disable = false; } static const TypeInfo ccw_machine_info = { @@ -842,8 +867,11 @@ static void ccw_machine_7_1_instance_options(MachineState *machine) static void ccw_machine_7_1_class_options(MachineClass *mc) { + S390CcwMachineClass *s390mc = S390_CCW_MACHINE_CLASS(mc); + ccw_machine_7_2_class_options(mc); compat_props_add(mc->compat_props, hw_compat_7_1, hw_compat_7_1_len); + s390mc->max_threads = S390_MAX_CPUS; } DEFINE_CCW_MACHINE(7_1, "7.1", false); diff --git a/hw/xen/meson.build b/hw/xen/meson.build index 08dc1f6..ae0ace3 100644 --- a/hw/xen/meson.build +++ b/hw/xen/meson.build @@ -18,7 +18,7 @@ if have_xen_pci_passthrough 'xen_pt_msi.c', )) else - xen_specific_ss.add('xen_pt_stub.c') + xen_specific_ss.add(files('xen_pt_stub.c')) endif specific_ss.add_all(when: ['CONFIG_XEN', xen], if_true: xen_specific_ss) diff --git a/include/exec/memory.h b/include/exec/memory.h index bfb1de8..a751c11 100644 --- a/include/exec/memory.h +++ b/include/exec/memory.h @@ -1970,7 +1970,7 @@ void memory_region_clear_dirty_bitmap(MemoryRegion *mr, hwaddr start, * querying the same page multiple times, which is especially useful for * display updates where the scanlines often are not page aligned. * - * The dirty bitmap region which gets copyed into the snapshot (and + * The dirty bitmap region which gets copied into the snapshot (and * cleared afterwards) can be larger than requested. The boundaries * are rounded up/down so complete bitmap longs (covering 64 pages on * 64bit hosts) can be copied over into the bitmap snapshot. Which diff --git a/include/hw/s390x/s390-virtio-ccw.h b/include/hw/s390x/s390-virtio-ccw.h index 8a0090a..4f8a39a 100644 --- a/include/hw/s390x/s390-virtio-ccw.h +++ b/include/hw/s390x/s390-virtio-ccw.h @@ -40,6 +40,7 @@ struct S390CcwMachineClass { bool cpu_model_allowed; bool css_migration_enabled; bool hpage_1m_allowed; + int max_threads; }; /* runtime-instrumentation allowed by the machine */ diff --git a/include/qemu/main-loop.h b/include/qemu/main-loop.h index aac707d..3c9a9a9 100644 --- a/include/qemu/main-loop.h +++ b/include/qemu/main-loop.h @@ -157,6 +157,8 @@ typedef void WaitObjectFunc(void *opaque); * in the main loop's calls to WaitForMultipleObjects. When the handle * is in a signaled state, QEMU will call @func. * + * If the same HANDLE is added twice, this function returns -1. + * * @handle: The Windows handle to be observed. * @func: A function to be called when @handle is in a signaled state. * @opaque: A pointer-size value that is passed to @func. diff --git a/include/qemu/module.h b/include/qemu/module.h index bd73607..c37ce74 100644 --- a/include/qemu/module.h +++ b/include/qemu/module.h @@ -61,16 +61,43 @@ typedef enum { #define fuzz_target_init(function) module_init(function, \ MODULE_INIT_FUZZ_TARGET) #define migration_init(function) module_init(function, MODULE_INIT_MIGRATION) -#define block_module_load_one(lib) module_load_one("block-", lib, false) -#define ui_module_load_one(lib) module_load_one("ui-", lib, false) -#define audio_module_load_one(lib) module_load_one("audio-", lib, false) +#define block_module_load(lib, errp) module_load("block-", lib, errp) +#define ui_module_load(lib, errp) module_load("ui-", lib, errp) +#define audio_module_load(lib, errp) module_load("audio-", lib, errp) void register_module_init(void (*fn)(void), module_init_type type); void register_dso_module_init(void (*fn)(void), module_init_type type); void module_call_init(module_init_type type); -bool module_load_one(const char *prefix, const char *lib_name, bool mayfail); -void module_load_qom_one(const char *type); + +/* + * module_load: attempt to load a module from a set of directories + * + * directories searched are: + * - getenv("QEMU_MODULE_DIR") + * - get_relocated_path(CONFIG_QEMU_MODDIR); + * - /var/run/qemu/${version_dir} + * + * prefix: a subsystem prefix, or the empty string ("audio-", ..., "") + * name: name of the module + * errp: error to set in case the module is found, but load failed. + * + * Return value: -1 on error (errp set if not NULL). + * 0 if module or one of its dependencies are not installed, + * 1 if the module is found and loaded, + * 2 if the module is already loaded, or module is built-in. + */ +int module_load(const char *prefix, const char *name, Error **errp); + +/* + * module_load_qom: attempt to load a module to provide a QOM type + * + * type: the type to be provided + * errp: error to set. + * + * Return value: as per module_load. + */ +int module_load_qom(const char *type, Error **errp); void module_load_qom_all(void); void module_allow_arch(const char *arch); diff --git a/meson.build b/meson.build index 1d44827..cf3e517 100644 --- a/meson.build +++ b/meson.build @@ -2165,7 +2165,7 @@ config_host_data.set('CONFIG_SPLICE', cc.links(gnu_source_prefix + ''' config_host_data.set('HAVE_MLOCKALL', cc.links(gnu_source_prefix + ''' #include <sys/mman.h> - int main(int argc, char *argv[]) { + int main(void) { return mlockall(MCL_FUTURE); }''')) @@ -2210,7 +2210,7 @@ config_host_data.set('HAVE_FSXATTR', cc.links(''' config_host_data.set('HAVE_BROKEN_SIZE_MAX', not cc.compiles(''' #include <stdint.h> #include <stdio.h> - int main(int argc, char *argv[]) { + int main(void) { return printf("%zu", SIZE_MAX); }''', args: ['-Werror'])) @@ -2327,7 +2327,7 @@ config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \ __m256i x = *(__m256i *)a; return _mm256_testz_si256(x, x); } - int main(int argc, char *argv[]) { return bar(argv[0]); } + int main(int argc, char *argv[]) { return bar(argv[argc - 1]); } '''), error_message: 'AVX2 not available').allowed()) config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \ @@ -2341,7 +2341,7 @@ config_host_data.set('CONFIG_AVX512F_OPT', get_option('avx512f') \ __m512i x = *(__m512i *)a; return _mm512_test_epi64_mask(x, x); } - int main(int argc, char *argv[]) { return bar(argv[0]); } + int main(int argc, char *argv[]) { return bar(argv[argc - 1]); } '''), error_message: 'AVX512F not available').allowed()) have_pvrdma = get_option('pvrdma') \ diff --git a/qapi/qom.json b/qapi/qom.json index 87fcad2..4db956f 100644 --- a/qapi/qom.json +++ b/qapi/qom.json @@ -589,7 +589,7 @@ # # @size: size of the memory region in bytes # -# @x-use-canonical-path-for-ramblock-id: if true, the canoncial path is used +# @x-use-canonical-path-for-ramblock-id: if true, the canonical path is used # for ramblock-id. Disable this for 4.0 # machine types or older to allow # migration with newer QEMU versions. diff --git a/qapi/virtio.json b/qapi/virtio.json index e47a8fb..872c7e3 100644 --- a/qapi/virtio.json +++ b/qapi/virtio.json @@ -15,7 +15,7 @@ # # @name: Name of the VirtIODevice # -# Since: 7.1 +# Since: 7.2 # ## { 'struct': 'VirtioInfo', @@ -32,7 +32,7 @@ # # Returns: List of gathered VirtIODevices # -# Since: 7.1 +# Since: 7.2 # # Example: # @@ -97,7 +97,7 @@ # # @log-size: vhost_dev log_size # -# Since: 7.1 +# Since: 7.2 # ## @@ -167,7 +167,7 @@ # Present if the given VirtIODevice has an active vhost # device. # -# Since: 7.1 +# Since: 7.2 # ## @@ -206,7 +206,7 @@ # # Returns: VirtioStatus of the virtio device # -# Since: 7.1 +# Since: 7.2 # # Examples: # @@ -452,7 +452,7 @@ # # @unknown-statuses: Virtio device statuses bitmap that have not been decoded # -# Since: 7.1 +# Since: 7.2 ## { 'struct': 'VirtioDeviceStatus', @@ -471,7 +471,7 @@ # @unknown-protocols: Vhost user device protocol features bitmap that # have not been decoded # -# Since: 7.1 +# Since: 7.2 ## { 'struct': 'VhostDeviceProtocols', @@ -492,7 +492,7 @@ # @unknown-dev-features: Virtio device features bitmap that have not # been decoded # -# Since: 7.1 +# Since: 7.2 ## { 'struct': 'VirtioDeviceFeatures', @@ -535,7 +535,7 @@ # # @signalled-used-valid: VirtQueue signalled_used_valid flag # -# Since: 7.1 +# Since: 7.2 # ## @@ -576,7 +576,7 @@ # shadow_avail_idx will not be displayed in the case where # the selected VirtIODevice has a running vhost device. # -# Since: 7.1 +# Since: 7.2 # # Examples: # @@ -666,7 +666,7 @@ # # @used-size: vhost_virtqueue used_size # -# Since: 7.1 +# Since: 7.2 # ## @@ -699,7 +699,7 @@ # # Returns: VirtVhostQueueStatus of the vhost_virtqueue # -# Since: 7.1 +# Since: 7.2 # # Examples: # @@ -767,7 +767,7 @@ # # @flags: List of descriptor flags # -# Since: 7.1 +# Since: 7.2 # ## @@ -787,7 +787,7 @@ # # @ring: VRingAvail ring[] entry at provided index # -# Since: 7.1 +# Since: 7.2 # ## @@ -805,7 +805,7 @@ # # @idx: VRingUsed index # -# Since: 7.1 +# Since: 7.2 # ## @@ -829,7 +829,7 @@ # # @used: VRingUsed info # -# Since: 7.1 +# Since: 7.2 # ## @@ -857,7 +857,7 @@ # # Returns: VirtioQueueElement information # -# Since: 7.1 +# Since: 7.2 # # Examples: # diff --git a/qemu-options.hx b/qemu-options.hx index 911d82a..dbdf9c3 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -1051,7 +1051,7 @@ SRST details on the external interface. ``-device isa-ipmi-kcs,bmc=id[,ioport=val][,irq=val]`` - Add a KCS IPMI interafce on the ISA bus. This also adds a + Add a KCS IPMI interface on the ISA bus. This also adds a corresponding ACPI and SMBIOS entries, if appropriate. ``bmc=id`` @@ -1071,7 +1071,7 @@ SRST is 0xe4 and the default interrupt is 5. ``-device pci-ipmi-kcs,bmc=id`` - Add a KCS IPMI interafce on the PCI bus. + Add a KCS IPMI interface on the PCI bus. ``bmc=id`` The BMC to connect to, one of ipmi-bmc-sim or ipmi-bmc-extern above. @@ -5283,8 +5283,8 @@ SRST read the colo-compare git log. ``-object cryptodev-backend-builtin,id=id[,queues=queues]`` - Creates a cryptodev backend which executes crypto opreation from - the QEMU cipher APIS. The id parameter is a unique ID that will + Creates a cryptodev backend which executes crypto operations from + the QEMU cipher APIs. The id parameter is a unique ID that will be used to reference this cryptodev backend from the ``virtio-crypto`` device. The queues parameter is optional, which specify the queue number of cryptodev backend, the default @@ -5551,7 +5551,7 @@ SRST file=/etc/qemu/vnc.allow Finally the ``/etc/qemu/vnc.allow`` file would contain the list - of x509 distingished names that are permitted access + of x509 distinguished names that are permitted access :: diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 026a56f..796434e 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -392,7 +392,7 @@ ## # @guest-file-flush: # -# Write file changes bufferred in userspace to disk/kernel buffers +# Write file changes buffered in userspace to disk/kernel buffers # # @handle: filehandle returned by guest-file-open # diff --git a/qom/object.c b/qom/object.c index e5cef30..e25f1e9 100644 --- a/qom/object.c +++ b/qom/object.c @@ -526,8 +526,13 @@ void object_initialize(void *data, size_t size, const char *typename) #ifdef CONFIG_MODULES if (!type) { - module_load_qom_one(typename); - type = type_get_by_name(typename); + int rv = module_load_qom(typename, &error_fatal); + if (rv > 0) { + type = type_get_by_name(typename); + } else { + error_report("missing object type '%s'", typename); + exit(1); + } } #endif if (!type) { @@ -1033,8 +1038,13 @@ ObjectClass *module_object_class_by_name(const char *typename) oc = object_class_by_name(typename); #ifdef CONFIG_MODULES if (!oc) { - module_load_qom_one(typename); - oc = object_class_by_name(typename); + Error *local_err = NULL; + int rv = module_load_qom(typename, &local_err); + if (rv > 0) { + oc = object_class_by_name(typename); + } else if (rv < 0) { + error_report_err(local_err); + } } #endif return oc; diff --git a/scripts/feature_to_c.sh b/scripts/feature_to_c.sh index b116989..c1f67c8 100644 --- a/scripts/feature_to_c.sh +++ b/scripts/feature_to_c.sh @@ -56,6 +56,7 @@ for input; do done echo +echo '#include "exec/gdbstub.h"' echo "const char *const xml_builtin[][2] = {" for input; do diff --git a/softmmu/qtest.c b/softmmu/qtest.c index afea769..d3e0ab4 100644 --- a/softmmu/qtest.c +++ b/softmmu/qtest.c @@ -753,12 +753,18 @@ static void qtest_process_command(CharBackend *chr, gchar **words) qtest_sendf(chr, "OK %"PRIi64"\n", (int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)); } else if (strcmp(words[0], "module_load") == 0) { + Error *local_err = NULL; + int rv; g_assert(words[1] && words[2]); qtest_send_prefix(chr); - if (module_load_one(words[1], words[2], false)) { + rv = module_load(words[1], words[2], &local_err); + if (rv > 0) { qtest_sendf(chr, "OK\n"); } else { + if (rv < 0) { + error_report_err(local_err); + } qtest_sendf(chr, "FAIL\n"); } } else if (qtest_enabled() && strcmp(words[0], "clock_set") == 0) { diff --git a/target/m68k/qregs.def b/target/m68k/qregs.h.inc index 1aadc62..1aadc62 100644 --- a/target/m68k/qregs.def +++ b/target/m68k/qregs.h.inc diff --git a/target/m68k/translate.c b/target/m68k/translate.c index 5cbde4b..1841831 100644 --- a/target/m68k/translate.c +++ b/target/m68k/translate.c @@ -39,7 +39,7 @@ #define DEFO32(name, offset) static TCGv QREG_##name; #define DEFO64(name, offset) static TCGv_i64 QREG_##name; -#include "qregs.def" +#include "qregs.h.inc" #undef DEFO32 #undef DEFO64 @@ -75,7 +75,7 @@ void m68k_tcg_init(void) #define DEFO64(name, offset) \ QREG_##name = tcg_global_mem_new_i64(cpu_env, \ offsetof(CPUM68KState, offset), #name); -#include "qregs.def" +#include "qregs.h.inc" #undef DEFO32 #undef DEFO64 diff --git a/target/s390x/tcg/insn-data.def b/target/s390x/tcg/insn-data.h.inc index 6382cea..7e952bd 100644 --- a/target/s390x/tcg/insn-data.def +++ b/target/s390x/tcg/insn-data.h.inc @@ -8,7 +8,7 @@ * * OPC = (op << 8) | op2 where op is the major, op2 the minor opcode * NAME = name of the opcode, used internally - * FMT = format of the opcode (defined in insn-format.def) + * FMT = format of the opcode (defined in insn-format.h.inc) * FAC = facility the opcode is available in (defined in DisasFacility) * I1 = func in1_xx fills o->in1 * I2 = func in2_xx fills o->in2 diff --git a/target/s390x/tcg/insn-format.def b/target/s390x/tcg/insn-format.h.inc index 6253edb..6253edb 100644 --- a/target/s390x/tcg/insn-format.def +++ b/target/s390x/tcg/insn-format.h.inc diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c index 03efccd..2fbdab7 100644 --- a/target/s390x/tcg/translate.c +++ b/target/s390x/tcg/translate.c @@ -1011,7 +1011,7 @@ static void free_compare(DisasCompare *c) #define F6(N, X1, X2, X3, X4, X5, X6) F0(N) typedef enum { -#include "insn-format.def" +#include "insn-format.h.inc" } DisasFormat; #undef F0 @@ -1076,7 +1076,7 @@ typedef struct DisasFormatInfo { #define F6(N, X1, X2, X3, X4, X5, X6) { { X1, X2, X3, X4, X5, X6 } }, static const DisasFormatInfo format_info[] = { -#include "insn-format.def" +#include "insn-format.h.inc" }; #undef F0 @@ -6143,7 +6143,7 @@ static void in2_insn(DisasContext *s, DisasOps *o) #define E(OPC, NM, FT, FC, I1, I2, P, W, OP, CC, D, FL) insn_ ## NM, enum DisasInsnEnum { -#include "insn-data.def" +#include "insn-data.h.inc" }; #undef E @@ -6223,7 +6223,7 @@ enum DisasInsnEnum { #define FAC_MIE3 S390_FEAT_MISC_INSTRUCTION_EXT3 /* miscellaneous-instruction-extensions facility 3 */ static const DisasInsn insn_info[] = { -#include "insn-data.def" +#include "insn-data.h.inc" }; #undef E @@ -6233,7 +6233,7 @@ static const DisasInsn insn_info[] = { static const DisasInsn *lookup_opc(uint16_t opc) { switch (opc) { -#include "insn-data.def" +#include "insn-data.h.inc" default: return NULL; } diff --git a/target/tricore/csfr.def b/target/tricore/csfr.h.inc index ff004cb..ff004cb 100644 --- a/target/tricore/csfr.def +++ b/target/tricore/csfr.h.inc diff --git a/target/tricore/translate.c b/target/tricore/translate.c index c5b7bfb..df9e46c 100644 --- a/target/tricore/translate.c +++ b/target/tricore/translate.c @@ -388,7 +388,7 @@ static inline void gen_mfcr(DisasContext *ctx, TCGv ret, int32_t offset) gen_helper_psw_read(ret, cpu_env); } else { switch (offset) { -#include "csfr.def" +#include "csfr.h.inc" } } } @@ -418,7 +418,7 @@ static inline void gen_mtcr(DisasContext *ctx, TCGv r1, gen_helper_psw_write(cpu_env, r1); } else { switch (offset) { -#include "csfr.def" +#include "csfr.h.inc" } } } else { diff --git a/tests/qtest/e1000e-test.c b/tests/qtest/e1000e-test.c index 4cdd823..08adc52 100644 --- a/tests/qtest/e1000e-test.c +++ b/tests/qtest/e1000e-test.c @@ -33,34 +33,11 @@ #include "qemu/bitops.h" #include "libqos/libqos-malloc.h" #include "libqos/e1000e.h" +#include "hw/net/e1000_regs.h" static void e1000e_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc) { - struct { - uint64_t buffer_addr; - union { - uint32_t data; - struct { - uint16_t length; - uint8_t cso; - uint8_t cmd; - } flags; - } lower; - union { - uint32_t data; - struct { - uint8_t status; - uint8_t css; - uint16_t special; - } fields; - } upper; - } descr; - - static const uint32_t dtyp_data = BIT(20); - static const uint32_t dtyp_ext = BIT(29); - static const uint32_t dcmd_rs = BIT(27); - static const uint32_t dcmd_eop = BIT(24); - static const uint32_t dsta_dd = BIT(0); + struct e1000_tx_desc descr; static const int data_len = 64; char buffer[64]; int ret; @@ -73,10 +50,10 @@ static void e1000e_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *a /* Prepare TX descriptor */ memset(&descr, 0, sizeof(descr)); descr.buffer_addr = cpu_to_le64(data); - descr.lower.data = cpu_to_le32(dcmd_rs | - dcmd_eop | - dtyp_ext | - dtyp_data | + descr.lower.data = cpu_to_le32(E1000_TXD_CMD_RS | + E1000_TXD_CMD_EOP | + E1000_TXD_CMD_DEXT | + E1000_TXD_DTYP_D | data_len); /* Put descriptor to the ring */ @@ -86,7 +63,8 @@ static void e1000e_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *a e1000e_wait_isr(d, E1000E_TX0_MSG_ID); /* Check DD bit */ - g_assert_cmphex(le32_to_cpu(descr.upper.data) & dsta_dd, ==, dsta_dd); + g_assert_cmphex(le32_to_cpu(descr.upper.data) & E1000_TXD_STAT_DD, ==, + E1000_TXD_STAT_DD); /* Check data sent to the backend */ ret = recv(test_sockets[0], &recv_len, sizeof(recv_len), 0); @@ -101,31 +79,7 @@ static void e1000e_send_verify(QE1000E *d, int *test_sockets, QGuestAllocator *a static void e1000e_receive_verify(QE1000E *d, int *test_sockets, QGuestAllocator *alloc) { - union { - struct { - uint64_t buffer_addr; - uint64_t reserved; - } read; - struct { - struct { - uint32_t mrq; - union { - uint32_t rss; - struct { - uint16_t ip_id; - uint16_t csum; - } csum_ip; - } hi_dword; - } lower; - struct { - uint32_t status_error; - uint16_t length; - uint16_t vlan; - } upper; - } wb; - } descr; - - static const uint32_t esta_dd = BIT(0); + union e1000_rx_desc_extended descr; char test[] = "TEST"; int len = htonl(sizeof(test)); @@ -162,7 +116,7 @@ static void e1000e_receive_verify(QE1000E *d, int *test_sockets, QGuestAllocator /* Check DD bit */ g_assert_cmphex(le32_to_cpu(descr.wb.upper.status_error) & - esta_dd, ==, esta_dd); + E1000_RXD_STAT_DD, ==, E1000_RXD_STAT_DD); /* Check data sent to the backend */ memread(data, buffer, sizeof(buffer)); diff --git a/tests/qtest/libqos/e1000e.c b/tests/qtest/libqos/e1000e.c index ed47e34..80b3e3d 100644 --- a/tests/qtest/libqos/e1000e.c +++ b/tests/qtest/libqos/e1000e.c @@ -18,6 +18,7 @@ #include "qemu/osdep.h" #include "hw/net/e1000_regs.h" +#include "hw/pci/pci_ids.h" #include "../libqtest.h" #include "pci-pc.h" #include "qemu/sockets.h" @@ -29,9 +30,9 @@ #include "e1000e.h" #define E1000E_IVAR_TEST_CFG \ - (E1000E_RX0_MSG_ID | E1000_IVAR_INT_ALLOC_VALID | \ - ((E1000E_TX0_MSG_ID | E1000_IVAR_INT_ALLOC_VALID) << 8) | \ - ((E1000E_OTHER_MSG_ID | E1000_IVAR_INT_ALLOC_VALID) << 16) | \ + (((E1000E_RX0_MSG_ID | E1000_IVAR_INT_ALLOC_VALID) << E1000_IVAR_RXQ0_SHIFT) | \ + ((E1000E_TX0_MSG_ID | E1000_IVAR_INT_ALLOC_VALID) << E1000_IVAR_TXQ0_SHIFT) | \ + ((E1000E_OTHER_MSG_ID | E1000_IVAR_INT_ALLOC_VALID) << E1000_IVAR_OTHER_SHIFT) | \ E1000_IVAR_TX_INT_EVERY_WB) #define E1000E_RING_LEN (0x1000) @@ -121,7 +122,7 @@ static void e1000e_pci_start_hw(QOSGraphObject *obj) /* Reset the device */ val = e1000e_macreg_read(&d->e1000e, E1000_CTRL); - e1000e_macreg_write(&d->e1000e, E1000_CTRL, val | E1000_CTRL_RST); + e1000e_macreg_write(&d->e1000e, E1000_CTRL, val | E1000_CTRL_RST | E1000_CTRL_SLU); /* Enable and configure MSI-X */ qpci_msix_enable(&d->pci_dev); @@ -129,8 +130,8 @@ static void e1000e_pci_start_hw(QOSGraphObject *obj) /* Check the device status - link and speed */ val = e1000e_macreg_read(&d->e1000e, E1000_STATUS); - g_assert_cmphex(val & (E1000_STATUS_LU | E1000_STATUS_LAN_INIT_DONE), - ==, E1000_STATUS_LU | E1000_STATUS_LAN_INIT_DONE); + g_assert_cmphex(val & (E1000_STATUS_LU | E1000_STATUS_ASDV_1000), + ==, E1000_STATUS_LU | E1000_STATUS_ASDV_1000); /* Initialize TX/RX logic */ e1000e_macreg_write(&d->e1000e, E1000_RCTL, 0); @@ -217,8 +218,8 @@ static void *e1000e_pci_create(void *pci_bus, QGuestAllocator *alloc, static void e1000e_register_nodes(void) { QPCIAddress addr = { - .vendor_id = 0x8086, - .device_id = 0x10D3, + .vendor_id = PCI_VENDOR_ID_INTEL, + .device_id = E1000_DEV_ID_82574L, }; /* FIXME: every test using this node needs to setup a -netdev socket,id=hs0 diff --git a/tests/qtest/libqtest.h b/tests/qtest/libqtest.h index 91a5f7e..fcf1c3c 100644 --- a/tests/qtest/libqtest.h +++ b/tests/qtest/libqtest.h @@ -736,7 +736,7 @@ bool qtest_has_device(const char *device); * qtest_qmp_device_add_qdict: * @qts: QTestState instance to operate on * @drv: Name of the device that should be added - * @arguments: QDict with properties for the device to intialize + * @arguments: QDict with properties for the device to initialize * * Generic hot-plugging test via the device_add QMP command with properties * supplied in form of QDict. Use NULL for empty properties list. diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c index d2eb107..442998d 100644 --- a/tests/qtest/migration-test.c +++ b/tests/qtest/migration-test.c @@ -1402,7 +1402,6 @@ static void test_precopy_unix_dirty_ring(void) } #ifdef CONFIG_GNUTLS -#ifndef _WIN32 static void test_precopy_unix_tls_psk(void) { g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs); @@ -1415,7 +1414,6 @@ static void test_precopy_unix_tls_psk(void) test_precopy_common(&args); } -#endif /* _WIN32 */ #ifdef CONFIG_TASN1 static void test_precopy_unix_tls_x509_default_host(void) @@ -1524,7 +1522,6 @@ static void test_precopy_tcp_plain(void) } #ifdef CONFIG_GNUTLS -#ifndef _WIN32 static void test_precopy_tcp_tls_psk_match(void) { MigrateCommon args = { @@ -1535,7 +1532,6 @@ static void test_precopy_tcp_tls_psk_match(void) test_precopy_common(&args); } -#endif /* _WIN32 */ static void test_precopy_tcp_tls_psk_mismatch(void) { @@ -1933,7 +1929,6 @@ static void test_multifd_tcp_zstd(void) #endif #ifdef CONFIG_GNUTLS -#ifndef _WIN32 static void * test_migrate_multifd_tcp_tls_psk_start_match(QTestState *from, QTestState *to) @@ -1941,7 +1936,6 @@ test_migrate_multifd_tcp_tls_psk_start_match(QTestState *from, test_migrate_precopy_tcp_multifd_start_common(from, to, "none"); return test_migrate_tls_psk_start_match(from, to); } -#endif /* _WIN32 */ static void * test_migrate_multifd_tcp_tls_psk_start_mismatch(QTestState *from, @@ -1993,7 +1987,6 @@ test_migrate_multifd_tls_x509_start_reject_anon_client(QTestState *from, } #endif /* CONFIG_TASN1 */ -#ifndef _WIN32 static void test_multifd_tcp_tls_psk_match(void) { MigrateCommon args = { @@ -2003,7 +1996,6 @@ static void test_multifd_tcp_tls_psk_match(void) }; test_precopy_common(&args); } -#endif /* _WIN32 */ static void test_multifd_tcp_tls_psk_mismatch(void) { @@ -2188,7 +2180,7 @@ static void calc_dirty_rate(QTestState *who, uint64_t calc_time) qobject_unref(qmp_command(who, "{ 'execute': 'calc-dirty-rate'," "'arguments': { " - "'calc-time': %ld," + "'calc-time': %" PRIu64 "," "'mode': 'dirty-ring' }}", calc_time)); } @@ -2203,7 +2195,7 @@ static void dirtylimit_set_all(QTestState *who, uint64_t dirtyrate) qobject_unref(qmp_command(who, "{ 'execute': 'set-vcpu-dirty-limit'," "'arguments': { " - "'dirty-rate': %ld } }", + "'dirty-rate': %" PRIu64 " } }", dirtyrate)); } @@ -2505,10 +2497,8 @@ int main(int argc, char **argv) qtest_add_func("/migration/precopy/unix/plain", test_precopy_unix_plain); qtest_add_func("/migration/precopy/unix/xbzrle", test_precopy_unix_xbzrle); #ifdef CONFIG_GNUTLS -#ifndef _WIN32 qtest_add_func("/migration/precopy/unix/tls/psk", test_precopy_unix_tls_psk); -#endif if (has_uffd) { /* @@ -2534,10 +2524,8 @@ int main(int argc, char **argv) qtest_add_func("/migration/precopy/tcp/plain", test_precopy_tcp_plain); #ifdef CONFIG_GNUTLS -#ifndef _WIN32 qtest_add_func("/migration/precopy/tcp/tls/psk/match", test_precopy_tcp_tls_psk_match); -#endif qtest_add_func("/migration/precopy/tcp/tls/psk/mismatch", test_precopy_tcp_tls_psk_mismatch); #ifdef CONFIG_TASN1 @@ -2581,10 +2569,8 @@ int main(int argc, char **argv) test_multifd_tcp_zstd); #endif #ifdef CONFIG_GNUTLS -#ifndef _WIN32 qtest_add_func("/migration/multifd/tcp/tls/psk/match", test_multifd_tcp_tls_psk_match); -#endif qtest_add_func("/migration/multifd/tcp/tls/psk/mismatch", test_multifd_tcp_tls_psk_mismatch); #ifdef CONFIG_TASN1 diff --git a/tests/unit/test-io-channel-command.c b/tests/unit/test-io-channel-command.c index 43e29c8..19f72ea 100644 --- a/tests/unit/test-io-channel-command.c +++ b/tests/unit/test-io-channel-command.c @@ -33,19 +33,13 @@ static void test_io_channel_command_fifo(bool async) { g_autofree gchar *tmpdir = g_dir_make_tmp("qemu-test-io-channel.XXXXXX", NULL); g_autofree gchar *fifo = g_strdup_printf("%s/%s", tmpdir, TEST_FIFO); - g_autoptr(GString) srcargs = g_string_new(socat); - g_autoptr(GString) dstargs = g_string_new(socat); - g_auto(GStrv) srcargv; - g_auto(GStrv) dstargv; + g_autofree gchar *srcargs = g_strdup_printf("%s - PIPE:%s,wronly", socat, fifo); + g_autofree gchar *dstargs = g_strdup_printf("%s PIPE:%s,rdonly -", socat, fifo); + g_auto(GStrv) srcargv = g_strsplit(srcargs, " ", -1); + g_auto(GStrv) dstargv = g_strsplit(dstargs, " ", -1); QIOChannel *src, *dst; QIOChannelTest *test; - g_string_append_printf(srcargs, " - PIPE:%s,wronly", fifo); - g_string_append_printf(dstargs, " PIPE:%s,rdonly -", fifo); - - srcargv = g_strsplit(srcargs->str, " ", -1); - dstargv = g_strsplit(dstargs->str, " ", -1); - src = QIO_CHANNEL(qio_channel_command_new_spawn((const char **) srcargv, O_WRONLY, &error_abort)); diff --git a/ui/console.c b/ui/console.c index 65c1178..3c0d9b0 100644 --- a/ui/console.c +++ b/ui/console.c @@ -2632,7 +2632,11 @@ bool qemu_display_find_default(DisplayOptions *opts) for (i = 0; i < (int)ARRAY_SIZE(prio); i++) { if (dpys[prio[i]] == NULL) { - ui_module_load_one(DisplayType_str(prio[i])); + Error *local_err = NULL; + int rv = ui_module_load(DisplayType_str(prio[i]), &local_err); + if (rv < 0) { + error_report_err(local_err); + } } if (dpys[prio[i]] == NULL) { continue; @@ -2650,7 +2654,11 @@ void qemu_display_early_init(DisplayOptions *opts) return; } if (dpys[opts->type] == NULL) { - ui_module_load_one(DisplayType_str(opts->type)); + Error *local_err = NULL; + int rv = ui_module_load(DisplayType_str(opts->type), &local_err); + if (rv < 0) { + error_report_err(local_err); + } } if (dpys[opts->type] == NULL) { error_report("Display '%s' is not available.", @@ -2680,7 +2688,11 @@ void qemu_display_help(void) printf("none\n"); for (idx = DISPLAY_TYPE_NONE; idx < DISPLAY_TYPE__MAX; idx++) { if (!dpys[idx]) { - ui_module_load_one(DisplayType_str(idx)); + Error *local_err = NULL; + int rv = ui_module_load(DisplayType_str(idx), &local_err); + if (rv < 0) { + error_report_err(local_err); + } } if (dpys[idx]) { printf("%s\n", DisplayType_str(dpys[idx]->type)); diff --git a/util/aio-win32.c b/util/aio-win32.c index 44003d6..80cfe01 100644 --- a/util/aio-win32.c +++ b/util/aio-win32.c @@ -326,9 +326,9 @@ void aio_dispatch(AioContext *ctx) bool aio_poll(AioContext *ctx, bool blocking) { AioHandler *node; - HANDLE events[MAXIMUM_WAIT_OBJECTS + 1]; + HANDLE events[MAXIMUM_WAIT_OBJECTS]; bool progress, have_select_revents, first; - int count; + unsigned count; int timeout; /* @@ -369,6 +369,7 @@ bool aio_poll(AioContext *ctx, bool blocking) QLIST_FOREACH_RCU(node, &ctx->aio_handlers, node) { if (!node->deleted && node->io_notify && aio_node_check(ctx, node->is_external)) { + assert(count < MAXIMUM_WAIT_OBJECTS); events[count++] = event_notifier_get_handle(node->e); } } diff --git a/util/main-loop.c b/util/main-loop.c index f00a254..10fa74c 100644 --- a/util/main-loop.c +++ b/util/main-loop.c @@ -363,20 +363,30 @@ void qemu_del_polling_cb(PollingFunc *func, void *opaque) /* Wait objects support */ typedef struct WaitObjects { int num; - int revents[MAXIMUM_WAIT_OBJECTS + 1]; - HANDLE events[MAXIMUM_WAIT_OBJECTS + 1]; - WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1]; - void *opaque[MAXIMUM_WAIT_OBJECTS + 1]; + int revents[MAXIMUM_WAIT_OBJECTS]; + HANDLE events[MAXIMUM_WAIT_OBJECTS]; + WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS]; + void *opaque[MAXIMUM_WAIT_OBJECTS]; } WaitObjects; static WaitObjects wait_objects = {0}; int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) { + int i; WaitObjects *w = &wait_objects; + if (w->num >= MAXIMUM_WAIT_OBJECTS) { return -1; } + + for (i = 0; i < w->num; i++) { + /* check if the same handle is added twice */ + if (w->events[i] == handle) { + return -1; + } + } + w->events[w->num] = handle; w->func[w->num] = func; w->opaque[w->num] = opaque; @@ -395,7 +405,7 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) if (w->events[i] == handle) { found = 1; } - if (found) { + if (found && i < (MAXIMUM_WAIT_OBJECTS - 1)) { w->events[i] = w->events[i + 1]; w->func[i] = w->func[i + 1]; w->opaque[i] = w->opaque[i + 1]; diff --git a/util/module.c b/util/module.c index 8ddb0e1..32e2631 100644 --- a/util/module.c +++ b/util/module.c @@ -21,6 +21,7 @@ #include "qemu/module.h" #include "qemu/cutils.h" #include "qemu/config-file.h" +#include "qapi/error.h" #ifdef CONFIG_MODULE_UPGRADES #include "qemu-version.h" #endif @@ -144,25 +145,22 @@ static bool module_check_arch(const QemuModinfo *modinfo) return true; } -static int module_load_file(const char *fname, bool mayfail, bool export_symbols) +/* + * module_load_dso: attempt to load an existing dso file + * + * fname: full pathname of the file to load + * export_symbols: if true, add the symbols to the global name space + * errp: error to set. + * + * Return value: true on success, false on error, and errp will be set. + */ +static bool module_load_dso(const char *fname, bool export_symbols, + Error **errp) { GModule *g_module; void (*sym)(void); - const char *dsosuf = CONFIG_HOST_DSOSUF; - int len = strlen(fname); - int suf_len = strlen(dsosuf); ModuleEntry *e, *next; - int ret, flags; - - if (len <= suf_len || strcmp(&fname[len - suf_len], dsosuf)) { - /* wrong suffix */ - ret = -EINVAL; - goto out; - } - if (access(fname, F_OK)) { - ret = -ENOENT; - goto out; - } + int flags; assert(QTAILQ_EMPTY(&dso_init_list)); @@ -172,48 +170,38 @@ static int module_load_file(const char *fname, bool mayfail, bool export_symbols } g_module = g_module_open(fname, flags); if (!g_module) { - if (!mayfail) { - fprintf(stderr, "Failed to open module: %s\n", - g_module_error()); - } - ret = -EINVAL; - goto out; + error_setg(errp, "failed to open module: %s", g_module_error()); + return false; } if (!g_module_symbol(g_module, DSO_STAMP_FUN_STR, (gpointer *)&sym)) { - fprintf(stderr, "Failed to initialize module: %s\n", - fname); - /* Print some info if this is a QEMU module (but from different build), - * this will make debugging user problems easier. */ + error_setg(errp, "failed to initialize module: %s", fname); + /* + * Print some info if this is a QEMU module (but from different build), + * this will make debugging user problems easier. + */ if (g_module_symbol(g_module, "qemu_module_dummy", (gpointer *)&sym)) { - fprintf(stderr, - "Note: only modules from the same build can be loaded.\n"); + error_append_hint(errp, + "Only modules from the same build can be loaded.\n"); } g_module_close(g_module); - ret = -EINVAL; - } else { - QTAILQ_FOREACH(e, &dso_init_list, node) { - e->init(); - register_module_init(e->init, e->type); - } - ret = 0; + return false; } + QTAILQ_FOREACH(e, &dso_init_list, node) { + e->init(); + register_module_init(e->init, e->type); + } trace_module_load_module(fname); QTAILQ_FOREACH_SAFE(e, &dso_init_list, node, next) { QTAILQ_REMOVE(&dso_init_list, e, node); g_free(e); } -out: - return ret; + return true; } -#endif -bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) +int module_load(const char *prefix, const char *name, Error **errp) { - bool success = false; - -#ifdef CONFIG_MODULES - char *fname = NULL; + int rv = -1; #ifdef CONFIG_MODULE_UPGRADES char *version_dir; #endif @@ -221,34 +209,52 @@ bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) char *dirs[5]; char *module_name; int i = 0, n_dirs = 0; - int ret; bool export_symbols = false; static GHashTable *loaded_modules; const QemuModinfo *modinfo; const char **sl; if (!g_module_supported()) { - fprintf(stderr, "Module is not supported by system.\n"); - return false; + error_setg(errp, "%s", "this platform does not support GLib modules"); + return -1; } if (!loaded_modules) { loaded_modules = g_hash_table_new(g_str_hash, g_str_equal); } - module_name = g_strdup_printf("%s%s", prefix, lib_name); + /* allocate all resources managed by the out: label here */ + module_name = g_strdup_printf("%s%s", prefix, name); if (g_hash_table_contains(loaded_modules, module_name)) { g_free(module_name); - return true; + return 2; /* module already loaded */ } g_hash_table_add(loaded_modules, module_name); + search_dir = getenv("QEMU_MODULE_DIR"); + if (search_dir != NULL) { + dirs[n_dirs++] = g_strdup_printf("%s", search_dir); + } + dirs[n_dirs++] = get_relocated_path(CONFIG_QEMU_MODDIR); + +#ifdef CONFIG_MODULE_UPGRADES + version_dir = g_strcanon(g_strdup(QEMU_PKGVERSION), + G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "+-.~", + '_'); + dirs[n_dirs++] = g_strdup_printf("/var/run/qemu/%s", version_dir); +#endif + assert(n_dirs <= ARRAY_SIZE(dirs)); + + /* end of resources managed by the out: label */ + for (modinfo = module_info; modinfo->name != NULL; modinfo++) { if (modinfo->arch) { if (strcmp(modinfo->name, module_name) == 0) { if (!module_check_arch(modinfo)) { - return false; + error_setg(errp, "module arch does not match: " + "expected '%s', got '%s'", module_arch, modinfo->arch); + goto out; } } } @@ -256,7 +262,11 @@ bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) if (strcmp(modinfo->name, module_name) == 0) { /* we depend on other module(s) */ for (sl = modinfo->deps; *sl != NULL; sl++) { - module_load_one("", *sl, false); + int subrv = module_load("", *sl, errp); + if (subrv <= 0) { + rv = subrv; + goto out; + } } } else { for (sl = modinfo->deps; *sl != NULL; sl++) { @@ -269,58 +279,52 @@ bool module_load_one(const char *prefix, const char *lib_name, bool mayfail) } } - search_dir = getenv("QEMU_MODULE_DIR"); - if (search_dir != NULL) { - dirs[n_dirs++] = g_strdup_printf("%s", search_dir); - } - dirs[n_dirs++] = get_relocated_path(CONFIG_QEMU_MODDIR); - -#ifdef CONFIG_MODULE_UPGRADES - version_dir = g_strcanon(g_strdup(QEMU_PKGVERSION), - G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "+-.~", - '_'); - dirs[n_dirs++] = g_strdup_printf("/var/run/qemu/%s", version_dir); -#endif - - assert(n_dirs <= ARRAY_SIZE(dirs)); - for (i = 0; i < n_dirs; i++) { - fname = g_strdup_printf("%s/%s%s", - dirs[i], module_name, CONFIG_HOST_DSOSUF); - ret = module_load_file(fname, mayfail, export_symbols); - g_free(fname); - fname = NULL; - /* Try loading until loaded a module file */ - if (!ret) { - success = true; - break; + char *fname = g_strdup_printf("%s/%s%s", + dirs[i], module_name, CONFIG_HOST_DSOSUF); + int ret = access(fname, F_OK); + if (ret != 0 && (errno == ENOENT || errno == ENOTDIR)) { + /* + * if we don't find the module in this dir, try the next one. + * If we don't find it in any dir, that can be fine too: user + * did not install the module. We will return 0 in this case + * with no error set. + */ + g_free(fname); + continue; + } else if (ret != 0) { + /* most common is EACCES here */ + error_setg_errno(errp, errno, "error trying to access %s", fname); + } else if (module_load_dso(fname, export_symbols, errp)) { + rv = 1; /* module successfully loaded */ } + g_free(fname); + goto out; } + rv = 0; /* module not found */ - if (!success) { +out: + if (rv <= 0) { g_hash_table_remove(loaded_modules, module_name); g_free(module_name); } - for (i = 0; i < n_dirs; i++) { g_free(dirs[i]); } - -#endif - return success; + return rv; } -#ifdef CONFIG_MODULES - static bool module_loaded_qom_all; -void module_load_qom_one(const char *type) +int module_load_qom(const char *type, Error **errp) { const QemuModinfo *modinfo; const char **sl; + int rv = 0; if (!type) { - return; + error_setg(errp, "%s", "type is NULL"); + return -1; } trace_module_lookup_object_type(type); @@ -333,15 +337,24 @@ void module_load_qom_one(const char *type) } for (sl = modinfo->objs; *sl != NULL; sl++) { if (strcmp(type, *sl) == 0) { - module_load_one("", modinfo->name, false); + if (rv > 0) { + error_setg(errp, "multiple modules providing '%s'", type); + return -1; + } + rv = module_load("", modinfo->name, errp); + if (rv < 0) { + return rv; + } } } } + return rv; } void module_load_qom_all(void) { const QemuModinfo *modinfo; + Error *local_err = NULL; if (module_loaded_qom_all) { return; @@ -354,7 +367,9 @@ void module_load_qom_all(void) if (!module_check_arch(modinfo)) { continue; } - module_load_one("", modinfo->name, false); + if (module_load("", modinfo->name, &local_err) < 0) { + error_report_err(local_err); + } } module_loaded_qom_all = true; } @@ -370,7 +385,10 @@ void qemu_load_module_for_opts(const char *group) } for (sl = modinfo->opts; *sl != NULL; sl++) { if (strcmp(group, *sl) == 0) { - module_load_one("", modinfo->name, false); + Error *local_err = NULL; + if (module_load("", modinfo->name, &local_err) < 0) { + error_report_err(local_err); + } } } } @@ -380,7 +398,8 @@ void qemu_load_module_for_opts(const char *group) void module_allow_arch(const char *arch) {} void qemu_load_module_for_opts(const char *group) {} -void module_load_qom_one(const char *type) {} +int module_load(const char *prefix, const char *name, Error **errp) { return 2; } +int module_load_qom(const char *type, Error **errp) { return 2; } void module_load_qom_all(void) {} #endif |