[PATCH for-6.0 9/9] spapr: spapr_drc_attach() cannot fail
All users are passing _abort already. Document the fact that spapr_drc_attach() should only be passed a free DRC, which is supposedly the case if appropriate checking is done earlier. Signed-off-by: Greg Kurz --- include/hw/ppc/spapr_drc.h | 8 +++- hw/ppc/spapr.c | 6 +++--- hw/ppc/spapr_drc.c | 8 ++-- hw/ppc/spapr_nvdimm.c | 2 +- hw/ppc/spapr_pci.c | 2 +- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index 165b281496bb..def3593adc8b 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -235,7 +235,13 @@ SpaprDrc *spapr_drc_by_index(uint32_t index); SpaprDrc *spapr_drc_by_id(const char *type, uint32_t id); int spapr_dt_drc(void *fdt, int offset, Object *owner, uint32_t drc_type_mask); -bool spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp); +/* + * These functions respectively abort if called with a device already + * attached or no device attached. In the case of spapr_drc_attach(), + * this means that the attachability of the DRC *must* be checked + * beforehand (eg. check drc->dev at pre-plug). + */ +void spapr_drc_attach(SpaprDrc *drc, DeviceState *d); void spapr_drc_detach(SpaprDrc *drc); /* Returns true if a hot plug/unplug request is pending */ diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 5e32d1d396b4..e0047f41073e 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3399,7 +3399,7 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, * that doesn't overlap with any existing mapping at pre-plug. The * corresponding LMB DRCs are thus assumed to be all attachable. */ -spapr_drc_attach(drc, dev, _abort); +spapr_drc_attach(drc, dev); if (!hotplugged) { spapr_drc_reset(drc); } @@ -3767,7 +3767,7 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev) * core being plugged into a free slot. Nothing should already * be attached to the corresponding DRC. */ -spapr_drc_attach(drc, dev, _abort); +spapr_drc_attach(drc, dev); if (hotplugged) { /* @@ -3920,7 +3920,7 @@ static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev) assert(drc); /* spapr_phb_pre_plug() already checked the DRC is attachable */ -spapr_drc_attach(drc, dev, _abort); +spapr_drc_attach(drc, dev); if (hotplugged) { spapr_hotplug_req_add_by_index(drc); diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 77718cde1ff2..f991cf89a08a 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -369,14 +369,11 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, } while (fdt_depth != 0); } -bool spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp) +void spapr_drc_attach(SpaprDrc *drc, DeviceState *d) { trace_spapr_drc_attach(spapr_drc_index(drc)); -if (drc->dev) { -error_setg(errp, "an attached device is still awaiting release"); -return false; -} +g_assert(!drc->dev); g_assert((drc->state == SPAPR_DRC_STATE_LOGICAL_UNUSABLE) || (drc->state == SPAPR_DRC_STATE_PHYSICAL_POWERON)); @@ -386,7 +383,6 @@ bool spapr_drc_attach(SpaprDrc *drc, DeviceState *d, Error **errp) object_get_typename(OBJECT(drc->dev)), (Object **)(>dev), NULL, 0); -return true; } static void spapr_drc_release(SpaprDrc *drc) diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c index 2f1c196e1b76..73ee006541a6 100644 --- a/hw/ppc/spapr_nvdimm.c +++ b/hw/ppc/spapr_nvdimm.c @@ -101,7 +101,7 @@ void spapr_add_nvdimm(DeviceState *dev, uint64_t slot) * pc_dimm_get_free_slot() provided a free slot at pre-plug. The * corresponding DRC is thus assumed to be attachable. */ -spapr_drc_attach(drc, dev, _abort); +spapr_drc_attach(drc, dev); if (hotplugged) { spapr_hotplug_req_add_by_index(drc); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 2829f298d9c1..e946bd5055cc 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1601,7 +1601,7 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, } /* spapr_pci_pre_plug() already checked the DRC is attachable */ -spapr_drc_attach(drc, DEVICE(pdev), _abort); +spapr_drc_attach(drc, DEVICE(pdev)); /* If this is function 0, signal hotplug for all the device functions. * Otherwise defer sending the hotplug event. -- 2.26.2
[PATCH for-6.0 4/9] spapr: Set compat mode in spapr_reset_vcpu()
When it comes to resetting the compat mode of the vCPUS, there are two situations to consider: (1) machine reset should set the compat mode back to the machine default, ie. spapr->max_compat_pvr (2) hot plugged vCPUs should set their compat mode to mach the boot vCPU, ie. POWERPC_CPU(first_cpu)->compat_pvr This is currently handled in two separate places: globally for all vCPUs from the machine reset code for (1) and for each thread of a core from the hotplug path for (2). Since the machine reset code already resets all vCPUs, starting with boot vCPU, consolidate the logic in spapr_reset_vcpu(). Special case the boot vCPU so that it resets its compat mode back to the machine default. Any other vCPU just need to match the compat mode of the boot vCPU. Failing to set the compat mode during machine reset is a fatal error, but not for hot plugged vCPUs. This is arguable because if we've been able to set the boot vCPU compat mode at CAS or during machine reset, it should definitely not fail for other vCPUs. Since spapr_reset_vcpu() already has a fatal error path for kvm_check_mmu() failures, do the same for ppc_set_compat(). This gets rid of an error path in spapr_core_plug(). It will allow further simplifications. Signed-off-by: Greg Kurz --- hw/ppc/spapr.c | 16 hw/ppc/spapr_cpu_core.c | 13 + 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index f58f77389e8e..da7586f548df 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1606,8 +1606,6 @@ static void spapr_machine_reset(MachineState *machine) spapr_ovec_cleanup(spapr->ov5_cas); spapr->ov5_cas = spapr_ovec_new(); -ppc_set_compat_all(spapr->max_compat_pvr, _fatal); - /* * This is fixing some of the default configuration of the XIVE * devices. To be called after the reset of the machine devices. @@ -3785,20 +3783,6 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, core_slot->cpu = OBJECT(dev); -/* - * Set compatibility mode to match the boot CPU, which was either set - * by the machine reset code or by CAS. - */ -if (hotplugged) { -for (i = 0; i < cc->nr_threads; i++) { -if (ppc_set_compat(core->threads[i], - POWERPC_CPU(first_cpu)->compat_pvr, - errp) < 0) { -return; -} -} -} - if (smc->pre_2_10_has_unused_icps) { for (i = 0; i < cc->nr_threads; i++) { cs = CPU(core->threads[i]); diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index 2f7dc3c23ded..17741a3fb77f 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -27,6 +27,7 @@ static void spapr_reset_vcpu(PowerPCCPU *cpu) { +PowerPCCPU *first_ppc_cpu = POWERPC_CPU(first_cpu); CPUState *cs = CPU(cpu); CPUPPCState *env = >env; PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); @@ -69,6 +70,18 @@ static void spapr_reset_vcpu(PowerPCCPU *cpu) kvm_check_mmu(cpu, _fatal); spapr_irq_cpu_intc_reset(spapr, cpu); + +/* + * The boot CPU is only reset during machine reset : reset its + * compatibility mode to the machine default. For other CPUs, + * either cold plugged or hot plugged, set the compatibility mode + * to match the boot CPU, which was either set by the machine reset + * code or by CAS. + */ +ppc_set_compat(cpu, + cpu == first_ppc_cpu ? + spapr->max_compat_pvr : first_ppc_cpu->compat_pvr, + _fatal); } void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, -- 2.26.2
[PATCH for-6.0 8/9] spapr: Do TPM proxy hotplug sanity checks at pre-plug
There can be only one TPM proxy at a time. This is currently checked at plug time. But this can be detected at pre-plug in order to error out earlier. This allows to get rid of error handling in the plug handler. Signed-off-by: Greg Kurz --- hw/ppc/spapr.c | 23 ++- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index bded059d59c8..5e32d1d396b4 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3957,17 +3957,28 @@ static void spapr_phb_unplug_request(HotplugHandler *hotplug_dev, } } -static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) +static +bool spapr_tpm_proxy_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, + Error **errp) { SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); -SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev); if (spapr->tpm_proxy != NULL) { error_setg(errp, "Only one TPM proxy can be specified for this machine"); -return; +return false; } +return true; +} + +static void spapr_tpm_proxy_plug(HotplugHandler *hotplug_dev, DeviceState *dev) +{ +SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); +SpaprTpmProxy *tpm_proxy = SPAPR_TPM_PROXY(dev); + +/* Already checked in spapr_tpm_proxy_pre_plug() */ +g_assert(spapr->tpm_proxy == NULL); + spapr->tpm_proxy = tpm_proxy; } @@ -3990,7 +4001,7 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { spapr_phb_plug(hotplug_dev, dev); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { -spapr_tpm_proxy_plug(hotplug_dev, dev, errp); +spapr_tpm_proxy_plug(hotplug_dev, dev); } } @@ -4053,6 +4064,8 @@ static void spapr_machine_device_pre_plug(HotplugHandler *hotplug_dev, spapr_core_pre_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { spapr_phb_pre_plug(hotplug_dev, dev, errp); +} else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { +spapr_tpm_proxy_pre_plug(hotplug_dev, dev, errp); } } -- 2.26.2
[PATCH for-6.0 3/9] spapr: Fix pre-2.10 dummy ICP hack
This hack registers dummy VMState entries of ICPs in order to support migration of old pseries machine types that used to create all smp.max_cpus possible ICPs at machine init. Part of the work is to unregister the dummy entries when plugging an actual vCPU core, and to register them back when unplugging the core. The code that unregisters the dummy ICPs in spapr_core_plug() is misplaced: if ppc_set_compat() fails afterwards, the hotplug operation will be cancelled and the dummy ICPs won't be registered back since the unplug handler isn't called. Unregister the dummy ICPs at the end of spapr_core_plug(). Signed-off-by: Greg Kurz --- The next patch makes this patch a bit useless. I post it anyway for the records because it is a programming error. --- hw/ppc/spapr.c | 14 +++--- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 394d28d9e081..f58f77389e8e 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3785,13 +3785,6 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, core_slot->cpu = OBJECT(dev); -if (smc->pre_2_10_has_unused_icps) { -for (i = 0; i < cc->nr_threads; i++) { -cs = CPU(core->threads[i]); -pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); -} -} - /* * Set compatibility mode to match the boot CPU, which was either set * by the machine reset code or by CAS. @@ -3805,6 +3798,13 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, } } } + +if (smc->pre_2_10_has_unused_icps) { +for (i = 0; i < cc->nr_threads; i++) { +cs = CPU(core->threads[i]); +pre_2_10_vmstate_unregister_dummy_icp(cs->cpu_index); +} +} } static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, -- 2.26.2
[PATCH for-6.0 7/9] spapr: Do PHB hoplug sanity check at pre-plug
We currently detect that a PHB index is already in use at plug time. But this can be decteted at pre-plug in order to error out earlier. This allows to pass _abort to spapr_drc_attach() and to end up with a plug handler that doesn't need to report errors anymore. Signed-off-by: Greg Kurz --- hw/ppc/spapr.c | 17 +++-- 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 81bac59887ab..bded059d59c8 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3872,6 +3872,7 @@ static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, SpaprPhbState *sphb = SPAPR_PCI_HOST_BRIDGE(dev); SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); const unsigned windows_supported = spapr_phb_windows_supported(sphb); +SpaprDrc *drc; if (dev->hotplugged && !smc->dr_phb_enabled) { error_setg(errp, "PHB hotplug not supported for this machine"); @@ -3883,6 +3884,12 @@ static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, return false; } +drc = spapr_drc_by_id(TYPE_SPAPR_DRC_PHB, sphb->index); +if (drc && drc->dev) { +error_setg(errp, "PHB %d already attached", sphb->index); +return false; +} + /* * This will check that sphb->index doesn't exceed the maximum number of * PHBs for the current machine type. @@ -3896,8 +3903,7 @@ static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, errp); } -static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) +static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev) { SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr); @@ -3913,9 +3919,8 @@ static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, /* hotplug hooks should check it's enabled before getting this far */ assert(drc); -if (!spapr_drc_attach(drc, dev, errp)) { -return; -} +/* spapr_phb_pre_plug() already checked the DRC is attachable */ +spapr_drc_attach(drc, dev, _abort); if (hotplugged) { spapr_hotplug_req_add_by_index(drc); @@ -3983,7 +3988,7 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { spapr_core_plug(hotplug_dev, dev); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { -spapr_phb_plug(hotplug_dev, dev, errp); +spapr_phb_plug(hotplug_dev, dev); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { spapr_tpm_proxy_plug(hotplug_dev, dev, errp); } -- 2.26.2
[PATCH for-6.0 1/9] spapr: Do PCI device hotplug sanity checks at pre-plug only
The PHB acts as the hotplug handler for PCI devices. It does some sanity checks on DR enablement, PCI bridge chassis numbers and multifunction. These checks are currently performed at plug time, but they would best sit in a pre-plug handler in order to error out as early as possible. Create a spapr_pci_pre_plug() handler and move all the checking there. Add a check that the associated DRC doesn't already have an attached device. This is equivalent to the slot availability check performed by do_pci_register_device() upon realization of the PCI device. This allows to pass _abort to spapr_drc_attach() and to end up with a plug handler that doesn't need to report errors anymore. Signed-off-by: Greg Kurz --- hw/ppc/spapr_pci.c | 43 +-- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index 88ce87f130a5..2829f298d9c1 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1532,8 +1532,8 @@ static bool bridge_has_valid_chassis_nr(Object *bridge, Error **errp) return true; } -static void spapr_pci_plug(HotplugHandler *plug_handler, - DeviceState *plugged_dev, Error **errp) +static void spapr_pci_pre_plug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, Error **errp) { SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler)); PCIDevice *pdev = PCI_DEVICE(plugged_dev); @@ -1542,9 +1542,6 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, PCIBus *bus = PCI_BUS(qdev_get_parent_bus(DEVICE(pdev))); uint32_t slotnr = PCI_SLOT(pdev->devfn); -/* if DR is disabled we don't need to do anything in the case of - * hotplug or coldplug callbacks - */ if (!phb->dr_enabled) { /* if this is a hotplug operation initiated by the user * we need to let them know it's not enabled @@ -1552,17 +1549,14 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, if (plugged_dev->hotplugged) { error_setg(errp, QERR_BUS_NO_HOTPLUG, object_get_typename(OBJECT(phb))); +return; } -return; } -g_assert(drc); - if (pc->is_bridge) { if (!bridge_has_valid_chassis_nr(OBJECT(plugged_dev), errp)) { return; } -spapr_pci_bridge_plug(phb, PCI_BRIDGE(plugged_dev)); } /* Following the QEMU convention used for PCIe multifunction @@ -1574,13 +1568,41 @@ static void spapr_pci_plug(HotplugHandler *plug_handler, error_setg(errp, "PCI: slot %d function 0 already occupied by %s," " additional functions can no longer be exposed to guest.", slotnr, bus->devices[PCI_DEVFN(slotnr, 0)]->name); +} + +if (drc && drc->dev) { +error_setg(errp, "PCI: slot %d already occupied by %s", slotnr, + pci_get_function_0(PCI_DEVICE(drc->dev))->name); return; } +} + +static void spapr_pci_plug(HotplugHandler *plug_handler, + DeviceState *plugged_dev, Error **errp) +{ +SpaprPhbState *phb = SPAPR_PCI_HOST_BRIDGE(DEVICE(plug_handler)); +PCIDevice *pdev = PCI_DEVICE(plugged_dev); +PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(plugged_dev); +SpaprDrc *drc = drc_from_dev(phb, pdev); +uint32_t slotnr = PCI_SLOT(pdev->devfn); -if (!spapr_drc_attach(drc, DEVICE(pdev), errp)) { +/* + * If DR is disabled we don't need to do anything in the case of + * hotplug or coldplug callbacks. + */ +if (!phb->dr_enabled) { return; } +g_assert(drc); + +if (pc->is_bridge) { +spapr_pci_bridge_plug(phb, PCI_BRIDGE(plugged_dev)); +} + +/* spapr_pci_pre_plug() already checked the DRC is attachable */ +spapr_drc_attach(drc, DEVICE(pdev), _abort); + /* If this is function 0, signal hotplug for all the device functions. * Otherwise defer sending the hotplug event. */ @@ -2223,6 +2245,7 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data) /* Supported by TYPE_SPAPR_MACHINE */ dc->user_creatable = true; set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories); +hp->pre_plug = spapr_pci_pre_plug; hp->plug = spapr_pci_plug; hp->unplug = spapr_pci_unplug; hp->unplug_request = spapr_pci_unplug_request; -- 2.26.2
[PATCH for-6.0 5/9] spapr: Simplify error path of spapr_core_plug()
spapr_core_pre_plug() already guarantees that the slot for the given core ID is available. It is thus safe to assume that spapr_find_cpu_slot() returns a slot during plug. Turn the error path into an assertion. It is also safe to assume that no device is attached to the corresponding DRC and that spapr_drc_attach() shouldn't fail. Pass _abort to spapr_drc_attach() and simplify error handling. Signed-off-by: Greg Kurz --- hw/ppc/spapr.c | 21 ++--- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index da7586f548df..cfca033c7b14 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3739,8 +3739,7 @@ int spapr_core_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, return 0; } -static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, -Error **errp) +static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev) { SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); MachineClass *mc = MACHINE_GET_CLASS(spapr); @@ -3755,20 +3754,20 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, int i; core_slot = spapr_find_cpu_slot(MACHINE(hotplug_dev), cc->core_id, ); -if (!core_slot) { -error_setg(errp, "Unable to find CPU core with core-id: %d", - cc->core_id); -return; -} +g_assert(core_slot); /* Already checked in spapr_core_pre_plug() */ + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, spapr_vcpu_id(spapr, cc->core_id)); g_assert(drc || !mc->has_hotpluggable_cpus); if (drc) { -if (!spapr_drc_attach(drc, dev, errp)) { -return; -} +/* + * spapr_core_pre_plug() already buys us this is a brand new + * core being plugged into a free slot. Nothing should already + * be attached to the corresponding DRC. + */ +spapr_drc_attach(drc, dev, _abort); if (hotplugged) { /* @@ -3981,7 +3980,7 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { spapr_memory_plug(hotplug_dev, dev); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { -spapr_core_plug(hotplug_dev, dev, errp); +spapr_core_plug(hotplug_dev, dev); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { spapr_phb_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_TPM_PROXY)) { -- 2.26.2
[PATCH for-6.0 2/9] spapr: Do NVDIMM/PC-DIMM device hotplug sanity checks at pre-plug only
Pre-plug of a memory device, be it an NVDIMM or a PC-DIMM, ensures that the memory slot is available and that addresses don't overlap with existing memory regions. The corresponding DRCs in the LMB and PMEM namespaces are thus necessarily attachable at plug time. Pass _abort to spapr_drc_attach() in spapr_add_lmbs() and spapr_add_nvdimm(). This allows to greatly simplify error handling on the plug path. Signed-off-by: Greg Kurz --- include/hw/ppc/spapr_nvdimm.h | 2 +- hw/ppc/spapr.c| 40 --- hw/ppc/spapr_nvdimm.c | 11 +- 3 files changed, 20 insertions(+), 33 deletions(-) diff --git a/include/hw/ppc/spapr_nvdimm.h b/include/hw/ppc/spapr_nvdimm.h index 344582d2f5f7..73be250e2ac9 100644 --- a/include/hw/ppc/spapr_nvdimm.h +++ b/include/hw/ppc/spapr_nvdimm.h @@ -30,6 +30,6 @@ int spapr_pmem_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, void spapr_dt_persistent_memory(SpaprMachineState *spapr, void *fdt); bool spapr_nvdimm_validate(HotplugHandler *hotplug_dev, NVDIMMDevice *nvdimm, uint64_t size, Error **errp); -bool spapr_add_nvdimm(DeviceState *dev, uint64_t slot, Error **errp); +void spapr_add_nvdimm(DeviceState *dev, uint64_t slot); #endif diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 12a012d9dd09..394d28d9e081 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3382,8 +3382,8 @@ int spapr_lmb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, return 0; } -static bool spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, - bool dedicated_hp_event_source, Error **errp) +static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, + bool dedicated_hp_event_source) { SpaprDrc *drc; uint32_t nr_lmbs = size/SPAPR_MEMORY_BLOCK_SIZE; @@ -3396,15 +3396,12 @@ static bool spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, addr / SPAPR_MEMORY_BLOCK_SIZE); g_assert(drc); -if (!spapr_drc_attach(drc, dev, errp)) { -while (addr > addr_start) { -addr -= SPAPR_MEMORY_BLOCK_SIZE; -drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, - addr / SPAPR_MEMORY_BLOCK_SIZE); -spapr_drc_detach(drc); -} -return false; -} +/* + * memory_device_get_free_addr() provided a range of free addresses + * that doesn't overlap with any existing mapping at pre-plug. The + * corresponding LMB DRCs are thus assumed to be all attachable. + */ +spapr_drc_attach(drc, dev, _abort); if (!hotplugged) { spapr_drc_reset(drc); } @@ -3425,11 +3422,9 @@ static bool spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, nr_lmbs); } } -return true; } -static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, - Error **errp) +static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev) { SpaprMachineState *ms = SPAPR_MACHINE(hotplug_dev); PCDIMMDevice *dimm = PC_DIMM(dev); @@ -3444,24 +3439,15 @@ static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev, if (!is_nvdimm) { addr = object_property_get_uint(OBJECT(dimm), PC_DIMM_ADDR_PROP, _abort); -if (!spapr_add_lmbs(dev, addr, size, -spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT), errp)) { -goto out_unplug; -} +spapr_add_lmbs(dev, addr, size, + spapr_ovec_test(ms->ov5_cas, OV5_HP_EVT)); } else { slot = object_property_get_int(OBJECT(dimm), PC_DIMM_SLOT_PROP, _abort); /* We should have valid slot number at this point */ g_assert(slot >= 0); -if (!spapr_add_nvdimm(dev, slot, errp)) { -goto out_unplug; -} +spapr_add_nvdimm(dev, slot); } - -return; - -out_unplug: -pc_dimm_unplug(dimm, MACHINE(ms)); } static void spapr_memory_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, @@ -4009,7 +3995,7 @@ static void spapr_machine_device_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { if (object_dynamic_cast(OBJECT(dev), TYPE_PC_DIMM)) { -spapr_memory_plug(hotplug_dev, dev, errp); +spapr_memory_plug(hotplug_dev, dev); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_CPU_CORE)) { spapr_core_plug(hotplug_dev, dev, errp); } else if (object_dynamic_cast(OBJECT(dev), TYPE_SPAPR_PCI_HOST_BRIDGE)) { diff --git a/hw/ppc/spapr_nvdimm.c b/hw/ppc/spapr_nvdimm.c index a833a63b5ed3..2f1c196e1b76 100644 ---
[PATCH for-6.0 6/9] spapr: Make PHB placement functions and spapr_pre_plug_phb() return status
Read documentation in "qapi/error.h" and changelog of commit e3fe3988d785 ("error: Document Error API usage rules") for rationale. Signed-off-by: Greg Kurz --- include/hw/ppc/spapr.h | 2 +- hw/ppc/spapr.c | 40 +++- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 2e89e36cfbdc..b7ced9faebf5 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -140,7 +140,7 @@ struct SpaprMachineClass { bool pre_5_1_assoc_refpoints; bool pre_5_2_numa_associativity; -void (*phb_placement)(SpaprMachineState *spapr, uint32_t index, +bool (*phb_placement)(SpaprMachineState *spapr, uint32_t index, uint64_t *buid, hwaddr *pio, hwaddr *mmio32, hwaddr *mmio64, unsigned n_dma, uint32_t *liobns, hwaddr *nv2gpa, diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index cfca033c7b14..81bac59887ab 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -3865,7 +3865,7 @@ int spapr_phb_dt_populate(SpaprDrc *drc, SpaprMachineState *spapr, return 0; } -static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, +static bool spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { SpaprMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev)); @@ -3875,24 +3875,25 @@ static void spapr_phb_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, if (dev->hotplugged && !smc->dr_phb_enabled) { error_setg(errp, "PHB hotplug not supported for this machine"); -return; +return false; } if (sphb->index == (uint32_t)-1) { error_setg(errp, "\"index\" for PAPR PHB is mandatory"); -return; +return false; } /* * This will check that sphb->index doesn't exceed the maximum number of * PHBs for the current machine type. */ -smc->phb_placement(spapr, sphb->index, - >buid, >io_win_addr, - >mem_win_addr, >mem64_win_addr, - windows_supported, sphb->dma_liobn, - >nv2_gpa_win_addr, >nv2_atsd_win_addr, - errp); +return +smc->phb_placement(spapr, sphb->index, + >buid, >io_win_addr, + >mem_win_addr, >mem64_win_addr, + windows_supported, sphb->dma_liobn, + >nv2_gpa_win_addr, >nv2_atsd_win_addr, + errp); } static void spapr_phb_plug(HotplugHandler *hotplug_dev, DeviceState *dev, @@ -4130,7 +4131,7 @@ static const CPUArchIdList *spapr_possible_cpu_arch_ids(MachineState *machine) return machine->possible_cpus; } -static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, +static bool spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, uint64_t *buid, hwaddr *pio, hwaddr *mmio32, hwaddr *mmio64, unsigned n_dma, uint32_t *liobns, @@ -4168,7 +4169,7 @@ static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, if (index >= SPAPR_MAX_PHBS) { error_setg(errp, "\"index\" for PAPR PHB is too large (max %llu)", SPAPR_MAX_PHBS - 1); -return; +return false; } *buid = base_buid + index; @@ -4182,6 +4183,7 @@ static void spapr_phb_placement(SpaprMachineState *spapr, uint32_t index, *nv2gpa = SPAPR_PCI_NV2RAM64_WIN_BASE + index * SPAPR_PCI_NV2RAM64_WIN_SIZE; *nv2atsd = SPAPR_PCI_NV2ATSD_WIN_BASE + index * SPAPR_PCI_NV2ATSD_WIN_SIZE; +return true; } static ICSState *spapr_ics_get(XICSFabric *dev, int irq) @@ -4561,18 +4563,21 @@ DEFINE_SPAPR_MACHINE(4_1, "4.1", false); /* * pseries-4.0 */ -static void phb_placement_4_0(SpaprMachineState *spapr, uint32_t index, +static bool phb_placement_4_0(SpaprMachineState *spapr, uint32_t index, uint64_t *buid, hwaddr *pio, hwaddr *mmio32, hwaddr *mmio64, unsigned n_dma, uint32_t *liobns, hwaddr *nv2gpa, hwaddr *nv2atsd, Error **errp) { -spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, liobns, -nv2gpa, nv2atsd, errp); +if (!spapr_phb_placement(spapr, index, buid, pio, mmio32, mmio64, n_dma, + liobns, nv2gpa, nv2atsd, errp)) { +return false; +} + *nv2gpa = 0; *nv2atsd = 0; +return true; } - static void spapr_machine_4_0_class_options(MachineClass *mc) { SpaprMachineClass *smc = SPAPR_MACHINE_CLASS(mc); @@ -4732,7 +4737,7 @@ DEFINE_SPAPR_MACHINE(2_8, "2.8", false); * pseries-2.7 */ -static void
[PATCH for-6.0 0/9] spapr: Perform hotplug sanity checks at pre-plug
Igor recently suggested that instead of failing in spapr_drc_attach() at plug time we should rather check that the DRC is attachable at pre-plug time. This allows to error out before the hot-plugged device is even realized and to come up with simpler plug callbacks. sPAPR currently supports hotplug of PCI devices, PHBs, CPU cores, PC-DIMM/NVDIMM memory and TPM proxy devices. Some of these already do sanity checks at pre-plug that are sufficient to ensure the DRC are attachables. Some others don't even have a pre-plug handler. This series adds the missing pieces so that all failing conditions are caught at pre-plug time instead of plug time for all devices. Greg Kurz (9): spapr: Do PCI device hotplug sanity checks at pre-plug only spapr: Do NVDIMM/PC-DIMM device hotplug sanity checks at pre-plug only spapr: Fix pre-2.10 dummy ICP hack spapr: Set compat mode in spapr_reset_vcpu() spapr: Simplify error path of spapr_core_plug() spapr: Make PHB placement functions and spapr_pre_plug_phb() return status spapr: Do PHB hoplug sanity check at pre-plug spapr: Do TPM proxy hotplug sanity checks at pre-plug spapr: spapr_drc_attach() cannot fail include/hw/ppc/spapr.h| 2 +- include/hw/ppc/spapr_drc.h| 8 +- include/hw/ppc/spapr_nvdimm.h | 2 +- hw/ppc/spapr.c| 157 -- hw/ppc/spapr_cpu_core.c | 13 +++ hw/ppc/spapr_drc.c| 8 +- hw/ppc/spapr_nvdimm.c | 11 +-- hw/ppc/spapr_pci.c| 43 +++--- 8 files changed, 138 insertions(+), 106 deletions(-) -- 2.26.2
Re: [PATCH v2] drivers/virt: vmgenid: add vm generation id driver
On Mon, Nov 16, 2020 at 4:35 PM Catangiu, Adrian Costin wrote: > This patch is a driver that exposes a monotonic incremental Virtual > Machine Generation u32 counter via a char-dev FS interface that > provides sync and async VmGen counter updates notifications. It also > provides VmGen counter retrieval and confirmation mechanisms. > > The hw provided UUID is not exposed to userspace, it is internally > used by the driver to keep accounting for the exposed VmGen counter. > The counter starts from zero when the driver is initialized and > monotonically increments every time the hw UUID changes (the VM > generation changes). > > On each hw UUID change, the new hypervisor-provided UUID is also fed > to the kernel RNG. As for v1: Is there a reasonable usecase for the "confirmation" mechanism? It doesn't seem very useful to me. How do you envision integrating this with libraries that have to work in restrictive seccomp sandboxes? If this was in the vDSO, that would be much easier.
[PULL 2/2] qboot: update to latest upstream
This also brings in two patches that Debian had to include, qboot_stop_using_inttypes.patch and qboot_no_jump_tables.diff. Reported-by: Michael Tokarev Signed-off-by: Paolo Bonzini Message-Id: <20201120152408.164346-1-pbonz...@redhat.com> Signed-off-by: Paolo Bonzini --- pc-bios/qboot.rom | Bin 65536 -> 65536 bytes roms/Makefile | 8 ++-- roms/qboot| 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/pc-bios/qboot.rom b/pc-bios/qboot.rom index 45eabc516692e2d134bbb630d133c7c2dcc9a9b6..7634106a0766913077e88dfcb1021c1168dcad3c 100644 GIT binary patch literal 65536 zcmeI4eRx#Wwg1mdCNN-hB7#OmjTRLuXi!_B;B`Pou{9cAqWFTM!a!TCRuaHof}z7p zPR69^i+!}!dwFY1du>Zwiy>0)1TaBK>!@j)Vzg5n?TIt$sHvoN%K3fPK4;!AQG1`~ z-amfNNy}MhukYG>uf6u#YrmX5R_m{Y;;B%w)VSd!O>3An#^y3j+Y-Cc zr`4|>=hJG6jjJYUnvopKqhlnGhyRVo;?sD9&+^608pDuLVO%?@~RG zZip^z2n;N3EfmO%!-zwI#kM09UAoQq)YWZ!PbEyv0>*wO|u|VLFJv=wJtQw^;9UC z=K@k_u-)+H6}OPnk^CWFRZbW@_lPCQ7$(z2RSkQ_}vB$3khByl z?U}tt@q=$7a)gqOdkJsb$%H=bF-mXXWXX(l`A_HNC2H$SU!qo$k z)#7K_C3^LMUfC~*?}iET!Tow$@5L+GI7k z|Kn5~C57&+?xzL5osn#zd-0{C?eK9$b&|(w=v}-WWyFum+(;I5$ZuH5zh25LtCakf z{0u*~btz+L8)bNRxVqmJ&0}KGuy*OOzrdjDYVm99b>k1@wM23K+1HKVkk?}r*PDIa zc%QtERNNPF0qb?+9l{-sk;2C^1f2UrGZsr<>~i` z&-@5GWo7%`vdSxvxJ)FTuuJRf8bl(7VKJmW)7$q`8}@sBJNF-5R}i_ra8BZh4@o4_ z#DO~{-)vF5Ko4E8D#d+dZ|j)cWtnfiPHy#*V=H4p#F(OLyJ*0F>zdBhG+H$ zTjYN)8pr$t`=-rT7UI8k1IdDc%0`*(6=c#EO>hG`rviUoAZNngL8uO zf>l917Bt@e2h-Dn;7!3Bf;R?l4lWGd61+8dMsRr0xA{3K@8j~1`pEnPkN7qXJN^3W zs^`z0Gp|aI8K1+p3vRmM#+w)3a_bqxeVZRWVC(ExI`j=`?zH}UJu%o{AxXCZ= z(zH^ot=#L=c4&_t*s(SzZnfAD&)U17YSMZ{B;Nj`KXC+dy^2?uKB`wHB~*ng2^gtx zby7c|Kd=8;-}By``Um>Le}6U3he~E{x*d|3T!v{yIyGluoskMz}V`^uXk- zzlQ?PzxNY8B{kn-Rjq_e(bN`Rh{{YShQ2VaA4KUt>aXbS?`;bQ;-P(|nM|RiLJ%`g(+_gZ{eJP@fy z^n3`342k@(5XpsoyRHqHy3$r1E37oNjtJPSJ2I@_wnx0SB|J~}*ekPKPSw#evsWjZ0_k0{_*fJy
[PULL 1/2] usb: fix kconfig for usb-xhci-sysbus
Remove the "default y" for USB_XHCI_SYSBUS because sysbus devices are not user creatable; boards that use them will specify them manually with "imply" or "select" clauses. It would be nice to keep the ability to remove PCIe and USB from microvm, since thos can be disabled on the command line and therefore should not be included if QEMU is configured --without-default-devices. However it's too late for 5.2 to figure out a place for the DSDT creation code. Reported-by: Bruce Rogers Cc: Gerd Hoffmann Signed-off-by: Paolo Bonzini --- hw/usb/Kconfig | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/usb/Kconfig b/hw/usb/Kconfig index 3b07d9cf68..7fbae18bc8 100644 --- a/hw/usb/Kconfig +++ b/hw/usb/Kconfig @@ -47,7 +47,6 @@ config USB_XHCI_NEC config USB_XHCI_SYSBUS bool -default y select USB_XHCI config USB_MUSB -- 2.26.2
[PULL 0/2] Kconfig, qboot changes for 2020-11-20
The following changes since commit 7fbd7e710323c8f4c5f6a38a8ae0e6726b5a4599: Merge remote-tracking branch 'remotes/stefanha-gitlab/tags/tracing-pull-request' into staging (2020-11-19 17:08:42 +) are available in the Git repository at: https://gitlab.com/bonzini/qemu.git tags/for-upstream for you to fetch changes up to 5983021eb6cd0fb8dfbac5211892f5231758d60b: qboot: update to latest upstream (2020-11-20 10:48:53 -0500) Bug fixes Paolo Bonzini (2): usb: fix kconfig for usb-xhci-sysbus qboot: update to latest upstream hw/usb/Kconfig| 1 - pc-bios/qboot.rom | Bin 65536 -> 65536 bytes roms/Makefile | 8 ++-- roms/qboot| 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) -- 2.26.2
Re: [PATCH RFC] vfio: Move the saving of the config space to the right place in VFIO migration
On Fri, 20 Nov 2020 22:05:49 +0800 Shenming Lu wrote: > On 2020/11/20 1:41, Alex Williamson wrote: > > On Thu, 19 Nov 2020 14:13:24 +0530 > > Kirti Wankhede wrote: > > > >> On 11/14/2020 2:47 PM, Shenming Lu wrote: > >>> When running VFIO migration, I found that the restoring of VFIO PCI > >>> device’s > >>> config space is before VGIC on ARM64 target. But generally, interrupt > >>> controllers > >>> need to be restored before PCI devices. > >> > >> Is there any other way by which VGIC can be restored before PCI device? > > As far as I know, it seems to have to depend on priorities in the > non-iterable process. > > >> > >>> Besides, if a VFIO PCI device is > >>> configured to have directly-injected MSIs (VLPIs), the restoring of its > >>> config > >>> space will trigger the configuring of these VLPIs (in kernel), where it > >>> would > >>> return an error as I saw due to the dependency on kvm’s vgic. > >>> > >> > >> Can this be fixed in kernel to re-initialize the kernel state? > > Did you mean to reconfigure these VLPIs when restoring kvm's vgic? > But the fact is that this error is not caused by kernel, it is due to the > incorrect > calling order of qemu... > > >> > >>> To avoid this, we can move the saving of the config space from the > >>> iterable > >>> process to the non-iterable process, so that it will be called after VGIC > >>> according to their priorities. > >>> > >> > >> With this change, at resume side, pre-copy phase data would reach > >> destination without restored config space. VFIO device on destination > >> might need it's config space setup and validated before it can accept > >> further VFIO device specific migration state. > >> > >> This also changes bit-stream, so it would break migration with original > >> migration patch-set. > > > > Config space can continue to change while in pre-copy, if we're only > > sending config space at the initiation of pre-copy, how are any changes > > that might occur before the VM is stopped conveyed to the target? For > > example the guest might reboot and a device returned to INTx mode from > > MSI during pre-copy. Thanks, > > What I see is that the config space is only saved once in > save_live_complete_precopy > currently... > As you said, a VFIO device might need it's config space setup first, and > the config space can continue to change while in pre-copy, Did you mean we > have to migrate the config space in save_live_iterate? > However, I still have a little doubt about the restoring dependence between > the qemu emulated config space and the device data... > > Besides, if we surely can't move the saving of the config space back, can we > just move some actions which are triggered by the restoring of the config > space > back (such as vfio_msix_enable())? It seems that the significant benefit to enabling interrupts during pre-copy would be to reduce the latency and failure potential during the final phase of migration. Do we have any data for how much it adds to the device contributed downtime to configure interrupts only at the final stage? My guess is that it's a measurable delay on its own. At the same time, we can't ignore the differences in machine specific dependencies and if we don't even sync the config space once the VM is stopped... this all seems not ready to call supported, especially if we have concerns already about migration bit-stream compatibility. Given our timing relative to QEMU 5.2, the only path I feel comfortable with is to move forward with downgrading vfio migration support to be enabled via an experimental option. Objections? Thanks, Alex > > The demo patch is as follows (but it seems that .save_state is not a > appropriate > place to do it. -_-): > > diff --git a/hw/vfio/migration.c b/hw/vfio/migration.c > index 55261562d4..9cf0310148 100644 > --- a/hw/vfio/migration.c > +++ b/hw/vfio/migration.c > @@ -44,6 +44,7 @@ > #define VFIO_MIG_FLAG_DEV_CONFIG_STATE (0xef12ULL) > #define VFIO_MIG_FLAG_DEV_SETUP_STATE (0xef13ULL) > #define VFIO_MIG_FLAG_DEV_DATA_STATE(0xef14ULL) > +#define VFIO_MIG_FLAG_DEV_STATE_TRIGGER (0xef15ULL) > > static int64_t bytes_transferred; > > @@ -368,6 +369,15 @@ static int vfio_save_device_config_state(QEMUFile *f, > void *opaque) > return qemu_file_get_error(f); > } > > +static void vfio_device_state_trigger(void *opaque) > +{ > +VFIODevice *vbasedev = opaque; > + > +if (vbasedev->ops && vbasedev->ops->vfio_trigger_config) { > +vbasedev->ops->vfio_trigger_config(vbasedev); > +} > +} > + > static int vfio_load_device_config_state(QEMUFile *f, void *opaque) > { > VFIODevice *vbasedev = opaque; > @@ -620,6 +630,13 @@ static int vfio_save_complete_precopy(QEMUFile *f, void > *opaque) > return ret; > } > > +static void vfio_save_state_trigger(QEMUFile *f, void *opaque) > +{ > +qemu_put_be64(f,
Re: [PATCH v2] drivers/virt: vmgenid: add vm generation id driver
Hello, +Cc Eric, Adrian On 11/19/20 6:36 PM, Alexander Graf wrote: > On 19.11.20 18:38, Mike Rapoport wrote: >> On Thu, Nov 19, 2020 at 01:51:18PM +0100, Alexander Graf wrote: >>> On 19.11.20 13:02, Christian Borntraeger wrote: On 16.11.20 16:34, Catangiu, Adrian Costin wrote: > - Background > > The VM Generation ID is a feature defined by Microsoft (paper: > http://go.microsoft.com/fwlink/?LinkId=260709) and supported by > multiple hypervisor vendors. > > The feature is required in virtualized environments by apps that work > with local copies/caches of world-unique data such as random values, > uuids, monotonically increasing counters, etc. > Such apps can be negatively affected by VM snapshotting when the VM > is either cloned or returned to an earlier point in time. > > The VM Generation ID is a simple concept meant to alleviate the issue > by providing a unique ID that changes each time the VM is restored > from a snapshot. The hw provided UUID value can be used to > differentiate between VMs or different generations of the same VM. > > - Problem > > The VM Generation ID is exposed through an ACPI device by multiple > hypervisor vendors but neither the vendors or upstream Linux have no > default driver for it leaving users to fend for themselves. [..] >>> The only piece where I'm unsure is how this will interact with CRIU. >> >> To C/R applications that use /dev/vmgenid CRIU need to be aware of it. >> Checkpointing and restoring withing the same "VM generation" shouldn't be >> a problem, but IMHO, making restore work after genid bump could be >> challenging. >> >> Alex, what scenario involving CRIU did you have in mind? > > You can in theory run into the same situation with containers that this > patch is solving for virtual machines. You could for example do a > snapshot of a prewarmed Java runtime with CRIU to get full JIT speeds > starting from the first request. > > That however means you run into the problem of predictable randomness > again. > >> >>> Can containers emulate ioctls and device nodes? >> >> Containers do not emulate ioctls but they can have /dev/vmgenid inside >> the container, so applications can use it the same way as outside the >> container. > > Hm. I suppose we could add a CAP_ADMIN ioctl interface to /dev/vmgenid > (when container people get to the point of needing it) that sets the > generation to "at least X". That way on restore, you could just call > that with "generation at snapshot"+1. > > That also means we need to have this interface available without virtual > machines then though, right? Sounds like a good idea. I guess, genvmid can be global on host, rather than per-userns or per-process for simplicity. Later if somebody will have a bottleneck on restore when every process on the machine wakes up from read() it could be virtualized, but doing it now sounds too early. ioctl() probably should go under checkpoint_restore_ns_capable(current_user_ns()), rather than CAP_SYS_ADMIN (I believe it should be safe from DOS as only CRIU should run with this capability, but worth to document this). Thanks, Dmitry
[PATCH 24/26] MAINTAINERS: Add entry for MIPS Loongson TCG
Add an entry for the TCG core related to Loongson. Signed-off-by: Philippe Mathieu-Daudé --- Adding Huacai and Jiaxun in case they want to be notified of changes, patch conditional to their individual approval. --- MAINTAINERS | 7 +++ 1 file changed, 7 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index ce7fe949036..be42b56300f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -240,6 +240,13 @@ F: include/hw/timer/mips_gictimer.h F: tests/tcg/mips/ K: ^Subject:.*(?i)mips +MIPS TCG CPUs (Loongson) +M: Philippe Mathieu-Daudé +R: Huacai Chen +R: Jiaxun Yang +S: Odd Fixes +F: target/mips/vendor-loong* + MIPS TCG CPUs (nanoMIPS ISA) S: Orphan F: disas/nanomips.* -- 2.26.2
[PATCH 22/26] target/mips: Extract Toshiba TXx9 translation routines
Extract 300 lines of the Toshiba TX19/TX39/TX49/TX79 translation routines to 'vendor-tx_translate.c.inc'. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 302 +--- target/mips/vendor-tx_translate.c.inc | 315 ++ 2 files changed, 316 insertions(+), 301 deletions(-) create mode 100644 target/mips/vendor-tx_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index 6b35498dd3d..a1cf1fe7f23 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -730,31 +730,6 @@ enum { * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit * or sixteen 8-bit paths. * - * Reference: - * - * The Toshiba TX System RISC TX79 Core Architecture manual, - * https://wiki.qemu.org/File:C790.pdf - * - * Three-Operand Multiply and Multiply-Add (4 instructions) - * - * MADD[rd,] rs, rt Multiply/Add - * MADDU [rd,] rs, rt Multiply/Add Unsigned - * MULT[rd,] rs, rt Multiply (3-operand) - * MULTU [rd,] rs, rt Multiply Unsigned (3-operand) - * - * Multiply Instructions for Pipeline 1 (10 instructions) - * -- - * MULT1 [rd,] rs, rt Multiply Pipeline 1 - * MULTU1 [rd,] rs, rt Multiply Unsigned Pipeline 1 - * DIV1rs, rtDivide Pipeline 1 - * DIVU1 rs, rtDivide Unsigned Pipeline 1 - * MADD1 [rd,] rs, rt Multiply-Add Pipeline 1 - * MADDU1 [rd,] rs, rt Multiply-Add Unsigned Pipeline 1 - * MFHI1 rdMove From HI1 Register - * MFLO1 rdMove From LO1 Register - * MTHI1 rsMove To HI1 Register - * MTLO1 rsMove To LO1 Register - * * Arithmetic (19 instructions) * * PADDB rd, rs, rtParallel Add Byte @@ -3046,44 +3021,6 @@ static void gen_shift(DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); } -#if defined(TARGET_MIPS64) -/* Copy GPR to and from TX79 HI1/LO1 register. */ -static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg) -{ -if (reg == 0 && (opc == OPC_MFHI1 || opc == OPC_MFLO1)) { -/* Treat as NOP. */ -return; -} - -switch (opc) { -case OPC_MFHI1: -tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]); -break; -case OPC_MFLO1: -tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]); -break; -case OPC_MTHI1: -if (reg != 0) { -tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]); -} else { -tcg_gen_movi_tl(cpu_HI[1], 0); -} -break; -case OPC_MTLO1: -if (reg != 0) { -tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]); -} else { -tcg_gen_movi_tl(cpu_LO[1], 0); -} -break; -default: -MIPS_INVAL("mfthilo1 TX79"); -generate_exception_end(ctx, EXCP_RI); -break; -} -} -#endif - /* Arithmetic on HI/LO registers */ static void gen_HILO(DisasContext *ctx, uint32_t opc, int acc, int reg) { @@ -3432,65 +3369,6 @@ static void gen_r6_muldiv(DisasContext *ctx, int opc, int rd, int rs, int rt) tcg_temp_free(t1); } -#if defined(TARGET_MIPS64) -static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt) -{ -TCGv t0, t1; - -t0 = tcg_temp_new(); -t1 = tcg_temp_new(); - -gen_load_gpr(t0, rs); -gen_load_gpr(t1, rt); - -switch (opc) { -case OPC_DIV1: -{ -TCGv t2 = tcg_temp_new(); -TCGv t3 = tcg_temp_new(); -tcg_gen_ext32s_tl(t0, t0); -tcg_gen_ext32s_tl(t1, t1); -tcg_gen_setcondi_tl(TCG_COND_EQ, t2, t0, INT_MIN); -tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, -1); -tcg_gen_and_tl(t2, t2, t3); -tcg_gen_setcondi_tl(TCG_COND_EQ, t3, t1, 0); -tcg_gen_or_tl(t2, t2, t3); -tcg_gen_movi_tl(t3, 0); -tcg_gen_movcond_tl(TCG_COND_NE, t1, t2, t3, t2, t1); -tcg_gen_div_tl(cpu_LO[1], t0, t1); -tcg_gen_rem_tl(cpu_HI[1], t0, t1); -tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]); -tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]); -tcg_temp_free(t3); -tcg_temp_free(t2); -} -break; -case OPC_DIVU1: -{ -TCGv t2 = tcg_const_tl(0); -TCGv t3 = tcg_const_tl(1); -tcg_gen_ext32u_tl(t0, t0); -tcg_gen_ext32u_tl(t1, t1); -tcg_gen_movcond_tl(TCG_COND_EQ, t1, t1, t2, t3, t1); -tcg_gen_divu_tl(cpu_LO[1], t0, t1); -tcg_gen_remu_tl(cpu_HI[1], t0, t1); -tcg_gen_ext32s_tl(cpu_LO[1], cpu_LO[1]); -tcg_gen_ext32s_tl(cpu_HI[1], cpu_HI[1]); -tcg_temp_free(t3); -tcg_temp_free(t2); -} -break; -default: -MIPS_INVAL("div1 TX79"); -
[PATCH 21/26] target/mips: Make pipeline 1 multiply opcodes generic
Special2 multiply opcodes are not specific to Toshiba TX79, and are not part of its multimedia extension. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 75 + 1 file changed, 38 insertions(+), 37 deletions(-) diff --git a/target/mips/translate.c b/target/mips/translate.c index 0914b89eae6..6b35498dd3d 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -330,6 +330,19 @@ enum { OPC_MUL = 0x02 | OPC_SPECIAL2, OPC_MSUB = 0x04 | OPC_SPECIAL2, OPC_MSUBU= 0x05 | OPC_SPECIAL2, + +/* Multiply Instructions for Pipeline 1 */ +OPC_MFHI1= 0x10 | OPC_SPECIAL2, +OPC_MTHI1= 0x11 | OPC_SPECIAL2, +OPC_MFLO1= 0x12 | OPC_SPECIAL2, +OPC_MTLO1= 0x13 | OPC_SPECIAL2, +OPC_MULT1= 0x18 | OPC_SPECIAL2, +OPC_MULTU1 = 0x19 | OPC_SPECIAL2, +OPC_DIV1 = 0x1A | OPC_SPECIAL2, +OPC_DIVU1= 0x1B | OPC_SPECIAL2, +OPC_MADD1= 0x20 | OPC_SPECIAL2, +OPC_MADDU1 = 0x21 | OPC_SPECIAL2, + /* Misc */ OPC_CLZ = 0x20 | OPC_SPECIAL2, OPC_CLO = 0x21 | OPC_SPECIAL2, @@ -933,21 +946,9 @@ enum { #define MASK_MMI(op) (MASK_OP_MAJOR(op) | ((op) & 0x3F)) enum { -MMI_OPC_MADD = 0x00 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADD */ -MMI_OPC_MADDU = 0x01 | MMI_OPC_CLASS_MMI, /* Same as OPC_MADDU */ MMI_OPC_PLZCW = 0x04 | MMI_OPC_CLASS_MMI, MMI_OPC_CLASS_MMI0 = 0x08 | MMI_OPC_CLASS_MMI, MMI_OPC_CLASS_MMI2 = 0x09 | MMI_OPC_CLASS_MMI, -MMI_OPC_MFHI1 = 0x10 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFHI */ -MMI_OPC_MTHI1 = 0x11 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTHI */ -MMI_OPC_MFLO1 = 0x12 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MFLO */ -MMI_OPC_MTLO1 = 0x13 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MTLO */ -MMI_OPC_MULT1 = 0x18 | MMI_OPC_CLASS_MMI, /* Same minor as OPC_MULT */ -MMI_OPC_MULTU1 = 0x19 | MMI_OPC_CLASS_MMI, /* Same min. as OPC_MULTU */ -MMI_OPC_DIV1 = 0x1A | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIV */ -MMI_OPC_DIVU1 = 0x1B | MMI_OPC_CLASS_MMI, /* Same minor as OPC_DIVU */ -MMI_OPC_MADD1 = 0x20 | MMI_OPC_CLASS_MMI, -MMI_OPC_MADDU1 = 0x21 | MMI_OPC_CLASS_MMI, MMI_OPC_CLASS_MMI1 = 0x28 | MMI_OPC_CLASS_MMI, MMI_OPC_CLASS_MMI3 = 0x29 | MMI_OPC_CLASS_MMI, MMI_OPC_PMFHL = 0x30 | MMI_OPC_CLASS_MMI, @@ -3049,26 +3050,26 @@ static void gen_shift(DisasContext *ctx, uint32_t opc, /* Copy GPR to and from TX79 HI1/LO1 register. */ static void gen_HILO1_tx79(DisasContext *ctx, uint32_t opc, int reg) { -if (reg == 0 && (opc == MMI_OPC_MFHI1 || opc == MMI_OPC_MFLO1)) { +if (reg == 0 && (opc == OPC_MFHI1 || opc == OPC_MFLO1)) { /* Treat as NOP. */ return; } switch (opc) { -case MMI_OPC_MFHI1: +case OPC_MFHI1: tcg_gen_mov_tl(cpu_gpr[reg], cpu_HI[1]); break; -case MMI_OPC_MFLO1: +case OPC_MFLO1: tcg_gen_mov_tl(cpu_gpr[reg], cpu_LO[1]); break; -case MMI_OPC_MTHI1: +case OPC_MTHI1: if (reg != 0) { tcg_gen_mov_tl(cpu_HI[1], cpu_gpr[reg]); } else { tcg_gen_movi_tl(cpu_HI[1], 0); } break; -case MMI_OPC_MTLO1: +case OPC_MTLO1: if (reg != 0) { tcg_gen_mov_tl(cpu_LO[1], cpu_gpr[reg]); } else { @@ -3443,7 +3444,7 @@ static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt) gen_load_gpr(t1, rt); switch (opc) { -case MMI_OPC_DIV1: +case OPC_DIV1: { TCGv t2 = tcg_temp_new(); TCGv t3 = tcg_temp_new(); @@ -3464,7 +3465,7 @@ static void gen_div1_tx79(DisasContext *ctx, uint32_t opc, int rs, int rt) tcg_temp_free(t2); } break; -case MMI_OPC_DIVU1: +case OPC_DIVU1: { TCGv t2 = tcg_const_tl(0); TCGv t3 = tcg_const_tl(1); @@ -3719,7 +3720,7 @@ static void gen_mul_txx9(DisasContext *ctx, uint32_t opc, gen_load_gpr(t1, rt); switch (opc) { -case MMI_OPC_MULT1: +case OPC_MULT1: acc = 1; /* Fall through */ case OPC_MULT: @@ -3738,7 +3739,7 @@ static void gen_mul_txx9(DisasContext *ctx, uint32_t opc, tcg_temp_free_i32(t3); } break; -case MMI_OPC_MULTU1: +case OPC_MULTU1: acc = 1; /* Fall through */ case OPC_MULTU: @@ -3757,10 +3758,10 @@ static void gen_mul_txx9(DisasContext *ctx, uint32_t opc, tcg_temp_free_i32(t3); } break; -case MMI_OPC_MADD1: +case OPC_MADD1: acc = 1; /* Fall through */ -case MMI_OPC_MADD: +case OPC_MADD: { TCGv_i64 t2 = tcg_temp_new_i64(); TCGv_i64 t3 = tcg_temp_new_i64(); @@ -3779,10 +3780,10 @@ static void gen_mul_txx9(DisasContext *ctx, uint32_t opc,
[PATCH 18/26] target/mips: Extract Loongson SIMD translation routines
LoongSIMD (formerly LoongMMI in Loongson 2E/F) is the 128-bit SIMD extension from the LoongISA. Extract 600 lines of translation routines to 'vendor-loong-simd_translate.c.inc'. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 598 + target/mips/vendor-loong-simd_translate.c.inc | 611 ++ 2 files changed, 612 insertions(+), 597 deletions(-) create mode 100644 target/mips/vendor-loong-simd_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index b01a16e9da4..105a104bb0c 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -330,19 +330,6 @@ enum { OPC_MUL = 0x02 | OPC_SPECIAL2, OPC_MSUB = 0x04 | OPC_SPECIAL2, OPC_MSUBU= 0x05 | OPC_SPECIAL2, -/* Loongson 2F */ -OPC_MULT_G_2F = 0x10 | OPC_SPECIAL2, -OPC_DMULT_G_2F = 0x11 | OPC_SPECIAL2, -OPC_MULTU_G_2F = 0x12 | OPC_SPECIAL2, -OPC_DMULTU_G_2F = 0x13 | OPC_SPECIAL2, -OPC_DIV_G_2F= 0x14 | OPC_SPECIAL2, -OPC_DDIV_G_2F = 0x15 | OPC_SPECIAL2, -OPC_DIVU_G_2F = 0x16 | OPC_SPECIAL2, -OPC_DDIVU_G_2F = 0x17 | OPC_SPECIAL2, -OPC_MOD_G_2F= 0x1c | OPC_SPECIAL2, -OPC_DMOD_G_2F = 0x1d | OPC_SPECIAL2, -OPC_MODU_G_2F = 0x1e | OPC_SPECIAL2, -OPC_DMODU_G_2F = 0x1f | OPC_SPECIAL2, /* Misc */ OPC_CLZ = 0x20 | OPC_SPECIAL2, OPC_CLO = 0x21 | OPC_SPECIAL2, @@ -4569,590 +4556,6 @@ static void gen_cl(DisasContext *ctx, uint32_t opc, } } -/* Godson integer instructions */ -static void gen_loongson_integer(DisasContext *ctx, uint32_t opc, - int rd, int rs, int rt) -{ -TCGv t0, t1; - -if (rd == 0) { -/* Treat as NOP. */ -return; -} - -switch (opc) { -case OPC_MULT_G_2E: -case OPC_MULT_G_2F: -case OPC_MULTU_G_2E: -case OPC_MULTU_G_2F: -#if defined(TARGET_MIPS64) -case OPC_DMULT_G_2E: -case OPC_DMULT_G_2F: -case OPC_DMULTU_G_2E: -case OPC_DMULTU_G_2F: -#endif -t0 = tcg_temp_new(); -t1 = tcg_temp_new(); -break; -default: -t0 = tcg_temp_local_new(); -t1 = tcg_temp_local_new(); -break; -} - -gen_load_gpr(t0, rs); -gen_load_gpr(t1, rt); - -switch (opc) { -case OPC_MULT_G_2E: -case OPC_MULT_G_2F: -tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); -tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -break; -case OPC_MULTU_G_2E: -case OPC_MULTU_G_2F: -tcg_gen_ext32u_tl(t0, t0); -tcg_gen_ext32u_tl(t1, t1); -tcg_gen_mul_tl(cpu_gpr[rd], t0, t1); -tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -break; -case OPC_DIV_G_2E: -case OPC_DIV_G_2F: -{ -TCGLabel *l1 = gen_new_label(); -TCGLabel *l2 = gen_new_label(); -TCGLabel *l3 = gen_new_label(); -tcg_gen_ext32s_tl(t0, t0); -tcg_gen_ext32s_tl(t1, t1); -tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); -tcg_gen_movi_tl(cpu_gpr[rd], 0); -tcg_gen_br(l3); -gen_set_label(l1); -tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2); -tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2); -tcg_gen_mov_tl(cpu_gpr[rd], t0); -tcg_gen_br(l3); -gen_set_label(l2); -tcg_gen_div_tl(cpu_gpr[rd], t0, t1); -tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -gen_set_label(l3); -} -break; -case OPC_DIVU_G_2E: -case OPC_DIVU_G_2F: -{ -TCGLabel *l1 = gen_new_label(); -TCGLabel *l2 = gen_new_label(); -tcg_gen_ext32u_tl(t0, t0); -tcg_gen_ext32u_tl(t1, t1); -tcg_gen_brcondi_tl(TCG_COND_NE, t1, 0, l1); -tcg_gen_movi_tl(cpu_gpr[rd], 0); -tcg_gen_br(l2); -gen_set_label(l1); -tcg_gen_divu_tl(cpu_gpr[rd], t0, t1); -tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -gen_set_label(l2); -} -break; -case OPC_MOD_G_2E: -case OPC_MOD_G_2F: -{ -TCGLabel *l1 = gen_new_label(); -TCGLabel *l2 = gen_new_label(); -TCGLabel *l3 = gen_new_label(); -tcg_gen_ext32u_tl(t0, t0); -tcg_gen_ext32u_tl(t1, t1); -tcg_gen_brcondi_tl(TCG_COND_EQ, t1, 0, l1); -tcg_gen_brcondi_tl(TCG_COND_NE, t0, INT_MIN, l2); -tcg_gen_brcondi_tl(TCG_COND_NE, t1, -1, l2); -gen_set_label(l1); -tcg_gen_movi_tl(cpu_gpr[rd], 0); -tcg_gen_br(l3); -gen_set_label(l2); -tcg_gen_rem_tl(cpu_gpr[rd], t0, t1); -tcg_gen_ext32s_tl(cpu_gpr[rd], cpu_gpr[rd]); -gen_set_label(l3); -} -break; -case OPC_MODU_G_2E: -case OPC_MODU_G_2F: -{ -TCGLabel *l1 = gen_new_label(); -
[PATCH 10/26] target/mips: Extract the microMIPS ISA helper definitions
Extract the microMIPS ISA helper definitions to 'isa-micromips_helper.h.inc'. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/helper.h | 10 ++ target/mips/isa-micromips_helper.h.inc | 17 + 2 files changed, 19 insertions(+), 8 deletions(-) create mode 100644 target/mips/isa-micromips_helper.h.inc diff --git a/target/mips/helper.h b/target/mips/helper.h index c15caed9fca..ee93c2de836 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -181,14 +181,6 @@ DEF_HELPER_2(dmtc0_entrylo1, void, env, i64) #endif /* !CONFIG_USER_ONLY */ -/* microMIPS functions */ -DEF_HELPER_4(lwm, void, env, tl, tl, i32) -DEF_HELPER_4(swm, void, env, tl, tl, i32) -#ifdef TARGET_MIPS64 -DEF_HELPER_4(ldm, void, env, tl, tl, i32) -DEF_HELPER_4(sdm, void, env, tl, tl, i32) -#endif - /* CP1 functions */ DEF_HELPER_2(cfc1, tl, env, i32) DEF_HELPER_4(ctc1, void, env, tl, i32, i32) @@ -427,6 +419,8 @@ DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_3(cache, void, env, tl, i32) +#include "isa-micromips_helper.h.inc" + #include "mod-mips-dsp_helper.h.inc" #include "mod-mips-msa_helper.h.inc" #include "mod-mips-mt_helper.h.inc" diff --git a/target/mips/isa-micromips_helper.h.inc b/target/mips/isa-micromips_helper.h.inc new file mode 100644 index 000..66a764c4aac --- /dev/null +++ b/target/mips/isa-micromips_helper.h.inc @@ -0,0 +1,17 @@ +/* + * microMIPS instruction emulation helpers for QEMU. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +DEF_HELPER_4(lwm, void, env, tl, tl, i32) +DEF_HELPER_4(swm, void, env, tl, tl, i32) +#ifdef TARGET_MIPS64 +DEF_HELPER_4(ldm, void, env, tl, tl, i32) +DEF_HELPER_4(sdm, void, env, tl, tl, i32) +#endif -- 2.26.2
[PATCH 25/26] MAINTAINERS: Add entry for MIPS Ingenic Xburst TCG
Add an entry for the TCG core related to Ingenic Xburst. Signed-off-by: Philippe Mathieu-Daudé --- Adding Craig Janeczek in case he wants to be notified of changes, patch conditional to his approval. --- MAINTAINERS | 6 ++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index be42b56300f..b6d98b95c47 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -247,6 +247,12 @@ R: Jiaxun Yang S: Odd Fixes F: target/mips/vendor-loong* +MIPS TCG CPUs (Ingenic Xburst) +M: Philippe Mathieu-Daudé +R: Craig Janeczek +S: Odd Fixes +F: target/mips/vendor-xburst* + MIPS TCG CPUs (nanoMIPS ISA) S: Orphan F: disas/nanomips.* -- 2.26.2
[PATCH 26/26] MAINTAINERS: Add entry for MIPS Toshiba TCG
Add an entry for the TCG core related to Toshiba TXx9. Signed-off-by: Philippe Mathieu-Daudé --- Adding Fredrik Noring in case he wants to be notified of changes, patch conditional to his approval. --- MAINTAINERS | 6 ++ 1 file changed, 6 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index b6d98b95c47..d97f0f1d66e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -253,6 +253,12 @@ R: Craig Janeczek S: Odd Fixes F: target/mips/vendor-xburst* +MIPS TCG CPUs (Toshiba TX) +M: Philippe Mathieu-Daudé +R: Fredrik Noring +S: Odd Fixes +F: target/mips/vendor-tx* + MIPS TCG CPUs (nanoMIPS ISA) S: Orphan F: disas/nanomips.* -- 2.26.2
[PATCH 23/26] target/mips: Extract Toshiba TX79 multimedia translation routines
Extract 600 lines of the the Toshiba TX79 multimedia translation routines to 'vendor-tx-mmi_translate.c.inc'. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 567 - target/mips/vendor-tx-mmi_translate.c.inc | 573 ++ target/mips/vendor-tx_translate.c.inc | 2 + 3 files changed, 575 insertions(+), 567 deletions(-) create mode 100644 target/mips/vendor-tx-mmi_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index a1cf1fe7f23..57e82079c50 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -719,405 +719,6 @@ enum { OPC_NMSUB_PS= 0x3E | OPC_CP3, }; - -/* - * Overview of the TX79-specific instruction set - * = - * - * The R5900 and the C790 have 128-bit wide GPRs, where the upper 64 bits - * are only used by the specific quadword (128-bit) LQ/SQ load/store - * instructions and certain multimedia instructions (MMIs). These MMIs - * configure the 128-bit data path as two 64-bit, four 32-bit, eight 16-bit - * or sixteen 8-bit paths. - * - * Arithmetic (19 instructions) - * - * PADDB rd, rs, rtParallel Add Byte - * PSUBB rd, rs, rtParallel Subtract Byte - * PADDH rd, rs, rtParallel Add Halfword - * PSUBH rd, rs, rtParallel Subtract Halfword - * PADDW rd, rs, rtParallel Add Word - * PSUBW rd, rs, rtParallel Subtract Word - * PADSBH rd, rs, rtParallel Add/Subtract Halfword - * PADDSB rd, rs, rtParallel Add with Signed Saturation Byte - * PSUBSB rd, rs, rtParallel Subtract with Signed Saturation Byte - * PADDSH rd, rs, rtParallel Add with Signed Saturation Halfword - * PSUBSH rd, rs, rtParallel Subtract with Signed Saturation Halfword - * PADDSW rd, rs, rtParallel Add with Signed Saturation Word - * PSUBSW rd, rs, rtParallel Subtract with Signed Saturation Word - * PADDUB rd, rs, rtParallel Add with Unsigned saturation Byte - * PSUBUB rd, rs, rtParallel Subtract with Unsigned saturation Byte - * PADDUH rd, rs, rtParallel Add with Unsigned saturation Halfword - * PSUBUH rd, rs, rtParallel Subtract with Unsigned saturation Halfword - * PADDUW rd, rs, rtParallel Add with Unsigned saturation Word - * PSUBUW rd, rs, rtParallel Subtract with Unsigned saturation Word - * - * Min/Max (4 instructions) - * - * PMAXH rd, rs, rtParallel Maximum Halfword - * PMINH rd, rs, rtParallel Minimum Halfword - * PMAXW rd, rs, rtParallel Maximum Word - * PMINW rd, rs, rtParallel Minimum Word - * - * Absolute (2 instructions) - * - - * PABSH rd, rtParallel Absolute Halfword - * PABSW rd, rtParallel Absolute Word - * - * Logical (4 instructions) - * - * PANDrd, rs, rtParallel AND - * POR rd, rs, rtParallel OR - * PXORrd, rs, rtParallel XOR - * PNORrd, rs, rtParallel NOR - * - * Shift (9 instructions) - * -- - * PSLLH rd, rt, saParallel Shift Left Logical Halfword - * PSRLH rd, rt, saParallel Shift Right Logical Halfword - * PSRAH rd, rt, saParallel Shift Right Arithmetic Halfword - * PSLLW rd, rt, saParallel Shift Left Logical Word - * PSRLW rd, rt, saParallel Shift Right Logical Word - * PSRAW rd, rt, saParallel Shift Right Arithmetic Word - * PSLLVW rd, rt, rsParallel Shift Left Logical Variable Word - * PSRLVW rd, rt, rsParallel Shift Right Logical Variable Word - * PSRAVW rd, rt, rsParallel Shift Right Arithmetic Variable Word - * - * Compare (6 instructions) - * - * PCGTB rd, rs, rtParallel Compare for Greater Than Byte - * PCEQB rd, rs, rtParallel Compare for Equal Byte - * PCGTH rd, rs, rtParallel Compare for Greater Than Halfword - * PCEQH rd, rs, rtParallel Compare for Equal Halfword - * PCGTW rd, rs, rtParallel Compare for Greater Than Word - * PCEQW rd, rs, rtParallel Compare for Equal Word - * - * LZC (1 instruction) - * --- - * PLZCW rd, rsParallel Leading Zero or One Count Word - * - * Quadword Load and Store (2 instructions) - * - * LQ rt, offset(base) Load Quadword - * SQ rt, offset(base) Store Quadword - * - * Multiply and Divide (19 instructions) - * - - * PMULTW rd, rs, rtParallel Multiply Word - * PMULTUW rd, rs, rtParallel Multiply Unsigned Word - * PDIVW rs, rtParallel Divide Word - * PDIVUW rs, rtParallel Divide
[PATCH 16/26] target/mips: Rename lmmi_helper.c as loong-simd_helper.c
The LoongMMI extension has been renamed LoongSIMD (part of the LoongISA). Rename the helper file accordingly. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/{lmmi_helper.c => vendor-loong-simd_helper.c} | 0 target/mips/meson.build | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename target/mips/{lmmi_helper.c => vendor-loong-simd_helper.c} (100%) diff --git a/target/mips/lmmi_helper.c b/target/mips/vendor-loong-simd_helper.c similarity index 100% rename from target/mips/lmmi_helper.c rename to target/mips/vendor-loong-simd_helper.c diff --git a/target/mips/meson.build b/target/mips/meson.build index b63ef41cb1d..e8f0c080099 100644 --- a/target/mips/meson.build +++ b/target/mips/meson.build @@ -4,10 +4,10 @@ 'fpu_helper.c', 'gdbstub.c', 'helper.c', - 'lmmi_helper.c', 'op_helper.c', 'mod-mips-dsp_helper.c', 'mod-mips-msa_helper.c', + 'vendor-loong-simd_helper.c', 'vendor-vr54xx_helper.c', 'translate.c', -- 2.26.2
[PATCH 06/26] target/mips: Extract DSP helper definitions
'MIPS DSP' is defined as a Module by MIPS. Extract the helper definitions to 'mod-mips-dsp_helper.h.inc'. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/helper.h | 335 + target/mips/mod-mips-dsp_helper.h.inc | 344 ++ 2 files changed, 345 insertions(+), 334 deletions(-) create mode 100644 target/mips/mod-mips-dsp_helper.h.inc diff --git a/target/mips/helper.h b/target/mips/helper.h index a44f42c6201..bce869f3718 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -447,341 +447,8 @@ DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_1(biadd, TCG_CALL_NO_RWG_SE, i64, i64) DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64) -/*** MIPS DSP ***/ -/* DSP Arithmetic Sub-class insns */ -DEF_HELPER_FLAGS_3(addq_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addq_s_ph, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(addq_qh, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addq_s_qh, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(addq_s_w, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(addq_pw, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addq_s_pw, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(addu_qb, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addu_s_qb, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(adduh_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(adduh_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(addu_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addu_s_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(addqh_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(addqh_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(addqh_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(addqh_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(addu_ob, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addu_s_ob, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(adduh_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(adduh_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(addu_qh, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addu_s_qh, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(subq_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subq_s_ph, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(subq_qh, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subq_s_qh, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(subq_s_w, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(subq_pw, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subq_s_pw, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(subu_qb, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subu_s_qb, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(subuh_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(subuh_r_qb, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(subu_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subu_s_ph, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(subqh_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(subqh_r_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(subqh_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(subqh_r_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_3(subu_ob, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subu_s_ob, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(subuh_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(subuh_r_ob, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(subu_qh, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(subu_s_qh, 0, tl, tl, tl, env) -#endif -DEF_HELPER_FLAGS_3(addsc, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_3(addwc, 0, tl, tl, tl, env) -DEF_HELPER_FLAGS_2(modsub, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_1(raddu_w_qb, TCG_CALL_NO_RWG_SE, tl, tl) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_1(raddu_l_ob, TCG_CALL_NO_RWG_SE, tl, tl) -#endif -DEF_HELPER_FLAGS_2(absq_s_qb, 0, tl, tl, env) -DEF_HELPER_FLAGS_2(absq_s_ph, 0, tl, tl, env) -DEF_HELPER_FLAGS_2(absq_s_w, 0, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_2(absq_s_ob, 0, tl, tl, env) -DEF_HELPER_FLAGS_2(absq_s_qh, 0, tl, tl, env) -DEF_HELPER_FLAGS_2(absq_s_pw, 0, tl, tl, env) -#endif -DEF_HELPER_FLAGS_2(precr_qb_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(precrq_qb_ph, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(precr_sra_ph_w, TCG_CALL_NO_RWG_SE, - tl, i32, tl, tl) -DEF_HELPER_FLAGS_3(precr_sra_r_ph_w, TCG_CALL_NO_RWG_SE, - tl, i32, tl, tl) -DEF_HELPER_FLAGS_2(precrq_ph_w, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(precrq_rs_ph_w, 0, tl, tl, tl, env) -#if defined(TARGET_MIPS64) -DEF_HELPER_FLAGS_2(precr_ob_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_3(precr_sra_qh_pw, - TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) -DEF_HELPER_FLAGS_3(precr_sra_r_qh_pw, - TCG_CALL_NO_RWG_SE, tl, tl, tl, i32) -DEF_HELPER_FLAGS_2(precrq_ob_qh, TCG_CALL_NO_RWG_SE, tl, tl, tl) -DEF_HELPER_FLAGS_2(precrq_qh_pw,
[PATCH 15/26] target/mips: Extract NEC Vr54xx translation routines
Extract the NEC Vr54xx translation routines to 'vendor-vr54xx_translate.c.inc'. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 86 + target/mips/vendor-vr54xx_translate.c.inc | 93 +++ 2 files changed, 95 insertions(+), 84 deletions(-) create mode 100644 target/mips/vendor-vr54xx_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index 095ee31ab5f..b01a16e9da4 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -295,26 +295,6 @@ enum { OPC_DLSA = 0x15 | OPC_SPECIAL, }; -/* Multiplication variants of the vr54xx. */ -#define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6))) - -enum { -OPC_VR54XX_MULS= (0x03 << 6) | OPC_MULT, -OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU, -OPC_VR54XX_MACC= (0x05 << 6) | OPC_MULT, -OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU, -OPC_VR54XX_MSAC= (0x07 << 6) | OPC_MULT, -OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU, -OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT, -OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU, -OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT, -OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU, -OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT, -OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU, -OPC_VR54XX_MSACHI = (0x0F << 6) | OPC_MULT, -OPC_VR54XX_MSACHIU = (0x0F << 6) | OPC_MULTU, -}; - /* REGIMM (rt field) opcodes */ #define MASK_REGIMM(op) (MASK_OP_MAJOR(op) | (op & (0x1F << 16))) @@ -4546,70 +4526,6 @@ static void gen_mul_txx9(DisasContext *ctx, uint32_t opc, tcg_temp_free(t1); } -static void gen_mul_vr54xx(DisasContext *ctx, uint32_t opc, - int rd, int rs, int rt) -{ -TCGv t0 = tcg_temp_new(); -TCGv t1 = tcg_temp_new(); - -gen_load_gpr(t0, rs); -gen_load_gpr(t1, rt); - -switch (opc) { -case OPC_VR54XX_MULS: -gen_helper_muls(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MULSU: -gen_helper_mulsu(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MACC: -gen_helper_macc(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MACCU: -gen_helper_maccu(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MSAC: -gen_helper_msac(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MSACU: -gen_helper_msacu(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MULHI: -gen_helper_mulhi(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MULHIU: -gen_helper_mulhiu(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MULSHI: -gen_helper_mulshi(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MULSHIU: -gen_helper_mulshiu(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MACCHI: -gen_helper_macchi(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MACCHIU: -gen_helper_macchiu(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MSACHI: -gen_helper_msachi(t0, cpu_env, t0, t1); -break; -case OPC_VR54XX_MSACHIU: -gen_helper_msachiu(t0, cpu_env, t0, t1); -break; -default: -MIPS_INVAL("mul vr54xx"); -generate_exception_end(ctx, EXCP_RI); -goto out; -} -gen_store_gpr(t0, rd); - - out: -tcg_temp_free(t0); -tcg_temp_free(t1); -} - static void gen_cl(DisasContext *ctx, uint32_t opc, int rd, int rs) { @@ -13022,6 +12938,8 @@ out: #include "mod-mips-dsp_translate.c.inc" +#include "vendor-vr54xx_translate.c.inc" + static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx) { int rs, rt, rd, sa; diff --git a/target/mips/vendor-vr54xx_translate.c.inc b/target/mips/vendor-vr54xx_translate.c.inc new file mode 100644 index 000..8c952a98ebc --- /dev/null +++ b/target/mips/vendor-vr54xx_translate.c.inc @@ -0,0 +1,93 @@ +/* + * MIPS NEC Vr54xx translation routines. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +/* Multiplication variants of the vr54xx. */ +#define MASK_MUL_VR54XX(op) (MASK_SPECIAL(op) | (op & (0x1F << 6))) + +enum { +OPC_VR54XX_MULS= (0x03 << 6) | OPC_MULT, +OPC_VR54XX_MULSU = (0x03 << 6) | OPC_MULTU, +OPC_VR54XX_MACC= (0x05 << 6) | OPC_MULT, +OPC_VR54XX_MACCU = (0x05 << 6) | OPC_MULTU, +OPC_VR54XX_MSAC= (0x07 << 6) | OPC_MULT, +OPC_VR54XX_MSACU = (0x07 << 6) | OPC_MULTU, +OPC_VR54XX_MULHI = (0x09 << 6) | OPC_MULT, +OPC_VR54XX_MULHIU = (0x09 << 6) | OPC_MULTU, +OPC_VR54XX_MULSHI = (0x0B << 6) | OPC_MULT, +OPC_VR54XX_MULSHIU = (0x0B << 6) | OPC_MULTU, +OPC_VR54XX_MACCHI = (0x0D << 6) | OPC_MULT, +OPC_VR54XX_MACCHIU = (0x0D << 6) | OPC_MULTU,
[PATCH 05/26] target/mips: Rename dsp_helper.c as mod-mips-dsp_helper.c
'MIPS DSP' is defined as a Module by MIPS, rename it as mod-mips-dsp_helper.c. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/{dsp_helper.c => mod-mips-dsp_helper.c} | 0 target/mips/meson.build | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename target/mips/{dsp_helper.c => mod-mips-dsp_helper.c} (100%) diff --git a/target/mips/dsp_helper.c b/target/mips/mod-mips-dsp_helper.c similarity index 100% rename from target/mips/dsp_helper.c rename to target/mips/mod-mips-dsp_helper.c diff --git a/target/mips/meson.build b/target/mips/meson.build index f2b1b599abc..cc4677d94dc 100644 --- a/target/mips/meson.build +++ b/target/mips/meson.build @@ -1,12 +1,12 @@ mips_ss = ss.source_set() mips_ss.add(files( 'cpu.c', - 'dsp_helper.c', 'fpu_helper.c', 'gdbstub.c', 'helper.c', 'lmmi_helper.c', 'op_helper.c', + 'mod-mips-dsp_helper.c', 'mod-mips-msa_helper.c', 'translate.c', -- 2.26.2
[PATCH 17/26] target/mips: Extract Loongson SIMD helper definitions
Extract the Loongson SIMD helper definitions to 'vendor-loong-simd_helper.h'. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/helper.h | 60 +-- target/mips/vendor-loong-simd_helper.h.inc | 69 ++ 2 files changed, 70 insertions(+), 59 deletions(-) create mode 100644 target/mips/vendor-loong-simd_helper.h.inc diff --git a/target/mips/helper.h b/target/mips/helper.h index 77d66018c8c..134dcaf0d59 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -343,65 +343,6 @@ DEF_HELPER_1(rdhwr_xnp, tl, env) DEF_HELPER_2(pmon, void, env, int) DEF_HELPER_1(wait, void, env) -/* Loongson multimedia functions. */ -DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddush, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddsb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddusb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(paddb, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(psubsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubush, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubsb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubusb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psubb, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(pshufh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(packsswh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(packsshb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(packushb, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(punpcklhw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpckhhw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpcklbh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpckhbh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpcklwd, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(punpckhwd, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(pavgh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pavgb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmaxsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pminsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmaxub, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pminub, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(pcmpeqw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpgtw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpeqh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpgth, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpeqb, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pcmpgtb, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(psllw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psllh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psrlw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psrlh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psraw, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(psrah, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(pmullh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmulhh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmulhuh, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_2(pmaddhw, TCG_CALL_NO_RWG_SE, i64, i64, i64) - -DEF_HELPER_FLAGS_2(pasubub, TCG_CALL_NO_RWG_SE, i64, i64, i64) -DEF_HELPER_FLAGS_1(biadd, TCG_CALL_NO_RWG_SE, i64, i64) -DEF_HELPER_FLAGS_1(pmovmskb, TCG_CALL_NO_RWG_SE, i64, i64) - DEF_HELPER_3(cache, void, env, tl, i32) #include "isa-micromips_helper.h.inc" @@ -411,3 +352,4 @@ DEF_HELPER_3(cache, void, env, tl, i32) #include "mod-mips-mt_helper.h.inc" #include "vendor-vr54xx_helper.h.inc" +#include "vendor-loong-simd_helper.h.inc" diff --git a/target/mips/vendor-loong-simd_helper.h.inc b/target/mips/vendor-loong-simd_helper.h.inc new file mode 100644 index 000..30e5fda66e9 --- /dev/null +++ b/target/mips/vendor-loong-simd_helper.h.inc @@ -0,0 +1,69 @@ +/* + * Loongson SIMD instruction emulation helpers for QEMU. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * Copyright (c) 2011 Richard Henderson + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +DEF_HELPER_FLAGS_2(paddsh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddush, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddh, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddw, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(paddsb, TCG_CALL_NO_RWG_SE,
[PATCH 19/26] target/mips: Extract Loongson EXTensions translation routines
LoongEXTs are general-purpose extensions from the LoongISA. Extract 440 lines of translation routines to 'vendor-loong-lext_translate.c.inc'. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 440 + target/mips/vendor-loong-lext_translate.c.inc | 450 ++ 2 files changed, 451 insertions(+), 439 deletions(-) create mode 100644 target/mips/vendor-loong-lext_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index 105a104bb0c..46306ab7e9c 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -399,48 +399,6 @@ enum { R6_OPC_SCD = 0x27 | OPC_SPECIAL3, }; -/* Loongson EXT load/store quad word opcodes */ -#define MASK_LOONGSON_GSLSQ(op) (MASK_OP_MAJOR(op) | (op & 0x8020)) -enum { -OPC_GSLQ= 0x0020 | OPC_LWC2, -OPC_GSLQC1 = 0x8020 | OPC_LWC2, -OPC_GSSHFL = OPC_LWC2, -OPC_GSSQ= 0x0020 | OPC_SWC2, -OPC_GSSQC1 = 0x8020 | OPC_SWC2, -OPC_GSSHFS = OPC_SWC2, -}; - -/* Loongson EXT shifted load/store opcodes */ -#define MASK_LOONGSON_GSSHFLS(op) (MASK_OP_MAJOR(op) | (op & 0xc03f)) -enum { -OPC_GSLWLC1 = 0x4 | OPC_GSSHFL, -OPC_GSLWRC1 = 0x5 | OPC_GSSHFL, -OPC_GSLDLC1 = 0x6 | OPC_GSSHFL, -OPC_GSLDRC1 = 0x7 | OPC_GSSHFL, -OPC_GSSWLC1 = 0x4 | OPC_GSSHFS, -OPC_GSSWRC1 = 0x5 | OPC_GSSHFS, -OPC_GSSDLC1 = 0x6 | OPC_GSSHFS, -OPC_GSSDRC1 = 0x7 | OPC_GSSHFS, -}; - -/* Loongson EXT LDC2/SDC2 opcodes */ -#define MASK_LOONGSON_LSDC2(op) (MASK_OP_MAJOR(op) | (op & 0x7)) - -enum { -OPC_GSLBX = 0x0 | OPC_LDC2, -OPC_GSLHX = 0x1 | OPC_LDC2, -OPC_GSLWX = 0x2 | OPC_LDC2, -OPC_GSLDX = 0x3 | OPC_LDC2, -OPC_GSLWXC1= 0x6 | OPC_LDC2, -OPC_GSLDXC1= 0x7 | OPC_LDC2, -OPC_GSSBX = 0x0 | OPC_SDC2, -OPC_GSSHX = 0x1 | OPC_SDC2, -OPC_GSSWX = 0x2 | OPC_SDC2, -OPC_GSSDX = 0x3 | OPC_SDC2, -OPC_GSSWXC1= 0x6 | OPC_SDC2, -OPC_GSSDXC1= 0x7 | OPC_SDC2, -}; - /* BSHFL opcodes */ #define MASK_BSHFL(op) (MASK_SPECIAL3(op) | (op & (0x1F << 6))) @@ -4556,403 +4514,6 @@ static void gen_cl(DisasContext *ctx, uint32_t opc, } } -static void gen_loongson_lswc2(DisasContext *ctx, int rt, - int rs, int rd) -{ -TCGv t0, t1, t2; -TCGv_i32 fp0; -#if defined(TARGET_MIPS64) -int lsq_rt1 = ctx->opcode & 0x1f; -int lsq_offset = sextract32(ctx->opcode, 6, 9) << 4; -#endif -int shf_offset = sextract32(ctx->opcode, 6, 8); - -t0 = tcg_temp_new(); - -switch (MASK_LOONGSON_GSLSQ(ctx->opcode)) { -#if defined(TARGET_MIPS64) -case OPC_GSLQ: -t1 = tcg_temp_new(); -gen_base_offset_addr(ctx, t0, rs, lsq_offset); -tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); -gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); -tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); -gen_store_gpr(t1, rt); -gen_store_gpr(t0, lsq_rt1); -tcg_temp_free(t1); -break; -case OPC_GSLQC1: -check_cp1_enabled(ctx); -t1 = tcg_temp_new(); -gen_base_offset_addr(ctx, t0, rs, lsq_offset); -tcg_gen_qemu_ld_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); -gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); -tcg_gen_qemu_ld_tl(t0, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); -gen_store_fpr64(ctx, t1, rt); -gen_store_fpr64(ctx, t0, lsq_rt1); -tcg_temp_free(t1); -break; -case OPC_GSSQ: -t1 = tcg_temp_new(); -gen_base_offset_addr(ctx, t0, rs, lsq_offset); -gen_load_gpr(t1, rt); -tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); -gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); -gen_load_gpr(t1, lsq_rt1); -tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); -tcg_temp_free(t1); -break; -case OPC_GSSQC1: -check_cp1_enabled(ctx); -t1 = tcg_temp_new(); -gen_base_offset_addr(ctx, t0, rs, lsq_offset); -gen_load_fpr64(ctx, t1, rt); -tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); -gen_base_offset_addr(ctx, t0, rs, lsq_offset + 8); -gen_load_fpr64(ctx, t1, lsq_rt1); -tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEQ | - ctx->default_tcg_memop_mask); -tcg_temp_free(t1); -break; -#endif -case OPC_GSSHFL: -switch (MASK_LOONGSON_GSSHFLS(ctx->opcode)) { -
[PATCH 14/26] target/mips: Extract NEC Vr54xx helper definitions
Extract the NEC Vr54xx helper definitions to 'vendor-vr54xx_helper.h'. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/helper.h | 17 ++--- target/mips/vendor-vr54xx_helper.h.inc | 24 2 files changed, 26 insertions(+), 15 deletions(-) create mode 100644 target/mips/vendor-vr54xx_helper.h.inc diff --git a/target/mips/helper.h b/target/mips/helper.h index ee93c2de836..77d66018c8c 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -20,21 +20,6 @@ DEF_HELPER_3(lld, tl, env, tl, int) #endif #endif -DEF_HELPER_3(muls, tl, env, tl, tl) -DEF_HELPER_3(mulsu, tl, env, tl, tl) -DEF_HELPER_3(macc, tl, env, tl, tl) -DEF_HELPER_3(maccu, tl, env, tl, tl) -DEF_HELPER_3(msac, tl, env, tl, tl) -DEF_HELPER_3(msacu, tl, env, tl, tl) -DEF_HELPER_3(mulhi, tl, env, tl, tl) -DEF_HELPER_3(mulhiu, tl, env, tl, tl) -DEF_HELPER_3(mulshi, tl, env, tl, tl) -DEF_HELPER_3(mulshiu, tl, env, tl, tl) -DEF_HELPER_3(macchi, tl, env, tl, tl) -DEF_HELPER_3(macchiu, tl, env, tl, tl) -DEF_HELPER_3(msachi, tl, env, tl, tl) -DEF_HELPER_3(msachiu, tl, env, tl, tl) - DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl) #ifdef TARGET_MIPS64 DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl) @@ -424,3 +409,5 @@ DEF_HELPER_3(cache, void, env, tl, i32) #include "mod-mips-dsp_helper.h.inc" #include "mod-mips-msa_helper.h.inc" #include "mod-mips-mt_helper.h.inc" + +#include "vendor-vr54xx_helper.h.inc" diff --git a/target/mips/vendor-vr54xx_helper.h.inc b/target/mips/vendor-vr54xx_helper.h.inc new file mode 100644 index 000..50b1f5b818d --- /dev/null +++ b/target/mips/vendor-vr54xx_helper.h.inc @@ -0,0 +1,24 @@ +/* + * MIPS NEC Vr54xx instruction emulation helpers for QEMU. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +DEF_HELPER_3(muls, tl, env, tl, tl) +DEF_HELPER_3(mulsu, tl, env, tl, tl) +DEF_HELPER_3(macc, tl, env, tl, tl) +DEF_HELPER_3(maccu, tl, env, tl, tl) +DEF_HELPER_3(msac, tl, env, tl, tl) +DEF_HELPER_3(msacu, tl, env, tl, tl) +DEF_HELPER_3(mulhi, tl, env, tl, tl) +DEF_HELPER_3(mulhiu, tl, env, tl, tl) +DEF_HELPER_3(mulshi, tl, env, tl, tl) +DEF_HELPER_3(mulshiu, tl, env, tl, tl) +DEF_HELPER_3(macchi, tl, env, tl, tl) +DEF_HELPER_3(macchiu, tl, env, tl, tl) +DEF_HELPER_3(msachi, tl, env, tl, tl) +DEF_HELPER_3(msachiu, tl, env, tl, tl) -- 2.26.2
[PATCH 13/26] target/mips: Extract NEC Vr54xx helpers to vendor-vr54xx_helper.c
Extract NEC Vr54xx helpers from op_helper.c to a new file: 'vendor-vr54xx_helper.c'. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/op_helper.c| 118 -- target/mips/vendor-vr54xx_helper.c | 131 + target/mips/meson.build| 1 + 3 files changed, 132 insertions(+), 118 deletions(-) create mode 100644 target/mips/vendor-vr54xx_helper.c diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c index dd09a4c714a..a900c008b5a 100644 --- a/target/mips/op_helper.c +++ b/target/mips/op_helper.c @@ -54,124 +54,6 @@ static void raise_exception(CPUMIPSState *env, uint32_t exception) do_raise_exception(env, exception, 0); } -/* 64 bits arithmetic for 32 bits hosts */ -static inline uint64_t get_HILO(CPUMIPSState *env) -{ -return ((uint64_t)(env->active_tc.HI[0]) << 32) | - (uint32_t)env->active_tc.LO[0]; -} - -static inline target_ulong set_HIT0_LO(CPUMIPSState *env, uint64_t HILO) -{ -env->active_tc.LO[0] = (int32_t)(HILO & 0x); -return env->active_tc.HI[0] = (int32_t)(HILO >> 32); -} - -static inline target_ulong set_HI_LOT0(CPUMIPSState *env, uint64_t HILO) -{ -target_ulong tmp = env->active_tc.LO[0] = (int32_t)(HILO & 0x); -env->active_tc.HI[0] = (int32_t)(HILO >> 32); -return tmp; -} - -/* Multiplication variants of the vr54xx. */ -target_ulong helper_muls(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ -return set_HI_LOT0(env, 0 - ((int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2)); -} - -target_ulong helper_mulsu(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ -return set_HI_LOT0(env, 0 - (uint64_t)(uint32_t)arg1 * - (uint64_t)(uint32_t)arg2); -} - -target_ulong helper_macc(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ -return set_HI_LOT0(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); -} - -target_ulong helper_macchi(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ -return set_HIT0_LO(env, (int64_t)get_HILO(env) + (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); -} - -target_ulong helper_maccu(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ -return set_HI_LOT0(env, (uint64_t)get_HILO(env) + - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); -} - -target_ulong helper_macchiu(CPUMIPSState *env, target_ulong arg1, -target_ulong arg2) -{ -return set_HIT0_LO(env, (uint64_t)get_HILO(env) + - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); -} - -target_ulong helper_msac(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ -return set_HI_LOT0(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); -} - -target_ulong helper_msachi(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ -return set_HIT0_LO(env, (int64_t)get_HILO(env) - (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); -} - -target_ulong helper_msacu(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ -return set_HI_LOT0(env, (uint64_t)get_HILO(env) - - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); -} - -target_ulong helper_msachiu(CPUMIPSState *env, target_ulong arg1, -target_ulong arg2) -{ -return set_HIT0_LO(env, (uint64_t)get_HILO(env) - - (uint64_t)(uint32_t)arg1 * (uint64_t)(uint32_t)arg2); -} - -target_ulong helper_mulhi(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ -return set_HIT0_LO(env, (int64_t)(int32_t)arg1 * (int64_t)(int32_t)arg2); -} - -target_ulong helper_mulhiu(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ -return set_HIT0_LO(env, (uint64_t)(uint32_t)arg1 * - (uint64_t)(uint32_t)arg2); -} - -target_ulong helper_mulshi(CPUMIPSState *env, target_ulong arg1, - target_ulong arg2) -{ -return set_HIT0_LO(env, 0 - (int64_t)(int32_t)arg1 * - (int64_t)(int32_t)arg2); -} - -target_ulong helper_mulshiu(CPUMIPSState *env, target_ulong arg1, -target_ulong arg2) -{ -return set_HIT0_LO(env, 0 - (uint64_t)(uint32_t)arg1 * - (uint64_t)(uint32_t)arg2); -} - static inline target_ulong bitswap(target_ulong v) { v = ((v >> 1) & (target_ulong)0xULL) | diff --git a/target/mips/vendor-vr54xx_helper.c b/target/mips/vendor-vr54xx_helper.c new file mode 100644 index
[PATCH 04/26] target/mips: Extract MSA translation routines
Extract 2200 lines from the huge translate.c to a new file, 'mod-mips-msa_translate.c.inc'. As there are too many inter- dependencies we don't compile it as another object, but keep including it in the big translate.o. We gain in code maintainability. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 2209 + target/mips/mod-mips-msa_translate.c.inc | 2218 ++ 2 files changed, 2219 insertions(+), 2208 deletions(-) create mode 100644 target/mips/mod-mips-msa_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index 5ec9fd7e92a..0ad59731810 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -1211,239 +1211,6 @@ enum { OPC_NMSUB_PS= 0x3E | OPC_CP3, }; -/* MSA Opcodes */ -#define MASK_MSA_MINOR(op) (MASK_OP_MAJOR(op) | (op & 0x3F)) -enum { -OPC_MSA_I8_00 = 0x00 | OPC_MSA, -OPC_MSA_I8_01 = 0x01 | OPC_MSA, -OPC_MSA_I8_02 = 0x02 | OPC_MSA, -OPC_MSA_I5_06 = 0x06 | OPC_MSA, -OPC_MSA_I5_07 = 0x07 | OPC_MSA, -OPC_MSA_BIT_09 = 0x09 | OPC_MSA, -OPC_MSA_BIT_0A = 0x0A | OPC_MSA, -OPC_MSA_3R_0D = 0x0D | OPC_MSA, -OPC_MSA_3R_0E = 0x0E | OPC_MSA, -OPC_MSA_3R_0F = 0x0F | OPC_MSA, -OPC_MSA_3R_10 = 0x10 | OPC_MSA, -OPC_MSA_3R_11 = 0x11 | OPC_MSA, -OPC_MSA_3R_12 = 0x12 | OPC_MSA, -OPC_MSA_3R_13 = 0x13 | OPC_MSA, -OPC_MSA_3R_14 = 0x14 | OPC_MSA, -OPC_MSA_3R_15 = 0x15 | OPC_MSA, -OPC_MSA_ELM = 0x19 | OPC_MSA, -OPC_MSA_3RF_1A = 0x1A | OPC_MSA, -OPC_MSA_3RF_1B = 0x1B | OPC_MSA, -OPC_MSA_3RF_1C = 0x1C | OPC_MSA, -OPC_MSA_VEC = 0x1E | OPC_MSA, - -/* MI10 instruction */ -OPC_LD_B= (0x20) | OPC_MSA, -OPC_LD_H= (0x21) | OPC_MSA, -OPC_LD_W= (0x22) | OPC_MSA, -OPC_LD_D= (0x23) | OPC_MSA, -OPC_ST_B= (0x24) | OPC_MSA, -OPC_ST_H= (0x25) | OPC_MSA, -OPC_ST_W= (0x26) | OPC_MSA, -OPC_ST_D= (0x27) | OPC_MSA, -}; - -enum { -/* I5 instruction df(bits 22..21) = _b, _h, _w, _d */ -OPC_ADDVI_df= (0x0 << 23) | OPC_MSA_I5_06, -OPC_CEQI_df = (0x0 << 23) | OPC_MSA_I5_07, -OPC_SUBVI_df= (0x1 << 23) | OPC_MSA_I5_06, -OPC_MAXI_S_df = (0x2 << 23) | OPC_MSA_I5_06, -OPC_CLTI_S_df = (0x2 << 23) | OPC_MSA_I5_07, -OPC_MAXI_U_df = (0x3 << 23) | OPC_MSA_I5_06, -OPC_CLTI_U_df = (0x3 << 23) | OPC_MSA_I5_07, -OPC_MINI_S_df = (0x4 << 23) | OPC_MSA_I5_06, -OPC_CLEI_S_df = (0x4 << 23) | OPC_MSA_I5_07, -OPC_MINI_U_df = (0x5 << 23) | OPC_MSA_I5_06, -OPC_CLEI_U_df = (0x5 << 23) | OPC_MSA_I5_07, -OPC_LDI_df = (0x6 << 23) | OPC_MSA_I5_07, - -/* I8 instruction */ -OPC_ANDI_B = (0x0 << 24) | OPC_MSA_I8_00, -OPC_BMNZI_B = (0x0 << 24) | OPC_MSA_I8_01, -OPC_SHF_B = (0x0 << 24) | OPC_MSA_I8_02, -OPC_ORI_B = (0x1 << 24) | OPC_MSA_I8_00, -OPC_BMZI_B = (0x1 << 24) | OPC_MSA_I8_01, -OPC_SHF_H = (0x1 << 24) | OPC_MSA_I8_02, -OPC_NORI_B = (0x2 << 24) | OPC_MSA_I8_00, -OPC_BSELI_B = (0x2 << 24) | OPC_MSA_I8_01, -OPC_SHF_W = (0x2 << 24) | OPC_MSA_I8_02, -OPC_XORI_B = (0x3 << 24) | OPC_MSA_I8_00, - -/* VEC/2R/2RF instruction */ -OPC_AND_V = (0x00 << 21) | OPC_MSA_VEC, -OPC_OR_V= (0x01 << 21) | OPC_MSA_VEC, -OPC_NOR_V = (0x02 << 21) | OPC_MSA_VEC, -OPC_XOR_V = (0x03 << 21) | OPC_MSA_VEC, -OPC_BMNZ_V = (0x04 << 21) | OPC_MSA_VEC, -OPC_BMZ_V = (0x05 << 21) | OPC_MSA_VEC, -OPC_BSEL_V = (0x06 << 21) | OPC_MSA_VEC, - -OPC_MSA_2R = (0x18 << 21) | OPC_MSA_VEC, -OPC_MSA_2RF = (0x19 << 21) | OPC_MSA_VEC, - -/* 2R instruction df(bits 17..16) = _b, _h, _w, _d */ -OPC_FILL_df = (0x00 << 18) | OPC_MSA_2R, -OPC_PCNT_df = (0x01 << 18) | OPC_MSA_2R, -OPC_NLOC_df = (0x02 << 18) | OPC_MSA_2R, -OPC_NLZC_df = (0x03 << 18) | OPC_MSA_2R, - -/* 2RF instruction df(bit 16) = _w, _d */ -OPC_FCLASS_df = (0x00 << 17) | OPC_MSA_2RF, -OPC_FTRUNC_S_df = (0x01 << 17) | OPC_MSA_2RF, -OPC_FTRUNC_U_df = (0x02 << 17) | OPC_MSA_2RF, -OPC_FSQRT_df= (0x03 << 17) | OPC_MSA_2RF, -OPC_FRSQRT_df = (0x04 << 17) | OPC_MSA_2RF, -OPC_FRCP_df = (0x05 << 17) | OPC_MSA_2RF, -OPC_FRINT_df= (0x06 << 17) | OPC_MSA_2RF, -OPC_FLOG2_df= (0x07 << 17) | OPC_MSA_2RF, -OPC_FEXUPL_df = (0x08 << 17) | OPC_MSA_2RF, -OPC_FEXUPR_df = (0x09 << 17) | OPC_MSA_2RF, -OPC_FFQL_df = (0x0A << 17) | OPC_MSA_2RF, -OPC_FFQR_df = (0x0B << 17) | OPC_MSA_2RF, -OPC_FTINT_S_df = (0x0C << 17) | OPC_MSA_2RF, -OPC_FTINT_U_df = (0x0D << 17) | OPC_MSA_2RF, -OPC_FFINT_S_df = (0x0E << 17) | OPC_MSA_2RF, -OPC_FFINT_U_df = (0x0F << 17) | OPC_MSA_2RF, - -/* 3R instruction df(bits 22..21) = _b, _h, _w, d */ -
[PATCH 08/26] target/mips: Extract Multi-Threading helper definitions
'MIPS MT' is defined as a Module by MIPS. Extract the helper definitions to 'mod-mips-mt_helper.h.inc'. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/helper.h | 24 +-- target/mips/mod-mips-mt_helper.h.inc | 36 2 files changed, 37 insertions(+), 23 deletions(-) create mode 100644 target/mips/mod-mips-mt_helper.h.inc diff --git a/target/mips/helper.h b/target/mips/helper.h index bce869f3718..c15caed9fca 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -179,25 +179,6 @@ DEF_HELPER_2(dmtc0_entrylo0, void, env, i64) DEF_HELPER_2(dmtc0_entrylo1, void, env, i64) #endif -/* MIPS MT functions */ -DEF_HELPER_2(mftgpr, tl, env, i32) -DEF_HELPER_2(mftlo, tl, env, i32) -DEF_HELPER_2(mfthi, tl, env, i32) -DEF_HELPER_2(mftacx, tl, env, i32) -DEF_HELPER_1(mftdsp, tl, env) -DEF_HELPER_3(mttgpr, void, env, tl, i32) -DEF_HELPER_3(mttlo, void, env, tl, i32) -DEF_HELPER_3(mtthi, void, env, tl, i32) -DEF_HELPER_3(mttacx, void, env, tl, i32) -DEF_HELPER_2(mttdsp, void, env, tl) -DEF_HELPER_0(dmt, tl) -DEF_HELPER_0(emt, tl) -DEF_HELPER_1(dvpe, tl, env) -DEF_HELPER_1(evpe, tl, env) - -/* R6 Multi-threading */ -DEF_HELPER_1(dvp, tl, env) -DEF_HELPER_1(evp, tl, env) #endif /* !CONFIG_USER_ONLY */ /* microMIPS functions */ @@ -208,9 +189,6 @@ DEF_HELPER_4(ldm, void, env, tl, tl, i32) DEF_HELPER_4(sdm, void, env, tl, tl, i32) #endif -DEF_HELPER_2(fork, void, tl, tl) -DEF_HELPER_2(yield, tl, env, tl) - /* CP1 functions */ DEF_HELPER_2(cfc1, tl, env, i32) DEF_HELPER_4(ctc1, void, env, tl, i32, i32) @@ -451,4 +429,4 @@ DEF_HELPER_3(cache, void, env, tl, i32) #include "mod-mips-dsp_helper.h.inc" #include "mod-mips-msa_helper.h.inc" - +#include "mod-mips-mt_helper.h.inc" diff --git a/target/mips/mod-mips-mt_helper.h.inc b/target/mips/mod-mips-mt_helper.h.inc new file mode 100644 index 000..0db58e2a780 --- /dev/null +++ b/target/mips/mod-mips-mt_helper.h.inc @@ -0,0 +1,36 @@ +/* + * MIPS Multi-Threading helpers for QEMU. + * + * Copyright (c) 2004-2005 Jocelyn Mayer + * Copyright (c) 2006 Marius Groeger (FPU operations) + * Copyright (c) 2006 Thiemo Seufer (MIPS32R2 support) + * Copyright (c) 2009 CodeSourcery (MIPS16 and microMIPS support) + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#ifndef CONFIG_USER_ONLY +DEF_HELPER_2(mftgpr, tl, env, i32) +DEF_HELPER_2(mftlo, tl, env, i32) +DEF_HELPER_2(mfthi, tl, env, i32) +DEF_HELPER_2(mftacx, tl, env, i32) +DEF_HELPER_1(mftdsp, tl, env) +DEF_HELPER_3(mttgpr, void, env, tl, i32) +DEF_HELPER_3(mttlo, void, env, tl, i32) +DEF_HELPER_3(mtthi, void, env, tl, i32) +DEF_HELPER_3(mttacx, void, env, tl, i32) +DEF_HELPER_2(mttdsp, void, env, tl) + +DEF_HELPER_0(dmt, tl) +DEF_HELPER_0(emt, tl) + +DEF_HELPER_1(dvpe, tl, env) +DEF_HELPER_1(evpe, tl, env) + +/* R6 Multi-threading */ +DEF_HELPER_1(dvp, tl, env) +DEF_HELPER_1(evp, tl, env) +#endif /* !CONFIG_USER_ONLY */ + +DEF_HELPER_2(fork, void, tl, tl) +DEF_HELPER_2(yield, tl, env, tl) -- 2.26.2
[PATCH 09/26] target/mips: Extract Code Compaction ASE translation routines
Extract 1200 lines from the huge translate.c to a new file, 'ase-mips16e_translate.c.inc'. As there are too many inter- dependencies we don't compile it as another object, but keep including it in the big translate.o. We gain in code maintainability. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/translate.c | 1161 +- target/mips/ase-mips16e_translate.c.inc | 1170 +++ 2 files changed, 1171 insertions(+), 1160 deletions(-) create mode 100644 target/mips/ase-mips16e_translate.c.inc diff --git a/target/mips/translate.c b/target/mips/translate.c index bc581a7a7a7..bae2064e7fa 100644 --- a/target/mips/translate.c +++ b/target/mips/translate.c @@ -13131,1167 +13131,8 @@ out: } /* ISA extensions (ASEs) */ -/* MIPS16 extension to MIPS32 */ -/* MIPS16 major opcodes */ -enum { - M16_OPC_ADDIUSP = 0x00, - M16_OPC_ADDIUPC = 0x01, - M16_OPC_B = 0x02, - M16_OPC_JAL = 0x03, - M16_OPC_BEQZ = 0x04, - M16_OPC_BNEQZ = 0x05, - M16_OPC_SHIFT = 0x06, - M16_OPC_LD = 0x07, - M16_OPC_RRIA = 0x08, - M16_OPC_ADDIU8 = 0x09, - M16_OPC_SLTI = 0x0a, - M16_OPC_SLTIU = 0x0b, - M16_OPC_I8 = 0x0c, - M16_OPC_LI = 0x0d, - M16_OPC_CMPI = 0x0e, - M16_OPC_SD = 0x0f, - M16_OPC_LB = 0x10, - M16_OPC_LH = 0x11, - M16_OPC_LWSP = 0x12, - M16_OPC_LW = 0x13, - M16_OPC_LBU = 0x14, - M16_OPC_LHU = 0x15, - M16_OPC_LWPC = 0x16, - M16_OPC_LWU = 0x17, - M16_OPC_SB = 0x18, - M16_OPC_SH = 0x19, - M16_OPC_SWSP = 0x1a, - M16_OPC_SW = 0x1b, - M16_OPC_RRR = 0x1c, - M16_OPC_RR = 0x1d, - M16_OPC_EXTEND = 0x1e, - M16_OPC_I64 = 0x1f -}; - -/* I8 funct field */ -enum { - I8_BTEQZ = 0x0, - I8_BTNEZ = 0x1, - I8_SWRASP = 0x2, - I8_ADJSP = 0x3, - I8_SVRS = 0x4, - I8_MOV32R = 0x5, - I8_MOVR32 = 0x7 -}; - -/* RRR f field */ -enum { - RRR_DADDU = 0x0, - RRR_ADDU = 0x1, - RRR_DSUBU = 0x2, - RRR_SUBU = 0x3 -}; - -/* RR funct field */ -enum { - RR_JR = 0x00, - RR_SDBBP = 0x01, - RR_SLT = 0x02, - RR_SLTU = 0x03, - RR_SLLV = 0x04, - RR_BREAK = 0x05, - RR_SRLV = 0x06, - RR_SRAV = 0x07, - RR_DSRL = 0x08, - RR_CMP = 0x0a, - RR_NEG = 0x0b, - RR_AND = 0x0c, - RR_OR = 0x0d, - RR_XOR = 0x0e, - RR_NOT = 0x0f, - RR_MFHI = 0x10, - RR_CNVT = 0x11, - RR_MFLO = 0x12, - RR_DSRA = 0x13, - RR_DSLLV = 0x14, - RR_DSRLV = 0x16, - RR_DSRAV = 0x17, - RR_MULT = 0x18, - RR_MULTU = 0x19, - RR_DIV = 0x1a, - RR_DIVU = 0x1b, - RR_DMULT = 0x1c, - RR_DMULTU = 0x1d, - RR_DDIV = 0x1e, - RR_DDIVU = 0x1f -}; - -/* I64 funct field */ -enum { - I64_LDSP = 0x0, - I64_SDSP = 0x1, - I64_SDRASP = 0x2, - I64_DADJSP = 0x3, - I64_LDPC = 0x4, - I64_DADDIU5 = 0x5, - I64_DADDIUPC = 0x6, - I64_DADDIUSP = 0x7 -}; - -/* RR ry field for CNVT */ -enum { - RR_RY_CNVT_ZEB = 0x0, - RR_RY_CNVT_ZEH = 0x1, - RR_RY_CNVT_ZEW = 0x2, - RR_RY_CNVT_SEB = 0x4, - RR_RY_CNVT_SEH = 0x5, - RR_RY_CNVT_SEW = 0x6, -}; - -static int xlat(int r) -{ - static int map[] = { 16, 17, 2, 3, 4, 5, 6, 7 }; - - return map[r]; -} - -static void gen_mips16_save(DisasContext *ctx, -int xsregs, int aregs, -int do_ra, int do_s0, int do_s1, -int framesize) -{ -TCGv t0 = tcg_temp_new(); -TCGv t1 = tcg_temp_new(); -TCGv t2 = tcg_temp_new(); -int args, astatic; - -switch (aregs) { -case 0: -case 1: -case 2: -case 3: -case 11: -args = 0; -break; -case 4: -case 5: -case 6: -case 7: -args = 1; -break; -case 8: -case 9: -case 10: -args = 2; -break; -case 12: -case 13: -args = 3; -break; -case 14: -args = 4; -break; -default: -generate_exception_end(ctx, EXCP_RI); -return; -} - -switch (args) { -case 4: -gen_base_offset_addr(ctx, t0, 29, 12); -gen_load_gpr(t1, 7); -tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); -/* Fall through */ -case 3: -gen_base_offset_addr(ctx, t0, 29, 8); -gen_load_gpr(t1, 6); -tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); -/* Fall through */ -case 2: -gen_base_offset_addr(ctx, t0, 29, 4); -gen_load_gpr(t1, 5); -tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); -/* Fall through */ -case 1: -gen_base_offset_addr(ctx, t0, 29, 0); -gen_load_gpr(t1, 4); -tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); -} - -gen_load_gpr(t0, 29); - -#define DECR_AND_STORE(reg) do { \ -tcg_gen_movi_tl(t2, -4); \ -gen_op_addr_add(ctx, t0, t0, t2);\ -gen_load_gpr(t1, reg); \ -tcg_gen_qemu_st_tl(t1, t0, ctx->mem_idx, MO_TEUL); \ -} while (0) - -if (do_ra) { -DECR_AND_STORE(31); -} - -switch (xsregs) { -case 7: -
[PATCH 02/26] target/mips: Extract MSA helpers to mod-mips-msa_helper.c
MSA means 'MIPS SIMD Architecture' and is defined as a Module by MIPS. Rename msa_helper.c as mod-mips-msa_helper.c, merge other MSA helpers from op_helper.c. Signed-off-by: Philippe Mathieu-Daudé --- .../{msa_helper.c => mod-mips-msa_helper.c} | 392 + target/mips/op_helper.c | 393 -- target/mips/meson.build | 3 +- 3 files changed, 394 insertions(+), 394 deletions(-) rename target/mips/{msa_helper.c => mod-mips-msa_helper.c} (94%) diff --git a/target/mips/msa_helper.c b/target/mips/mod-mips-msa_helper.c similarity index 94% rename from target/mips/msa_helper.c rename to target/mips/mod-mips-msa_helper.c index b89b4c44902..56fca86a242 100644 --- a/target/mips/msa_helper.c +++ b/target/mips/mod-mips-msa_helper.c @@ -8201,3 +8201,395 @@ void helper_msa_ffint_u_df(CPUMIPSState *env, uint32_t df, uint32_t wd, msa_move_v(pwd, pwx); } + +/* Data format min and max values */ +#define DF_BITS(df) (1 << ((df) + 3)) + +/* Element-by-element access macros */ +#define DF_ELEMENTS(df) (MSA_WRLEN / DF_BITS(df)) + +#if !defined(CONFIG_USER_ONLY) +#define MEMOP_IDX(DF) \ +TCGMemOpIdx oi = make_memop_idx(MO_TE | DF | MO_UNALN, \ +cpu_mmu_index(env, false)); +#else +#define MEMOP_IDX(DF) +#endif + +void helper_msa_ld_b(CPUMIPSState *env, uint32_t wd, + target_ulong addr) +{ +wr_t *pwd = &(env->active_fpu.fpr[wd].wr); +MEMOP_IDX(DF_BYTE) +#if !defined(CONFIG_USER_ONLY) +#if !defined(HOST_WORDS_BIGENDIAN) +pwd->b[0] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); +pwd->b[1] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); +pwd->b[2] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC()); +pwd->b[3] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC()); +pwd->b[4] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC()); +pwd->b[5] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC()); +pwd->b[6] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC()); +pwd->b[7] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC()); +pwd->b[8] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC()); +pwd->b[9] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC()); +pwd->b[10] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC()); +pwd->b[11] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC()); +pwd->b[12] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC()); +pwd->b[13] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC()); +pwd->b[14] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC()); +pwd->b[15] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC()); +#else +pwd->b[0] = helper_ret_ldub_mmu(env, addr + (7 << DF_BYTE), oi, GETPC()); +pwd->b[1] = helper_ret_ldub_mmu(env, addr + (6 << DF_BYTE), oi, GETPC()); +pwd->b[2] = helper_ret_ldub_mmu(env, addr + (5 << DF_BYTE), oi, GETPC()); +pwd->b[3] = helper_ret_ldub_mmu(env, addr + (4 << DF_BYTE), oi, GETPC()); +pwd->b[4] = helper_ret_ldub_mmu(env, addr + (3 << DF_BYTE), oi, GETPC()); +pwd->b[5] = helper_ret_ldub_mmu(env, addr + (2 << DF_BYTE), oi, GETPC()); +pwd->b[6] = helper_ret_ldub_mmu(env, addr + (1 << DF_BYTE), oi, GETPC()); +pwd->b[7] = helper_ret_ldub_mmu(env, addr + (0 << DF_BYTE), oi, GETPC()); +pwd->b[8] = helper_ret_ldub_mmu(env, addr + (15 << DF_BYTE), oi, GETPC()); +pwd->b[9] = helper_ret_ldub_mmu(env, addr + (14 << DF_BYTE), oi, GETPC()); +pwd->b[10] = helper_ret_ldub_mmu(env, addr + (13 << DF_BYTE), oi, GETPC()); +pwd->b[11] = helper_ret_ldub_mmu(env, addr + (12 << DF_BYTE), oi, GETPC()); +pwd->b[12] = helper_ret_ldub_mmu(env, addr + (11 << DF_BYTE), oi, GETPC()); +pwd->b[13] = helper_ret_ldub_mmu(env, addr + (10 << DF_BYTE), oi, GETPC()); +pwd->b[14] = helper_ret_ldub_mmu(env, addr + (9 << DF_BYTE), oi, GETPC()); +pwd->b[15] = helper_ret_ldub_mmu(env, addr + (8 << DF_BYTE), oi, GETPC()); +#endif +#else +#if !defined(HOST_WORDS_BIGENDIAN) +pwd->b[0] = cpu_ldub_data(env, addr + (0 << DF_BYTE)); +pwd->b[1] = cpu_ldub_data(env, addr + (1 << DF_BYTE)); +pwd->b[2] = cpu_ldub_data(env, addr + (2 << DF_BYTE)); +pwd->b[3] = cpu_ldub_data(env, addr + (3 << DF_BYTE)); +pwd->b[4] = cpu_ldub_data(env, addr + (4 << DF_BYTE)); +pwd->b[5] = cpu_ldub_data(env, addr + (5 << DF_BYTE)); +pwd->b[6] = cpu_ldub_data(env, addr + (6 << DF_BYTE)); +pwd->b[7] = cpu_ldub_data(env, addr + (7 << DF_BYTE)); +pwd->b[8] = cpu_ldub_data(env, addr + (8 << DF_BYTE)); +pwd->b[9] = cpu_ldub_data(env, addr + (9 << DF_BYTE)); +pwd->b[10] = cpu_ldub_data(env, addr + (10 << DF_BYTE)); +pwd->b[11] = cpu_ldub_data(env, addr
[PATCH 03/26] target/mips: Extract MSA helper definitions
Keep all MSA-related code altogether. Signed-off-by: Philippe Mathieu-Daudé --- target/mips/helper.h | 437 + target/mips/mod-mips-msa_helper.h.inc | 443 ++ 2 files changed, 446 insertions(+), 434 deletions(-) create mode 100644 target/mips/mod-mips-msa_helper.h.inc diff --git a/target/mips/helper.h b/target/mips/helper.h index e97655dc0eb..a44f42c6201 100644 --- a/target/mips/helper.h +++ b/target/mips/helper.h @@ -781,438 +781,7 @@ DEF_HELPER_FLAGS_3(dmthlip, 0, void, tl, tl, env) DEF_HELPER_FLAGS_3(wrdsp, 0, void, tl, tl, env) DEF_HELPER_FLAGS_2(rddsp, 0, tl, tl, env) -/* MIPS SIMD Architecture */ - -DEF_HELPER_3(msa_nloc_b, void, env, i32, i32) -DEF_HELPER_3(msa_nloc_h, void, env, i32, i32) -DEF_HELPER_3(msa_nloc_w, void, env, i32, i32) -DEF_HELPER_3(msa_nloc_d, void, env, i32, i32) - -DEF_HELPER_3(msa_nlzc_b, void, env, i32, i32) -DEF_HELPER_3(msa_nlzc_h, void, env, i32, i32) -DEF_HELPER_3(msa_nlzc_w, void, env, i32, i32) -DEF_HELPER_3(msa_nlzc_d, void, env, i32, i32) - -DEF_HELPER_3(msa_pcnt_b, void, env, i32, i32) -DEF_HELPER_3(msa_pcnt_h, void, env, i32, i32) -DEF_HELPER_3(msa_pcnt_w, void, env, i32, i32) -DEF_HELPER_3(msa_pcnt_d, void, env, i32, i32) - -DEF_HELPER_4(msa_binsl_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_binsl_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_binsl_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_binsl_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_binsr_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_binsr_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_binsr_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_binsr_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_bmnz_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bmz_v, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bsel_v, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_bclr_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bclr_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bclr_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bclr_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_bneg_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bneg_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bneg_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bneg_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_bset_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bset_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bset_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_bset_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_add_a_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_add_a_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_add_a_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_add_a_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_adds_a_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_a_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_a_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_a_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_adds_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_adds_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_adds_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_addv_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_addv_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_addv_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_addv_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_hadd_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_hadd_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_hadd_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_hadd_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_hadd_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_hadd_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_ave_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ave_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ave_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ave_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_ave_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ave_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ave_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ave_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_aver_s_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_aver_s_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_aver_s_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_aver_s_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_aver_u_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_aver_u_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_aver_u_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_aver_u_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_ceq_b, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ceq_h, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ceq_w, void, env, i32, i32, i32) -DEF_HELPER_4(msa_ceq_d, void, env, i32, i32, i32) - -DEF_HELPER_4(msa_cle_s_b, void, env, i32, i32, i32)
[PATCH 01/26] target/mips: Extract FPU helpers to 'fpu_helper.h'
Extract FPU specific helpers from "internal.h" to "fpu_helper.h". Signed-off-by: Philippe Mathieu-Daudé --- target/mips/fpu_helper.h | 50 ++ target/mips/internal.h | 42 linux-user/mips/cpu_loop.c | 1 + target/mips/fpu_helper.c | 1 + target/mips/gdbstub.c | 1 + target/mips/kvm.c | 1 + target/mips/machine.c | 1 + target/mips/msa_helper.c | 1 + target/mips/translate.c| 1 + 9 files changed, 57 insertions(+), 42 deletions(-) create mode 100644 target/mips/fpu_helper.h diff --git a/target/mips/fpu_helper.h b/target/mips/fpu_helper.h new file mode 100644 index 000..83c698d583f --- /dev/null +++ b/target/mips/fpu_helper.h @@ -0,0 +1,50 @@ +/* + * Helpers for emulation of FPU-related MIPS instructions. + * + * Copyright (C) 2004-2005 Jocelyn Mayer + * + * SPDX-License-Identifier: LGPL-2.1-or-later + */ +#include "fpu/softfloat-helpers.h" +#include "cpu.h" + +extern unsigned int ieee_rm[]; + +uint32_t float_class_s(uint32_t arg, float_status *fst); +uint64_t float_class_d(uint64_t arg, float_status *fst); + +static inline void restore_rounding_mode(CPUMIPSState *env) +{ +set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], +>active_fpu.fp_status); +} + +static inline void restore_flush_mode(CPUMIPSState *env) +{ +set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0, + >active_fpu.fp_status); +} + +static inline void restore_snan_bit_mode(CPUMIPSState *env) +{ +set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0, +>active_fpu.fp_status); +} + +static inline void restore_fp_status(CPUMIPSState *env) +{ +restore_rounding_mode(env); +restore_flush_mode(env); +restore_snan_bit_mode(env); +} + +static inline void restore_msa_fp_status(CPUMIPSState *env) +{ +float_status *status = >active_tc.msa_fp_status; +int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM; +bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0; + +set_float_rounding_mode(ieee_rm[rounding_mode], status); +set_flush_to_zero(flush_to_zero, status); +set_flush_inputs_to_zero(flush_to_zero, status); +} diff --git a/target/mips/internal.h b/target/mips/internal.h index dd8a7809b64..7bea3af0b29 100644 --- a/target/mips/internal.h +++ b/target/mips/internal.h @@ -8,8 +8,6 @@ #ifndef MIPS_INTERNAL_H #define MIPS_INTERNAL_H -#include "fpu/softfloat-helpers.h" - /* * MMU types, the first four entries have the same layout as the * CP0C0_MT field. @@ -222,48 +220,8 @@ bool mips_cpu_tlb_fill(CPUState *cs, vaddr address, int size, bool probe, uintptr_t retaddr); /* op_helper.c */ -uint32_t float_class_s(uint32_t arg, float_status *fst); -uint64_t float_class_d(uint64_t arg, float_status *fst); - -extern unsigned int ieee_rm[]; void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask); -static inline void restore_rounding_mode(CPUMIPSState *env) -{ -set_float_rounding_mode(ieee_rm[env->active_fpu.fcr31 & 3], ->active_fpu.fp_status); -} - -static inline void restore_flush_mode(CPUMIPSState *env) -{ -set_flush_to_zero((env->active_fpu.fcr31 & (1 << FCR31_FS)) != 0, - >active_fpu.fp_status); -} - -static inline void restore_snan_bit_mode(CPUMIPSState *env) -{ -set_snan_bit_is_one((env->active_fpu.fcr31 & (1 << FCR31_NAN2008)) == 0, ->active_fpu.fp_status); -} - -static inline void restore_fp_status(CPUMIPSState *env) -{ -restore_rounding_mode(env); -restore_flush_mode(env); -restore_snan_bit_mode(env); -} - -static inline void restore_msa_fp_status(CPUMIPSState *env) -{ -float_status *status = >active_tc.msa_fp_status; -int rounding_mode = (env->active_tc.msacsr & MSACSR_RM_MASK) >> MSACSR_RM; -bool flush_to_zero = (env->active_tc.msacsr & MSACSR_FS_MASK) != 0; - -set_float_rounding_mode(ieee_rm[rounding_mode], status); -set_flush_to_zero(flush_to_zero, status); -set_flush_inputs_to_zero(flush_to_zero, status); -} - static inline void restore_pamask(CPUMIPSState *env) { if (env->hflags & MIPS_HFLAG_ELPA) { diff --git a/linux-user/mips/cpu_loop.c b/linux-user/mips/cpu_loop.c index cfe7ba5c47d..b58dbeb83d1 100644 --- a/linux-user/mips/cpu_loop.c +++ b/linux-user/mips/cpu_loop.c @@ -23,6 +23,7 @@ #include "cpu_loop-common.h" #include "elf.h" #include "internal.h" +#include "fpu_helper.h" # ifdef TARGET_ABI_MIPSO32 # define MIPS_SYSCALL_NUMBER_UNUSED -1 diff --git a/target/mips/fpu_helper.c b/target/mips/fpu_helper.c index 020b768e87b..a74dc18d746 100644 --- a/target/mips/fpu_helper.c +++ b/target/mips/fpu_helper.c @@ -31,6 +31,7 @@ #include "exec/memop.h" #include "sysemu/kvm.h" #include "fpu/softfloat.h" +#include "fpu_helper.h" /* Complex FPU
[PATCH 00/26] target/mips: Explode 60% of the 32K-lines translate.c
Hi, This series, while boring, helps maintainability. I simply exploded 60% of the huge target/mips/translate.c, reducing it from 32K lines of code to 13500. The small overhead in the diffstat is due to entries added in MAINTAINERS and license boilerplate addition: 20225 insertions(+), 19987 deletions(-) While being a massive diff, it is a no-brain review using 'git-diff --color-moved=dimmed-zebra' which highlights very few changes: #include and license lines. The exploded new layout, which allows more useful filtering with the get_maintainer.pl script, is: - MIPS ISA, ASE and modules: . isa-micromips_helper.h.inc . isa-nanomips_translate.c.inc . ase-mips16e_translate.c.inc . mod-mips-dsp_helper.c . mod-mips-dsp_helper.h.inc . mod-mips-dsp_translate.c.inc . mod-mips-msa_helper.h.inc . mod-mips-msa_translate.c.inc . mod-mips-msa_helper.c . mod-mips-mt_helper.h.inc - MIPS Vendor Specific: . vendor-loong-simd_helper.c . vendor-loong-lext_translate.c.inc . vendor-loong-simd_helper.h.inc . vendor-loong-simd_translate.c.inc . vendor-tx-mmi_translate.c.inc . vendor-tx_translate.c.inc . vendor-vr54xx_helper.c . vendor-vr54xx_helper.h.inc . vendor-vr54xx_translate.c.inc . vendor-xburst_translate.c.inc There should be no logical code change (only code movement). The series is available at: https://gitlab.com/philmd/qemu.git branches/mips_translate_explode Regards, Phil. Philippe Mathieu-Daudé (26): target/mips: Extract FPU helpers to 'fpu_helper.h' target/mips: Extract MSA helpers to mod-mips-msa_helper.c target/mips: Extract MSA helper definitions target/mips: Extract MSA translation routines target/mips: Rename dsp_helper.c as mod-mips-dsp_helper.c target/mips: Extract DSP helper definitions target/mips: Extract DSP translation routines target/mips: Extract Multi-Threading helper definitions target/mips: Extract Code Compaction ASE translation routines target/mips: Extract the microMIPS ISA helper definitions target/mips: Extract the microMIPS ISA translation routines target/mips: Extract nanoMIPS ISA translation routines target/mips: Extract NEC Vr54xx helpers to vendor-vr54xx_helper.c target/mips: Extract NEC Vr54xx helper definitions target/mips: Extract NEC Vr54xx translation routines target/mips: Rename lmmi_helper.c as loong-simd_helper.c target/mips: Extract Loongson SIMD helper definitions target/mips: Extract Loongson SIMD translation routines target/mips: Extract Loongson EXTensions translation routines target/mips: Extract XBurst Media eXtension Unit translation routines target/mips: Make pipeline 1 multiply opcodes generic target/mips: Extract Toshiba TXx9 translation routines target/mips: Extract Toshiba TX79 multimedia translation routines MAINTAINERS: Add entry for MIPS Loongson TCG MAINTAINERS: Add entry for MIPS Ingenic Xburst TCG MAINTAINERS: Add entry for MIPS Toshiba TCG target/mips/fpu_helper.h |50 + target/mips/helper.h | 881 +- target/mips/internal.h|42 - linux-user/mips/cpu_loop.c| 1 + target/mips/fpu_helper.c | 1 + target/mips/gdbstub.c | 1 + target/mips/kvm.c | 1 + target/mips/machine.c | 1 + .../{dsp_helper.c => mod-mips-dsp_helper.c} | 2 + .../{msa_helper.c => mod-mips-msa_helper.c} | 393 + target/mips/op_helper.c | 511 - target/mips/translate.c | 18598 +--- ...mi_helper.c => vendor-loong-simd_helper.c} | 0 target/mips/vendor-vr54xx_helper.c| 131 + MAINTAINERS |20 + target/mips/ase-mips16e_translate.c.inc | 1170 + target/mips/isa-micromips_helper.h.inc|17 + target/mips/isa-micromips_translate.c.inc | 3316 +++ target/mips/isa-nanomips_translate.c.inc | 4839 target/mips/meson.build | 8 +- target/mips/mod-mips-dsp_helper.h.inc | 344 + target/mips/mod-mips-dsp_translate.c.inc | 2158 ++ target/mips/mod-mips-msa_helper.h.inc | 443 + target/mips/mod-mips-msa_translate.c.inc | 2218 ++ target/mips/mod-mips-mt_helper.h.inc |36 + target/mips/vendor-loong-lext_translate.c.inc | 450 + target/mips/vendor-loong-simd_helper.h.inc|69 + target/mips/vendor-loong-simd_translate.c.inc | 611 + target/mips/vendor-tx-mmi_translate.c.inc | 573 + target/mips/vendor-tx_translate.c.inc | 317 + target/mips/vendor-vr54xx_helper.h.inc|24 + target/mips/vendor-vr54xx_translate.c.inc |93 + target/mips/vendor-xburst_translate.c.inc | 2893 +++ 33 files changed, 20225 insertions(+), 19987 deletions(-) create mode 100644 target/mips/fpu_helper.h rename target/mips/{dsp_helper.c => mod-mips-dsp_helper.c}
Re: [PATCH v1 1/6] scripts/ci: clean up default args logic a little
On 11/17/20 2:36 PM, Alex Bennée wrote: This allows us to do: ./scripts/ci/gitlab-pipeline-status -w -b HEAD -p 2961854 to check out own pipeline status of a recently pushed branch. Signed-off-by: Alex Bennée --- scripts/ci/gitlab-pipeline-status | 24 +--- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/scripts/ci/gitlab-pipeline-status b/scripts/ci/gitlab-pipeline-status index bac8233079..78e72f6008 100755 --- a/scripts/ci/gitlab-pipeline-status +++ b/scripts/ci/gitlab-pipeline-status @@ -31,7 +31,7 @@ class NoPipelineFound(Exception): """Communication is successfull but pipeline is not found.""" -def get_local_branch_commit(branch='staging'): +def get_local_branch_commit(branch): """ Returns the commit sha1 for the *local* branch named "staging" Need to reword the method's docstring. Otherwise, Reviewed-by: Wainer dos Santos Moschetta """ @@ -126,18 +126,16 @@ def create_parser(): help=('The GitLab project ID. Defaults to the project ' 'for https://gitlab.com/qemu-project/qemu, that ' 'is, "%(default)s"')) -try: -default_commit = get_local_branch_commit() -commit_required = False -except ValueError: -default_commit = '' -commit_required = True -parser.add_argument('-c', '--commit', required=commit_required, -default=default_commit, +parser.add_argument('-b', '--branch', type=str, default="staging", +help=('Specify the branch to check. ' + 'Use HEAD for your current branch. ' + 'Otherwise looks at "%(default)s"')) +parser.add_argument('-c', '--commit', +default=None, help=('Look for a pipeline associated with the given ' 'commit. If one is not explicitly given, the ' - 'commit associated with the local branch named ' - '"staging" is used. Default: %(default)s')) + 'commit associated with the default branch ' + 'is used.')) parser.add_argument('--verbose', action='store_true', default=False, help=('A minimal verbosity level that prints the ' 'overall result of the check/wait')) @@ -149,6 +147,10 @@ def main(): """ parser = create_parser() args = parser.parse_args() + +if not args.commit: +args.commit = get_local_branch_commit(args.branch) + success = False try: if args.wait:
Re: [PULL 0/4] docs + qtest patches
On Fri, 20 Nov 2020 at 17:18, Thomas Huth wrote: > > Hi Peter, > > the following changes since commit 7fbd7e710323c8f4c5f6a38a8ae0e6726b5a4599: > > Merge remote-tracking branch > 'remotes/stefanha-gitlab/tags/tracing-pull-request' into staging (2020-11-19 > 17:08:42 +) > > are available in the Git repository at: > > https://gitlab.com/huth/qemu.git tags/pull-request-2020-11-20 > > for you to fetch changes up to 88a8b27e556f5cb49a19d4c98a96590f61b74ed2: > > qtest: do not return freed argument vector from qtest_rsp (2020-11-20 > 15:04:16 +0100) > > gitlab-CI run: https://gitlab.com/huth/qemu/-/pipelines/219170774 > > > * Some small qtest fixes > * One documentation update Applied, thanks. Please update the changelog at https://wiki.qemu.org/ChangeLog/5.2 for any user-visible changes. -- PMM
[Bug 1674925] Re: Qemu PPC64 kvm no display if --device virtio-gpu-pci is selected
The QEMU project is currently considering to move its bug tracking to another system. For this we need to know which bugs are still valid and which could be closed already. Thus we are setting older bugs to "Incomplete" now. If you still think this bug report here is valid, then please switch the state back to "New" within the next 60 days, otherwise this report will be marked as "Expired". Or mark it as "Fix Released" if the problem has been solved with a newer version of QEMU already. Thank you and sorry for the inconvenience. ** Changed in: qemu Status: New => Incomplete -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1674925 Title: Qemu PPC64 kvm no display if --device virtio-gpu-pci is selected Status in QEMU: Incomplete Bug description: Hi, i did many tests on qemu 2.8 on my BE machines and i found an issue that i think was need to be reported Test Machines BE 970MP if i setup qemu with qemu-system-ppc64 -M 1024 --display sdl(or gtk),gl=on --device virtio- gpu-pci,virgl --enable-kvm and so and so result is doubled window one is vga other is virtio-gpu-pci without any start of the VM . pratically i dont have any output of openbios and on the virtual serial output the same issue i found is if i select: qemu-system-ppc64 -M 1024 --display gtk(or sdl) --device virtio-gpu-pci --enable-kvm and so and so i had been try to change all the -M types of all kind of pseries without any positive result. Ciao Luigi To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1674925/+subscriptions
[Bug 1619991] Re: Concurrent VMs crash w/ GPU passthrough and multiple disks
The QEMU project is currently considering to move its bug tracking to another system. For this we need to know which bugs are still valid and which could be closed already. Thus we are setting older bugs to "Incomplete" now. If you still think this bug report here is valid, then please switch the state back to "New" within the next 60 days, otherwise this report will be marked as "Expired". Or mark it as "Fix Released" if the problem has been solved with a newer version of QEMU already. Thank you and sorry for the inconvenience. ** Changed in: qemu Status: New => Incomplete -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1619991 Title: Concurrent VMs crash w/ GPU passthrough and multiple disks Status in QEMU: Incomplete Bug description: When running multiple VMs with GPU passthrugh, both VMs will crash unless all virtual disks are on the same physical volume as root, likely on all X58 chipset motherboards. I've tested with 3. Expected Behavior: No Crash Result: Both VMs GPU drivers fail and the guest OS are unrecoverable, usually within seconds, though the degree of "fickleness" of it depends on the multidisk setup. Reproducibility: 100% Steps to reproduce: * Install OS (In my case Debian Jessie/Proxmox), and update to latest * Setup VMs * Setup up GPU passthrough with 1 GPU per VM, and one for host, as per https://pve.proxmox.com/wiki/Pci_passthrough * Setup up USB passthrough * Launch both VM * Observe "everything is working" * Stop VMs * Add a second disk to one of the VMs, which exists on a separate physical disk from Host OS / * Observe both VMs crash when the virtual disk which exists on separate physical media is used (i.e. copy files to the disk) * Stop VMs * Remove new disk, and move Guest OS virtual root disk to separate physical media. * Observe both VMs crash around the time GPU driver is loaded on one As I mentioned earlier, there is some degree of difference in how difficult it is to trigger a crash, depending on the multidisk setup. For instance, when / is ZFS, and the virtual disks exist on a separate ZFS raid-z volume, both VMs must be doing some relatively intensive HW 3d acceleration in order to trigger the crash. Passing two GPU to one VM works fine all the time, and running either VM on its in general will not trigger a crash. There are many variables I have yet to test, such as using sata instead of virtio for the virtual disks, however unfortunately I do not have anything from std err or logs to indicate what the problem could be. kernel verion: Linux test-ve 4.4.15-1-pve (other versions >= 4.2.1 and <= 4.7.? tested) qemu version: 2.6.0 pve-qemu-kvm_2.6-1 motherboards tested: rampage iii, ga-ex58-ud5, asus Psomething CPUs tested: i7 920, X5670 KVM invocation 1: /usr/bin/kvm \ -id 101 \ -chardev socket,id=qmp,path=/var/run/qemu-server/101.qmp,server,nowait \ -mon chardev=qmp,mode=control \ -pidfile /var/run/qemu-server/101.pid \ -daemonize \ -smbios type=1,uuid=450e337e-244c-429b-9aa8-afb7aee037e8 \ -drive if=pflash,format=raw,readonly,file=/usr/share/kvm/OVMF-pure-efi.fd \ -drive if=pflash,format=raw,file=/root/101-OVMF_VARS-pure-efi.fd \ -name Madzia-PC \ -smp 12,sockets=1,cores=12,maxcpus=12 \ -nodefaults \ -boot menu=on,strict=on,reboot-timeout=1000 \ -vga none \ -nographic \ -no-hpet \ -cpu host,hv_vendor_id=Nvidia43FIX,hv_spinlocks=0x1fff,hv_vapic,hv_time,hv_reset,hv_vpindex,hv_runtime,hv_relaxed,+kvm_pv_unhalt,+kvm_pv_eoi,kvm=off \ -m 8192 \ -object memory-backend-ram,id=ram-node0,size=8192M \ -numa node,nodeid=0,cpus=0-11,memdev=ram-node0 \ -k en-us -readconfig /usr/share/qemu-server/pve-q35.cfg \ -device usb-tablet,id=tablet,bus=ehci.0,port=1 \ -device vfio-pci,host=04:00.0,id=hostpci0,bus=ich9-pcie-port-1,addr=0x0 \ -device vfio-pci,host=04:00.1,id=hostpci1,bus=ich9-pcie-port-2,addr=0x0 \ -device usb-host,hostbus=1,hostport=6.1,id=usb0 \ -device usb-host,hostbus=1,hostport=6.2.1,id=usb1 \ -device usb-host,hostbus=1,hostport=6.2.2,id=usb2 \ -device usb-host,hostbus=1,hostport=6.2.3,id=usb3 \ -device usb-host,hostbus=1,hostport=6.2,id=usb4 \ -device usb-host,hostbus=1,hostport=6.3,id=usb5 \ -device usb-host,hostbus=1,hostport=6.4,id=usb6 \ -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x3 \ -iscsi initiator-name=iqn.1993-08.org.debian:01:3f3df5515b13 \ -drive file=/dev/pve/vm-101-disk-1,if=none,id=drive-virtio0,cache=writeback,format=raw,aio=threads,detect-zeroes=on \ -device virtio-blk-pci,drive=drive-virtio0,id=virtio0,bus=pci.0,addr=0xa,bootindex=100 \ -netdev type=tap,id=net0,ifname=tap101i0,script=/var/lib/qemu-server/pve-bridge,downscript=/var/lib/qemu-server/pve-bridgedown,vhost=on \ -device
Re: [RFC PATCH 25/27] vhost: Do not commit vhost used idx on vhost_virtqueue_stop
On Fri, Nov 20, 2020 at 8:12 PM Eugenio Pérez wrote: > > ... if sw lm is enabled > > Signed-off-by: Eugenio Pérez > --- > hw/virtio/vhost.c | 15 ++- > 1 file changed, 10 insertions(+), 5 deletions(-) > > diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c > index cb44b9997f..cf000b979f 100644 > --- a/hw/virtio/vhost.c > +++ b/hw/virtio/vhost.c > @@ -1424,17 +1424,22 @@ static void vhost_virtqueue_stop(struct vhost_dev > *dev, > struct vhost_vring_state state = { > .index = vhost_vq_index, > }; > -int r; > +int r = -1; > > if (virtio_queue_get_desc_addr(vdev, idx) == 0) { > /* Don't stop the virtqueue which might have not been started */ > return; > } > > -r = dev->vhost_ops->vhost_get_vring_base(dev, ); > -if (r < 0) { > -VHOST_OPS_DEBUG("vhost VQ %u ring restore failed: %d", idx, r); > -/* Connection to the backend is broken, so let's sync internal > +if (!dev->sw_lm_enabled) { > +r = dev->vhost_ops->vhost_get_vring_base(dev, ); > +if (r < 0) { > +VHOST_OPS_DEBUG("vhost VQ %u ring restore failed: %d", idx, r); > +} > +} > + > +if (!dev->sw_lm_enabled || r < 0) { This test should actually test for `dev->sw_lm_enabled`, not for negation. > +/* Connection to the backend is unusable, so let's sync internal > * last avail idx to the device used idx. > */ > virtio_queue_restore_last_avail_idx(vdev, idx); > -- > 2.18.4 >
Re: [RFC PATCH 00/27] vDPA software assisted live migration
Patchew URL: https://patchew.org/QEMU/20201120185105.279030-1-epere...@redhat.com/ Hi, This series seems to have some coding style problems. See output below for more information: Type: series Message-id: 20201120185105.279030-1-epere...@redhat.com Subject: [RFC PATCH 00/27] vDPA software assisted live migration === TEST SCRIPT BEGIN === #!/bin/bash git rev-parse base > /dev/null || exit 0 git config --local diff.renamelimit 0 git config --local diff.renames True git config --local diff.algorithm histogram ./scripts/checkpatch.pl --mailback base.. === TEST SCRIPT END === Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384 From https://github.com/patchew-project/qemu - [tag update] patchew/20201117173635.29101-1-alex.ben...@linaro.org -> patchew/20201117173635.29101-1-alex.ben...@linaro.org * [new tag] patchew/20201120185105.279030-1-epere...@redhat.com -> patchew/20201120185105.279030-1-epere...@redhat.com Switched to a new branch 'test' af2fe22 vhost: forbid vhost devices logging 405925c vhost: Add vhost_hdev_can_sw_lm 7f2955b vhost: Do not commit vhost used idx on vhost_virtqueue_stop b68d3d5 vhost: iommu changes 74f282a vhost: unmap qemu's shadow virtqueues on sw live migration c999e86 vhost: Add vhost_virtqueue_memory_map 6e5f219 vhost: Add vhost_virtqueue_memory_unmap d5054c8 vhost: Return used buffers 806db46 vhost: add vhost_vring_get_buf_rcu b6b8168 vhost: add vhost_vring_poll_rcu ca44882 vhost: add vhost_vring_set_notification_rcu 3183f62 virtio: Expose virtqueue_alloc_element 4ead0ac vhost: Do not invalidate signalled used ceb76a4 virtio: Remove virtio_queue_get_used_notify_split 6aacdfe vhost: Send buffers to device 9fcc98d virtio: Add virtio_queue_full 41da0f8 virtio: const-ify all virtio_tswap* functions a3c92f1 vhost: Allocate shadow vring b40b3f7 vhost: Route host->guest notification through qemu 92ea117 vhost: Add a flag for software assisted Live Migration ace8c10 vhost: Route guest->host notification through qemu 6be11a6 virtio: Add virtio_queue_get_used_notify_split 47d4485 vhost: Add hdev->dev.sw_lm_vq_handler 7dbc8e5 vhost: add vhost_kernel_set_vring_enable 4e51c5c vhost: Move log resize/put to vhost_dev_set_log b964abc vhost: Add device callback in vhost_migration_log 264504e vhost: Add vhost_dev_can_log === OUTPUT BEGIN === 1/27 Checking commit 264504ee0018 (vhost: Add vhost_dev_can_log) 2/27 Checking commit b964abc315bd (vhost: Add device callback in vhost_migration_log) 3/27 Checking commit 4e51c5cec56d (vhost: Move log resize/put to vhost_dev_set_log) 4/27 Checking commit 7dbc8e5c64c3 (vhost: add vhost_kernel_set_vring_enable) 5/27 Checking commit 47d4485458d1 (vhost: Add hdev->dev.sw_lm_vq_handler) 6/27 Checking commit 6be11a63e3b4 (virtio: Add virtio_queue_get_used_notify_split) 7/27 Checking commit ace8c1034f83 (vhost: Route guest->host notification through qemu) WARNING: added, moved or deleted file(s), does MAINTAINERS need updating? #24: new file mode 100644 total: 0 errors, 1 warnings, 245 lines checked Patch 7/27 has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. 8/27 Checking commit 92ea11700e32 (vhost: Add a flag for software assisted Live Migration) WARNING: Block comments use a leading /* on a separate line #46: FILE: hw/virtio/vhost.c:1581: +/* We've been called after migration is completed, so no need to WARNING: Block comments use * on subsequent lines #47: FILE: hw/virtio/vhost.c:1582: +/* We've been called after migration is completed, so no need to + disable it again total: 0 errors, 2 warnings, 45 lines checked Patch 8/27 has style problems, please review. If any of these errors are false positives report them to the maintainer, see CHECKPATCH in MAINTAINERS. 9/27 Checking commit b40b3f79355c (vhost: Route host->guest notification through qemu) 10/27 Checking commit a3c92f15b554 (vhost: Allocate shadow vring) 11/27 Checking commit 41da0f8e02b2 (virtio: const-ify all virtio_tswap* functions) 12/27 Checking commit 9fcc98da9cd9 (virtio: Add virtio_queue_full) 13/27 Checking commit 6aacdfe0e0ba (vhost: Send buffers to device) ERROR: memory barrier without comment #50: FILE: hw/virtio/vhost-sw-lm-ring.c:45: +smp_rmb(); WARNING: Block comments use a leading /* on a separate line #98: FILE: hw/virtio/vhost-sw-lm-ring.c:93: +/* virtqueue_add: WARNING: Block comments use a leading /* on a separate line #125: FILE: hw/virtio/vhost-sw-lm-ring.c:120: +/* Put entry in available array (but don't update avail->idx until they WARNING: Block comments use a trailing */ on a separate line #126: FILE: hw/virtio/vhost-sw-lm-ring.c:121: + * do sync). */ ERROR: g_free(NULL) is safe this check is probably not required #147: FILE: hw/virtio/vhost-sw-lm-ring.c:142: +if (vq->ring_id_maps[host_head]) { +g_free(vq->ring_id_maps[host_head]); ERROR: braces {} are necessary for all arms of this statement #185:
[Bug 1346784] Re: qemu internal memory areas visible to a guest via /proc/self/maps
I think this had been fixed here: https://git.qemu.org/?p=qemu.git;a=commitdiff;h=d67f4aaae8379b44b3b51ff0 ** Changed in: qemu Status: New => Fix Released -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1346784 Title: qemu internal memory areas visible to a guest via /proc/self/maps Status in QEMU: Fix Released Bug description: Qemu internal memory areas are not suppressed in the output and are visible to a guest via /proc/self/maps. $ echo "int main() { return 0; }" > /tmp/test.c $ gcc -m32 -fsanitize=address -fno-common -Wall -g -fPIC -o /tmp/test /tmp/test.c $ qemu-i386-static -R 0 /tmp/test We use -R option because the binary can't be executed under stock version of Qemu with address sanitizer instrumentations (Asan). Qemu memory map looks the following way where GUEST valid addresses are marked with * and invalid with @@@: * 08048000-08049000 r-xp 08:01 28835889 /tmp/test * 08049000-0804a000 rw-p 08:01 28835889 /tmp/test * 1000-2400 rw-p 00:00 0 * 2400-2800 ---p 00:00 0 * 2800-4000 rw-p 00:00 0 * 4000-40001000 ---p 00:00 0 * 40001000-40801000 rw-p 00:00 0 [stack] * 40801000-40821000 r-xp 08:01 26738694 /lib32/ld-2.19.so * 40821000-40822000 r--p 0001f000 08:01 26738694 /lib32/ld-2.19.so * 40822000-40823000 rw-p 0002 08:01 26738694 /lib32/ld-2.19.so * 40823000-40827000 rw-p 00:00 0 * 40827000-408ca000 r-xp 08:01 49424994 /home/michail/build/lib32/libasan.so.1.0.0 * 408ca000-408cc000 rw-p 000a3000 08:01 49424994 /home/michail/build/lib32/libasan.so.1.0.0 * 408cc000-40d24000 rw-p 00:00 0 * 40d3c000-40ee2000 r-xp 08:01 26738695 /lib32/libc-2.19.so * 40ee2000-40ee4000 r--p 001a6000 08:01 26738695 /lib32/libc-2.19.so * 40ee4000-40ee5000 rw-p 001a8000 08:01 26738695 /lib32/libc-2.19.so * 40ee5000-40ee8000 rw-p 00:00 0 * 40ee8000-40f0 r-xp 08:01 26738711 /lib32/libpthread-2.19.so * 40f0-40f01000 r--p 00017000 08:01 26738711 /lib32/libpthread-2.19.so * 40f01000-40f02000 rw-p 00018000 08:01 26738711 /lib32/libpthread-2.19.so * 40f02000-40f04000 rw-p 00:00 0 * 40f04000-40f07000 r-xp 08:01 26738708 /lib32/libdl-2.19.so * 40f07000-40f08000 r--p 2000 08:01 26738708 /lib32/libdl-2.19.so * 40f08000-40f09000 rw-p 3000 08:01 26738708 /lib32/libdl-2.19.so * 40f09000-40fee000 r-xp 08:01 49424965 /home/michail/build/lib32/libstdc++.so.6.0.20 * 40fee000-40ff2000 r--p 000e5000 08:01 49424965 /home/michail/build/lib32/libstdc++.so.6.0.20 * 40ff2000-40ff3000 rw-p 000e9000 08:01 49424965 /home/michail/build/lib32/libstdc++.so.6.0.20 * 40ff3000-40ffa000 rw-p 00:00 0 * 40ffa000-4103e000 r-xp 08:01 26738698 /lib32/libm-2.19.so * 4103e000-4103f000 r--p 00043000 08:01 26738698 /lib32/libm-2.19.so * 4103f000-4104 rw-p 00044000 08:01 26738698 /lib32/libm-2.19.so * 4104-41041000 rw-p 00:00 0 * 41041000-4105b000 r-xp 08:01 49424637 /home/michail/build/lib32/libgcc_s.so.1 * 4105b000-4105c000 rw-p 00019000 08:01 49424637 /home/michail/build/lib32/libgcc_s.so.1 * 4105c000-4105e000 rw-p 00:00 0 * 4105f000-41061000 rw-p 00:00 0 * 41065000-421ed000 rw-p 00:00 0 * 421ee000-421f1000 rw-p 00:00 0 * 6000-6033b000 r-xp 08:01 48760980 /home/michail/build/bin/qemu-i386-static * 6053b000-60546000 rw-p 0033b000 08:01 48760980 /home/michail/build/bin/qemu-i386-static * 60546000-6059a000 rw-p 00:00 0 * 6059a000-6259b000 rwxp 00:00 0 * 6259b000-625ae000 rw-p 00:00 0 * 62dce000-62e12000 rw-p 00:00 0 [heap] @@@ 7f3f5e6a9000 - 7f3f61f28000 rw-p 00:00 0 @@@ 7fffad13 - 7fffad132000 r-xp 00:00 0 [vdso] @@@ ff60 - ff601000 r-xp 00:00 0 [vsyscall] qemu-i386-static and its heap are in ranges which are valid and be reported to guest in case of maps file reading. The issue is related to early reported bugs: http://lists.nongnu.org/archive/html/qemu-devel/2014-07/msg02793.html http://lists.nongnu.org/archive/html/qemu-devel/2014-07/msg03085.html To manage notifications about this bug go to:
Re: [RFC v4 9/9] i386: split cpu accelerators from cpu.c
On Fri, Nov 20, 2020 at 07:47:11PM +0100, Claudio Fontana wrote: > On 11/20/20 6:44 PM, Eduardo Habkost wrote: > > On Fri, Nov 20, 2020 at 03:49:09PM +0100, Claudio Fontana wrote: > >> split cpu.c into: > >> > >> cpu.ccpuid and common x86 cpu functionality > >> host-cpu.c host x86 cpu functions and "host" cpu type > >> kvm/cpu.cKVM x86 cpu type > >> hvf/cpu.cHVF x86 cpu type > >> tcg/cpu.cTCG x86 cpu type > >> > >> The link to the accel class is set in the X86CPUClass classes > >> at MODULE_INIT_ACCEL_CPU time, when the accelerator is known. > >> > >> Signed-off-by: Claudio Fontana > > [...] > >> +static void hvf_cpu_accel_class_init(ObjectClass *oc, void *data) > >> +{ > >> +X86CPUAccelClass *acc = X86_CPU_ACCEL_CLASS(oc); > >> + > >> +acc->cpu_realizefn = host_cpu_realizefn; > >> +acc->cpu_common_class_init = hvf_cpu_common_class_init; > >> +acc->cpu_instance_init = hvf_cpu_instance_init; > >> +}; > >> +static const TypeInfo hvf_cpu_accel_type_info = { > >> +.name = X86_CPU_ACCEL_TYPE_NAME("hvf"), > >> + > >> +.parent = TYPE_X86_CPU_ACCEL, > >> +.class_init = hvf_cpu_accel_class_init, > >> +}; > >> +static void hvf_cpu_accel_register_types(void) > >> +{ > >> +type_register_static(_cpu_accel_type_info); > >> +} > >> +type_init(hvf_cpu_accel_register_types); > >> + > >> +static void hvf_cpu_accel_init(void) > >> +{ > >> +if (hvf_enabled()) { > >> +x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("hvf")); > >> +} > >> +} > >> + > >> +accel_cpu_init(hvf_cpu_accel_init); > > > > The point of my suggestion of using QOM is to not require > > separate accel_cpu_init() functions and (hvf|tcg|kvm)_enabled() > > checks. > > > > If we still have separate accel_cpu_init() functions for calling > > x86_cpu_accel_init() with the right argument, using a pointer to > > static variables like _cpu_accel (like you did before) was > > simpler and required less boilerplate code. > > > > Yes I agree. > > > > > > > > However, the difference is that with the X86_CPU_ACCEL_TYPE_NAME > > macro + object_class_by_name(), you don't need the separate > > accel_cpu_init() functions for each accelerator. > > > > All you need is a single: > > > > x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME(chosen_accel_name)); > > > > call somewhere in the initialization path. > > > Makes sense. The problem is just determining chosen_accel_name. Yeah, that was a challenge. do_configure_accelerator() knows what's the chosen accel name, though. We can also do it inside accel_init_machine(), if we can determine the correct accel name from the AccelState object. > > > > > > A good place for the x86_cpu_accel_init() call would be > > do_configure_accelerator(), but the function is arch-specific. > > That's why I suggested a cpu_accel_arch_init() function at > > https://lore.kernel.org/qemu-devel/20201118220750.gp1509...@habkost.net > > > > > Fine by me. I'd use a specific init step for this, but that also works. A separate module init function has no easy access to the accel name, but in this case I'd say it's on purpose: the intended use case for module init functions is to unconditionally register features provided by a code module. They shouldn't look at any runtime configuration or runtime state. -- Eduardo
[Bug 1395217] Re: Networking in qemu 2.0.0 and beyond is not compatible with Open Solaris (Illumos) 5.11
The QEMU project is currently considering to move its bug tracking to another system. For this we need to know which bugs are still valid and which could be closed already. Thus we are setting older bugs to "Incomplete" now. If you still think this bug report here is valid, then please switch the state back to "New" within the next 60 days, otherwise this report will be marked as "Expired". Or mark it as "Fix Released" if the problem has been solved with a newer version of QEMU already. Thank you and sorry for the inconvenience. ** Changed in: qemu Status: New => Incomplete -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1395217 Title: Networking in qemu 2.0.0 and beyond is not compatible with Open Solaris (Illumos) 5.11 Status in QEMU: Incomplete Bug description: The networking code in qemu in versions 2.0.0 and beyond is non- functional with Solaris/Illumos 5.11 images. Building 1.7.1, 2.0.0, 2.0.2, 2.1.2,and 2.2.0rc1with the following standard Slackware config: # From Slackware build tree . . . ./configure \ --prefix=/usr \ --libdir=/usr/lib64 \ --sysconfdir=/etc \ --localstatedir=/var \ --enable-gtk \ --enable-system \ --enable-kvm \ --disable-debug-info \ --enable-virtfs \ --enable-sdl \ --audio-drv-list=alsa,oss,sdl,esd \ --enable-libusb \ --disable-vnc \ --target-list=x86_64-linux-user,i386-linux-user,x86_64-softmmu,i386-softmmu \ --enable-spice \ --enable-usb-redir And attempting to run the same VM image with the following command (or via virt-manager): macaddress="DE:AD:BE:EF:3F:A4" qemu-system-x86_64 nex4x -cdrom /dev/cdrom -name "Nex41" -cpu Westmere -machine accel=kvm -smp 2 -m 4000 -net nic,macaddr=$macaddress -net bridge,br=b r0 -net dump,file=/usr1/tmp/ -drive file=nex4x_d1 -drive file=nex4x_d2 -enable-kvm Gives success on 1.7.1, and a deaf VM on all subsequent versions. Notable in validating my config, is that a Windows 7 image runs cleanly with networking on *all* builds, so my configuration appears to be good - qemu just hates Solaris at this point. Watching with wireshark (as well as pulling network traces from qemu as noted above) it appears that the notable difference in the two configs is that for some reason, Solaris gets stuck arping for it's own interface on startup, and never really comes on line on the network. If other hosts attempt to ping the Solaris instance, they can successfully arp the bad VM, but not the other way around. To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1395217/+subscriptions
Re: [PATCH v1 3/6] tests/avocado: clean-up socket directory after run
On 11/17/20 2:36 PM, Alex Bennée wrote: Previously we were leaving temporary directories behind. While the QEMUMachine does make efforts to clean up after itself the directory belongs to the calling function. We use TemporaryDirectory to wrap this although we explicitly clear the reference in tearDown() as it doesn't get cleaned up otherwise. This patch fixes the problem introduced on patch 02 of this series. Signed-off-by: Alex Bennée --- tests/acceptance/avocado_qemu/__init__.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py index 3033b2cabe..bf54e419da 100644 --- a/tests/acceptance/avocado_qemu/__init__.py +++ b/tests/acceptance/avocado_qemu/__init__.py @@ -171,8 +171,8 @@ class Test(avocado.Test): self.cancel("No QEMU binary defined or found in the build tree") def _new_vm(self, *args): -sd = tempfile.mkdtemp(prefix="avocado_qemu_sock_") -vm = QEMUMachine(self.qemu_bin, sock_dir=sd) +self._sd = tempfile.TemporaryDirectory(prefix="avo_qemu_sock_") Double-checking that you really meant "avo" or if your fingers forgot to type the remaining letters. :) - Wainer +vm = QEMUMachine(self.qemu_bin, sock_dir=self._sd.name) if args: vm.add_args(*args) return vm @@ -193,6 +193,7 @@ class Test(avocado.Test): def tearDown(self): for vm in self._vms.values(): vm.shutdown() +self._sd = None def fetch_asset(self, name, asset_hash=None, algorithm=None,
[RFC PATCH 24/27] vhost: iommu changes
Since vhost is now asking for qemu's VA, iommu needs to be bypassed. Signed-off-by: Eugenio Pérez --- hw/virtio/vhost.c | 17 + 1 file changed, 17 insertions(+) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index eebfac4455..cb44b9997f 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1109,6 +1109,10 @@ static int vhost_sw_live_migration_start(struct vhost_dev *dev) assert(dev->vhost_ops->vhost_set_vring_enable); dev->vhost_ops->vhost_set_vring_enable(dev, false); +if (vhost_dev_has_iommu(dev)) { +r = vhost_backend_invalidate_device_iotlb(dev, 0, -1ULL); +assert(r == 0); +} for (idx = 0; idx < dev->nvqs; ++idx) { struct vhost_virtqueue *vq = >vqs[idx]; @@ -1269,6 +1273,19 @@ int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write) trace_vhost_iotlb_miss(dev, 1); +if (dev->sw_lm_enabled) { +uaddr = iova; +len = 4096; +ret = vhost_backend_update_device_iotlb(dev, iova, uaddr, len, +IOMMU_RW); +if (ret) { +trace_vhost_iotlb_miss(dev, 2); +error_report("Fail to update device iotlb"); +} + +return ret; +} + iotlb = address_space_get_iotlb_entry(dev->vdev->dma_as, iova, write, MEMTXATTRS_UNSPECIFIED); -- 2.18.4
Re: [RFC PATCH 00/27] vDPA software assisted live migration
The main intention with this POC/RFC is to serve as a base to implement SW LM in vdpa devices. To implement in vhost-vdpa devices, the high priority is to achieve an interface for vdpa to stop the device without losing its state, i.e., the avail_idx the destination device should start fetching descriptors from. Following this POC, an implementation on vdpa_sim will be performed. Apart from that, there is a TODO list about this series, they will be solved as the code is marked as valid. They don't affect the device, just internal qemu's code, and in case of change of direction it is easy to modify or delete. Comments about these are welcome. - Currently, it hijacks the log mechanism to know when migration is starting/done. Maybe it would be cleaner to forward migrate status from virtio_vmstate_change, since there is no need for the memory listener. However, this could make "memory backend" abstraction (also TODO) more complicated. This would drop patches 2,3 entirely. - There is a reverse search in a list on "vhost_dev_from_virtio" for each notification. Not really efficient, and it leads to a race condition at device destruction. - Implement new capabilities (no iommu, packed vq, event_idx, ...) - Lot of assertions need to be converted to proper error handling. Thanks! On Fri, Nov 20, 2020 at 8:02 PM Eugenio Pérez wrote: > > This series enable vDPA software assisted live migration for vhost-net > devices. This is a new method of vhost devices migration: Instead of > relay on vDPA device's dirty logging capability, SW assisted LM > intercepts dataplane, forwarding the descriptors between VM and device. > > In this migration mode, qemu offers a new vring to the device to > read and write into, and disable vhost notifiers, processing guest and > vhost notifications in qemu. On used buffer relay, qemu will mark the > dirty memory as with plain virtio-net devices. This way, devices does > not need to have dirty page logging capability. > > This series is a POC doing SW LM for vhost-net devices, which already > have dirty page logging capabilities. None of the changes have actual > effect with current devices until last two patches (26 and 27) are > applied, but they can be rebased on top of any other. These checks the > device to meet all requirements, and disable vhost-net devices logging > so migration goes through SW LM. This last patch is not meant to be > applied in the final revision, it is in the series just for testing > purposes. > > For use SW assisted LM these vhost-net devices need to be instantiated: > * With IOMMU (iommu_platform=on,ats=on) > * Without event_idx (event_idx=off) > > Just the notification forwarding (with no descriptor relay) can be > achieved with patches 7 and 9, and starting migration. Partial applies > between 13 and 24 will not work while migrating on source, and patch > 25 is needed for the destination to resume network activity. > > It is based on the ideas of DPDK SW assisted LM, in the series of > DPDK's https://patchwork.dpdk.org/cover/48370/ . > > Comments are welcome. > > Thanks! > > Eugenio Pérez (27): > vhost: Add vhost_dev_can_log > vhost: Add device callback in vhost_migration_log > vhost: Move log resize/put to vhost_dev_set_log > vhost: add vhost_kernel_set_vring_enable > vhost: Add hdev->dev.sw_lm_vq_handler > virtio: Add virtio_queue_get_used_notify_split > vhost: Route guest->host notification through qemu > vhost: Add a flag for software assisted Live Migration > vhost: Route host->guest notification through qemu > vhost: Allocate shadow vring > virtio: const-ify all virtio_tswap* functions > virtio: Add virtio_queue_full > vhost: Send buffers to device > virtio: Remove virtio_queue_get_used_notify_split > vhost: Do not invalidate signalled used > virtio: Expose virtqueue_alloc_element > vhost: add vhost_vring_set_notification_rcu > vhost: add vhost_vring_poll_rcu > vhost: add vhost_vring_get_buf_rcu > vhost: Return used buffers > vhost: Add vhost_virtqueue_memory_unmap > vhost: Add vhost_virtqueue_memory_map > vhost: unmap qemu's shadow virtqueues on sw live migration > vhost: iommu changes > vhost: Do not commit vhost used idx on vhost_virtqueue_stop > vhost: Add vhost_hdev_can_sw_lm > vhost: forbid vhost devices logging > > hw/virtio/vhost-sw-lm-ring.h | 39 +++ > include/hw/virtio/vhost.h | 5 + > include/hw/virtio/virtio-access.h | 8 +- > include/hw/virtio/virtio.h| 4 + > hw/net/virtio-net.c | 39 ++- > hw/virtio/vhost-backend.c | 29 ++ > hw/virtio/vhost-sw-lm-ring.c | 268 +++ > hw/virtio/vhost.c | 431 +- > hw/virtio/virtio.c| 18 +- > hw/virtio/meson.build | 2 +- > 10 files changed, 758 insertions(+), 85 deletions(-) > create mode 100644 hw/virtio/vhost-sw-lm-ring.h > create mode 100644 hw/virtio/vhost-sw-lm-ring.c > > -- > 2.18.4 > >
Re: [PATCH v1 2/6] tests: add prefixes to the bare mkdtemp calls
On 11/17/20 2:36 PM, Alex Bennée wrote: The first step to debug a thing is to know what created the thing in the first place. Add some prefixes so random tmpdir's have something grep in the code. Yeah, it indeed helps. Signed-off-by: Alex Bennée --- v2 - fix long lines --- python/qemu/machine.py| 3 ++- tests/acceptance/avocado_qemu/__init__.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) Reviewed-by: Wainer dos Santos Moschetta diff --git a/python/qemu/machine.py b/python/qemu/machine.py index 6420f01bed..64d966aeeb 100644 --- a/python/qemu/machine.py +++ b/python/qemu/machine.py @@ -303,7 +303,8 @@ class QEMUMachine: return args def _pre_launch(self) -> None: -self._temp_dir = tempfile.mkdtemp(dir=self._test_dir) +self._temp_dir = tempfile.mkdtemp(prefix="qemu-machine-", + dir=self._test_dir) self._qemu_log_path = os.path.join(self._temp_dir, self._name + ".log") self._qemu_log_file = open(self._qemu_log_path, 'wb') diff --git a/tests/acceptance/avocado_qemu/__init__.py b/tests/acceptance/avocado_qemu/__init__.py index 4cda037187..3033b2cabe 100644 --- a/tests/acceptance/avocado_qemu/__init__.py +++ b/tests/acceptance/avocado_qemu/__init__.py @@ -171,7 +171,8 @@ class Test(avocado.Test): self.cancel("No QEMU binary defined or found in the build tree") def _new_vm(self, *args): -vm = QEMUMachine(self.qemu_bin, sock_dir=tempfile.mkdtemp()) +sd = tempfile.mkdtemp(prefix="avocado_qemu_sock_") +vm = QEMUMachine(self.qemu_bin, sock_dir=sd) if args: vm.add_args(*args) return vm
[RFC PATCH 23/27] vhost: unmap qemu's shadow virtqueues on sw live migration
Since vhost does not need to access it, it has no sense to keep it mapped. Signed-off-by: Eugenio Pérez --- hw/virtio/vhost.c | 1 + 1 file changed, 1 insertion(+) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index f640d4edf0..eebfac4455 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1124,6 +1124,7 @@ static int vhost_sw_live_migration_start(struct vhost_dev *dev) dev->sw_lm_shadow_vq[idx] = vhost_sw_lm_shadow_vq(dev, idx); event_notifier_set_handler(>masked_notifier, vhost_handle_call); +vhost_virtqueue_memory_unmap(dev, >vqs[idx], true); vhost_vring_write_addr(dev->sw_lm_shadow_vq[idx], ); r = dev->vhost_ops->vhost_set_vring_addr(dev, ); -- 2.18.4
[RFC PATCH 25/27] vhost: Do not commit vhost used idx on vhost_virtqueue_stop
... if sw lm is enabled Signed-off-by: Eugenio Pérez --- hw/virtio/vhost.c | 15 ++- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index cb44b9997f..cf000b979f 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1424,17 +1424,22 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev, struct vhost_vring_state state = { .index = vhost_vq_index, }; -int r; +int r = -1; if (virtio_queue_get_desc_addr(vdev, idx) == 0) { /* Don't stop the virtqueue which might have not been started */ return; } -r = dev->vhost_ops->vhost_get_vring_base(dev, ); -if (r < 0) { -VHOST_OPS_DEBUG("vhost VQ %u ring restore failed: %d", idx, r); -/* Connection to the backend is broken, so let's sync internal +if (!dev->sw_lm_enabled) { +r = dev->vhost_ops->vhost_get_vring_base(dev, ); +if (r < 0) { +VHOST_OPS_DEBUG("vhost VQ %u ring restore failed: %d", idx, r); +} +} + +if (!dev->sw_lm_enabled || r < 0) { +/* Connection to the backend is unusable, so let's sync internal * last avail idx to the device used idx. */ virtio_queue_restore_last_avail_idx(vdev, idx); -- 2.18.4
[RFC PATCH 19/27] vhost: add vhost_vring_get_buf_rcu
Signed-off-by: Eugenio Pérez --- hw/virtio/vhost-sw-lm-ring.h | 1 + hw/virtio/vhost-sw-lm-ring.c | 29 + 2 files changed, 30 insertions(+) diff --git a/hw/virtio/vhost-sw-lm-ring.h b/hw/virtio/vhost-sw-lm-ring.h index 03257d60c1..429a125558 100644 --- a/hw/virtio/vhost-sw-lm-ring.h +++ b/hw/virtio/vhost-sw-lm-ring.h @@ -19,6 +19,7 @@ typedef struct VhostShadowVirtqueue VhostShadowVirtqueue; bool vhost_vring_kick(VhostShadowVirtqueue *vq); int vhost_vring_add(VhostShadowVirtqueue *vq, VirtQueueElement *elem); +VirtQueueElement *vhost_vring_get_buf_rcu(VhostShadowVirtqueue *vq, size_t sz); /* Called within rcu_read_lock(). */ void vhost_vring_set_notification_rcu(VhostShadowVirtqueue *vq, bool enable); diff --git a/hw/virtio/vhost-sw-lm-ring.c b/hw/virtio/vhost-sw-lm-ring.c index 3652889d8e..4fafd1b278 100644 --- a/hw/virtio/vhost-sw-lm-ring.c +++ b/hw/virtio/vhost-sw-lm-ring.c @@ -187,6 +187,35 @@ int vhost_vring_add(VhostShadowVirtqueue *vq, VirtQueueElement *elem) return 0; } +VirtQueueElement *vhost_vring_get_buf_rcu(VhostShadowVirtqueue *vq, size_t sz) +{ +const vring_used_t *used = vq->vring.used; +VirtQueueElement *ret; +vring_used_elem_t used_elem; +uint16_t last_used; + +if (!vhost_vring_poll_rcu(vq)) { +return NULL; +} + +last_used = vq->used_idx & (vq->vring.num - 1); +used_elem.id = virtio_tswap32(vq->vdev, used->ring[last_used].id); +used_elem.len = virtio_tswap32(vq->vdev, used->ring[last_used].len); + +if (unlikely(used_elem.id >= vq->vring.num)) { +virtio_error(vq->vdev, "Device says index %u is available", + used_elem.id); +return NULL; +} + +ret = vq->ring_id_maps[used_elem.id]; +ret->len = used_elem.len; + +vq->used_idx++; + +return ret; +} + void vhost_vring_write_addr(const VhostShadowVirtqueue *vq, struct vhost_vring_addr *addr) { -- 2.18.4
[RFC PATCH 27/27] vhost: forbid vhost devices logging
This is NOT a commit intended for merge, but for test the patchset. Signed-off-by: Eugenio Pérez --- hw/virtio/vhost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 44a51ccf5e..069e5c915d 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -79,7 +79,7 @@ static struct vhost_dev *vhost_dev_from_virtio(const VirtIODevice *vdev) static bool vhost_dev_can_log(const struct vhost_dev *hdev) { -return hdev->features & (0x1ULL << VHOST_F_LOG_ALL); +return false; } static void vhost_dev_sync_region(struct vhost_dev *dev, -- 2.18.4
[RFC PATCH 22/27] vhost: Add vhost_virtqueue_memory_map
To make it symmetric with _unmap. Signed-off-by: Eugenio Pérez --- hw/virtio/vhost.c | 68 ++- 1 file changed, 44 insertions(+), 24 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index eafbbaa751..f640d4edf0 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -827,6 +827,42 @@ static void vhost_virtqueue_memory_unmap(struct vhost_dev *dev, } } +static int vhost_virtqueue_memory_map(struct vhost_dev *dev, + struct vhost_virtqueue *vq, + unsigned int vhost_vq_index) +{ +int r; +hwaddr a, l, s; + +a = vq->desc_phys; +s = l = vq->desc_size; +vq->desc = vhost_memory_map(dev, a, , false); +if (!vq->desc || l != s) { +return -ENOMEM; +} + +a = vq->avail_phys; +s = l = vq->avail_size; +vq->avail = vhost_memory_map(dev, a, , false); +if (!vq->avail || l != s) { +return -ENOMEM; +} + +a = vq->used_phys; +s = l = vq->used_size; +vq->used = vhost_memory_map(dev, a, , true); +if (!vq->used || l != s) { +return -ENOMEM; +} + +r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev->log_enabled); +if (r < 0) { +return -errno; +} + +return 0; +} + static int vhost_dev_set_features(struct vhost_dev *dev, bool enable_log) { @@ -1271,7 +1307,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); VirtioBusState *vbus = VIRTIO_BUS(qbus); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(vbus); -hwaddr s, l, a; +hwaddr a; int r; int vhost_vq_index = dev->vhost_ops->vhost_get_vq_index(dev, idx); struct vhost_vring_file file = { @@ -1311,31 +1347,15 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, } } -vq->desc_size = s = l = virtio_queue_get_desc_size(vdev, idx); +vq->desc_size = virtio_queue_get_desc_size(vdev, idx); vq->desc_phys = a; -vq->desc = vhost_memory_map(dev, a, , false); -if (!vq->desc || l != s) { -r = -ENOMEM; -goto fail_alloc; -} -vq->avail_size = s = l = virtio_queue_get_avail_size(vdev, idx); -vq->avail_phys = a = virtio_queue_get_avail_addr(vdev, idx); -vq->avail = vhost_memory_map(dev, a, , false); -if (!vq->avail || l != s) { -r = -ENOMEM; -goto fail_alloc; -} -vq->used_size = s = l = virtio_queue_get_used_size(vdev, idx); -vq->used_phys = a = virtio_queue_get_used_addr(vdev, idx); -vq->used = vhost_memory_map(dev, a, , true); -if (!vq->used || l != s) { -r = -ENOMEM; -goto fail_alloc; -} +vq->avail_size = virtio_queue_get_avail_size(vdev, idx); +vq->avail_phys = virtio_queue_get_avail_addr(vdev, idx); +vq->used_size = virtio_queue_get_used_size(vdev, idx); +vq->used_phys = virtio_queue_get_used_addr(vdev, idx); -r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev->log_enabled); -if (r < 0) { -r = -errno; +r = vhost_virtqueue_memory_map(dev, vq, vhost_vq_index); +if (r) { goto fail_alloc; } -- 2.18.4
[RFC PATCH 16/27] virtio: Expose virtqueue_alloc_element
Specify VirtQueueElement * as return type makes no harm at this moment. Signed-off-by: Eugenio Pérez --- include/hw/virtio/virtio.h | 2 ++ hw/virtio/virtio.c | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 79212141a6..ee8fe96f32 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -196,6 +196,8 @@ void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len, unsigned int idx); void virtqueue_map(VirtIODevice *vdev, VirtQueueElement *elem); +VirtQueueElement *virtqueue_alloc_element(size_t sz, unsigned out_num, + unsigned in_num); void *virtqueue_pop(VirtQueue *vq, size_t sz); unsigned int virtqueue_drop_all(VirtQueue *vq); void *qemu_get_virtqueue_element(VirtIODevice *vdev, QEMUFile *f, size_t sz); diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index ad9dc5dfa7..a89525f067 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -1400,7 +1400,8 @@ void virtqueue_map(VirtIODevice *vdev, VirtQueueElement *elem) false); } -static void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_num) +VirtQueueElement *virtqueue_alloc_element(size_t sz, unsigned out_num, + unsigned in_num) { VirtQueueElement *elem; size_t in_addr_ofs = QEMU_ALIGN_UP(sz, __alignof__(elem->in_addr[0])); -- 2.18.4
[RFC PATCH 14/27] virtio: Remove virtio_queue_get_used_notify_split
No more uses beyond this point Signed-off-by: Eugenio Pérez --- include/hw/virtio/virtio.h | 1 - hw/virtio/virtio.c | 14 -- 2 files changed, 15 deletions(-) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 0a7f5cc63e..79212141a6 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -225,7 +225,6 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id); void virtio_notify_config(VirtIODevice *vdev); -bool virtio_queue_get_used_notify_split(VirtQueue *vq); bool virtio_queue_get_notification(VirtQueue *vq); void virtio_queue_set_notification(VirtQueue *vq, int enable); diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 77ca5f6b6f..ad9dc5dfa7 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -377,20 +377,6 @@ static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val) vq->used_idx = val; } -bool virtio_queue_get_used_notify_split(VirtQueue *vq) -{ -VRingMemoryRegionCaches *caches; -hwaddr pa = offsetof(VRingUsed, flags); -uint16_t flags; - -RCU_READ_LOCK_GUARD(); - -caches = vring_get_region_caches(vq); -assert(caches); -flags = virtio_lduw_phys_cached(vq->vdev, >used, pa); -return !(VRING_USED_F_NO_NOTIFY & flags); -} - /* Called within rcu_read_lock(). */ static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask) { -- 2.18.4
[RFC PATCH 26/27] vhost: Add vhost_hdev_can_sw_lm
This allows a device to migrate if it meet a few requirements. Signed-off-by: Eugenio Pérez --- hw/virtio/vhost.c | 34 +- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index cf000b979f..44a51ccf5e 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -1529,6 +1529,37 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq) event_notifier_cleanup(>masked_notifier); } +static bool vhost_hdev_can_sw_lm(struct vhost_dev *hdev) +{ +const char *cause = NULL; + +if (hdev->features & (VIRTIO_F_IOMMU_PLATFORM)) { +cause = "have iommu"; +} else if (hdev->features & VIRTIO_F_RING_PACKED) { +cause = "is packed"; +} else if (hdev->features & VIRTIO_RING_F_EVENT_IDX) { +cause = "Have event idx"; +} else if (hdev->features & VIRTIO_RING_F_INDIRECT_DESC) { +cause = "Supports indirect descriptors"; +} else if (hdev->nvqs != 2) { +cause = "!= 2 #vq supported"; +} else if (!hdev->vhost_ops->vhost_net_set_backend) { +cause = "cannot pause device"; +} + +if (cause) { +if (!hdev->migration_blocker) { +error_setg(>migration_blocker, +"Migration disabled: vhost lacks VHOST_F_LOG_ALL feature and %s.", +cause); +} + +return false; +} + +return true; +} + int vhost_dev_init(struct vhost_dev *hdev, void *opaque, VhostBackendType backend_type, uint32_t busyloop_timeout) { @@ -1604,7 +1635,8 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, }; if (hdev->migration_blocker == NULL) { -if (!vhost_dev_can_log(hdev)) { +if (!vhost_dev_can_log(hdev) && !vhost_hdev_can_sw_lm(hdev) +&& hdev->migration_blocker == NULL) { error_setg(>migration_blocker, "Migration disabled: vhost lacks VHOST_F_LOG_ALL feature."); } else if (vhost_dev_log_is_shared(hdev) && !qemu_memfd_alloc_check()) { -- 2.18.4
[RFC PATCH 21/27] vhost: Add vhost_virtqueue_memory_unmap
This is not a huge gain but helps in later changes. Signed-off-by: Eugenio Pérez --- hw/virtio/vhost.c | 38 -- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 9a3c580dcf..eafbbaa751 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -812,6 +812,21 @@ static int vhost_virtqueue_set_addr(struct vhost_dev *dev, return 0; } +static void vhost_virtqueue_memory_unmap(struct vhost_dev *dev, +struct vhost_virtqueue *vq, +bool used_is_dirty) +{ +if (vq->used) { +vhost_memory_unmap(dev, vq->used, vq->used_size, used_is_dirty, 0); +} +if (vq->avail) { +vhost_memory_unmap(dev, vq->avail, vq->avail_size, 0, 0); +} +if (vq->desc) { +vhost_memory_unmap(dev, vq->desc, vq->desc_size, 0, 0); +} +} + static int vhost_dev_set_features(struct vhost_dev *dev, bool enable_log) { @@ -1301,21 +1316,21 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, vq->desc = vhost_memory_map(dev, a, , false); if (!vq->desc || l != s) { r = -ENOMEM; -goto fail_alloc_desc; +goto fail_alloc; } vq->avail_size = s = l = virtio_queue_get_avail_size(vdev, idx); vq->avail_phys = a = virtio_queue_get_avail_addr(vdev, idx); vq->avail = vhost_memory_map(dev, a, , false); if (!vq->avail || l != s) { r = -ENOMEM; -goto fail_alloc_avail; +goto fail_alloc; } vq->used_size = s = l = virtio_queue_get_used_size(vdev, idx); vq->used_phys = a = virtio_queue_get_used_addr(vdev, idx); vq->used = vhost_memory_map(dev, a, , true); if (!vq->used || l != s) { r = -ENOMEM; -goto fail_alloc_used; +goto fail_alloc; } r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev->log_enabled); @@ -1358,15 +1373,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev, fail_vector: fail_kick: fail_alloc: -vhost_memory_unmap(dev, vq->used, virtio_queue_get_used_size(vdev, idx), - 0, 0); -fail_alloc_used: -vhost_memory_unmap(dev, vq->avail, virtio_queue_get_avail_size(vdev, idx), - 0, 0); -fail_alloc_avail: -vhost_memory_unmap(dev, vq->desc, virtio_queue_get_desc_size(vdev, idx), - 0, 0); -fail_alloc_desc: +vhost_virtqueue_memory_unmap(dev, vq, false); return r; } @@ -1408,12 +1415,7 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev, vhost_vq_index); } -vhost_memory_unmap(dev, vq->used, virtio_queue_get_used_size(vdev, idx), - 1, virtio_queue_get_used_size(vdev, idx)); -vhost_memory_unmap(dev, vq->avail, virtio_queue_get_avail_size(vdev, idx), - 0, virtio_queue_get_avail_size(vdev, idx)); -vhost_memory_unmap(dev, vq->desc, virtio_queue_get_desc_size(vdev, idx), - 0, virtio_queue_get_desc_size(vdev, idx)); +vhost_virtqueue_memory_unmap(dev, vq, true); } static void vhost_eventfd_add(MemoryListener *listener, -- 2.18.4
[RFC PATCH 10/27] vhost: Allocate shadow vring
Signed-off-by: Eugenio Pérez --- hw/virtio/vhost-sw-lm-ring.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/virtio/vhost-sw-lm-ring.c b/hw/virtio/vhost-sw-lm-ring.c index cbf53965cd..cd7b5ba772 100644 --- a/hw/virtio/vhost-sw-lm-ring.c +++ b/hw/virtio/vhost-sw-lm-ring.c @@ -16,8 +16,11 @@ #include "qemu/event_notifier.h" typedef struct VhostShadowVirtqueue { +struct vring vring; EventNotifier hdev_notifier; VirtQueue *vq; + +vring_desc_t descs[]; } VhostShadowVirtqueue; static inline bool vhost_vring_should_kick(VhostShadowVirtqueue *vq) @@ -37,10 +40,12 @@ VhostShadowVirtqueue *vhost_sw_lm_shadow_vq(struct vhost_dev *dev, int idx) .index = idx }; VirtQueue *vq = virtio_get_queue(dev->vdev, idx); +unsigned num = virtio_queue_get_num(dev->vdev, idx); +size_t ring_size = vring_size(num, VRING_DESC_ALIGN_SIZE); VhostShadowVirtqueue *svq; int r; -svq = g_new0(VhostShadowVirtqueue, 1); +svq = g_malloc0(sizeof(*svq) + ring_size); svq->vq = vq; r = event_notifier_init(>hdev_notifier, 0); -- 2.18.4
[RFC PATCH 12/27] virtio: Add virtio_queue_full
Signed-off-by: Eugenio Pérez --- include/hw/virtio/virtio.h | 2 ++ hw/virtio/virtio.c | 15 +-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index b9b8497ea0..0a7f5cc63e 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -233,6 +233,8 @@ int virtio_queue_ready(VirtQueue *vq); int virtio_queue_empty(VirtQueue *vq); +bool virtio_queue_full(const VirtQueue *vq); + /* Host binding interface. */ uint32_t virtio_config_readb(VirtIODevice *vdev, uint32_t addr); diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 3469946538..77ca5f6b6f 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -684,6 +684,17 @@ int virtio_queue_empty(VirtQueue *vq) } } +static bool virtio_queue_full_rcu(const VirtQueue *vq) +{ +return vq->inuse >= vq->vring.num; +} + +bool virtio_queue_full(const VirtQueue *vq) +{ +RCU_READ_LOCK_GUARD(); +return virtio_queue_full_rcu(vq); +} + static void virtqueue_unmap_sg(VirtQueue *vq, const VirtQueueElement *elem, unsigned int len) { @@ -1453,7 +1464,7 @@ static void *virtqueue_split_pop(VirtQueue *vq, size_t sz) max = vq->vring.num; -if (vq->inuse >= vq->vring.num) { +if (unlikely(virtio_queue_full_rcu(vq))) { virtio_error(vdev, "Virtqueue size exceeded"); goto done; } @@ -1588,7 +1599,7 @@ static void *virtqueue_packed_pop(VirtQueue *vq, size_t sz) max = vq->vring.num; -if (vq->inuse >= vq->vring.num) { +if (unlikely(virtio_queue_full_rcu(vq))) { virtio_error(vdev, "Virtqueue size exceeded"); goto done; } -- 2.18.4
[RFC PATCH 20/27] vhost: Return used buffers
Signed-off-by: Eugenio Pérez --- hw/virtio/vhost-sw-lm-ring.h | 3 +++ hw/virtio/vhost-sw-lm-ring.c | 14 +++ hw/virtio/vhost.c| 46 +--- 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/hw/virtio/vhost-sw-lm-ring.h b/hw/virtio/vhost-sw-lm-ring.h index 429a125558..0c4fa772c7 100644 --- a/hw/virtio/vhost-sw-lm-ring.h +++ b/hw/virtio/vhost-sw-lm-ring.h @@ -17,6 +17,9 @@ typedef struct VhostShadowVirtqueue VhostShadowVirtqueue; +VirtIODevice *vhost_vring_vdev(VhostShadowVirtqueue *svq); +VirtQueue *vhost_vring_vdev_vq(VhostShadowVirtqueue *svq); + bool vhost_vring_kick(VhostShadowVirtqueue *vq); int vhost_vring_add(VhostShadowVirtqueue *vq, VirtQueueElement *elem); VirtQueueElement *vhost_vring_get_buf_rcu(VhostShadowVirtqueue *vq, size_t sz); diff --git a/hw/virtio/vhost-sw-lm-ring.c b/hw/virtio/vhost-sw-lm-ring.c index 4fafd1b278..244c722910 100644 --- a/hw/virtio/vhost-sw-lm-ring.c +++ b/hw/virtio/vhost-sw-lm-ring.c @@ -46,6 +46,16 @@ typedef struct VhostShadowVirtqueue { vring_desc_t descs[]; } VhostShadowVirtqueue; +VirtIODevice *vhost_vring_vdev(VhostShadowVirtqueue *svq) +{ +return svq->vdev; +} + +VirtQueue *vhost_vring_vdev_vq(VhostShadowVirtqueue *svq) +{ +return svq->vq; +} + static bool vhost_vring_should_kick_rcu(VhostShadowVirtqueue *vq) { VirtIODevice *vdev = vq->vdev; @@ -179,10 +189,6 @@ static int vhost_vring_add_split(VhostShadowVirtqueue *vq, int vhost_vring_add(VhostShadowVirtqueue *vq, VirtQueueElement *elem) { int host_head = vhost_vring_add_split(vq, elem); -if (vq->ring_id_maps[host_head]) { -g_free(vq->ring_id_maps[host_head]); -} - vq->ring_id_maps[host_head] = elem; return 0; } diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index ac2bc14190..9a3c580dcf 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -986,17 +986,50 @@ static void handle_sw_lm_vq(VirtIODevice *vdev, VirtQueue *vq) } while(!virtio_queue_empty(vq)); } +static void handle_sw_lm_vq_call(struct vhost_dev *hdev, + VhostShadowVirtqueue *svq) +{ +VirtQueueElement *elem; +VirtIODevice *vdev = vhost_vring_vdev(svq); +VirtQueue *vq = vhost_vring_vdev_vq(svq); +uint16_t idx = virtio_get_queue_index(vq); + +RCU_READ_LOCK_GUARD(); +/* + * Make used all buffers as possible. + */ +do { +unsigned i = 0; + +vhost_vring_set_notification_rcu(svq, false); +while (true) { +elem = vhost_vring_get_buf_rcu(svq, sizeof(*elem)); +if (!elem) { +break; +} + +assert(i < virtio_queue_get_num(vdev, idx)); +virtqueue_fill(vq, elem, elem->len, i++); +} + +virtqueue_flush(vq, i); +virtio_notify_irqfd(vdev, vq); + +vhost_vring_set_notification_rcu(svq, true); +} while (vhost_vring_poll_rcu(svq)); +} + static void vhost_handle_call(EventNotifier *n) { struct vhost_virtqueue *hvq = container_of(n, struct vhost_virtqueue, masked_notifier); struct vhost_dev *vdev = hvq->dev; -int idx = vdev->vq_index + (hvq == >vqs[0] ? 0 : 1); -VirtQueue *vq = virtio_get_queue(vdev->vdev, idx); +int idx = hvq == >vqs[0] ? 0 : 1; +VhostShadowVirtqueue *vq = vdev->sw_lm_shadow_vq[idx]; if (event_notifier_test_and_clear(n)) { -virtio_notify_irqfd(vdev->vdev, vq); +handle_sw_lm_vq_call(vdev, vq); } } @@ -1028,6 +1061,7 @@ static int vhost_sw_live_migration_start(struct vhost_dev *dev) for (idx = 0; idx < dev->nvqs; ++idx) { struct vhost_virtqueue *vq = >vqs[idx]; +unsigned num = virtio_queue_get_num(dev->vdev, idx); struct vhost_vring_addr addr = { .index = idx, }; @@ -1044,6 +1078,12 @@ static int vhost_sw_live_migration_start(struct vhost_dev *dev) r = dev->vhost_ops->vhost_set_vring_addr(dev, ); assert(r == 0); +r = vhost_backend_update_device_iotlb(dev, addr.used_user_addr, + addr.used_user_addr, + sizeof(vring_used_elem_t) * num, + IOMMU_RW); +assert(r == 0); + r = dev->vhost_ops->vhost_set_vring_base(dev, ); assert(r == 0); } -- 2.18.4
[RFC PATCH 18/27] vhost: add vhost_vring_poll_rcu
Signed-off-by: Eugenio Pérez --- hw/virtio/vhost-sw-lm-ring.h | 2 ++ hw/virtio/vhost-sw-lm-ring.c | 18 ++ 2 files changed, 20 insertions(+) diff --git a/hw/virtio/vhost-sw-lm-ring.h b/hw/virtio/vhost-sw-lm-ring.h index c537500d9e..03257d60c1 100644 --- a/hw/virtio/vhost-sw-lm-ring.h +++ b/hw/virtio/vhost-sw-lm-ring.h @@ -22,6 +22,8 @@ int vhost_vring_add(VhostShadowVirtqueue *vq, VirtQueueElement *elem); /* Called within rcu_read_lock(). */ void vhost_vring_set_notification_rcu(VhostShadowVirtqueue *vq, bool enable); +/* Called within rcu_read_lock(). */ +bool vhost_vring_poll_rcu(VhostShadowVirtqueue *vq); void vhost_vring_write_addr(const VhostShadowVirtqueue *vq, struct vhost_vring_addr *addr); diff --git a/hw/virtio/vhost-sw-lm-ring.c b/hw/virtio/vhost-sw-lm-ring.c index c3244c550e..3652889d8e 100644 --- a/hw/virtio/vhost-sw-lm-ring.c +++ b/hw/virtio/vhost-sw-lm-ring.c @@ -34,6 +34,12 @@ typedef struct VhostShadowVirtqueue { /* Next free descriptor */ uint16_t free_head; +/* Last seen used idx */ +uint16_t shadow_used_idx; + +/* Next head to consume from device */ +uint16_t used_idx; + /* Cache for exposed notification flag */ bool notification; @@ -83,6 +89,18 @@ void vhost_vring_set_notification_rcu(VhostShadowVirtqueue *vq, bool enable) smp_mb(); } +bool vhost_vring_poll_rcu(VhostShadowVirtqueue *vq) +{ +if (vq->used_idx != vq->shadow_used_idx) { +return true; +} + +smp_rmb(); +vq->shadow_used_idx = virtio_tswap16(vq->vdev, vq->vring.used->idx); + +return vq->used_idx != vq->shadow_used_idx; +} + static void vhost_vring_write_descs(VhostShadowVirtqueue *vq, const struct iovec *iovec, size_t num, bool more_descs, bool write) -- 2.18.4
[RFC PATCH 09/27] vhost: Route host->guest notification through qemu
Signed-off-by: Eugenio Pérez --- hw/virtio/vhost-sw-lm-ring.c | 3 +++ hw/virtio/vhost.c| 20 2 files changed, 23 insertions(+) diff --git a/hw/virtio/vhost-sw-lm-ring.c b/hw/virtio/vhost-sw-lm-ring.c index 0192e77831..cbf53965cd 100644 --- a/hw/virtio/vhost-sw-lm-ring.c +++ b/hw/virtio/vhost-sw-lm-ring.c @@ -50,6 +50,9 @@ VhostShadowVirtqueue *vhost_sw_lm_shadow_vq(struct vhost_dev *dev, int idx) r = dev->vhost_ops->vhost_set_vring_kick(dev, ); assert(r == 0); +vhost_virtqueue_mask(dev, dev->vdev, idx, true); +vhost_virtqueue_pending(dev, idx); + return svq; } diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 1d55e26d45..9352c56bfa 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -960,12 +960,29 @@ static void handle_sw_lm_vq(VirtIODevice *vdev, VirtQueue *vq) vhost_vring_kick(svq); } +static void vhost_handle_call(EventNotifier *n) +{ +struct vhost_virtqueue *hvq = container_of(n, + struct vhost_virtqueue, + masked_notifier); +struct vhost_dev *vdev = hvq->dev; +int idx = vdev->vq_index + (hvq == >vqs[0] ? 0 : 1); +VirtQueue *vq = virtio_get_queue(vdev->vdev, idx); + +if (event_notifier_test_and_clear(n)) { +virtio_queue_invalidate_signalled_used(vdev->vdev, idx); +virtio_notify_irqfd(vdev->vdev, vq); +} +} + static int vhost_sw_live_migration_stop(struct vhost_dev *dev) { int idx; vhost_dev_enable_notifiers(dev, dev->vdev); for (idx = 0; idx < dev->nvqs; ++idx) { +vhost_virtqueue_mask(dev, dev->vdev, idx, false); +vhost_virtqueue_pending(dev, idx); vhost_sw_lm_shadow_vq_free(dev->sw_lm_shadow_vq[idx]); } @@ -977,7 +994,10 @@ static int vhost_sw_live_migration_start(struct vhost_dev *dev) int idx; for (idx = 0; idx < dev->nvqs; ++idx) { +struct vhost_virtqueue *vq = >vqs[idx]; + dev->sw_lm_shadow_vq[idx] = vhost_sw_lm_shadow_vq(dev, idx); +event_notifier_set_handler(>masked_notifier, vhost_handle_call); } vhost_dev_disable_notifiers(dev, dev->vdev); -- 2.18.4
[RFC PATCH 08/27] vhost: Add a flag for software assisted Live Migration
Signed-off-by: Eugenio Pérez --- include/hw/virtio/vhost.h | 1 + hw/virtio/vhost.c | 17 +++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 93cc3f1ae3..ef920a8076 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -84,6 +84,7 @@ struct vhost_dev { uint64_t backend_cap; bool started; bool log_enabled; +bool sw_lm_enabled; uint64_t log_size; VhostShadowVirtqueue *sw_lm_shadow_vq[2]; VirtIOHandleOutput sw_lm_vq_handler; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index a55b684b5f..1d55e26d45 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -988,11 +988,16 @@ static int vhost_sw_live_migration_start(struct vhost_dev *dev) static int vhost_sw_live_migration_enable(struct vhost_dev *dev, bool enable_lm) { +int r; + if (enable_lm) { -return vhost_sw_live_migration_start(dev); +r = vhost_sw_live_migration_start(dev); } else { -return vhost_sw_live_migration_stop(dev); +r = vhost_sw_live_migration_stop(dev); } + +dev->sw_lm_enabled = enable_lm; +return r; } static void vhost_sw_lm_global_start(MemoryListener *listener) @@ -1466,6 +1471,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, hdev->log = NULL; hdev->log_size = 0; hdev->log_enabled = false; +hdev->sw_lm_enabled = false; hdev->started = false; memory_listener_register(>memory_listener, _space_memory); QLIST_INSERT_HEAD(_devices, hdev, entry); @@ -1571,6 +1577,13 @@ void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev) BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); int i, r; +if (hdev->sw_lm_enabled) { +/* We've been called after migration is completed, so no need to + disable it again +*/ +return; +} + for (i = 0; i < hdev->nvqs; ++i) { r = virtio_bus_set_host_notifier(VIRTIO_BUS(qbus), hdev->vq_index + i, false); -- 2.18.4
[RFC PATCH 17/27] vhost: add vhost_vring_set_notification_rcu
Signed-off-by: Eugenio Pérez --- hw/virtio/vhost-sw-lm-ring.h | 4 hw/virtio/vhost-sw-lm-ring.c | 23 +++ 2 files changed, 27 insertions(+) diff --git a/hw/virtio/vhost-sw-lm-ring.h b/hw/virtio/vhost-sw-lm-ring.h index 29d21feaf4..c537500d9e 100644 --- a/hw/virtio/vhost-sw-lm-ring.h +++ b/hw/virtio/vhost-sw-lm-ring.h @@ -19,6 +19,10 @@ typedef struct VhostShadowVirtqueue VhostShadowVirtqueue; bool vhost_vring_kick(VhostShadowVirtqueue *vq); int vhost_vring_add(VhostShadowVirtqueue *vq, VirtQueueElement *elem); + +/* Called within rcu_read_lock(). */ +void vhost_vring_set_notification_rcu(VhostShadowVirtqueue *vq, bool enable); + void vhost_vring_write_addr(const VhostShadowVirtqueue *vq, struct vhost_vring_addr *addr); diff --git a/hw/virtio/vhost-sw-lm-ring.c b/hw/virtio/vhost-sw-lm-ring.c index aed005c2d9..c3244c550e 100644 --- a/hw/virtio/vhost-sw-lm-ring.c +++ b/hw/virtio/vhost-sw-lm-ring.c @@ -34,6 +34,9 @@ typedef struct VhostShadowVirtqueue { /* Next free descriptor */ uint16_t free_head; +/* Cache for exposed notification flag */ +bool notification; + vring_desc_t descs[]; } VhostShadowVirtqueue; @@ -60,6 +63,26 @@ bool vhost_vring_kick(VhostShadowVirtqueue *vq) : true; } +void vhost_vring_set_notification_rcu(VhostShadowVirtqueue *vq, bool enable) +{ +uint16_t notification_flag; + +if (vq->notification == enable) { +return; +} + +notification_flag = virtio_tswap16(vq->vdev, VRING_AVAIL_F_NO_INTERRUPT); + +vq->notification = enable; +if (enable) { +vq->vring.avail->flags &= ~notification_flag; +} else { +vq->vring.avail->flags |= notification_flag; +} + +smp_mb(); +} + static void vhost_vring_write_descs(VhostShadowVirtqueue *vq, const struct iovec *iovec, size_t num, bool more_descs, bool write) -- 2.18.4
[RFC PATCH 15/27] vhost: Do not invalidate signalled used
Since we are in control of guest' VQ again, we can trust on it. Signed-off-by: Eugenio Pérez --- hw/virtio/vhost.c | 1 - 1 file changed, 1 deletion(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 304e0baa61..ac2bc14190 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -996,7 +996,6 @@ static void vhost_handle_call(EventNotifier *n) VirtQueue *vq = virtio_get_queue(vdev->vdev, idx); if (event_notifier_test_and_clear(n)) { -virtio_queue_invalidate_signalled_used(vdev->vdev, idx); virtio_notify_irqfd(vdev->vdev, vq); } } -- 2.18.4
[RFC PATCH 02/27] vhost: Add device callback in vhost_migration_log
This allows code to reuse the logic to not to re-enable or re-disable migration mechanisms. Code works the same way as before. Signed-off-by: Eugenio Pérez --- hw/virtio/vhost.c | 12 +++- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 2bd8cdf893..2adb2718c1 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -862,7 +862,9 @@ err_features: return r; } -static int vhost_migration_log(MemoryListener *listener, bool enable) +static int vhost_migration_log(MemoryListener *listener, + bool enable, + int (*device_cb)(struct vhost_dev *, bool)) { struct vhost_dev *dev = container_of(listener, struct vhost_dev, memory_listener); @@ -877,14 +879,14 @@ static int vhost_migration_log(MemoryListener *listener, bool enable) r = 0; if (!enable) { -r = vhost_dev_set_log(dev, false); +r = device_cb(dev, false); if (r < 0) { goto check_dev_state; } vhost_log_put(dev, false); } else { vhost_dev_log_resize(dev, vhost_get_log_size(dev)); -r = vhost_dev_set_log(dev, true); +r = device_cb(dev, true); if (r < 0) { goto check_dev_state; } @@ -916,7 +918,7 @@ static void vhost_log_global_start(MemoryListener *listener) { int r; -r = vhost_migration_log(listener, true); +r = vhost_migration_log(listener, true, vhost_dev_set_log); if (r < 0) { abort(); } @@ -926,7 +928,7 @@ static void vhost_log_global_stop(MemoryListener *listener) { int r; -r = vhost_migration_log(listener, false); +r = vhost_migration_log(listener, false, vhost_dev_set_log); if (r < 0) { abort(); } -- 2.18.4
[Bug 824074] Re: Provide runtime option to expose the supported list of keymaps for vnc
The QEMU project is currently considering to move its bug tracking to another system. For this we need to know which bugs are still valid and which could be closed already. Thus we are setting older bugs to "Incomplete" now. If you still think this bug report here is valid, then please switch the state back to "New" within the next 60 days, otherwise this report will be marked as "Expired". Or mark it as "Fix Released" if the problem has been solved with a newer version of QEMU already. Thank you and sorry for the inconvenience. ** Changed in: qemu Status: New => Incomplete -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/824074 Title: Provide runtime option to expose the supported list of keymaps for vnc Status in QEMU: Incomplete Bug description: As discussed in the ganeti group[1], I'm opening this bug to request that qemu provides a runtime command or switch to list the supported keymaps for vnc. [1] - http://groups.google.com/group/ganeti/browse_thread/thread/dd524f5311d8d79e To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/824074/+subscriptions
[RFC PATCH 07/27] vhost: Route guest->host notification through qemu
Signed-off-by: Eugenio Pérez --- hw/virtio/vhost-sw-lm-ring.h | 26 + include/hw/virtio/vhost.h| 3 ++ hw/virtio/vhost-sw-lm-ring.c | 60 + hw/virtio/vhost.c| 100 +-- hw/virtio/meson.build| 2 +- 5 files changed, 187 insertions(+), 4 deletions(-) create mode 100644 hw/virtio/vhost-sw-lm-ring.h create mode 100644 hw/virtio/vhost-sw-lm-ring.c diff --git a/hw/virtio/vhost-sw-lm-ring.h b/hw/virtio/vhost-sw-lm-ring.h new file mode 100644 index 00..86dc081b93 --- /dev/null +++ b/hw/virtio/vhost-sw-lm-ring.h @@ -0,0 +1,26 @@ +/* + * vhost software live migration ring + * + * SPDX-FileCopyrightText: Red Hat, Inc. 2020 + * SPDX-FileContributor: Author: Eugenio Pérez + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#ifndef VHOST_SW_LM_RING_H +#define VHOST_SW_LM_RING_H + +#include "qemu/osdep.h" + +#include "hw/virtio/virtio.h" +#include "hw/virtio/vhost.h" + +typedef struct VhostShadowVirtqueue VhostShadowVirtqueue; + +bool vhost_vring_kick(VhostShadowVirtqueue *vq); + +VhostShadowVirtqueue *vhost_sw_lm_shadow_vq(struct vhost_dev *dev, int idx); + +void vhost_sw_lm_shadow_vq_free(VhostShadowVirtqueue *vq); + +#endif diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index b5b7496537..93cc3f1ae3 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -54,6 +54,8 @@ struct vhost_iommu { QLIST_ENTRY(vhost_iommu) iommu_next; }; +typedef struct VhostShadowVirtqueue VhostShadowVirtqueue; + typedef struct VhostDevConfigOps { /* Vhost device config space changed callback */ @@ -83,6 +85,7 @@ struct vhost_dev { bool started; bool log_enabled; uint64_t log_size; +VhostShadowVirtqueue *sw_lm_shadow_vq[2]; VirtIOHandleOutput sw_lm_vq_handler; Error *migration_blocker; const VhostOps *vhost_ops; diff --git a/hw/virtio/vhost-sw-lm-ring.c b/hw/virtio/vhost-sw-lm-ring.c new file mode 100644 index 00..0192e77831 --- /dev/null +++ b/hw/virtio/vhost-sw-lm-ring.c @@ -0,0 +1,60 @@ +/* + * vhost software live migration ring + * + * SPDX-FileCopyrightText: Red Hat, Inc. 2020 + * SPDX-FileContributor: Author: Eugenio Pérez + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "hw/virtio/vhost-sw-lm-ring.h" +#include "hw/virtio/vhost.h" + +#include "standard-headers/linux/vhost_types.h" +#include "standard-headers/linux/virtio_ring.h" + +#include "qemu/event_notifier.h" + +typedef struct VhostShadowVirtqueue { +EventNotifier hdev_notifier; +VirtQueue *vq; +} VhostShadowVirtqueue; + +static inline bool vhost_vring_should_kick(VhostShadowVirtqueue *vq) +{ +return virtio_queue_get_used_notify_split(vq->vq); +} + +bool vhost_vring_kick(VhostShadowVirtqueue *vq) +{ +return vhost_vring_should_kick(vq) ? event_notifier_set(>hdev_notifier) + : true; +} + +VhostShadowVirtqueue *vhost_sw_lm_shadow_vq(struct vhost_dev *dev, int idx) +{ +struct vhost_vring_file file = { +.index = idx +}; +VirtQueue *vq = virtio_get_queue(dev->vdev, idx); +VhostShadowVirtqueue *svq; +int r; + +svq = g_new0(VhostShadowVirtqueue, 1); +svq->vq = vq; + +r = event_notifier_init(>hdev_notifier, 0); +assert(r == 0); + +file.fd = event_notifier_get_fd(>hdev_notifier); +r = dev->vhost_ops->vhost_set_vring_kick(dev, ); +assert(r == 0); + +return svq; +} + +void vhost_sw_lm_shadow_vq_free(VhostShadowVirtqueue *vq) +{ +event_notifier_cleanup(>hdev_notifier); +g_free(vq); +} diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 9cbd52a7f1..a55b684b5f 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -13,6 +13,8 @@ * GNU GPL, version 2 or (at your option) any later version. */ +#include "hw/virtio/vhost-sw-lm-ring.h" + #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/virtio/vhost.h" @@ -61,6 +63,20 @@ bool vhost_has_free_slot(void) return slots_limit > used_memslots; } +static struct vhost_dev *vhost_dev_from_virtio(const VirtIODevice *vdev) +{ +struct vhost_dev *hdev; + +QLIST_FOREACH(hdev, _devices, entry) { +if (hdev->vdev == vdev) { +return hdev; +} +} + +assert(hdev); +return NULL; +} + static bool vhost_dev_can_log(const struct vhost_dev *hdev) { return hdev->features & (0x1ULL << VHOST_F_LOG_ALL); @@ -148,6 +164,12 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev, return 0; } +static void vhost_log_sync_nop(MemoryListener *listener, + MemoryRegionSection *section) +{ +return; +} + static void vhost_log_sync(MemoryListener *listener, MemoryRegionSection *section) { @@ -928,6 +950,71 @@ static void vhost_log_global_stop(MemoryListener *listener) } } +static void handle_sw_lm_vq(VirtIODevice *vdev, VirtQueue *vq) +{ +struct vhost_dev *hdev =
[RFC PATCH 13/27] vhost: Send buffers to device
Signed-off-by: Eugenio Pérez --- hw/virtio/vhost-sw-lm-ring.h | 3 + hw/virtio/vhost-sw-lm-ring.c | 134 +-- hw/virtio/vhost.c| 59 ++- 3 files changed, 189 insertions(+), 7 deletions(-) diff --git a/hw/virtio/vhost-sw-lm-ring.h b/hw/virtio/vhost-sw-lm-ring.h index 86dc081b93..29d21feaf4 100644 --- a/hw/virtio/vhost-sw-lm-ring.h +++ b/hw/virtio/vhost-sw-lm-ring.h @@ -18,6 +18,9 @@ typedef struct VhostShadowVirtqueue VhostShadowVirtqueue; bool vhost_vring_kick(VhostShadowVirtqueue *vq); +int vhost_vring_add(VhostShadowVirtqueue *vq, VirtQueueElement *elem); +void vhost_vring_write_addr(const VhostShadowVirtqueue *vq, + struct vhost_vring_addr *addr); VhostShadowVirtqueue *vhost_sw_lm_shadow_vq(struct vhost_dev *dev, int idx); diff --git a/hw/virtio/vhost-sw-lm-ring.c b/hw/virtio/vhost-sw-lm-ring.c index cd7b5ba772..aed005c2d9 100644 --- a/hw/virtio/vhost-sw-lm-ring.c +++ b/hw/virtio/vhost-sw-lm-ring.c @@ -9,6 +9,7 @@ #include "hw/virtio/vhost-sw-lm-ring.h" #include "hw/virtio/vhost.h" +#include "hw/virtio/virtio-access.h" #include "standard-headers/linux/vhost_types.h" #include "standard-headers/linux/virtio_ring.h" @@ -19,21 +20,140 @@ typedef struct VhostShadowVirtqueue { struct vring vring; EventNotifier hdev_notifier; VirtQueue *vq; +VirtIODevice *vdev; + +/* Map for returning guest's descriptors */ +VirtQueueElement **ring_id_maps; + +/* Next head to expose to device */ +uint16_t avail_idx_shadow; + +/* Number of descriptors added since last notification */ +uint16_t num_added; + +/* Next free descriptor */ +uint16_t free_head; vring_desc_t descs[]; } VhostShadowVirtqueue; -static inline bool vhost_vring_should_kick(VhostShadowVirtqueue *vq) +static bool vhost_vring_should_kick_rcu(VhostShadowVirtqueue *vq) { -return virtio_queue_get_used_notify_split(vq->vq); +VirtIODevice *vdev = vq->vdev; +vq->num_added = 0; + +smp_rmb(); +return !(vq->vring.used->flags + & virtio_tswap16(vdev, VRING_USED_F_NO_NOTIFY)); } +static bool vhost_vring_should_kick(VhostShadowVirtqueue *vq) +{ +RCU_READ_LOCK_GUARD(); +return vhost_vring_should_kick_rcu(vq); +} + + bool vhost_vring_kick(VhostShadowVirtqueue *vq) { return vhost_vring_should_kick(vq) ? event_notifier_set(>hdev_notifier) : true; } +static void vhost_vring_write_descs(VhostShadowVirtqueue *vq, +const struct iovec *iovec, +size_t num, bool more_descs, bool write) +{ +uint16_t i = vq->free_head, last = vq->free_head; +unsigned n; +const VirtIODevice *vdev = vq->vdev; +uint16_t flags = write ? virtio_tswap16(vdev, VRING_DESC_F_WRITE) : 0; +vring_desc_t *descs = vq->vring.desc; + +if (num == 0) { +return; +} + +for (n = 0; n < num; n++) { +if (more_descs || (n + 1 < num)) { +descs[i].flags = flags | virtio_tswap16(vdev, VRING_DESC_F_NEXT); +} else { +descs[i].flags = flags; +} +descs[i].addr = virtio_tswap64(vdev, (hwaddr)iovec[n].iov_base); +descs[i].len = virtio_tswap32(vdev, iovec[n].iov_len); + +last = i; +i = virtio_tswap16(vdev, descs[i].next); +} + +vq->free_head = virtio_tswap16(vdev, descs[last].next); +} + +/* virtqueue_add: + * @vq: The #VirtQueue + * @elem: The #VirtQueueElement + * + * Add an avail element to a virtqueue. + */ +static int vhost_vring_add_split(VhostShadowVirtqueue *vq, + const VirtQueueElement *elem) +{ +int head; +unsigned avail_idx; +const VirtIODevice *vdev; +vring_avail_t *avail; + +RCU_READ_LOCK_GUARD(); +vdev = vq->vdev; +avail = vq->vring.avail; + +head = vq->free_head; + +/* We need some descriptors here */ +assert(elem->out_num || elem->in_num); + +vhost_vring_write_descs(vq, elem->out_sg, elem->out_num, + elem->in_num > 0, false); +vhost_vring_write_descs(vq, elem->in_sg, elem->in_num, false, true); + +/* Put entry in available array (but don't update avail->idx until they + * do sync). */ +avail_idx = vq->avail_idx_shadow & (vq->vring.num - 1); +avail->ring[avail_idx] = virtio_tswap16(vdev, head); +vq->avail_idx_shadow++; + +/* Expose descriptors to device */ +smp_wmb(); +avail->idx = virtio_tswap16(vdev, vq->avail_idx_shadow); + +/* threoretically possible. Kick just in case */ +if (unlikely(vq->num_added++ == (uint16_t)-1)) { +vhost_vring_kick(vq); +} + +return head; +} + +int vhost_vring_add(VhostShadowVirtqueue *vq, VirtQueueElement *elem) +{ +int host_head = vhost_vring_add_split(vq, elem); +if (vq->ring_id_maps[host_head]) { +g_free(vq->ring_id_maps[host_head]); +} + +
[RFC PATCH 00/27] vDPA software assisted live migration
This series enable vDPA software assisted live migration for vhost-net devices. This is a new method of vhost devices migration: Instead of relay on vDPA device's dirty logging capability, SW assisted LM intercepts dataplane, forwarding the descriptors between VM and device. In this migration mode, qemu offers a new vring to the device to read and write into, and disable vhost notifiers, processing guest and vhost notifications in qemu. On used buffer relay, qemu will mark the dirty memory as with plain virtio-net devices. This way, devices does not need to have dirty page logging capability. This series is a POC doing SW LM for vhost-net devices, which already have dirty page logging capabilities. None of the changes have actual effect with current devices until last two patches (26 and 27) are applied, but they can be rebased on top of any other. These checks the device to meet all requirements, and disable vhost-net devices logging so migration goes through SW LM. This last patch is not meant to be applied in the final revision, it is in the series just for testing purposes. For use SW assisted LM these vhost-net devices need to be instantiated: * With IOMMU (iommu_platform=on,ats=on) * Without event_idx (event_idx=off) Just the notification forwarding (with no descriptor relay) can be achieved with patches 7 and 9, and starting migration. Partial applies between 13 and 24 will not work while migrating on source, and patch 25 is needed for the destination to resume network activity. It is based on the ideas of DPDK SW assisted LM, in the series of DPDK's https://patchwork.dpdk.org/cover/48370/ . Comments are welcome. Thanks! Eugenio Pérez (27): vhost: Add vhost_dev_can_log vhost: Add device callback in vhost_migration_log vhost: Move log resize/put to vhost_dev_set_log vhost: add vhost_kernel_set_vring_enable vhost: Add hdev->dev.sw_lm_vq_handler virtio: Add virtio_queue_get_used_notify_split vhost: Route guest->host notification through qemu vhost: Add a flag for software assisted Live Migration vhost: Route host->guest notification through qemu vhost: Allocate shadow vring virtio: const-ify all virtio_tswap* functions virtio: Add virtio_queue_full vhost: Send buffers to device virtio: Remove virtio_queue_get_used_notify_split vhost: Do not invalidate signalled used virtio: Expose virtqueue_alloc_element vhost: add vhost_vring_set_notification_rcu vhost: add vhost_vring_poll_rcu vhost: add vhost_vring_get_buf_rcu vhost: Return used buffers vhost: Add vhost_virtqueue_memory_unmap vhost: Add vhost_virtqueue_memory_map vhost: unmap qemu's shadow virtqueues on sw live migration vhost: iommu changes vhost: Do not commit vhost used idx on vhost_virtqueue_stop vhost: Add vhost_hdev_can_sw_lm vhost: forbid vhost devices logging hw/virtio/vhost-sw-lm-ring.h | 39 +++ include/hw/virtio/vhost.h | 5 + include/hw/virtio/virtio-access.h | 8 +- include/hw/virtio/virtio.h| 4 + hw/net/virtio-net.c | 39 ++- hw/virtio/vhost-backend.c | 29 ++ hw/virtio/vhost-sw-lm-ring.c | 268 +++ hw/virtio/vhost.c | 431 +- hw/virtio/virtio.c| 18 +- hw/virtio/meson.build | 2 +- 10 files changed, 758 insertions(+), 85 deletions(-) create mode 100644 hw/virtio/vhost-sw-lm-ring.h create mode 100644 hw/virtio/vhost-sw-lm-ring.c -- 2.18.4
[RFC PATCH 06/27] virtio: Add virtio_queue_get_used_notify_split
This function is just used for a few commits, so SW LM is developed incrementally, and it is deleted after it is useful. For a few commits, only the events (irqfd, eventfd) are forwarded. This series adds descriptors forwarding on top of that. Signed-off-by: Eugenio Pérez --- include/hw/virtio/virtio.h | 1 + hw/virtio/virtio.c | 14 ++ 2 files changed, 15 insertions(+) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index b7ece7a6a8..b9b8497ea0 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -225,6 +225,7 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id); void virtio_notify_config(VirtIODevice *vdev); +bool virtio_queue_get_used_notify_split(VirtQueue *vq); bool virtio_queue_get_notification(VirtQueue *vq); void virtio_queue_set_notification(VirtQueue *vq, int enable); diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index ceb58fda6c..3469946538 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -377,6 +377,20 @@ static inline void vring_used_idx_set(VirtQueue *vq, uint16_t val) vq->used_idx = val; } +bool virtio_queue_get_used_notify_split(VirtQueue *vq) +{ +VRingMemoryRegionCaches *caches; +hwaddr pa = offsetof(VRingUsed, flags); +uint16_t flags; + +RCU_READ_LOCK_GUARD(); + +caches = vring_get_region_caches(vq); +assert(caches); +flags = virtio_lduw_phys_cached(vq->vdev, >used, pa); +return !(VRING_USED_F_NO_NOTIFY & flags); +} + /* Called within rcu_read_lock(). */ static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask) { -- 2.18.4
[RFC PATCH 11/27] virtio: const-ify all virtio_tswap* functions
They do not modify vdev, so these should be const as qemu coding style guideline. Signed-off-by: Eugenio Pérez --- include/hw/virtio/virtio-access.h | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/hw/virtio/virtio-access.h b/include/hw/virtio/virtio-access.h index 6818a23a2d..7474f89b5f 100644 --- a/include/hw/virtio/virtio-access.h +++ b/include/hw/virtio/virtio-access.h @@ -24,7 +24,7 @@ #define LEGACY_VIRTIO_IS_BIENDIAN 1 #endif -static inline bool virtio_access_is_big_endian(VirtIODevice *vdev) +static inline bool virtio_access_is_big_endian(const VirtIODevice *vdev) { #if defined(LEGACY_VIRTIO_IS_BIENDIAN) return virtio_is_big_endian(vdev); @@ -147,7 +147,7 @@ static inline uint64_t virtio_ldq_p(VirtIODevice *vdev, const void *ptr) } } -static inline uint16_t virtio_tswap16(VirtIODevice *vdev, uint16_t s) +static inline uint16_t virtio_tswap16(const VirtIODevice *vdev, uint16_t s) { #ifdef HOST_WORDS_BIGENDIAN return virtio_access_is_big_endian(vdev) ? s : bswap16(s); @@ -213,7 +213,7 @@ static inline void virtio_tswap16s(VirtIODevice *vdev, uint16_t *s) *s = virtio_tswap16(vdev, *s); } -static inline uint32_t virtio_tswap32(VirtIODevice *vdev, uint32_t s) +static inline uint32_t virtio_tswap32(const VirtIODevice *vdev, uint32_t s) { #ifdef HOST_WORDS_BIGENDIAN return virtio_access_is_big_endian(vdev) ? s : bswap32(s); @@ -227,7 +227,7 @@ static inline void virtio_tswap32s(VirtIODevice *vdev, uint32_t *s) *s = virtio_tswap32(vdev, *s); } -static inline uint64_t virtio_tswap64(VirtIODevice *vdev, uint64_t s) +static inline uint64_t virtio_tswap64(const VirtIODevice *vdev, uint64_t s) { #ifdef HOST_WORDS_BIGENDIAN return virtio_access_is_big_endian(vdev) ? s : bswap64(s); -- 2.18.4
[RFC PATCH 04/27] vhost: add vhost_kernel_set_vring_enable
Signed-off-by: Eugenio Pérez --- hw/virtio/vhost-backend.c | 29 + 1 file changed, 29 insertions(+) diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index 222bbcc62d..317f1f96fa 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -201,6 +201,34 @@ static int vhost_kernel_get_vq_index(struct vhost_dev *dev, int idx) return idx - dev->vq_index; } +static int vhost_kernel_set_vq_enable(struct vhost_dev *dev, unsigned idx, + bool enable) +{ +struct vhost_vring_file file = { +.index = idx, +}; + +if (!enable) { +file.fd = -1; /* Pass -1 to unbind from file. */ +} else { +struct vhost_net *vn_dev = container_of(dev, struct vhost_net, dev); +file.fd = vn_dev->backend; +} + +return vhost_kernel_net_set_backend(dev, ); +} + +static int vhost_kernel_set_vring_enable(struct vhost_dev *dev, int enable) +{ +int i; + +for (i = 0; i < dev->nvqs; ++i) { +vhost_kernel_set_vq_enable(dev, i, enable); +} + +return 0; +} + #ifdef CONFIG_VHOST_VSOCK static int vhost_kernel_vsock_set_guest_cid(struct vhost_dev *dev, uint64_t guest_cid) @@ -317,6 +345,7 @@ static const VhostOps kernel_ops = { .vhost_set_owner = vhost_kernel_set_owner, .vhost_reset_device = vhost_kernel_reset_device, .vhost_get_vq_index = vhost_kernel_get_vq_index, +.vhost_set_vring_enable = vhost_kernel_set_vring_enable, #ifdef CONFIG_VHOST_VSOCK .vhost_vsock_set_guest_cid = vhost_kernel_vsock_set_guest_cid, .vhost_vsock_set_running = vhost_kernel_vsock_set_running, -- 2.18.4
[RFC PATCH 05/27] vhost: Add hdev->dev.sw_lm_vq_handler
Only virtio-net honors it. Signed-off-by: Eugenio Pérez --- include/hw/virtio/vhost.h | 1 + hw/net/virtio-net.c | 39 --- 2 files changed, 29 insertions(+), 11 deletions(-) diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 4a8bc75415..b5b7496537 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -83,6 +83,7 @@ struct vhost_dev { bool started; bool log_enabled; uint64_t log_size; +VirtIOHandleOutput sw_lm_vq_handler; Error *migration_blocker; const VhostOps *vhost_ops; void *opaque; diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index 9179013ac4..9a69ae3598 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -2628,24 +2628,32 @@ static void virtio_net_tx_bh(void *opaque) } } -static void virtio_net_add_queue(VirtIONet *n, int index) +static void virtio_net_add_queue(VirtIONet *n, int index, + VirtIOHandleOutput custom_handler) { VirtIODevice *vdev = VIRTIO_DEVICE(n); +VirtIOHandleOutput rx_vq_handler = virtio_net_handle_rx; +VirtIOHandleOutput tx_vq_handler; +bool tx_timer = n->net_conf.tx && !strcmp(n->net_conf.tx, "timer"); + +if (custom_handler) { +rx_vq_handler = tx_vq_handler = custom_handler; +} else if (tx_timer) { +tx_vq_handler = virtio_net_handle_tx_timer; +} else { +tx_vq_handler = virtio_net_handle_tx_bh; +} n->vqs[index].rx_vq = virtio_add_queue(vdev, n->net_conf.rx_queue_size, - virtio_net_handle_rx); + rx_vq_handler); +n->vqs[index].tx_vq = virtio_add_queue(vdev, n->net_conf.tx_queue_size, + tx_vq_handler); -if (n->net_conf.tx && !strcmp(n->net_conf.tx, "timer")) { -n->vqs[index].tx_vq = -virtio_add_queue(vdev, n->net_conf.tx_queue_size, - virtio_net_handle_tx_timer); +if (tx_timer) { n->vqs[index].tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, virtio_net_tx_timer, >vqs[index]); } else { -n->vqs[index].tx_vq = -virtio_add_queue(vdev, n->net_conf.tx_queue_size, - virtio_net_handle_tx_bh); n->vqs[index].tx_bh = qemu_bh_new(virtio_net_tx_bh, >vqs[index]); } @@ -2677,6 +2685,10 @@ static void virtio_net_del_queue(VirtIONet *n, int index) static void virtio_net_change_num_queues(VirtIONet *n, int new_max_queues) { VirtIODevice *vdev = VIRTIO_DEVICE(n); +NetClientState *nc = n->nic->conf->peers.ncs[0]; +struct vhost_net *hdev = get_vhost_net(nc); +VirtIOHandleOutput custom_handler = hdev ? hdev->dev.sw_lm_vq_handler + : NULL; int old_num_queues = virtio_get_num_queues(vdev); int new_num_queues = new_max_queues * 2 + 1; int i; @@ -2702,7 +2714,7 @@ static void virtio_net_change_num_queues(VirtIONet *n, int new_max_queues) for (i = old_num_queues - 1; i < new_num_queues - 1; i += 2) { /* new_num_queues > old_num_queues */ -virtio_net_add_queue(n, i / 2); +virtio_net_add_queue(n, i / 2, custom_handler); } /* add ctrl_vq last */ @@ -3256,6 +3268,8 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) VirtIODevice *vdev = VIRTIO_DEVICE(dev); VirtIONet *n = VIRTIO_NET(dev); NetClientState *nc; +struct vhost_net *hdev; +VirtIOHandleOutput custom_handler; int i; if (n->net_conf.mtu) { @@ -3347,8 +3361,11 @@ static void virtio_net_device_realize(DeviceState *dev, Error **errp) n->net_conf.tx_queue_size = MIN(virtio_net_max_tx_queue_size(n), n->net_conf.tx_queue_size); +nc = n->nic_conf.peers.ncs[0]; +hdev = get_vhost_net(nc); +custom_handler = hdev ? hdev->dev.sw_lm_vq_handler : NULL; for (i = 0; i < n->max_queues; i++) { -virtio_net_add_queue(n, i); +virtio_net_add_queue(n, i, custom_handler); } n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl); -- 2.18.4
[PATCH] virtio: reset device on bad guest index in virtio_load()
If we find a queue with an inconsistent guest index value, explicitly mark the device as needing a reset - and broken - via virtio_error(). There's at least one driver implementation - the virtio-win NetKVM driver - that is able to handle a VIRTIO_CONFIG_S_NEEDS_RESET notification and successfully restore the device to a working state. Other implementations do not correctly handle this, but as the VQ is not in a functional state anyway, this is still worth doing. Signed-off-by: John Levon --- hw/virtio/virtio.c | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index ceb58fda6c..eff35fab7c 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3161,12 +3161,15 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) nheads = vring_avail_idx(>vq[i]) - vdev->vq[i].last_avail_idx; /* Check it isn't doing strange things with descriptor numbers. */ if (nheads > vdev->vq[i].vring.num) { -qemu_log_mask(LOG_GUEST_ERROR, - "VQ %d size 0x%x Guest index 0x%x " - "inconsistent with Host index 0x%x: delta 0x%x", - i, vdev->vq[i].vring.num, - vring_avail_idx(>vq[i]), - vdev->vq[i].last_avail_idx, nheads); +virtio_error(vdev, "VQ %d size 0x%x Guest index 0x%x " + "inconsistent with Host index 0x%x: delta 0x%x", + i, vdev->vq[i].vring.num, + vring_avail_idx(>vq[i]), + vdev->vq[i].last_avail_idx, nheads); +vdev->vq[i].used_idx = 0; +vdev->vq[i].shadow_avail_idx = 0; +vdev->vq[i].inuse = 0; +continue; } vdev->vq[i].used_idx = vring_used_idx(>vq[i]); vdev->vq[i].shadow_avail_idx = vring_avail_idx(>vq[i]); -- 2.22.3
[Bug 1214884] Re: Support VDI (Virtualbox) snapshots
The QEMU project is currently considering to move its bug tracking to another system. For this we need to know which bugs are still valid and which could be closed already. Thus we are setting older bugs to "Incomplete" now. If you still think this bug report here is valid, then please switch the state back to "New" within the next 60 days, otherwise this report will be marked as "Expired". Or mark it as "Fix Released" if the problem has been solved with a newer version of QEMU already. Thank you and sorry for the inconvenience. ** Changed in: qemu Status: New => Incomplete -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1214884 Title: Support VDI (Virtualbox) snapshots Status in QEMU: Incomplete Bug description: Please support Snapshots in VDI images. It seems that VirtualBox uses a snapshot for any changes to the main system disc. Even when the user does not create a snapshot. So if I want to mount a VDI disc with the recent system changes, I have to mount the Snapshot. Thanks To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1214884/+subscriptions
[RFC PATCH 01/27] vhost: Add vhost_dev_can_log
Just syntactic sugar. Signed-off-by: Eugenio Pérez --- hw/virtio/vhost.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 614ccc2bcb..2bd8cdf893 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -61,6 +61,11 @@ bool vhost_has_free_slot(void) return slots_limit > used_memslots; } +static bool vhost_dev_can_log(const struct vhost_dev *hdev) +{ +return hdev->features & (0x1ULL << VHOST_F_LOG_ALL); +} + static void vhost_dev_sync_region(struct vhost_dev *dev, MemoryRegionSection *section, uint64_t mfirst, uint64_t mlast, @@ -1347,7 +1352,7 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, }; if (hdev->migration_blocker == NULL) { -if (!(hdev->features & (0x1ULL << VHOST_F_LOG_ALL))) { +if (!vhost_dev_can_log(hdev)) { error_setg(>migration_blocker, "Migration disabled: vhost lacks VHOST_F_LOG_ALL feature."); } else if (vhost_dev_log_is_shared(hdev) && !qemu_memfd_alloc_check()) { -- 2.18.4
[RFC PATCH 03/27] vhost: Move log resize/put to vhost_dev_set_log
Software assisted live migration does not allocate vhost log. Signed-off-by: Eugenio Pérez --- hw/virtio/vhost.c | 24 +--- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 2adb2718c1..9cbd52a7f1 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -828,6 +828,10 @@ static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log) int r, i, idx; hwaddr addr; +if (enable_log) { +vhost_dev_log_resize(dev, vhost_get_log_size(dev)); +} + r = vhost_dev_set_features(dev, enable_log); if (r < 0) { goto err_features; @@ -850,6 +854,10 @@ static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log) goto err_vq; } } + +if (!enable_log) { +vhost_log_put(dev, false); +} return 0; err_vq: for (; i >= 0; --i) { @@ -877,22 +885,8 @@ static int vhost_migration_log(MemoryListener *listener, return 0; } -r = 0; -if (!enable) { -r = device_cb(dev, false); -if (r < 0) { -goto check_dev_state; -} -vhost_log_put(dev, false); -} else { -vhost_dev_log_resize(dev, vhost_get_log_size(dev)); -r = device_cb(dev, true); -if (r < 0) { -goto check_dev_state; -} -} +r = device_cb(dev, enable); -check_dev_state: dev->log_enabled = enable; /* * vhost-user-* devices could change their state during log -- 2.18.4
[Bug 1284090] Re: RFE: QMP: report error reason in BLOCK_IO_ERROR message
The QEMU project is currently considering to move its bug tracking to another system. For this we need to know which bugs are still valid and which could be closed already. Thus we are setting older bugs to "Incomplete" now. If you still think this bug report here is valid, then please switch the state back to "New" within the next 60 days, otherwise this report will be marked as "Expired". Or mark it as "Fix Released" if the problem has been solved with a newer version of QEMU already. Thank you and sorry for the inconvenience. ** Changed in: qemu Status: New => Incomplete -- You received this bug notification because you are a member of qemu- devel-ml, which is subscribed to QEMU. https://bugs.launchpad.net/bugs/1284090 Title: RFE: QMP: report error reason in BLOCK_IO_ERROR message Status in QEMU: Incomplete Bug description: when a disk drive is configured with the error policy enospc for write errors, the monitoring client needs a way to distinguish betwwen generic I/O error and the I/O error for space exausted. The JSON QMP protocol lacks this information: the BLOCK_IO_ERROR message does not provide a reason or code for the error verified, so the monitoring client cannot distinguish the source of the errors. verified against git 105a060188dc6fdd4551571a966514d1a5f6815a To manage notifications about this bug go to: https://bugs.launchpad.net/qemu/+bug/1284090/+subscriptions
Re: [RFC v4 9/9] i386: split cpu accelerators from cpu.c
On 11/20/20 6:44 PM, Eduardo Habkost wrote: > On Fri, Nov 20, 2020 at 03:49:09PM +0100, Claudio Fontana wrote: >> split cpu.c into: >> >> cpu.ccpuid and common x86 cpu functionality >> host-cpu.c host x86 cpu functions and "host" cpu type >> kvm/cpu.cKVM x86 cpu type >> hvf/cpu.cHVF x86 cpu type >> tcg/cpu.cTCG x86 cpu type >> >> The link to the accel class is set in the X86CPUClass classes >> at MODULE_INIT_ACCEL_CPU time, when the accelerator is known. >> >> Signed-off-by: Claudio Fontana > [...] >> +static void hvf_cpu_accel_class_init(ObjectClass *oc, void *data) >> +{ >> +X86CPUAccelClass *acc = X86_CPU_ACCEL_CLASS(oc); >> + >> +acc->cpu_realizefn = host_cpu_realizefn; >> +acc->cpu_common_class_init = hvf_cpu_common_class_init; >> +acc->cpu_instance_init = hvf_cpu_instance_init; >> +}; >> +static const TypeInfo hvf_cpu_accel_type_info = { >> +.name = X86_CPU_ACCEL_TYPE_NAME("hvf"), >> + >> +.parent = TYPE_X86_CPU_ACCEL, >> +.class_init = hvf_cpu_accel_class_init, >> +}; >> +static void hvf_cpu_accel_register_types(void) >> +{ >> +type_register_static(_cpu_accel_type_info); >> +} >> +type_init(hvf_cpu_accel_register_types); >> + >> +static void hvf_cpu_accel_init(void) >> +{ >> +if (hvf_enabled()) { >> +x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME("hvf")); >> +} >> +} >> + >> +accel_cpu_init(hvf_cpu_accel_init); > > The point of my suggestion of using QOM is to not require > separate accel_cpu_init() functions and (hvf|tcg|kvm)_enabled() > checks. > > If we still have separate accel_cpu_init() functions for calling > x86_cpu_accel_init() with the right argument, using a pointer to > static variables like _cpu_accel (like you did before) was > simpler and required less boilerplate code. Yes I agree. > > However, the difference is that with the X86_CPU_ACCEL_TYPE_NAME > macro + object_class_by_name(), you don't need the separate > accel_cpu_init() functions for each accelerator. > > All you need is a single: > > x86_cpu_accel_init(X86_CPU_ACCEL_TYPE_NAME(chosen_accel_name)); > > call somewhere in the initialization path. Makes sense. The problem is just determining chosen_accel_name. > > A good place for the x86_cpu_accel_init() call would be > do_configure_accelerator(), but the function is arch-specific. > That's why I suggested a cpu_accel_arch_init() function at > https://lore.kernel.org/qemu-devel/20201118220750.gp1509...@habkost.net > Fine by me. I'd use a specific init step for this, but that also works. Ciao, Clauidio
[PATCH] virtio: reset device on bad guest index in virtio_load()
If we find a queue with an inconsistent guest index value, explicitly mark the device as needing a reset - and broken - via virtio_error(). There's at least one driver implementation - the virtio-win NetKVM driver - that is able to handle a VIRTIO_CONFIG_S_NEEDS_RESET notification and successfully restore the device to a working state. Other implementations do not correctly handle this, but as the VQ is not in a functional state anyway, this is still worth doing. Signed-off-by: John Levon --- hw/virtio/virtio.c | 15 +-- 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index ceb58fda6c..eff35fab7c 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -3161,12 +3161,15 @@ int virtio_load(VirtIODevice *vdev, QEMUFile *f, int version_id) nheads = vring_avail_idx(>vq[i]) - vdev->vq[i].last_avail_idx; /* Check it isn't doing strange things with descriptor numbers. */ if (nheads > vdev->vq[i].vring.num) { -qemu_log_mask(LOG_GUEST_ERROR, - "VQ %d size 0x%x Guest index 0x%x " - "inconsistent with Host index 0x%x: delta 0x%x", - i, vdev->vq[i].vring.num, - vring_avail_idx(>vq[i]), - vdev->vq[i].last_avail_idx, nheads); +virtio_error(vdev, "VQ %d size 0x%x Guest index 0x%x " + "inconsistent with Host index 0x%x: delta 0x%x", + i, vdev->vq[i].vring.num, + vring_avail_idx(>vq[i]), + vdev->vq[i].last_avail_idx, nheads); +vdev->vq[i].used_idx = 0; +vdev->vq[i].shadow_avail_idx = 0; +vdev->vq[i].inuse = 0; +continue; } vdev->vq[i].used_idx = vring_used_idx(>vq[i]); vdev->vq[i].shadow_avail_idx = vring_avail_idx(>vq[i]); -- 2.22.3
Re: [PATCH v2 3/8] qnum: QNumValue type for QNum value literals
On Fri, Nov 20, 2020 at 06:29:16AM +0100, Markus Armbruster wrote: > Eduardo Habkost writes: > > > On Thu, Nov 19, 2020 at 11:24:52AM +0100, Markus Armbruster wrote: > >> Marc-André Lureau writes: > >> > >> > On Tue, Nov 17, 2020 at 6:42 PM Eduardo Habkost > >> > wrote: > >> > > >> >> On Tue, Nov 17, 2020 at 12:37:56PM +0400, Marc-André Lureau wrote: > >> >> > On Tue, Nov 17, 2020 at 2:43 AM Eduardo Habkost > >> >> wrote: > >> >> > > >> >> > > Provide a separate QNumValue type that can be used for QNum value > >> >> > > literals without the referencing counting and memory allocation > >> >> > > features provided by QObject. > >> >> > > > >> >> > > Signed-off-by: Eduardo Habkost > >> >> > > --- > >> >> > > Changes v1 -> v2: > >> >> > > * Fix "make check" failure, by updating check-qnum unit test to > >> >> > > use the new struct fields > >> >> > > --- > >> >> > > include/qapi/qmp/qnum.h | 40 +++-- > >> >> > > qobject/qnum.c | 78 > >> >> > > - > >> >> > > tests/check-qnum.c | 14 > >> >> > > 3 files changed, 84 insertions(+), 48 deletions(-) > >> >> > > > >> >> > > diff --git a/include/qapi/qmp/qnum.h b/include/qapi/qmp/qnum.h > >> >> > > index 55c27b1c24..62fbdfda68 100644 > >> >> > > --- a/include/qapi/qmp/qnum.h > >> >> > > +++ b/include/qapi/qmp/qnum.h > >> >> > > @@ -46,20 +46,56 @@ typedef enum { > >> >> > > * in range: qnum_get_try_int() / qnum_get_try_uint() check range > >> >> > > and > >> >> > > * convert under the hood. > >> >> > > */ > >> >> > > -struct QNum { > >> >> > > -struct QObjectBase_ base; > >> >> > > + > >> >> > > +/** > >> >> > > + * struct QNumValue: the value of a QNum > >> >> > > + * > >> >> > > + * QNumValue literals can be constructed using the `QNUM_VAL_INT`, > >> >> > > + * `QNUM_VAL_UINT`, and `QNUM_VAL_DOUBLE` macros. > >> >> > > + */ > >> >> > > +typedef struct QNumValue { > >> >> > > +/* private: */ > >> > >> Do we care? > > > > Are you asking if we want to make them private, or if we want to > > document them as private (assuming they are). > > > > The answer to the latter is yes ("private:" is an indication to > > kernel-doc). The answer to the former seems to be "no", based on > > your other comments. > > > > Or maybe `kind` should be public and `u` should be private? > > You're factoring out a part of struct QNum into new struct QNumValue. > struct QNum is not private before the patch. I see no need to start > making it or parts of it private now. I don't want to change the rules, just to document the existing implicit rules. If you say QNum.u was never private, I won't argue. > > When the structure of a data type is to be kept away from its users, I > prefer to keep it out of the public header, so the compiler enforces the > encapsulation. I prefer that too, except that it is impossible when users of the API need the compiler to know the struct size. -- Eduardo
Re: [PATCH v2 4/8] qnum: qnum_value_is_equal() function
On Fri, Nov 20, 2020 at 07:52:31AM +0100, Markus Armbruster wrote: > Eduardo Habkost writes: > > > On Thu, Nov 19, 2020 at 11:27:40AM +0100, Markus Armbruster wrote: > > [...] > >> > +bool qnum_is_equal(const QObject *x, const QObject *y) > >> > +{ > >> > +const QNum *qnum_x = qobject_to(QNum, x); > >> > +const QNum *qnum_y = qobject_to(QNum, y); > >> > >> Humor me: blank line between declarations and statements, please. > > > > I can do it. But why do you prefer it that way? > > Habit borne out of C lacking other visual cues to distinguish > declarations and statements. Why is the distinction important, when many variable declarations also include initializer expressions that can be as complex as other statements? (The qobject_to() calls above are an example). > > Declaration or statement? Tell me quick, don't analyze! > > mumble(*mutter)(); > > This "obviously" declares @mutter as pointer to function returning > mumble. > > Except when @mumble isn't a typedef name, but a function taking one > argument and returning a function that takes no argument. Then it > passes *mutter to mumble(), and calls its return value. > > The whole point of coding style is to help readers along. Two stylistic > conventions that can help here: > > 1. In a function call, no space between the expression denoting the >called function and the (parenthesized) argument list. Elsewhere, >space. > >So, when the example above is indeed a declaration, write it as > > mumble (*mutter)(); > >If it's function calls, write it as > > mumble(*mutter)(); This makes lots of sense. Starting with a word followed by space is what makes declarations visually distinguishable. > > 2. Separate declarations from statements with a blank line. Do not mix >them. I'm not sure about this one, and I'm actually glad it is not part of CODING_STYLE. :) (I'll still follow your advice as maintainer of that piece of code, of course) -- Eduardo
Re: [PATCH RFC 0/5] Fix accidental crash in iotest 30
20.11.2020 20:22, Kevin Wolf wrote: Am 20.11.2020 um 17:43 hat Vladimir Sementsov-Ogievskiy geschrieben: 20.11.2020 19:36, Kevin Wolf wrote: Am 20.11.2020 um 17:16 hat Vladimir Sementsov-Ogievskiy geschrieben: Hi all! As Peter recently noted, iotest 30 accidentally fails. I found that Qemu crashes due to interleaving of graph-update operations of parallel mirror and stream block-jobs. I haven't found the time yet to properly look into this or your other thread where you had a similar question, but there is one thing I'm wondering: Why can the nested job even make progress and run its completion handler? When we modify the graph, we should have drained the subtree in question, so in theory while one job finishes and modifies the graph, there should be no way for the other job to make progress and get interleaved - it shouldn't be able to start I/O requests and much less to run its completion handler and modify the graph. Are we missing drained sections somewhere or do they fail to achieve what I think they should achieve? It all looks like both jobs are reached their finish simultaneously. So, all progress is done in both jobs. And they go concurrently to completion procedures which interleaves. So, there no more io through blk, which is restricted by drained sections. They can't be truly simultaneous because they run in the same thread. During job completion, this is the main thread. No, they not truly simultaneous, but completions may interleave through nested aio_poll loops. However as soon as job_is_completed() returns true, it seems we're not pausing the job any more when one of its nodes gets drained. Possibly also relevant: The job->busy = false in job_exit(). The comment there says it's a lie, but we might deadlock otherwise. This problem will probably affect other callers, too, which drain a subtree and then resonably expect that nobody will modify the graph until they end the drained section. So I think the problem that we need to address is that jobs run their completion handlers even though they are supposed to be paused by a drain. Hmm. I always thought about drained section as about thing that stops IO requests, not other operations.. And we do graph modifications in drained section to avoid in-flight IO requests during graph modification. I'm not saying that your graph modification locks are a bad idea, but they are probably not a complete solution. Hmm. What do you mean? It's of course not complete, as I didn't protect every graph modification procedure.. But if we do protect all such things and do graph modifications always under this mutex, it should work I think. -- Best regards, Vladimir
[PATCH v2 1/2] Update linux headers
This is a placeholder for a proper run of scripts/update-linux-headers.sh Signed-off-by: Eric Farman --- linux-headers/linux/vfio.h | 1 + 1 file changed, 1 insertion(+) diff --git a/linux-headers/linux/vfio.h b/linux-headers/linux/vfio.h index b92dcc4daf..609099e455 100644 --- a/linux-headers/linux/vfio.h +++ b/linux-headers/linux/vfio.h @@ -820,6 +820,7 @@ enum { enum { VFIO_CCW_IO_IRQ_INDEX, VFIO_CCW_CRW_IRQ_INDEX, + VFIO_CCW_REQ_IRQ_INDEX, VFIO_CCW_NUM_IRQS }; -- 2.17.1
[PATCH v2 0/2] vfio-ccw: Implement request notifier
Updated QEMU code for the request notifier, to match version 2 of the kernel code [1]. No changes since the v1/RFC [2], other than including Conny's r-b on patch 2 (Thank you!). This registers the QEMU vfio-ccw code's ability to respond to a request from the kernel to release the device, because of a (probably fatal) device error that has removed it from the host configuration, and thus its ability to be used by the guest. [1] https://lore.kernel.org/kvm/20201120180740.87837-1-far...@linux.ibm.com/ [2] https://lore.kernel.org/qemu-devel/20201117032605.56831-1-far...@linux.ibm.com/ Eric Farman (2): Update linux headers vfio-ccw: Connect the device request notifier hw/vfio/ccw.c | 40 ++ linux-headers/linux/vfio.h | 1 + 2 files changed, 37 insertions(+), 4 deletions(-) -- 2.17.1
[PATCH v2 2/2] vfio-ccw: Connect the device request notifier
Now that the vfio-ccw code has a notifier interface to request that a device be unplugged, let's wire that together. Signed-off-by: Eric Farman Reviewed-by: Cornelia Huck --- hw/vfio/ccw.c | 40 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c index d2755d7fc5..bc78a0ad76 100644 --- a/hw/vfio/ccw.c +++ b/hw/vfio/ccw.c @@ -49,6 +49,7 @@ struct VFIOCCWDevice { struct ccw_crw_region *crw_region; EventNotifier io_notifier; EventNotifier crw_notifier; +EventNotifier req_notifier; bool force_orb_pfch; bool warned_orb_pfch; }; @@ -287,6 +288,21 @@ static void vfio_ccw_crw_read(VFIOCCWDevice *vcdev) } while (1); } +static void vfio_ccw_req_notifier_handler(void *opaque) +{ +VFIOCCWDevice *vcdev = opaque; +Error *err = NULL; + +if (!event_notifier_test_and_clear(>req_notifier)) { +return; +} + +qdev_unplug(DEVICE(vcdev), ); +if (err) { +warn_reportf_err(err, VFIO_MSG_PREFIX, vcdev->vdev.name); +} +} + static void vfio_ccw_crw_notifier_handler(void *opaque) { VFIOCCWDevice *vcdev = opaque; @@ -386,6 +402,10 @@ static void vfio_ccw_register_irq_notifier(VFIOCCWDevice *vcdev, notifier = >crw_notifier; fd_read = vfio_ccw_crw_notifier_handler; break; +case VFIO_CCW_REQ_IRQ_INDEX: +notifier = >req_notifier; +fd_read = vfio_ccw_req_notifier_handler; +break; default: error_setg(errp, "vfio: Unsupported device irq(%d)", irq); return; @@ -440,6 +460,9 @@ static void vfio_ccw_unregister_irq_notifier(VFIOCCWDevice *vcdev, case VFIO_CCW_CRW_IRQ_INDEX: notifier = >crw_notifier; break; +case VFIO_CCW_REQ_IRQ_INDEX: +notifier = >req_notifier; +break; default: error_report("vfio: Unsupported device irq(%d)", irq); return; @@ -661,20 +684,28 @@ static void vfio_ccw_realize(DeviceState *dev, Error **errp) vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX, ); if (err) { -goto out_notifier_err; +goto out_io_notifier_err; } if (vcdev->crw_region) { vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX, ); if (err) { -vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); -goto out_notifier_err; +goto out_crw_notifier_err; } } +vfio_ccw_register_irq_notifier(vcdev, VFIO_CCW_REQ_IRQ_INDEX, ); +if (err) { +goto out_req_notifier_err; +} + return; -out_notifier_err: +out_req_notifier_err: +vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX); +out_crw_notifier_err: +vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); +out_io_notifier_err: vfio_ccw_put_region(vcdev); out_region_err: vfio_ccw_put_device(vcdev); @@ -696,6 +727,7 @@ static void vfio_ccw_unrealize(DeviceState *dev) S390CCWDeviceClass *cdc = S390_CCW_DEVICE_GET_CLASS(cdev); VFIOGroup *group = vcdev->vdev.group; +vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_REQ_IRQ_INDEX); vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_CRW_IRQ_INDEX); vfio_ccw_unregister_irq_notifier(vcdev, VFIO_CCW_IO_IRQ_INDEX); vfio_ccw_put_region(vcdev); -- 2.17.1
Re: [RFC v3 8/9] module: introduce MODULE_INIT_ACCEL_CPU
On Fri, Nov 20, 2020 at 06:41:35PM +0100, Claudio Fontana wrote: > On 11/20/20 6:19 PM, Eduardo Habkost wrote: > > On Fri, Nov 20, 2020 at 01:13:33PM +0100, Claudio Fontana wrote: > >> On 11/18/20 11:07 PM, Eduardo Habkost wrote: > >>> On Wed, Nov 18, 2020 at 08:13:18PM +0100, Paolo Bonzini wrote: > On 18/11/20 18:30, Eduardo Habkost wrote: > >> Adding a layer of indirect calls is not very different from monkey > >> patching > >> though. > > > > I'm a little bothered by monkey patching, but I'm more > > bothered by having to: > > > > (1) register (module_init()) a function (kvm_cpu_accel_register()) that > >(2) register (accel_register_call()) a function > > (kvm_cpu_accel_init()) that > > (3) register (x86_cpu_accel_init()) a data structure (X86CPUAccel > > kvm_cpu_accel) that > >(4) will be saved in multiple QOM classes, so that > > (5) we will call the right X86CPUClass.accel method at the > > right moment > > (common_class_init(), instance_init(), realizefn()), > > where: > >step 4 must be done before any CPU object is created > > (otherwise X86CPUAccel.instance_init & X86CPUAccel.realizefn > > will be silently ignored), and > >step 3 must be done after all QOM types were registered. > > > >> You also have to consider that accel currently does not exist in > >> usermode > >> emulators, so that's an issue too. I would rather get a simple change > >> in > >> quickly, instead of designing the perfect class hierarchy. > > > > It doesn't have to be perfect. I agree that simple is better. > > > > To me, registering a QOM type and looking it up when necessary is > > simpler than the above. Even if it's a weird class having no > > object instances. It probably could be an interface type. > > Registering a QOM type still has quite some boilerplate. [...] > >>> > >>> We're working on that. :) > >>> > [...] Also > registering a > QOM type has a public side effect (shows up in qom-list-types). In > general > I don't look at QOM unless I want its property mechanism, but maybe > that's > just me. > >>> > >>> We have lots of internal-use-only types returned by > >>> qom-list-types, I don't think it's a big deal. > >>> > > >> Perhaps another idea would be to allow adding interfaces to classes > >> *separately from the registration of the types*. Then we can use it to > >> add > >> SOFTMMU_ACCEL and I386_ACCEL interfaces to a bare bones accel class, > >> and > >> add the accel object to usermode emulators. > > > > I'm not sure I follow. What do you mean by bare bones accel > > class, and when exactly would you add the new interfaces to the > > classes? > > A bare bones accel class would not have init_machine and setup_post > methods; > those would be in a TYPE_SOFTMMU_ACCEL interface. It would still have > properties (such as tb-size for TCG) and would be able to register compat > properties. > > > > [1] > > > >>> > >>> Oh, I think I see. This could save us having a lot of parallel type > >>> hierarchies. > >>> > > Where would I add it, I don't know. It could be a simple public wrapper > around type_initialize_interface() if we add a new MODULE_INIT_* phase > after > QOM. > > Or without adding a new phase, it could be a class_type->array of > (interface_type, init_fn) hash table. type_initialize would look up the > class_type by name, add the interfaces would to the class with > type_initialize_interface, and then call the init_fn to fill in the > vtable. > >>> > >>> That sounds nice. I don't think Claudio's cleanup should be > >>> blocked until this new mechanism is ready, though. > >>> > >>> We don't really need the type representing X86CPUAccel to be a > >>> subtype of TYPE_ACCEL or an interface implemented by > >>> current_machine->accelerator, in the first version. We just need > >>> a simple way for the CPU initialization code to find the correct > >>> X86CPUAccel struct. > >>> > >>> While we don't have the new mechanism, it can be just a: > >>> object_class_by_name("%s-x86-cpu-accel" % (accel->name)) > >>> call. > >>> > >>> Below is a rough draft of what I mean. There's still lots of > >>> room for cleaning it up (especially getting rid of the > >>> X86CPUClass.common_class_init and X86CPUClass.accel fields). > >>> > >>> git tree at > >>> https://gitlab.com/ehabkost/qemu/-/commits/work/qom-based-x86-cpu-accel > >>> > >>> Signed-off-by: Eduardo Habkost > > [...] > >>> /** > >>> - * X86CPUAccel: > >>> - * @name: string name of the X86 CPU Accelerator > >>> - * > >>> + * X86CPUAccelInterface: > >>> * @common_class_init: initializer for the common cpu > >>> *
Re: [PATCH-for-5.2 v2] hw/intc: fix heap-buffer-overflow in rxicu_realize()
Hi Peter, On 11/20/20 5:41 PM, Peter Maydell wrote: > On Fri, 20 Nov 2020 at 13:44, Peter Maydell wrote: >> >> On Wed, 11 Nov 2020 at 14:18, Chen Qun wrote: >>> >>> When 'j = icu->nr_sense – 1', the 'j < icu->nr_sense' condition is true, >>> then 'j = icu->nr_sense', the'icu->init_sense[j]' has out-of-bounds access. > >>> Suggested-by: Peter Maydell >>> Reported-by: Euler Robot >>> Signed-off-by: Chen Qun >> >> >> Reviewed-by: Peter Maydell > > I'll take this via target-arm.next, I guess. Sorry I missed this patch while preparing the latest Renesas pull request. I filter for hw/rx/ and didn't notice this (also I was not Cc'ed in v1). BTW to make things clear, I'm not maintaining this subsystem, I simply try to cover for Yoshinori who is not very active. As there are no other patch, I appreciate you taking this via your ARM queue. Thanks, Phil.
[PATCH for-6.0 7/8] spapr: Drop "nr_servers" argument of the sPAPR IC activate() operation
This argument isn't used by the backends anymore. Signed-off-by: Greg Kurz --- include/hw/ppc/spapr_irq.h | 3 +-- hw/intc/spapr_xive.c | 3 +-- hw/intc/xics_spapr.c | 3 +-- hw/ppc/spapr_irq.c | 3 +-- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h index c22a72c9e270..3e1c619d4c06 100644 --- a/include/hw/ppc/spapr_irq.h +++ b/include/hw/ppc/spapr_irq.h @@ -43,8 +43,7 @@ DECLARE_CLASS_CHECKERS(SpaprInterruptControllerClass, SPAPR_INTC, struct SpaprInterruptControllerClass { InterfaceClass parent; -int (*activate)(SpaprInterruptController *intc, uint32_t nr_servers, -Error **errp); +int (*activate)(SpaprInterruptController *intc, Error **errp); void (*deactivate)(SpaprInterruptController *intc); /* diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index d13a2955ce9b..8331026fdb12 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -754,8 +754,7 @@ static void spapr_xive_dt(SpaprInterruptController *intc, uint32_t nr_servers, plat_res_int_priorities, sizeof(plat_res_int_priorities))); } -static int spapr_xive_activate(SpaprInterruptController *intc, - uint32_t nr_servers, Error **errp) +static int spapr_xive_activate(SpaprInterruptController *intc, Error **errp) { SpaprXive *xive = SPAPR_XIVE(intc); diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c index ce147e8980ed..8810bd93c856 100644 --- a/hw/intc/xics_spapr.c +++ b/hw/intc/xics_spapr.c @@ -426,8 +426,7 @@ static int xics_spapr_post_load(SpaprInterruptController *intc, int version_id) return 0; } -static int xics_spapr_activate(SpaprInterruptController *intc, - uint32_t nr_servers, Error **errp) +static int xics_spapr_activate(SpaprInterruptController *intc, Error **errp) { if (kvm_enabled()) { return spapr_irq_init_kvm(xics_kvm_connect, intc, diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index be6f4041e433..f2897fbc942a 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -480,7 +480,6 @@ static void set_active_intc(SpaprMachineState *spapr, SpaprInterruptController *new_intc) { SpaprInterruptControllerClass *sicc; -uint32_t nr_servers = spapr_max_server_number(spapr); assert(new_intc); @@ -498,7 +497,7 @@ static void set_active_intc(SpaprMachineState *spapr, sicc = SPAPR_INTC_GET_CLASS(new_intc); if (sicc->activate) { -sicc->activate(new_intc, nr_servers, _fatal); +sicc->activate(new_intc, _fatal); } spapr->active_intc = new_intc; -- 2.26.2
[PATCH for-6.0 8/8] spapr: Drop "nr_servers" argument of the sPAPR IC dt() operation
This argument isn't used by the backends anymore. Signed-off-by: Greg Kurz --- include/hw/ppc/spapr_irq.h | 6 ++ hw/intc/spapr_xive.c | 4 ++-- hw/intc/xics_spapr.c | 4 ++-- hw/ppc/spapr.c | 2 +- hw/ppc/spapr_irq.c | 5 ++--- 5 files changed, 9 insertions(+), 12 deletions(-) diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h index 3e1c619d4c06..e2519e4bc596 100644 --- a/include/hw/ppc/spapr_irq.h +++ b/include/hw/ppc/spapr_irq.h @@ -61,8 +61,7 @@ struct SpaprInterruptControllerClass { /* These methods should only be called on the active intc */ void (*set_irq)(SpaprInterruptController *intc, int irq, int val); void (*print_info)(SpaprInterruptController *intc, Monitor *mon); -void (*dt)(SpaprInterruptController *intc, uint32_t nr_servers, - void *fdt, uint32_t phandle); +void (*dt)(SpaprInterruptController *intc, void *fdt, uint32_t phandle); int (*post_load)(SpaprInterruptController *intc, int version_id); }; @@ -73,8 +72,7 @@ int spapr_irq_cpu_intc_create(struct SpaprMachineState *spapr, void spapr_irq_cpu_intc_reset(struct SpaprMachineState *spapr, PowerPCCPU *cpu); void spapr_irq_cpu_intc_destroy(struct SpaprMachineState *spapr, PowerPCCPU *cpu); void spapr_irq_print_info(struct SpaprMachineState *spapr, Monitor *mon); -void spapr_irq_dt(struct SpaprMachineState *spapr, uint32_t nr_servers, - void *fdt, uint32_t phandle); +void spapr_irq_dt(struct SpaprMachineState *spapr, void *fdt, uint32_t phandle); uint32_t spapr_irq_nr_msis(struct SpaprMachineState *spapr); int spapr_irq_msi_alloc(struct SpaprMachineState *spapr, uint32_t num, bool align, diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 8331026fdb12..749cff9bf2b9 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -691,8 +691,8 @@ static void spapr_xive_print_info(SpaprInterruptController *intc, Monitor *mon) spapr_xive_pic_print_info(xive, mon); } -static void spapr_xive_dt(SpaprInterruptController *intc, uint32_t nr_servers, - void *fdt, uint32_t phandle) +static void spapr_xive_dt(SpaprInterruptController *intc, void *fdt, + uint32_t phandle) { SpaprXive *xive = SPAPR_XIVE(intc); int node; diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c index 8810bd93c856..a790b59f1bbc 100644 --- a/hw/intc/xics_spapr.c +++ b/hw/intc/xics_spapr.c @@ -312,8 +312,8 @@ static void ics_spapr_realize(DeviceState *dev, Error **errp) spapr_register_hypercall(H_IPOLL, h_ipoll); } -static void xics_spapr_dt(SpaprInterruptController *intc, uint32_t nr_servers, - void *fdt, uint32_t phandle) +static void xics_spapr_dt(SpaprInterruptController *intc, void *fdt, + uint32_t phandle) { uint32_t interrupt_server_ranges_prop[] = { 0, cpu_to_be32(ICS_SPAPR(intc)->nr_servers), diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 21de0456446b..595dd1b81ce1 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1164,7 +1164,7 @@ void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space) _FDT(fdt_setprop_cell(fdt, 0, "#size-cells", 2)); /* /interrupt controller */ -spapr_irq_dt(spapr, spapr_max_server_number(spapr), fdt, PHANDLE_INTC); +spapr_irq_dt(spapr, fdt, PHANDLE_INTC); ret = spapr_dt_memory(spapr, fdt); if (ret < 0) { diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index f2897fbc942a..f93476d00a59 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -271,13 +271,12 @@ void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon) sicc->print_info(spapr->active_intc, mon); } -void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers, - void *fdt, uint32_t phandle) +void spapr_irq_dt(SpaprMachineState *spapr, void *fdt, uint32_t phandle) { SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(spapr->active_intc); -sicc->dt(spapr->active_intc, nr_servers, fdt, phandle); +sicc->dt(spapr->active_intc, fdt, phandle); } uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr) -- 2.26.2
[PATCH for-6.0 2/8] spapr/xive: Introduce spapr_xive_nr_ends()
We're going to kill the "nr_ends" field in a subsequent patch. Prepare ground by using an helper instead of peeking into the sPAPR XIVE structure directly. Signed-off-by: Greg Kurz --- include/hw/ppc/spapr_xive.h | 1 + hw/intc/spapr_xive.c| 23 ++- hw/intc/spapr_xive_kvm.c| 4 ++-- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/include/hw/ppc/spapr_xive.h b/include/hw/ppc/spapr_xive.h index 26c8d90d7196..4b967f13c030 100644 --- a/include/hw/ppc/spapr_xive.h +++ b/include/hw/ppc/spapr_xive.h @@ -75,6 +75,7 @@ void spapr_xive_map_mmio(SpaprXive *xive); int spapr_xive_end_to_target(uint8_t end_blk, uint32_t end_idx, uint32_t *out_server, uint8_t *out_prio); +uint32_t spapr_xive_nr_ends(const SpaprXive *xive); /* * KVM XIVE device helpers diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 60e0d5769dcc..f473ad9cba47 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -192,7 +192,7 @@ void spapr_xive_pic_print_info(SpaprXive *xive, Monitor *mon) uint32_t end_idx = xive_get_field64(EAS_END_INDEX, eas->w); XiveEND *end; -assert(end_idx < xive->nr_ends); +assert(end_idx < spapr_xive_nr_ends(xive)); end = >endt[end_idx]; if (xive_end_is_valid(end)) { @@ -270,7 +270,7 @@ static void spapr_xive_reset(void *dev) } /* Clear all ENDs */ -for (i = 0; i < xive->nr_ends; i++) { +for (i = 0; i < spapr_xive_nr_ends(xive); i++) { spapr_xive_end_reset(>endt[i]); } } @@ -288,6 +288,11 @@ static void spapr_xive_instance_init(Object *obj) xive->fd = -1; } +uint32_t spapr_xive_nr_ends(const SpaprXive *xive) +{ +return xive->nr_ends; +} + static void spapr_xive_realize(DeviceState *dev, Error **errp) { SpaprXive *xive = SPAPR_XIVE(dev); @@ -336,7 +341,7 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp) * Allocate the routing tables */ xive->eat = g_new0(XiveEAS, xive->nr_irqs); -xive->endt = g_new0(XiveEND, xive->nr_ends); +xive->endt = g_new0(XiveEND, spapr_xive_nr_ends(xive)); xive->nodename = g_strdup_printf("interrupt-controller@%" PRIx64, xive->tm_base + XIVE_TM_USER_PAGE * (1 << TM_SHIFT)); @@ -375,7 +380,7 @@ static int spapr_xive_get_end(XiveRouter *xrtr, { SpaprXive *xive = SPAPR_XIVE(xrtr); -if (end_idx >= xive->nr_ends) { +if (end_idx >= spapr_xive_nr_ends(xive)) { return -1; } @@ -389,7 +394,7 @@ static int spapr_xive_write_end(XiveRouter *xrtr, uint8_t end_blk, { SpaprXive *xive = SPAPR_XIVE(xrtr); -if (end_idx >= xive->nr_ends) { +if (end_idx >= spapr_xive_nr_ends(xive)) { return -1; } @@ -1138,7 +1143,7 @@ static target_ulong h_int_get_source_config(PowerPCCPU *cpu, /* EAS_END_BLOCK is unused on sPAPR */ end_idx = xive_get_field64(EAS_END_INDEX, eas.w); -assert(end_idx < xive->nr_ends); +assert(end_idx < spapr_xive_nr_ends(xive)); end = >endt[end_idx]; nvt_blk = xive_get_field32(END_W6_NVT_BLOCK, end->w6); @@ -1216,7 +1221,7 @@ static target_ulong h_int_get_queue_info(PowerPCCPU *cpu, return H_P2; } -assert(end_idx < xive->nr_ends); +assert(end_idx < spapr_xive_nr_ends(xive)); end = >endt[end_idx]; args[0] = xive->end_base + (1ull << (end_xsrc->esb_shift + 1)) * end_idx; @@ -1304,7 +1309,7 @@ static target_ulong h_int_set_queue_config(PowerPCCPU *cpu, return H_P2; } -assert(end_idx < xive->nr_ends); +assert(end_idx < spapr_xive_nr_ends(xive)); memcpy(, >endt[end_idx], sizeof(XiveEND)); switch (qsize) { @@ -1470,7 +1475,7 @@ static target_ulong h_int_get_queue_config(PowerPCCPU *cpu, return H_P2; } -assert(end_idx < xive->nr_ends); +assert(end_idx < spapr_xive_nr_ends(xive)); end = >endt[end_idx]; args[0] = 0; diff --git a/hw/intc/spapr_xive_kvm.c b/hw/intc/spapr_xive_kvm.c index 66bf4c06fe55..1566016f0e28 100644 --- a/hw/intc/spapr_xive_kvm.c +++ b/hw/intc/spapr_xive_kvm.c @@ -531,7 +531,7 @@ static int kvmppc_xive_get_queues(SpaprXive *xive, Error **errp) int i; int ret; -for (i = 0; i < xive->nr_ends; i++) { +for (i = 0; i < spapr_xive_nr_ends(xive); i++) { if (!xive_end_is_valid(>endt[i])) { continue; } @@ -701,7 +701,7 @@ int kvmppc_xive_post_load(SpaprXive *xive, int version_id) assert(xive->fd != -1); /* Restore the ENDT first. The targetting depends on it. */ -for (i = 0; i < xive->nr_ends; i++) { +for (i = 0; i < spapr_xive_nr_ends(xive); i++) { if (!xive_end_is_valid(>endt[i])) { continue; } -- 2.26.2
[PATCH for-6.0 6/8] spapr/xics: Add "nr-servers" property
The sPAPR ICS device exposes the range of vCPU ids it can handle in the "ibm,interrupt-server-ranges" FDT property. The highest vCPU id, ie. spapr_max_server_number(), is obtained from the machine through the "nr_servers" argument of the generic spapr_irq_dt() call. We want to drop the "nr_servers" argument from the API because it doesn't make sense for the sPAPR XIVE device actually. On POWER9, we also pass the highest vCPU id to the KVM XICS-on-XIVE device, in order to optimize resource allocation in the HW. This is enough motivation to introduce an "nr-servers" property and to use it for both purposes. Signed-off-by: Greg Kurz --- include/hw/ppc/spapr.h | 4 ++-- include/hw/ppc/xics_spapr.h | 21 +--- hw/intc/xics_kvm.c | 2 +- hw/intc/xics_spapr.c| 38 - hw/ppc/spapr.c | 5 +++-- hw/ppc/spapr_irq.c | 7 +-- 6 files changed, 54 insertions(+), 23 deletions(-) diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 2e89e36cfbdc..b76c84a2f884 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -10,7 +10,7 @@ #include "hw/ppc/spapr_irq.h" #include "qom/object.h" #include "hw/ppc/spapr_xive.h" /* For SpaprXive */ -#include "hw/ppc/xics.h"/* For ICSState */ +#include "hw/ppc/xics_spapr.h" /* For IcsSpaprState */ #include "hw/ppc/spapr_tpm_proxy.h" struct SpaprVioBus; @@ -230,7 +230,7 @@ struct SpaprMachineState { SpaprIrq *irq; qemu_irq *qirqs; SpaprInterruptController *active_intc; -ICSState *ics; +IcsSpaprState *ics; SpaprXive *xive; bool cmd_line_caps[SPAPR_CAP_NUM]; diff --git a/include/hw/ppc/xics_spapr.h b/include/hw/ppc/xics_spapr.h index de752c0d2c7e..1a483a873b62 100644 --- a/include/hw/ppc/xics_spapr.h +++ b/include/hw/ppc/xics_spapr.h @@ -28,12 +28,27 @@ #define XICS_SPAPR_H #include "hw/ppc/spapr.h" +#include "hw/ppc/xics.h" #include "qom/object.h" +typedef struct IcsSpaprState { +/*< private >*/ +ICPState parent_obj; + +/* + * The ICS needs to know the upper limit to vCPU ids it + * might be exposed to in order to size the vCPU id range + * in "ibm,interrupt-server-ranges" and to optimize HW + * resource allocation when using the XICS-on-XIVE KVM + * device. It is the purpose of the "nr-servers" property + * which *must* be set to a non-null value before realizing + * the ICS. + */ +uint32_t nr_servers; +} IcsSpaprState; + #define TYPE_ICS_SPAPR "ics-spapr" -/* This is reusing the ICSState typedef from TYPE_ICS */ -DECLARE_INSTANCE_CHECKER(ICSState, ICS_SPAPR, - TYPE_ICS_SPAPR) +DECLARE_INSTANCE_CHECKER(IcsSpaprState, ICS_SPAPR, TYPE_ICS_SPAPR) int xics_kvm_connect(SpaprInterruptController *intc, uint32_t nr_servers, Error **errp); diff --git a/hw/intc/xics_kvm.c b/hw/intc/xics_kvm.c index 570d635bcc08..ecbbda0e249b 100644 --- a/hw/intc/xics_kvm.c +++ b/hw/intc/xics_kvm.c @@ -350,7 +350,7 @@ void ics_kvm_set_irq(ICSState *ics, int srcno, int val) int xics_kvm_connect(SpaprInterruptController *intc, uint32_t nr_servers, Error **errp) { -ICSState *ics = ICS_SPAPR(intc); +ICSState *ics = ICS(intc); int rc; CPUState *cs; Error *local_err = NULL; diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c index 8ae4f41459c3..ce147e8980ed 100644 --- a/hw/intc/xics_spapr.c +++ b/hw/intc/xics_spapr.c @@ -34,6 +34,7 @@ #include "hw/ppc/xics.h" #include "hw/ppc/xics_spapr.h" #include "hw/ppc/fdt.h" +#include "hw/qdev-properties.h" #include "qapi/visitor.h" /* @@ -154,7 +155,7 @@ static void rtas_set_xive(PowerPCCPU *cpu, SpaprMachineState *spapr, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { -ICSState *ics = spapr->ics; +ICSState *ics = ICS(spapr->ics); uint32_t nr, srcno, server, priority; CHECK_EMULATED_XICS_RTAS(spapr, rets); @@ -189,7 +190,7 @@ static void rtas_get_xive(PowerPCCPU *cpu, SpaprMachineState *spapr, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { -ICSState *ics = spapr->ics; +ICSState *ics = ICS(spapr->ics); uint32_t nr, srcno; CHECK_EMULATED_XICS_RTAS(spapr, rets); @@ -221,7 +222,7 @@ static void rtas_int_off(PowerPCCPU *cpu, SpaprMachineState *spapr, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { -ICSState *ics = spapr->ics; +ICSState *ics = ICS(spapr->ics); uint32_t nr, srcno; CHECK_EMULATED_XICS_RTAS(spapr, rets); @@ -254,7 +255,7 @@ static void rtas_int_on(PowerPCCPU *cpu, SpaprMachineState *spapr, uint32_t nargs, target_ulong args, uint32_t nret, target_ulong rets) { -ICSState *ics = spapr->ics;
[PATCH for-6.0 0/8] spapr: Address the confusion between IPI numbers and vCPU ids
A regression was recently fixed in the sPAPR XIVE code for QEMU 5.2 RC3 [1]. It boiled down to a confusion between IPI numbers and vCPU ids, which happen to be numerically equal in general, but are really different entities that can diverge in some setups. When this happens, we end up misconfiguring XIVE in a way that is almost fatal for the guest. The confusion comes from XICS which has historically assumed equality between interrupt server numbers and vCPU ids, as mentionned in a comment back from 2011 in the linux kernel icp_native_init_one_node() function: /* This code does the theorically broken assumption that the interrupt * server numbers are the same as the hard CPU numbers. * This happens to be the case so far but we are playing with fire... * should be fixed one of these days. -BenH. */ This assumption crept into QEMU through the "ibm,interrupt-server-ranges" property of the "interrupt-controller" node in the DT. This property contains ranges of consecutive vCPU ids defined as (first id, # of ids). In the case of QEMU, we define a single range starting from 0 up to the highest vCPU id, as returned by spapr_max_server_number(). This has always been associated to the "nr_servers" wording when naming variables or function arguments. When XIVE got added, we introduced an sPAPR IRQ abstraction to be able to control several interrupt controller backends. The sPAPR IRQ base class provides a dt() handler used to populate the "interrupt-controller" node in the DT. This handler takes an "nr_server" argument inherited from XICS and we ended up using it to populate the "ibm,xive-lisn-ranges" property used with XIVE, which has completely different semantics. It contain ranges of interrupt numbers that the guest can use for any purpose. Since one obvious purpose is IPI, its first range should just be able to accomodate all possible vCPUs. In the case of QEMU, we define a single range starting from 0 up to "nr_server" but we should rather size it to the number of vCPUs actually (ie. smp.max_cpus). This series aims at getting rid of the "nr_server" argument in the sPAPR IC handlers. Since both the highest possible vCPU id and the maximum number of vCPUs are invariants for XICS and XIVE respectively, let's make them device properties to be configured by the machine when it creates the interrupt controllers and use them where needed. This doesn't cause any visible change to setups using the default VSMT machine settings. This changes "ibm,xive-lisn-ranges" for setups that mess with VSMT, but this is acceptable since linux only allocates one interrupt per vCPU and the higher part of the range was never used. [1] https://git.qemu.org/?p=qemu.git;a=commit;h=6d24795ee7e3199d199d3c415312c93382ad1807 Greg Kurz (8): spapr/xive: Turn some sanity checks into assertions spapr/xive: Introduce spapr_xive_nr_ends() spapr/xive: Add "nr-servers" property spapr/xive: Add "nr-ipis" property spapr/xics: Drop unused argument to xics_kvm_has_broken_disconnect() spapr/xics: Add "nr-servers" property spapr: Drop "nr_servers" argument of the sPAPR IC activate() operation spapr: Drop "nr_servers" argument of the sPAPR IC dt() operation include/hw/ppc/spapr.h | 4 +-- include/hw/ppc/spapr_irq.h | 9 ++--- include/hw/ppc/spapr_xive.h | 25 - include/hw/ppc/xics_spapr.h | 23 +--- hw/intc/spapr_xive.c| 72 ++--- hw/intc/spapr_xive_kvm.c| 4 +-- hw/intc/xics_kvm.c | 4 +-- hw/intc/xics_spapr.c| 45 ++- hw/ppc/spapr.c | 7 ++-- hw/ppc/spapr_irq.c | 27 +++--- 10 files changed, 141 insertions(+), 79 deletions(-) -- 2.26.2
Re: [PATCH v1 4/6] gitlab: move remaining x86 check-tcg targets to gitlab
On 11/17/20 2:36 PM, Alex Bennée wrote: The GCC check-tcg (user) test in particular was very prone to timing out on Travis. We only actually need to move the some-softmmu builds across as we already have coverage for linux-user. As --enable-debug-tcg does increase the run time somewhat as more debug is put in let's restrict that to just the plugins build. It's unlikely that a plugins enabled build is going to hide a sanity failure in core TCG code so let the plugin builds do the heavy lifting on checking TCG sanity so the non-plugin builds can run swiftly. Now the only remaining check-tcg builds on Travis are for the various non-x86 arches. Signed-off-by: Alex Bennée Message-Id: <20201110192316.26397-10-alex.ben...@linaro.org> --- .gitlab-ci.yml | 17 + .travis.yml| 26 -- 2 files changed, 17 insertions(+), 26 deletions(-) Reviewed-by: Wainer dos Santos Moschetta diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9a8b375188..b406027a55 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -247,6 +247,15 @@ build-user: CONFIGURE_ARGS: --disable-tools --disable-system MAKE_CHECK_ARGS: check-tcg +# Only build the softmmu targets we have check-tcg tests for +build-some-softmmu: + <<: *native_build_job_definition + variables: +IMAGE: debian-all-test-cross +CONFIGURE_ARGS: --disable-tools --enable-debug-tcg +TARGETS: xtensa-softmmu arm-softmmu aarch64-softmmu alpha-softmmu +MAKE_CHECK_ARGS: check-tcg + # Run check-tcg against linux-user (with plugins) # we skip sparc64-linux-user until it has been fixed somewhat # we skip cris-linux-user as it doesn't use the common run loop @@ -258,6 +267,14 @@ build-user-plugins: MAKE_CHECK_ARGS: check-tcg timeout: 1h 30m +build-some-softmmu-plugins: + <<: *native_build_job_definition + variables: +IMAGE: debian-all-test-cross +CONFIGURE_ARGS: --disable-tools --disable-user --enable-plugins --enable-debug-tcg +TARGETS: xtensa-softmmu arm-softmmu aarch64-softmmu alpha-softmmu +MAKE_CHECK_ARGS: check-tcg + build-clang: <<: *native_build_job_definition variables: diff --git a/.travis.yml b/.travis.yml index a3d78171ca..bac085f800 100644 --- a/.travis.yml +++ b/.travis.yml @@ -301,32 +301,6 @@ jobs: - ${SRC_DIR}/configure ${CONFIG} --extra-cflags="-g3 -O0 -fsanitize=thread" || { cat config.log meson-logs/meson-log.txt && exit 1; } -# Run check-tcg against linux-user -- name: "GCC check-tcg (user)" - env: -- CONFIG="--disable-system --enable-debug-tcg" -- TEST_BUILD_CMD="make build-tcg" -- TEST_CMD="make check-tcg" -- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg" - - -# Run check-tcg against softmmu targets -- name: "GCC check-tcg (some-softmmu)" - env: -- CONFIG="--enable-debug-tcg --target-list=xtensa-softmmu,arm-softmmu,aarch64-softmmu,alpha-softmmu" -- TEST_BUILD_CMD="make build-tcg" -- TEST_CMD="make check-tcg" -- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg" - - -# Run check-tcg against softmmu targets (with plugins) -- name: "GCC plugins check-tcg (some-softmmu)" - env: -- CONFIG="--enable-plugins --enable-debug-tcg --target-list=xtensa-softmmu,arm-softmmu,aarch64-softmmu,alpha-softmmu" -- TEST_BUILD_CMD="make build-tcg" -- TEST_CMD="make check-tcg" -- CACHE_NAME="${TRAVIS_BRANCH}-linux-gcc-debug-tcg" - - name: "[aarch64] GCC check-tcg" arch: arm64 dist: focal
[PATCH for-6.0 1/8] spapr/xive: Turn some sanity checks into assertions
The sPAPR XIVE device is created by the machine in spapr_irq_init(). The latter overrides any value provided by the user with -global for the "nr-irqs" and "nr-ends" properties with strictly positive values. It seems reasonable to assume these properties should never be 0, which wouldn't make much sense by the way. Signed-off-by: Greg Kurz --- hw/intc/spapr_xive.c | 14 -- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/hw/intc/spapr_xive.c b/hw/intc/spapr_xive.c index 1fa09f287ac0..60e0d5769dcc 100644 --- a/hw/intc/spapr_xive.c +++ b/hw/intc/spapr_xive.c @@ -296,22 +296,16 @@ static void spapr_xive_realize(DeviceState *dev, Error **errp) XiveENDSource *end_xsrc = >end_source; Error *local_err = NULL; +/* Set by spapr_irq_init() */ +g_assert(xive->nr_irqs); +g_assert(xive->nr_ends); + sxc->parent_realize(dev, _err); if (local_err) { error_propagate(errp, local_err); return; } -if (!xive->nr_irqs) { -error_setg(errp, "Number of interrupt needs to be greater 0"); -return; -} - -if (!xive->nr_ends) { -error_setg(errp, "Number of interrupt needs to be greater 0"); -return; -} - /* * Initialize the internal sources, for IPIs and virtual devices. */ -- 2.26.2