mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
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:
@@ -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);
|
||||
|
||||
|
||||
+7
-2
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+15
-8
@@ -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);
|
||||
|
||||
+6
-6
@@ -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
|
||||
|
||||
+23
-2
@@ -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,
|
||||
|
||||
+4
-2
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+67
-12
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
+8
-16
@@ -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;
|
||||
|
||||
+6
-2
@@ -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.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user