aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2021-11-15 21:56:15 +0100
committerRichard Henderson <richard.henderson@linaro.org>2021-11-15 21:56:15 +0100
commit757b8dd4e970038538b2e027120ab4594bebdebc (patch)
treeb70c7fa0d161d12a3278e7d7153dca7f0d5d14fb
parent42f6c9179be4401974dd3a75ee72defd16b5092d (diff)
parent18416c62e36a79823a9e28f6b2260aa13c25e1d9 (diff)
Merge tag 'for_upstream' of git://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging
pci,pc,virtio: bugfixes pci power management fixes acpi hotplug fixes misc other fixes Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Mon 15 Nov 2021 05:15:09 PM CET # gpg: using RSA key 5D09FD0871C8F85B94CA8A0D281F0DB8D28D5469 # gpg: issuer "mst@redhat.com" # gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>" [full] # gpg: aka "Michael S. Tsirkin <mst@redhat.com>" [full] * tag 'for_upstream' of git://git.kernel.org/pub/scm/virt/kvm/mst/qemu: pcie: expire pending delete pcie: fast unplug when slot power is off pcie: factor out pcie_cap_slot_unplug() pcie: add power indicator blink check pcie: implement slot power control for pcie root ports pci: implement power state vdpa: Check for existence of opts.vhostdev vdpa: Replace qemu_open_old by qemu_open at virtio: use virtio accessor to access packed event virtio: use virtio accessor to access packed descriptor flags tests: bios-tables-test update expected blobs hw/i386/acpi-build: Deny control on PCIe Native Hot-plug in _OSC bios-tables-test: Allow changes in DSDT ACPI tables hw/acpi/ich9: Add compat prop to keep HPC bit set for 6.1 machine type pcie: rename 'native-hotplug' to 'x-native-hotplug' hw/mem/pc-dimm: Restrict NUMA-specific code to NUMA machines vhost: Fix last vq queue index of devices with no cvq vhost: Rename last_index to vq_index_end softmmu/qdev-monitor: fix use-after-free in qdev_set_id() net/vhost-vdpa: fix memory leak in vhost_vdpa_get_max_queue_pairs() Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--hw/acpi/ich9.c18
-rw-r--r--hw/i386/acpi-build.c12
-rw-r--r--hw/i386/pc.c2
-rw-r--r--hw/i386/pc_q35.c9
-rw-r--r--hw/mem/pc-dimm.c23
-rw-r--r--hw/net/vhost_net.c12
-rw-r--r--hw/pci/pci.c25
-rw-r--r--hw/pci/pci_host.c6
-rw-r--r--hw/pci/pcie.c79
-rw-r--r--hw/pci/pcie_port.c2
-rw-r--r--hw/virtio/vhost-vdpa.c2
-rw-r--r--hw/virtio/virtio.c24
-rw-r--r--include/hw/acpi/ich9.h1
-rw-r--r--include/hw/pci/pci.h2
-rw-r--r--include/hw/qdev-core.h1
-rw-r--r--include/hw/virtio/vhost.h4
-rw-r--r--net/vhost-vdpa.c8
-rw-r--r--softmmu/qdev-monitor.c6
-rw-r--r--tests/data/acpi/q35/DSDTbin8289 -> 8289 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.acpihmatbin9614 -> 9614 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.bridgebin11003 -> 11003 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.cphpbin8753 -> 8753 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.dimmpxmbin9943 -> 9943 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.ipmibtbin8364 -> 8364 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.ivrsbin8306 -> 8306 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.memhpbin9648 -> 9648 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.mmio64bin9419 -> 9419 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.multi-bridgebin8583 -> 8583 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.nohpetbin8147 -> 8147 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.numamembin8295 -> 8295 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.tis.tpm12bin8894 -> 8894 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.tis.tpm2bin8894 -> 8894 bytes
-rw-r--r--tests/data/acpi/q35/DSDT.xapicbin35652 -> 35652 bytes
33 files changed, 176 insertions, 60 deletions
diff --git a/hw/acpi/ich9.c b/hw/acpi/ich9.c
index 1ee2ba2c50..ebe08ed831 100644
--- a/hw/acpi/ich9.c
+++ b/hw/acpi/ich9.c
@@ -419,6 +419,20 @@ static void ich9_pm_set_acpi_pci_hotplug(Object *obj, bool value, Error **errp)
s->pm.use_acpi_hotplug_bridge = value;
}
+static bool ich9_pm_get_keep_pci_slot_hpc(Object *obj, Error **errp)
+{
+ ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
+
+ return s->pm.keep_pci_slot_hpc;
+}
+
+static void ich9_pm_set_keep_pci_slot_hpc(Object *obj, bool value, Error **errp)
+{
+ ICH9LPCState *s = ICH9_LPC_DEVICE(obj);
+
+ s->pm.keep_pci_slot_hpc = value;
+}
+
void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm)
{
static const uint32_t gpe0_len = ICH9_PMIO_GPE0_LEN;
@@ -428,6 +442,7 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm)
pm->disable_s4 = 0;
pm->s4_val = 2;
pm->use_acpi_hotplug_bridge = true;
+ pm->keep_pci_slot_hpc = true;
object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE,
&pm->pm_io_base, OBJ_PROP_FLAG_READ);
@@ -454,6 +469,9 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm)
object_property_add_bool(obj, ACPI_PM_PROP_ACPI_PCIHP_BRIDGE,
ich9_pm_get_acpi_pci_hotplug,
ich9_pm_set_acpi_pci_hotplug);
+ object_property_add_bool(obj, "x-keep-pci-slot-hpc",
+ ich9_pm_get_keep_pci_slot_hpc,
+ ich9_pm_set_keep_pci_slot_hpc);
}
void ich9_pm_device_pre_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index a3ad6abd33..a99c6e4fe3 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1337,7 +1337,7 @@ static void build_x86_acpi_pci_hotplug(Aml *table, uint64_t pcihp_addr)
aml_append(table, scope);
}
-static Aml *build_q35_osc_method(void)
+static Aml *build_q35_osc_method(bool enable_native_pcie_hotplug)
{
Aml *if_ctx;
Aml *if_ctx2;
@@ -1359,8 +1359,10 @@ static Aml *build_q35_osc_method(void)
/*
* Always allow native PME, AER (no dependencies)
* Allow SHPC (PCI bridges can have SHPC controller)
+ * Disable PCIe Native Hot-plug if ACPI PCI Hot-plug is enabled.
*/
- aml_append(if_ctx, aml_and(a_ctrl, aml_int(0x1F), a_ctrl));
+ aml_append(if_ctx, aml_and(a_ctrl,
+ aml_int(0x1E | (enable_native_pcie_hotplug ? 0x1 : 0x0)), a_ctrl));
if_ctx2 = aml_if(aml_lnot(aml_equal(aml_arg(1), aml_int(1))));
/* Unknown revision */
@@ -1449,7 +1451,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
aml_append(dev, aml_name_decl("_ADR", aml_int(0)));
aml_append(dev, aml_name_decl("_UID", aml_int(pcmc->pci_root_uid)));
- aml_append(dev, build_q35_osc_method());
+ aml_append(dev, build_q35_osc_method(!pm->pcihp_bridge_en));
aml_append(sb_scope, dev);
if (mcfg_valid) {
aml_append(sb_scope, build_q35_dram_controller(&mcfg));
@@ -1565,7 +1567,9 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
if (pci_bus_is_express(bus)) {
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A08")));
aml_append(dev, aml_name_decl("_CID", aml_eisaid("PNP0A03")));
- aml_append(dev, build_q35_osc_method());
+
+ /* Expander bridges do not have ACPI PCI Hot-plug enabled */
+ aml_append(dev, build_q35_osc_method(true));
} else {
aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0A03")));
}
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 2592a82148..a2ef40ecbc 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -98,6 +98,7 @@ GlobalProperty pc_compat_6_1[] = {
{ TYPE_X86_CPU, "hv-version-id-build", "0x1bbc" },
{ TYPE_X86_CPU, "hv-version-id-major", "0x0006" },
{ TYPE_X86_CPU, "hv-version-id-minor", "0x0001" },
+ { "ICH9-LPC", "x-keep-pci-slot-hpc", "false" },
};
const size_t pc_compat_6_1_len = G_N_ELEMENTS(pc_compat_6_1);
@@ -107,6 +108,7 @@ GlobalProperty pc_compat_6_0[] = {
{ "qemu64" "-" TYPE_X86_CPU, "stepping", "3" },
{ TYPE_X86_CPU, "x-vendor-cpuid-only", "off" },
{ "ICH9-LPC", ACPI_PM_PROP_ACPI_PCIHP_BRIDGE, "off" },
+ { "ICH9-LPC", "x-keep-pci-slot-hpc", "true" },
};
const size_t pc_compat_6_0_len = G_N_ELEMENTS(pc_compat_6_0);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 797e09500b..e1e100316d 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -137,6 +137,7 @@ static void pc_q35_init(MachineState *machine)
DriveInfo *hd[MAX_SATA_PORTS];
MachineClass *mc = MACHINE_GET_CLASS(machine);
bool acpi_pcihp;
+ bool keep_pci_slot_hpc;
/* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory
* and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping
@@ -242,8 +243,12 @@ static void pc_q35_init(MachineState *machine)
ACPI_PM_PROP_ACPI_PCIHP_BRIDGE,
NULL);
- if (acpi_pcihp) {
- object_register_sugar_prop(TYPE_PCIE_SLOT, "native-hotplug",
+ keep_pci_slot_hpc = object_property_get_bool(OBJECT(lpc),
+ "x-keep-pci-slot-hpc",
+ NULL);
+
+ if (!keep_pci_slot_hpc && acpi_pcihp) {
+ object_register_sugar_prop(TYPE_PCIE_SLOT, "x-native-hotplug",
"false", true);
}
diff --git a/hw/mem/pc-dimm.c b/hw/mem/pc-dimm.c
index a3a2560301..48b913aba6 100644
--- a/hw/mem/pc-dimm.c
+++ b/hw/mem/pc-dimm.c
@@ -181,7 +181,21 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp)
PCDIMMDevice *dimm = PC_DIMM(dev);
PCDIMMDeviceClass *ddc = PC_DIMM_GET_CLASS(dimm);
MachineState *ms = MACHINE(qdev_get_machine());
- int nb_numa_nodes = ms->numa_state->num_nodes;
+
+ if (ms->numa_state) {
+ int nb_numa_nodes = ms->numa_state->num_nodes;
+
+ if (((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) ||
+ (!nb_numa_nodes && dimm->node)) {
+ error_setg(errp, "'DIMM property " PC_DIMM_NODE_PROP " has value %"
+ PRIu32 "' which exceeds the number of numa nodes: %d",
+ dimm->node, nb_numa_nodes ? nb_numa_nodes : 1);
+ return;
+ }
+ } else if (dimm->node > 0) {
+ error_setg(errp, "machine doesn't support NUMA");
+ return;
+ }
if (!dimm->hostmem) {
error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set");
@@ -191,13 +205,6 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp)
object_get_canonical_path_component(OBJECT(dimm->hostmem)));
return;
}
- if (((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) ||
- (!nb_numa_nodes && dimm->node)) {
- error_setg(errp, "'DIMM property " PC_DIMM_NODE_PROP " has value %"
- PRIu32 "' which exceeds the number of numa nodes: %d",
- dimm->node, nb_numa_nodes ? nb_numa_nodes : 1);
- return;
- }
if (ddc->realize) {
ddc->realize(dimm, errp);
diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c
index 0d888f29a6..30379d2ca4 100644
--- a/hw/net/vhost_net.c
+++ b/hw/net/vhost_net.c
@@ -232,10 +232,10 @@ fail:
}
static void vhost_net_set_vq_index(struct vhost_net *net, int vq_index,
- int last_index)
+ int vq_index_end)
{
net->dev.vq_index = vq_index;
- net->dev.last_index = last_index;
+ net->dev.vq_index_end = vq_index_end;
}
static int vhost_net_start_one(struct vhost_net *net,
@@ -326,11 +326,11 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
VirtIONet *n = VIRTIO_NET(dev);
int nvhosts = data_queue_pairs + cvq;
struct vhost_net *net;
- int r, e, i, last_index = data_queue_pairs * 2;
+ int r, e, i, index_end = data_queue_pairs * 2;
NetClientState *peer;
- if (!cvq) {
- last_index -= 1;
+ if (cvq) {
+ index_end += 1;
}
if (!k->set_guest_notifiers) {
@@ -347,7 +347,7 @@ int vhost_net_start(VirtIODevice *dev, NetClientState *ncs,
}
net = get_vhost_net(peer);
- vhost_net_set_vq_index(net, i * 2, last_index);
+ vhost_net_set_vq_index(net, i * 2, index_end);
/* Suppress the masking guest notifiers on vhost user
* because vhost user doesn't interrupt masking/unmasking
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index 4a84e478ce..e5993c1ef5 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -1380,6 +1380,9 @@ static void pci_update_mappings(PCIDevice *d)
continue;
new_addr = pci_bar_address(d, i, r->type, r->size);
+ if (!d->has_power) {
+ new_addr = PCI_BAR_UNMAPPED;
+ }
/* This bar isn't changed */
if (new_addr == r->addr)
@@ -1464,8 +1467,8 @@ void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val_in, int
if (range_covers_byte(addr, l, PCI_COMMAND)) {
pci_update_irq_disabled(d, was_irq_disabled);
memory_region_set_enabled(&d->bus_master_enable_region,
- pci_get_word(d->config + PCI_COMMAND)
- & PCI_COMMAND_MASTER);
+ (pci_get_word(d->config + PCI_COMMAND)
+ & PCI_COMMAND_MASTER) && d->has_power);
}
msi_write_config(d, addr, val_in, l);
@@ -2182,6 +2185,8 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp)
pci_qdev_unrealize(DEVICE(pci_dev));
return;
}
+
+ pci_set_power(pci_dev, true);
}
PCIDevice *pci_new_multifunction(int devfn, bool multifunction,
@@ -2853,6 +2858,22 @@ MSIMessage pci_get_msi_message(PCIDevice *dev, int vector)
return msg;
}
+void pci_set_power(PCIDevice *d, bool state)
+{
+ if (d->has_power == state) {
+ return;
+ }
+
+ d->has_power = state;
+ pci_update_mappings(d);
+ memory_region_set_enabled(&d->bus_master_enable_region,
+ (pci_get_word(d->config + PCI_COMMAND)
+ & PCI_COMMAND_MASTER) && d->has_power);
+ if (!d->has_power) {
+ pci_device_reset(d);
+ }
+}
+
static const TypeInfo pci_device_type_info = {
.name = TYPE_PCI_DEVICE,
.parent = TYPE_DEVICE,
diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c
index cf02f0d6a5..7beafd40a8 100644
--- a/hw/pci/pci_host.c
+++ b/hw/pci/pci_host.c
@@ -74,7 +74,8 @@ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
/* non-zero functions are only exposed when function 0 is present,
* allowing direct removal of unexposed functions.
*/
- if (pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) {
+ if ((pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) ||
+ !pci_dev->has_power) {
return;
}
@@ -97,7 +98,8 @@ uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
/* non-zero functions are only exposed when function 0 is present,
* allowing direct removal of unexposed functions.
*/
- if (pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) {
+ if ((pci_dev->qdev.hotplugged && !pci_get_function_0(pci_dev)) ||
+ !pci_dev->has_power) {
return ~0x0;
}
diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c
index 914a9bf3d1..c5ed266337 100644
--- a/hw/pci/pcie.c
+++ b/hw/pci/pcie.c
@@ -366,6 +366,29 @@ static void hotplug_event_clear(PCIDevice *dev)
}
}
+static void pcie_set_power_device(PCIBus *bus, PCIDevice *dev, void *opaque)
+{
+ bool *power = opaque;
+
+ pci_set_power(dev, *power);
+}
+
+static void pcie_cap_update_power(PCIDevice *hotplug_dev)
+{
+ uint8_t *exp_cap = hotplug_dev->config + hotplug_dev->exp.exp_cap;
+ PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(hotplug_dev));
+ uint32_t sltcap = pci_get_long(exp_cap + PCI_EXP_SLTCAP);
+ uint16_t sltctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL);
+ bool power = true;
+
+ if (sltcap & PCI_EXP_SLTCAP_PCP) {
+ power = (sltctl & PCI_EXP_SLTCTL_PCC) == PCI_EXP_SLTCTL_PWR_ON;
+ }
+
+ pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
+ pcie_set_power_device, &power);
+}
+
/*
* A PCI Express Hot-Plug Event has occurred, so update slot status register
* and notify OS of the event if necessary.
@@ -434,6 +457,7 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
pci_word_test_and_set_mask(exp_cap + PCI_EXP_LNKSTA,
PCI_EXP_LNKSTA_DLLLA);
}
+ pcie_cap_update_power(hotplug_pdev);
return;
}
@@ -451,6 +475,7 @@ void pcie_cap_slot_plug_cb(HotplugHandler *hotplug_dev, DeviceState *dev,
}
pcie_cap_slot_event(hotplug_pdev,
PCI_EXP_HP_EV_PDC | PCI_EXP_HP_EV_ABP);
+ pcie_cap_update_power(hotplug_pdev);
}
}
@@ -472,6 +497,25 @@ static void pcie_unplug_device(PCIBus *bus, PCIDevice *dev, void *opaque)
object_unparent(OBJECT(dev));
}
+static void pcie_cap_slot_do_unplug(PCIDevice *dev)
+{
+ PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(dev));
+ uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
+ uint32_t lnkcap = pci_get_long(exp_cap + PCI_EXP_LNKCAP);
+
+ pci_for_each_device_under_bus(sec_bus, pcie_unplug_device, NULL);
+
+ pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
+ PCI_EXP_SLTSTA_PDS);
+ if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA ||
+ (lnkcap & PCI_EXP_LNKCAP_DLLLARC)) {
+ pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA,
+ PCI_EXP_LNKSTA_DLLLA);
+ }
+ pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
+ PCI_EXP_SLTSTA_PDC);
+}
+
void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
DeviceState *dev, Error **errp)
{
@@ -481,6 +525,7 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
PCIDevice *hotplug_pdev = PCI_DEVICE(hotplug_dev);
uint8_t *exp_cap = hotplug_pdev->config + hotplug_pdev->exp.exp_cap;
uint32_t sltcap = pci_get_word(exp_cap + PCI_EXP_SLTCAP);
+ uint16_t sltctl = pci_get_word(exp_cap + PCI_EXP_SLTCTL);
/* Check if hot-unplug is disabled on the slot */
if ((sltcap & PCI_EXP_SLTCAP_HPC) == 0) {
@@ -496,7 +541,15 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
return;
}
+ if ((sltctl & PCI_EXP_SLTCTL_PIC) == PCI_EXP_SLTCTL_PWR_IND_BLINK) {
+ error_setg(errp, "Hot-unplug failed: "
+ "guest is busy (power indicator blinking)");
+ return;
+ }
+
dev->pending_deleted_event = true;
+ dev->pending_deleted_expires_ms =
+ qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 5000; /* 5 secs */
/* In case user cancel the operation of multi-function hot-add,
* remove the function that is unexposed to guest individually,
@@ -509,6 +562,16 @@ void pcie_cap_slot_unplug_request_cb(HotplugHandler *hotplug_dev,
return;
}
+ if (((sltctl & PCI_EXP_SLTCTL_PIC) == PCI_EXP_SLTCTL_PWR_IND_OFF) &&
+ ((sltctl & PCI_EXP_SLTCTL_PCC) == PCI_EXP_SLTCTL_PWR_OFF)) {
+ /* slot is powered off -> unplug without round-trip to the guest */
+ pcie_cap_slot_do_unplug(hotplug_pdev);
+ hotplug_event_notify(hotplug_pdev);
+ pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
+ PCI_EXP_SLTSTA_ABP);
+ return;
+ }
+
pcie_cap_slot_push_attention_button(hotplug_pdev);
}
@@ -625,6 +688,7 @@ void pcie_cap_slot_reset(PCIDevice *dev)
PCI_EXP_SLTSTA_PDC |
PCI_EXP_SLTSTA_ABP);
+ pcie_cap_update_power(dev);
hotplug_event_update_event_status(dev);
}
@@ -643,7 +707,6 @@ void pcie_cap_slot_write_config(PCIDevice *dev,
uint32_t pos = dev->exp.exp_cap;
uint8_t *exp_cap = dev->config + pos;
uint16_t sltsta = pci_get_word(exp_cap + PCI_EXP_SLTSTA);
- uint32_t lnkcap = pci_get_long(exp_cap + PCI_EXP_LNKCAP);
if (ranges_overlap(addr, len, pos + PCI_EXP_SLTSTA, 2)) {
/*
@@ -693,18 +756,9 @@ void pcie_cap_slot_write_config(PCIDevice *dev,
(val & PCI_EXP_SLTCTL_PIC_OFF) == PCI_EXP_SLTCTL_PIC_OFF &&
(!(old_slt_ctl & PCI_EXP_SLTCTL_PCC) ||
(old_slt_ctl & PCI_EXP_SLTCTL_PIC_OFF) != PCI_EXP_SLTCTL_PIC_OFF)) {
- PCIBus *sec_bus = pci_bridge_get_sec_bus(PCI_BRIDGE(dev));
- pci_for_each_device_under_bus(sec_bus, pcie_unplug_device, NULL);
- pci_word_test_and_clear_mask(exp_cap + PCI_EXP_SLTSTA,
- PCI_EXP_SLTSTA_PDS);
- if (dev->cap_present & QEMU_PCIE_LNKSTA_DLLLA ||
- (lnkcap & PCI_EXP_LNKCAP_DLLLARC)) {
- pci_word_test_and_clear_mask(exp_cap + PCI_EXP_LNKSTA,
- PCI_EXP_LNKSTA_DLLLA);
- }
- pci_word_test_and_set_mask(exp_cap + PCI_EXP_SLTSTA,
- PCI_EXP_SLTSTA_PDC);
+ pcie_cap_slot_do_unplug(dev);
}
+ pcie_cap_update_power(dev);
hotplug_event_notify(dev);
@@ -731,6 +785,7 @@ int pcie_cap_slot_post_load(void *opaque, int version_id)
{
PCIDevice *dev = opaque;
hotplug_event_update_event_status(dev);
+ pcie_cap_update_power(dev);
return 0;
}
diff --git a/hw/pci/pcie_port.c b/hw/pci/pcie_port.c
index da850e8dde..e95c1e5519 100644
--- a/hw/pci/pcie_port.c
+++ b/hw/pci/pcie_port.c
@@ -148,7 +148,7 @@ static Property pcie_slot_props[] = {
DEFINE_PROP_UINT8("chassis", PCIESlot, chassis, 0),
DEFINE_PROP_UINT16("slot", PCIESlot, slot, 0),
DEFINE_PROP_BOOL("hotplug", PCIESlot, hotplug, true),
- DEFINE_PROP_BOOL("native-hotplug", PCIESlot, native_hotplug, true),
+ DEFINE_PROP_BOOL("x-native-hotplug", PCIESlot, native_hotplug, true),
DEFINE_PROP_END_OF_LIST()
};
diff --git a/hw/virtio/vhost-vdpa.c b/hw/virtio/vhost-vdpa.c
index 0d8051426c..bcaf00e09f 100644
--- a/hw/virtio/vhost-vdpa.c
+++ b/hw/virtio/vhost-vdpa.c
@@ -645,7 +645,7 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
}
- if (dev->vq_index + dev->nvqs != dev->last_index) {
+ if (dev->vq_index + dev->nvqs != dev->vq_index_end) {
return 0;
}
diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c
index cc69a9b881..ea7c079fb0 100644
--- a/hw/virtio/virtio.c
+++ b/hw/virtio/virtio.c
@@ -247,13 +247,10 @@ static void vring_packed_event_read(VirtIODevice *vdev,
hwaddr off_off = offsetof(VRingPackedDescEvent, off_wrap);
hwaddr off_flags = offsetof(VRingPackedDescEvent, flags);
- address_space_read_cached(cache, off_flags, &e->flags,
- sizeof(e->flags));
+ e->flags = virtio_lduw_phys_cached(vdev, cache, off_flags);
/* Make sure flags is seen before off_wrap */
smp_rmb();
- address_space_read_cached(cache, off_off, &e->off_wrap,
- sizeof(e->off_wrap));
- virtio_tswap16s(vdev, &e->off_wrap);
+ e->off_wrap = virtio_lduw_phys_cached(vdev, cache, off_off);
virtio_tswap16s(vdev, &e->flags);
}
@@ -263,8 +260,7 @@ static void vring_packed_off_wrap_write(VirtIODevice *vdev,
{
hwaddr off = offsetof(VRingPackedDescEvent, off_wrap);
- virtio_tswap16s(vdev, &off_wrap);
- address_space_write_cached(cache, off, &off_wrap, sizeof(off_wrap));
+ virtio_stw_phys_cached(vdev, cache, off, off_wrap);
address_space_cache_invalidate(cache, off, sizeof(off_wrap));
}
@@ -273,8 +269,7 @@ static void vring_packed_flags_write(VirtIODevice *vdev,
{
hwaddr off = offsetof(VRingPackedDescEvent, flags);
- virtio_tswap16s(vdev, &flags);
- address_space_write_cached(cache, off, &flags, sizeof(flags));
+ virtio_stw_phys_cached(vdev, cache, off, flags);
address_space_cache_invalidate(cache, off, sizeof(flags));
}
@@ -507,11 +502,9 @@ static void vring_packed_desc_read_flags(VirtIODevice *vdev,
MemoryRegionCache *cache,
int i)
{
- address_space_read_cached(cache,
- i * sizeof(VRingPackedDesc) +
- offsetof(VRingPackedDesc, flags),
- flags, sizeof(*flags));
- virtio_tswap16s(vdev, flags);
+ hwaddr off = i * sizeof(VRingPackedDesc) + offsetof(VRingPackedDesc, flags);
+
+ *flags = virtio_lduw_phys_cached(vdev, cache, off);
}
static void vring_packed_desc_read(VirtIODevice *vdev,
@@ -564,8 +557,7 @@ static void vring_packed_desc_write_flags(VirtIODevice *vdev,
{
hwaddr off = i * sizeof(VRingPackedDesc) + offsetof(VRingPackedDesc, flags);
- virtio_tswap16s(vdev, &desc->flags);
- address_space_write_cached(cache, off, &desc->flags, sizeof(desc->flags));
+ virtio_stw_phys_cached(vdev, cache, off, desc->flags);
address_space_cache_invalidate(cache, off, sizeof(desc->flags));
}
diff --git a/include/hw/acpi/ich9.h b/include/hw/acpi/ich9.h
index f04f1791bd..7ca92843c6 100644
--- a/include/hw/acpi/ich9.h
+++ b/include/hw/acpi/ich9.h
@@ -56,6 +56,7 @@ typedef struct ICH9LPCPMRegs {
AcpiCpuHotplug gpe_cpu;
CPUHotplugState cpuhp_state;
+ bool keep_pci_slot_hpc;
bool use_acpi_hotplug_bridge;
AcpiPciHpState acpi_pci_hotplug;
MemHotplugState acpi_memory_hotplug;
diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h
index 5c4016b995..e7cdf2d5ec 100644
--- a/include/hw/pci/pci.h
+++ b/include/hw/pci/pci.h
@@ -268,6 +268,7 @@ typedef struct PCIReqIDCache PCIReqIDCache;
struct PCIDevice {
DeviceState qdev;
bool partially_hotplugged;
+ bool has_power;
/* PCI config space */
uint8_t *config;
@@ -908,5 +909,6 @@ extern const VMStateDescription vmstate_pci_device;
}
MSIMessage pci_get_msi_message(PCIDevice *dev, int vector);
+void pci_set_power(PCIDevice *pci_dev, bool state);
#endif
diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h
index 72622bd337..20d3066595 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -181,6 +181,7 @@ struct DeviceState {
char *canonical_path;
bool realized;
bool pending_deleted_event;
+ int64_t pending_deleted_expires_ms;
QDict *opts;
int hotplugged;
bool allow_unplug_during_migration;
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 3fa0b554ef..58a73e7b7a 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -74,8 +74,8 @@ struct vhost_dev {
unsigned int nvqs;
/* the first virtqueue which would be used by this vhost dev */
int vq_index;
- /* the last vq index for the virtio device (not vhost) */
- int last_index;
+ /* one past the last vq index for the virtio device (not vhost) */
+ int vq_index_end;
/* if non-zero, minimum required value for max_queues */
int num_queues;
uint64_t features;
diff --git a/net/vhost-vdpa.c b/net/vhost-vdpa.c
index 49ab322511..2e3c22a8c7 100644
--- a/net/vhost-vdpa.c
+++ b/net/vhost-vdpa.c
@@ -214,7 +214,7 @@ static NetClientState *net_vhost_vdpa_init(NetClientState *peer,
static int vhost_vdpa_get_max_queue_pairs(int fd, int *has_cvq, Error **errp)
{
unsigned long config_size = offsetof(struct vhost_vdpa_config, buf);
- struct vhost_vdpa_config *config;
+ g_autofree struct vhost_vdpa_config *config = NULL;
__virtio16 *max_queue_pairs;
uint64_t features;
int ret;
@@ -260,8 +260,12 @@ int net_init_vhost_vdpa(const Netdev *netdev, const char *name,
assert(netdev->type == NET_CLIENT_DRIVER_VHOST_VDPA);
opts = &netdev->u.vhost_vdpa;
+ if (!opts->vhostdev) {
+ error_setg(errp, "vdpa character device not specified with vhostdev");
+ return -1;
+ }
- vdpa_device_fd = qemu_open_old(opts->vhostdev, O_RDWR);
+ vdpa_device_fd = qemu_open(opts->vhostdev, O_RDWR, errp);
if (vdpa_device_fd == -1) {
return -errno;
}
diff --git a/softmmu/qdev-monitor.c b/softmmu/qdev-monitor.c
index b5aaae4b8c..01f3834db5 100644
--- a/softmmu/qdev-monitor.c
+++ b/softmmu/qdev-monitor.c
@@ -593,8 +593,8 @@ const char *qdev_set_id(DeviceState *dev, char *id, Error **errp)
if (prop) {
dev->id = id;
} else {
- g_free(id);
error_setg(errp, "Duplicate device ID '%s'", id);
+ g_free(id);
return NULL;
}
} else {
@@ -937,7 +937,9 @@ void qmp_device_del(const char *id, Error **errp)
{
DeviceState *dev = find_device_state(id, errp);
if (dev != NULL) {
- if (dev->pending_deleted_event) {
+ if (dev->pending_deleted_event &&
+ (dev->pending_deleted_expires_ms == 0 ||
+ dev->pending_deleted_expires_ms > qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL))) {
error_setg(errp, "Device %s is already in the "
"process of unplug", id);
return;
diff --git a/tests/data/acpi/q35/DSDT b/tests/data/acpi/q35/DSDT
index 281fc82c03..c1965f6051 100644
--- a/tests/data/acpi/q35/DSDT
+++ b/tests/data/acpi/q35/DSDT
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.acpihmat b/tests/data/acpi/q35/DSDT.acpihmat
index 8c1e05a11a..f24d4874bf 100644
--- a/tests/data/acpi/q35/DSDT.acpihmat
+++ b/tests/data/acpi/q35/DSDT.acpihmat
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.bridge b/tests/data/acpi/q35/DSDT.bridge
index 6f1464b6c7..424d51bd1c 100644
--- a/tests/data/acpi/q35/DSDT.bridge
+++ b/tests/data/acpi/q35/DSDT.bridge
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.cphp b/tests/data/acpi/q35/DSDT.cphp
index f8337ff519..f1275606f6 100644
--- a/tests/data/acpi/q35/DSDT.cphp
+++ b/tests/data/acpi/q35/DSDT.cphp
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.dimmpxm b/tests/data/acpi/q35/DSDT.dimmpxm
index fe5820d93d..76e451e829 100644
--- a/tests/data/acpi/q35/DSDT.dimmpxm
+++ b/tests/data/acpi/q35/DSDT.dimmpxm
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.ipmibt b/tests/data/acpi/q35/DSDT.ipmibt
index 6317410658..6ad2411d0e 100644
--- a/tests/data/acpi/q35/DSDT.ipmibt
+++ b/tests/data/acpi/q35/DSDT.ipmibt
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.ivrs b/tests/data/acpi/q35/DSDT.ivrs
index b0eafe90e5..cad26e3f0c 100644
--- a/tests/data/acpi/q35/DSDT.ivrs
+++ b/tests/data/acpi/q35/DSDT.ivrs
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.memhp b/tests/data/acpi/q35/DSDT.memhp
index 9bc11518fc..4e9cb3dc68 100644
--- a/tests/data/acpi/q35/DSDT.memhp
+++ b/tests/data/acpi/q35/DSDT.memhp
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.mmio64 b/tests/data/acpi/q35/DSDT.mmio64
index 713288a12e..eb5a1c7171 100644
--- a/tests/data/acpi/q35/DSDT.mmio64
+++ b/tests/data/acpi/q35/DSDT.mmio64
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.multi-bridge b/tests/data/acpi/q35/DSDT.multi-bridge
index a24c713d22..45808eb03b 100644
--- a/tests/data/acpi/q35/DSDT.multi-bridge
+++ b/tests/data/acpi/q35/DSDT.multi-bridge
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.nohpet b/tests/data/acpi/q35/DSDT.nohpet
index e8202e6ddf..83d1aa00ac 100644
--- a/tests/data/acpi/q35/DSDT.nohpet
+++ b/tests/data/acpi/q35/DSDT.nohpet
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.numamem b/tests/data/acpi/q35/DSDT.numamem
index 151e7cf429..050aaa237b 100644
--- a/tests/data/acpi/q35/DSDT.numamem
+++ b/tests/data/acpi/q35/DSDT.numamem
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.tis.tpm12 b/tests/data/acpi/q35/DSDT.tis.tpm12
index c96b5277a1..0ebdf6fbd7 100644
--- a/tests/data/acpi/q35/DSDT.tis.tpm12
+++ b/tests/data/acpi/q35/DSDT.tis.tpm12
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.tis.tpm2 b/tests/data/acpi/q35/DSDT.tis.tpm2
index c92d4d29c7..dcbb7f0af3 100644
--- a/tests/data/acpi/q35/DSDT.tis.tpm2
+++ b/tests/data/acpi/q35/DSDT.tis.tpm2
Binary files differ
diff --git a/tests/data/acpi/q35/DSDT.xapic b/tests/data/acpi/q35/DSDT.xapic
index 119fc90f1f..17552ce363 100644
--- a/tests/data/acpi/q35/DSDT.xapic
+++ b/tests/data/acpi/q35/DSDT.xapic
Binary files differ