mirror of https://gitee.com/openkylin/qemu.git
pci,pc,virtio: bugfixes
pci power management fixes acpi hotplug fixes misc other fixes Signed-off-by: Michael S. Tsirkin <mst@redhat.com> -----BEGIN PGP SIGNATURE----- iQFDBAABCAAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmGSh40PHG1zdEByZWRo YXQuY29tAAoJECgfDbjSjVRpH2AH/RLY+ONL98GT4D+hi8MGCOhN669jrPbAqJ1L l9p2GxDoXSD4PCDReU3VCzLtRsxsv/camgMx/DnDxaZtdgKm8SlXGJutMtNHpTY6 PHZLMLoixZSsKi6Tm3xGut/FSzsTZl4Gc3rqwaryHQLqptNO+XQJSBmP+oEAdjAd nKVepHRveOTVVBBzCmoNpFA+BEXRTItdfG0ZKprPkXUobc2jeV7ymkTX9s2OBLEf /pE49tZj1K4ab8g4+RY4cFEFoDZbXZ55Aq3ck5LAb47qIr/1cXPVP7PxINmasy4Y H+oTUpWLBM7rFbdP/GBFANu5HkEQ5pnjeosWYOKsopE4UFCyDxc= =y9C8 -----END PGP SIGNATURE----- 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>
This commit is contained in:
commit
757b8dd4e9
|
@ -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,
|
||||
|
|
|
@ -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")));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
25
hw/pci/pci.c
25
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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue