mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu into staging
virtio,pci,pc: features, fixes, tests SPCR acpi table can now be disabled vhost-vdpa can now report hashing capability to guest PPTT acpi table now tells guest vCPUs are identical vost-user-blk now shuts down faster loongarch64 now supports bios-tables-test intel_iommu now supports ATS cxl now supports DCD Fabric Management Command Set arm now supports acpi pci hotplug fixes, cleanups Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # -----BEGIN PGP SIGNATURE----- # # iQFDBAABCgAtFiEEXQn9CHHI+FuUyooNKB8NuNKNVGkFAmh1+7APHG1zdEByZWRo # YXQuY29tAAoJECgfDbjSjVRpcZ8H/2udpCZ49vjPB8IwQAGdFTw2TWVdxUQFHexQ # pOsCGyFBNAXqD1bmb8lwWyYVJ08WELyL6xWsQ5tfVPiXpKYYHPHl4rNr/SPoyNcv # joY++tagudmOki2DU7nfJ+rPIIuigOTUHbv4TZciwcHle6f65s0iKXhR1sL0cj4i # TS6iJlApSuJInrBBUxuxSUomXk79mFTNKRiXj1k58LRw6JOUEgYvtIW8i+mOUcTg # h1dZphxEQr/oG+a2pM8GOVJ1AFaBPSfgEnRM4kTX9QuTIDCeMAKUBo/mwOk6PV7z # ZhSrDPLrea27XKGL++EJm0fFJ/AsHF1dTks2+c0rDrSK+UV87Zc= # =sktm # -----END PGP SIGNATURE----- # gpg: Signature made Tue 15 Jul 2025 02:56:48 EDT # 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] # Primary key fingerprint: 0270 606B 6F3C DF3D 0B17 0970 C350 3912 AFBE 8E67 # Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA 8A0D 281F 0DB8 D28D 5469 * tag 'for_upstream' of https://git.kernel.org/pub/scm/virt/kvm/mst/qemu: (97 commits) hw/cxl: mailbox-utils: 0x5605 - FMAPI Initiate DC Release hw/cxl: mailbox-utils: 0x5604 - FMAPI Initiate DC Add hw/cxl: Create helper function to create DC Event Records from extents hw/cxl: mailbox-utils: 0x5603 - FMAPI Get DC Region Extent Lists hw/cxl: mailbox-utils: 0x5602 - FMAPI Set DC Region Config hw/mem: cxl_type3: Add DC Region bitmap lock hw/cxl: Move definition for dynamic_capacity_uuid and enum for DC event types to header hw/cxl: mailbox-utils: 0x5601 - FMAPI Get Host Region Config hw/mem: cxl_type3: Add dsmas_flags to CXLDCRegion struct hw/cxl: mailbox-utils: 0x5600 - FMAPI Get DCD Info hw/cxl: fix DC extent capacity tracking tests: virt: Update expected ACPI tables for virt test hw/acpi/aml-build: Build a root node in the PPTT table hw/acpi/aml-build: Set identical implementation flag for PPTT processor nodes tests: virt: Allow changes to PPTT test table qtest/bios-tables-test: Generate reference blob for DSDT.acpipcihp qtest/bios-tables-test: Generate reference blob for DSDT.hpoffacpiindex tests/qtest/bios-tables-test: Add aarch64 ACPI PCI hotplug test tests/qtest/bios-tables-test: Prepare for addition of acpi pci hp tests hw/arm/virt: Let virt support pci hotplug/unplug GED event ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com> Conflicts: net/vhost-vdpa.c vhost_vdpa_set_steering_ebpf() was removed, resolve the context conflict.
This commit is contained in:
@@ -22,7 +22,6 @@
|
||||
#include "system/accel-ops.h"
|
||||
#include "system/cpus.h"
|
||||
#include "exec/cpu-common.h"
|
||||
#include "exec/tswap.h"
|
||||
#include "exec/replay-core.h"
|
||||
#include "exec/log.h"
|
||||
#include "hw/core/cpu.h"
|
||||
@@ -85,9 +84,3 @@ void cpu_abort(CPUState *cpu, const char *fmt, ...)
|
||||
#endif
|
||||
abort();
|
||||
}
|
||||
|
||||
#undef target_big_endian
|
||||
bool target_big_endian(void)
|
||||
{
|
||||
return TARGET_BIG_ENDIAN;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
const VMStateDescription vmstate_acpi_pcihp_pci_status;
|
||||
|
||||
void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus,
|
||||
void acpi_pcihp_init(Object *owner, AcpiPciHpState *s,
|
||||
MemoryRegion *address_space_io, uint16_t io_base)
|
||||
{
|
||||
}
|
||||
|
||||
+21
-6
@@ -160,7 +160,7 @@ void crs_replace_with_free_ranges(GPtrArray *ranges,
|
||||
*/
|
||||
static void crs_range_merge(GPtrArray *range)
|
||||
{
|
||||
GPtrArray *tmp = g_ptr_array_new_with_free_func(crs_range_free);
|
||||
g_autoptr(GPtrArray) tmp = g_ptr_array_new_with_free_func(crs_range_free);
|
||||
CrsRangeEntry *entry;
|
||||
uint64_t range_base, range_limit;
|
||||
int i;
|
||||
@@ -191,7 +191,6 @@ static void crs_range_merge(GPtrArray *range)
|
||||
entry = g_ptr_array_index(tmp, i);
|
||||
crs_range_insert(range, entry->base, entry->limit);
|
||||
}
|
||||
g_ptr_array_free(tmp, true);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -2153,12 +2152,25 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
int64_t socket_id = -1, cluster_id = -1, core_id = -1;
|
||||
uint32_t socket_offset = 0, cluster_offset = 0, core_offset = 0;
|
||||
uint32_t pptt_start = table_data->len;
|
||||
uint32_t root_offset;
|
||||
int n;
|
||||
AcpiTable table = { .sig = "PPTT", .rev = 2,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
acpi_table_begin(&table, table_data);
|
||||
|
||||
/*
|
||||
* Build a root node for all the processor nodes. Otherwise when
|
||||
* building a multi-socket system each socket tree is separated
|
||||
* and will be hard for the OS like Linux to know whether the
|
||||
* system is homogeneous.
|
||||
*/
|
||||
root_offset = table_data->len - pptt_start;
|
||||
build_processor_hierarchy_node(table_data,
|
||||
(1 << 0) | /* Physical package */
|
||||
(1 << 4), /* Identical Implementation */
|
||||
0, 0, NULL, 0);
|
||||
|
||||
/*
|
||||
* This works with the assumption that cpus[n].props.*_id has been
|
||||
* sorted from top to down levels in mc->possible_cpu_arch_ids().
|
||||
@@ -2173,8 +2185,9 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
core_id = -1;
|
||||
socket_offset = table_data->len - pptt_start;
|
||||
build_processor_hierarchy_node(table_data,
|
||||
(1 << 0), /* Physical package */
|
||||
0, socket_id, NULL, 0);
|
||||
(1 << 0) | /* Physical package */
|
||||
(1 << 4), /* Identical Implementation */
|
||||
root_offset, socket_id, NULL, 0);
|
||||
}
|
||||
|
||||
if (mc->smp_props.clusters_supported && mc->smp_props.has_clusters) {
|
||||
@@ -2184,7 +2197,8 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
core_id = -1;
|
||||
cluster_offset = table_data->len - pptt_start;
|
||||
build_processor_hierarchy_node(table_data,
|
||||
(0 << 0), /* Not a physical package */
|
||||
(0 << 0) | /* Not a physical package */
|
||||
(1 << 4), /* Identical Implementation */
|
||||
socket_offset, cluster_id, NULL, 0);
|
||||
}
|
||||
} else {
|
||||
@@ -2202,7 +2216,8 @@ void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
core_id = cpus->cpus[n].props.core_id;
|
||||
core_offset = table_data->len - pptt_start;
|
||||
build_processor_hierarchy_node(table_data,
|
||||
(0 << 0), /* Not a physical package */
|
||||
(0 << 0) | /* Not a physical package */
|
||||
(1 << 4), /* Identical Implementation */
|
||||
cluster_offset, core_id, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
#include "hw/acpi/bios-linker-loader.h"
|
||||
#include "hw/nvram/fw_cfg.h"
|
||||
|
||||
#include "qemu/bswap.h"
|
||||
|
||||
/*
|
||||
* Linker/loader is a paravirtualized interface that passes commands to guest.
|
||||
* The commands can be used to request guest to
|
||||
|
||||
@@ -12,10 +12,13 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "hw/acpi/acpi.h"
|
||||
#include "hw/acpi/pcihp.h"
|
||||
#include "hw/acpi/generic_event_device.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/irq.h"
|
||||
#include "hw/mem/pc-dimm.h"
|
||||
#include "hw/mem/nvdimm.h"
|
||||
#include "hw/pci/pci_device.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qemu/error-report.h"
|
||||
@@ -26,6 +29,7 @@ static const uint32_t ged_supported_events[] = {
|
||||
ACPI_GED_PWR_DOWN_EVT,
|
||||
ACPI_GED_NVDIMM_HOTPLUG_EVT,
|
||||
ACPI_GED_CPU_HOTPLUG_EVT,
|
||||
ACPI_GED_PCI_HOTPLUG_EVT,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -121,6 +125,12 @@ void build_ged_aml(Aml *table, const char *name, HotplugHandler *hotplug_dev,
|
||||
aml_notify(aml_name("\\_SB.NVDR"),
|
||||
aml_int(0x80)));
|
||||
break;
|
||||
case ACPI_GED_PCI_HOTPLUG_EVT:
|
||||
aml_append(if_ctx,
|
||||
aml_acquire(aml_name("\\_SB.PCI0.BLCK"), 0xFFFF));
|
||||
aml_append(if_ctx, aml_call0("\\_SB.PCI0.PCNT"));
|
||||
aml_append(if_ctx, aml_release(aml_name("\\_SB.PCI0.BLCK")));
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
* Please make sure all the events in ged_supported_events[]
|
||||
@@ -227,6 +237,14 @@ static const MemoryRegionOps ged_regs_ops = {
|
||||
},
|
||||
};
|
||||
|
||||
static void acpi_ged_device_pre_plug_cb(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
|
||||
acpi_pcihp_device_pre_plug_cb(hotplug_dev, dev, errp);
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
|
||||
DeviceState *dev, Error **errp)
|
||||
{
|
||||
@@ -240,6 +258,8 @@ static void acpi_ged_device_plug_cb(HotplugHandler *hotplug_dev,
|
||||
}
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||
acpi_cpu_plug_cb(hotplug_dev, &s->cpuhp_state, dev, errp);
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
|
||||
acpi_pcihp_device_plug_cb(hotplug_dev, &s->pcihp_state, dev, errp);
|
||||
} else {
|
||||
error_setg(errp, "virt: device plug request for unsupported device"
|
||||
" type: %s", object_get_typename(OBJECT(dev)));
|
||||
@@ -256,6 +276,9 @@ static void acpi_ged_unplug_request_cb(HotplugHandler *hotplug_dev,
|
||||
acpi_memory_unplug_request_cb(hotplug_dev, &s->memhp_state, dev, errp);
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||
acpi_cpu_unplug_request_cb(hotplug_dev, &s->cpuhp_state, dev, errp);
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
|
||||
acpi_pcihp_device_unplug_request_cb(hotplug_dev, &s->pcihp_state,
|
||||
dev, errp);
|
||||
} else {
|
||||
error_setg(errp, "acpi: device unplug request for unsupported device"
|
||||
" type: %s", object_get_typename(OBJECT(dev)));
|
||||
@@ -271,6 +294,8 @@ static void acpi_ged_unplug_cb(HotplugHandler *hotplug_dev,
|
||||
acpi_memory_unplug_cb(&s->memhp_state, dev, errp);
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_CPU)) {
|
||||
acpi_cpu_unplug_cb(&s->cpuhp_state, dev, errp);
|
||||
} else if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_DEVICE)) {
|
||||
acpi_pcihp_device_unplug_cb(hotplug_dev, &s->pcihp_state, dev, errp);
|
||||
} else {
|
||||
error_setg(errp, "acpi: device unplug for unsupported device"
|
||||
" type: %s", object_get_typename(OBJECT(dev)));
|
||||
@@ -299,6 +324,8 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
|
||||
sel = ACPI_GED_NVDIMM_HOTPLUG_EVT;
|
||||
} else if (ev & ACPI_CPU_HOTPLUG_STATUS) {
|
||||
sel = ACPI_GED_CPU_HOTPLUG_EVT;
|
||||
} else if (ev & ACPI_PCI_HOTPLUG_STATUS) {
|
||||
sel = ACPI_GED_PCI_HOTPLUG_EVT;
|
||||
} else {
|
||||
/* Unknown event. Return without generating interrupt. */
|
||||
warn_report("GED: Unsupported event %d. No irq injected", ev);
|
||||
@@ -318,6 +345,10 @@ static void acpi_ged_send_event(AcpiDeviceIf *adev, AcpiEventStatusBits ev)
|
||||
|
||||
static const Property acpi_ged_properties[] = {
|
||||
DEFINE_PROP_UINT32("ged-event", AcpiGedState, ged_event_bitmap, 0),
|
||||
DEFINE_PROP_BOOL(ACPI_PM_PROP_ACPI_PCIHP_BRIDGE, AcpiGedState,
|
||||
pcihp_state.use_acpi_hotplug_bridge, 0),
|
||||
DEFINE_PROP_LINK("bus", AcpiGedState, pcihp_state.root,
|
||||
TYPE_PCI_BUS, PCIBus *),
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_memhp_state = {
|
||||
@@ -386,6 +417,25 @@ static const VMStateDescription vmstate_ghes_state = {
|
||||
}
|
||||
};
|
||||
|
||||
static bool pcihp_needed(void *opaque)
|
||||
{
|
||||
AcpiGedState *s = opaque;
|
||||
return s->pcihp_state.use_acpi_hotplug_bridge;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_pcihp_state = {
|
||||
.name = "acpi-ged/pcihp",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = pcihp_needed,
|
||||
.fields = (const VMStateField[]) {
|
||||
VMSTATE_PCI_HOTPLUG(pcihp_state,
|
||||
AcpiGedState,
|
||||
NULL, NULL),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_acpi_ged = {
|
||||
.name = "acpi-ged",
|
||||
.version_id = 1,
|
||||
@@ -398,6 +448,7 @@ static const VMStateDescription vmstate_acpi_ged = {
|
||||
&vmstate_memhp_state,
|
||||
&vmstate_cpuhp_state,
|
||||
&vmstate_ghes_state,
|
||||
&vmstate_pcihp_state,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
@@ -406,9 +457,13 @@ static void acpi_ged_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
|
||||
AcpiGedState *s = ACPI_GED(dev);
|
||||
AcpiPciHpState *pcihp_state = &s->pcihp_state;
|
||||
uint32_t ged_events;
|
||||
int i;
|
||||
|
||||
if (pcihp_state->use_acpi_hotplug_bridge) {
|
||||
s->ged_event_bitmap |= ACPI_GED_PCI_HOTPLUG_EVT;
|
||||
}
|
||||
ged_events = ctpop32(s->ged_event_bitmap);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(ged_supported_events) && ged_events; i++) {
|
||||
@@ -428,6 +483,13 @@ static void acpi_ged_realize(DeviceState *dev, Error **errp)
|
||||
cpu_hotplug_hw_init(&s->container_cpuhp, OBJECT(dev),
|
||||
&s->cpuhp_state, 0);
|
||||
break;
|
||||
case ACPI_GED_PCI_HOTPLUG_EVT:
|
||||
memory_region_init(&s->container_pcihp, OBJECT(dev),
|
||||
ACPI_PCIHP_REGION_NAME, ACPI_PCIHP_SIZE);
|
||||
sysbus_init_mmio(sbd, &s->container_pcihp);
|
||||
acpi_pcihp_init(OBJECT(s), &s->pcihp_state,
|
||||
&s->container_pcihp, 0);
|
||||
qbus_set_hotplug_handler(BUS(s->pcihp_state.root), OBJECT(dev));
|
||||
}
|
||||
ged_events--;
|
||||
}
|
||||
@@ -469,20 +531,34 @@ static void acpi_ged_initfn(Object *obj)
|
||||
sysbus_init_mmio(sbd, &ged_st->regs);
|
||||
}
|
||||
|
||||
static void ged_reset_hold(Object *obj, ResetType type)
|
||||
{
|
||||
AcpiGedState *s = ACPI_GED(obj);
|
||||
|
||||
if (s->pcihp_state.use_acpi_hotplug_bridge) {
|
||||
acpi_pcihp_reset(&s->pcihp_state);
|
||||
}
|
||||
}
|
||||
|
||||
static void acpi_ged_class_init(ObjectClass *class, const void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(class);
|
||||
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(class);
|
||||
AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_CLASS(class);
|
||||
ResettableClass *rc = RESETTABLE_CLASS(class);
|
||||
AcpiGedClass *gedc = ACPI_GED_CLASS(class);
|
||||
|
||||
dc->desc = "ACPI Generic Event Device";
|
||||
device_class_set_props(dc, acpi_ged_properties);
|
||||
dc->vmsd = &vmstate_acpi_ged;
|
||||
dc->realize = acpi_ged_realize;
|
||||
|
||||
hc->pre_plug = acpi_ged_device_pre_plug_cb;
|
||||
hc->plug = acpi_ged_device_plug_cb;
|
||||
hc->unplug_request = acpi_ged_unplug_request_cb;
|
||||
hc->unplug = acpi_ged_unplug_cb;
|
||||
resettable_class_set_parent_phases(rc, NULL, ged_reset_hold, NULL,
|
||||
&gedc->parent_phases);
|
||||
|
||||
adevc->ospm_status = acpi_ged_ospm_status;
|
||||
adevc->send_event = acpi_ged_send_event;
|
||||
@@ -494,6 +570,7 @@ static const TypeInfo acpi_ged_info = {
|
||||
.instance_size = sizeof(AcpiGedState),
|
||||
.instance_init = acpi_ged_initfn,
|
||||
.class_init = acpi_ged_class_init,
|
||||
.class_size = sizeof(AcpiGedClass),
|
||||
.interfaces = (const InterfaceInfo[]) {
|
||||
{ TYPE_HOTPLUG_HANDLER },
|
||||
{ TYPE_ACPI_DEVICE_IF },
|
||||
|
||||
+6
-1
@@ -322,9 +322,10 @@ void ich9_pm_init(PCIDevice *lpc_pci, ICH9LPCPMRegs *pm, qemu_irq sci_irq)
|
||||
}
|
||||
|
||||
if (pm->acpi_pci_hotplug.use_acpi_hotplug_bridge) {
|
||||
object_property_set_link(OBJECT(lpc_pci), "bus",
|
||||
OBJECT(pci_get_bus(lpc_pci)), &error_abort);
|
||||
acpi_pcihp_init(OBJECT(lpc_pci),
|
||||
&pm->acpi_pci_hotplug,
|
||||
pci_get_bus(lpc_pci),
|
||||
pci_address_space_io(lpc_pci),
|
||||
ACPI_PCIHP_ADDR_ICH9);
|
||||
|
||||
@@ -428,6 +429,10 @@ void ich9_pm_add_properties(Object *obj, ICH9LPCPMRegs *pm)
|
||||
|
||||
object_property_add_uint32_ptr(obj, ACPI_PM_PROP_PM_IO_BASE,
|
||||
&pm->pm_io_base, OBJ_PROP_FLAG_READ);
|
||||
object_property_add_link(obj, "bus", TYPE_PCI_BUS,
|
||||
(Object **)&pm->acpi_pci_hotplug.root,
|
||||
object_property_allow_set_link,
|
||||
OBJ_PROP_LINK_STRONG);
|
||||
object_property_add(obj, ACPI_PM_PROP_GPE0_BLK, "uint32",
|
||||
ich9_pm_get_gpe0_blk,
|
||||
NULL, NULL, pm);
|
||||
|
||||
@@ -35,3 +35,57 @@ void build_pci_bridge_aml(AcpiDevAmlIf *adev, Aml *scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Aml *build_pci_bridge_edsm(void)
|
||||
{
|
||||
Aml *method, *ifctx;
|
||||
Aml *zero = aml_int(0);
|
||||
Aml *func = aml_arg(2);
|
||||
Aml *ret = aml_local(0);
|
||||
Aml *aidx = aml_local(1);
|
||||
Aml *params = aml_arg(4);
|
||||
|
||||
method = aml_method("EDSM", 5, AML_SERIALIZED);
|
||||
|
||||
/* get supported functions */
|
||||
ifctx = aml_if(aml_equal(func, zero));
|
||||
{
|
||||
/* 1: have supported functions */
|
||||
/* 7: support for function 7 */
|
||||
const uint8_t caps = 1 | BIT(7);
|
||||
build_append_pci_dsm_func0_common(ifctx, ret);
|
||||
aml_append(ifctx, aml_store(aml_int(caps), aml_index(ret, zero)));
|
||||
aml_append(ifctx, aml_return(ret));
|
||||
}
|
||||
aml_append(method, ifctx);
|
||||
|
||||
/* handle specific functions requests */
|
||||
/*
|
||||
* PCI Firmware Specification 3.1
|
||||
* 4.6.7. _DSM for Naming a PCI or PCI Express Device Under
|
||||
* Operating Systems
|
||||
*/
|
||||
ifctx = aml_if(aml_equal(func, aml_int(7)));
|
||||
{
|
||||
Aml *pkg = aml_package(2);
|
||||
aml_append(pkg, zero);
|
||||
/* optional, if not impl. should return null string */
|
||||
aml_append(pkg, aml_string("%s", ""));
|
||||
aml_append(ifctx, aml_store(pkg, ret));
|
||||
|
||||
/*
|
||||
* IASL is fine when initializing Package with computational data,
|
||||
* however it makes guest unhappy /it fails to process such AML/.
|
||||
* So use runtime assignment to set acpi-index after initializer
|
||||
* to make OSPM happy.
|
||||
*/
|
||||
aml_append(ifctx,
|
||||
aml_store(aml_derefof(aml_index(params, aml_int(0))), aidx));
|
||||
aml_append(ifctx, aml_store(aidx, aml_index(ret, zero)));
|
||||
aml_append(ifctx, aml_return(ret));
|
||||
}
|
||||
aml_append(method, ifctx);
|
||||
|
||||
return method;
|
||||
}
|
||||
|
||||
|
||||
@@ -301,3 +301,53 @@ void build_srat_generic_affinity_structures(GArray *table_data)
|
||||
object_child_foreach_recursive(object_get_root(), build_acpi_generic_port,
|
||||
table_data);
|
||||
}
|
||||
|
||||
Aml *build_pci_host_bridge_osc_method(bool enable_native_pcie_hotplug)
|
||||
{
|
||||
Aml *if_ctx;
|
||||
Aml *if_ctx2;
|
||||
Aml *else_ctx;
|
||||
Aml *method;
|
||||
Aml *a_cwd1 = aml_name("CDW1");
|
||||
Aml *a_ctrl = aml_local(0);
|
||||
|
||||
method = aml_method("_OSC", 4, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_create_dword_field(aml_arg(3), aml_int(0), "CDW1"));
|
||||
|
||||
if_ctx = aml_if(aml_equal(
|
||||
aml_arg(0), aml_touuid("33DB4D5B-1FF7-401C-9657-7441C03DD766")));
|
||||
aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(4), "CDW2"));
|
||||
aml_append(if_ctx, aml_create_dword_field(aml_arg(3), aml_int(8), "CDW3"));
|
||||
|
||||
aml_append(if_ctx, aml_store(aml_name("CDW3"), a_ctrl));
|
||||
|
||||
/*
|
||||
* 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(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 */
|
||||
aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x08), a_cwd1));
|
||||
aml_append(if_ctx, if_ctx2);
|
||||
|
||||
if_ctx2 = aml_if(aml_lnot(aml_equal(aml_name("CDW3"), a_ctrl)));
|
||||
/* Capabilities bits were masked */
|
||||
aml_append(if_ctx2, aml_or(a_cwd1, aml_int(0x10), a_cwd1));
|
||||
aml_append(if_ctx, if_ctx2);
|
||||
|
||||
/* Update DWORD3 in the buffer */
|
||||
aml_append(if_ctx, aml_store(a_ctrl, aml_name("CDW3")));
|
||||
aml_append(method, if_ctx);
|
||||
|
||||
else_ctx = aml_else();
|
||||
/* Unrecognized UUID */
|
||||
aml_append(else_ctx, aml_or(a_cwd1, aml_int(4), a_cwd1));
|
||||
aml_append(method, else_ctx);
|
||||
|
||||
aml_append(method, aml_return(aml_arg(3)));
|
||||
return method;
|
||||
}
|
||||
|
||||
+428
-11
@@ -26,7 +26,8 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/acpi/pcihp.h"
|
||||
|
||||
#include "hw/acpi/aml-build.h"
|
||||
#include "hw/acpi/acpi_aml_interface.h"
|
||||
#include "hw/pci-host/i440fx.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/pci/pci_bridge.h"
|
||||
@@ -39,9 +40,9 @@
|
||||
#include "migration/vmstate.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qom/qom-qobject.h"
|
||||
#include "qobject/qnum.h"
|
||||
#include "trace.h"
|
||||
|
||||
#define ACPI_PCIHP_SIZE 0x0018
|
||||
#define PCI_UP_BASE 0x0000
|
||||
#define PCI_DOWN_BASE 0x0004
|
||||
#define PCI_EJ_BASE 0x0008
|
||||
@@ -97,10 +98,10 @@ static void *acpi_set_bsel(PCIBus *bus, void *opaque)
|
||||
return info;
|
||||
}
|
||||
|
||||
static void acpi_set_pci_info(bool has_bridge_hotplug)
|
||||
static void acpi_set_pci_info(AcpiPciHpState *s)
|
||||
{
|
||||
static bool bsel_is_set;
|
||||
Object *host = acpi_get_i386_pci_host();
|
||||
bool has_bridge_hotplug = s->use_acpi_hotplug_bridge;
|
||||
PCIBus *bus;
|
||||
BSELInfo info = { .bsel_alloc = ACPI_PCIHP_BSEL_DEFAULT,
|
||||
.has_bridge_hotplug = has_bridge_hotplug };
|
||||
@@ -110,11 +111,8 @@ static void acpi_set_pci_info(bool has_bridge_hotplug)
|
||||
}
|
||||
bsel_is_set = true;
|
||||
|
||||
if (!host) {
|
||||
return;
|
||||
}
|
||||
|
||||
bus = PCI_HOST_BRIDGE(host)->bus;
|
||||
bus = s->root;
|
||||
if (bus) {
|
||||
/* Scan all PCI buses. Set property to enable acpi based hotplug. */
|
||||
pci_for_each_bus_depth_first(bus, acpi_set_bsel, NULL, &info);
|
||||
@@ -264,7 +262,7 @@ static void acpi_pcihp_update(AcpiPciHpState *s)
|
||||
|
||||
void acpi_pcihp_reset(AcpiPciHpState *s)
|
||||
{
|
||||
acpi_set_pci_info(s->use_acpi_hotplug_bridge);
|
||||
acpi_set_pci_info(s);
|
||||
acpi_pcihp_update(s);
|
||||
}
|
||||
|
||||
@@ -495,13 +493,13 @@ static const MemoryRegionOps acpi_pcihp_io_ops = {
|
||||
},
|
||||
};
|
||||
|
||||
void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus,
|
||||
void acpi_pcihp_init(Object *owner, AcpiPciHpState *s,
|
||||
MemoryRegion *io, uint16_t io_base)
|
||||
{
|
||||
s->io_len = ACPI_PCIHP_SIZE;
|
||||
s->io_base = io_base;
|
||||
|
||||
s->root = root_bus;
|
||||
assert(s->root);
|
||||
|
||||
memory_region_init_io(&s->io, owner, &acpi_pcihp_io_ops, s,
|
||||
"acpi-pci-hotplug", s->io_len);
|
||||
@@ -513,6 +511,425 @@ void acpi_pcihp_init(Object *owner, AcpiPciHpState *s, PCIBus *root_bus,
|
||||
OBJ_PROP_FLAG_READ);
|
||||
}
|
||||
|
||||
void build_append_pci_dsm_func0_common(Aml *ctx, Aml *retvar)
|
||||
{
|
||||
Aml *UUID, *ifctx1;
|
||||
uint8_t byte_list[1] = { 0 }; /* nothing supported yet */
|
||||
|
||||
aml_append(ctx, aml_store(aml_buffer(1, byte_list), retvar));
|
||||
/*
|
||||
* PCI Firmware Specification 3.1
|
||||
* 4.6. _DSM Definitions for PCI
|
||||
*/
|
||||
UUID = aml_touuid("E5C937D0-3553-4D7A-9117-EA4D19C3434D");
|
||||
ifctx1 = aml_if(aml_lnot(aml_equal(aml_arg(0), UUID)));
|
||||
{
|
||||
/* call is for unsupported UUID, bail out */
|
||||
aml_append(ifctx1, aml_return(retvar));
|
||||
}
|
||||
aml_append(ctx, ifctx1);
|
||||
|
||||
ifctx1 = aml_if(aml_lless(aml_arg(1), aml_int(2)));
|
||||
{
|
||||
/* call is for unsupported REV, bail out */
|
||||
aml_append(ifctx1, aml_return(retvar));
|
||||
}
|
||||
aml_append(ctx, ifctx1);
|
||||
}
|
||||
|
||||
static Aml *aml_pci_pdsm(void)
|
||||
{
|
||||
Aml *method, *ifctx, *ifctx1;
|
||||
Aml *ret = aml_local(0);
|
||||
Aml *caps = aml_local(1);
|
||||
Aml *acpi_index = aml_local(2);
|
||||
Aml *zero = aml_int(0);
|
||||
Aml *one = aml_int(1);
|
||||
Aml *not_supp = aml_int(0xFFFFFFFF);
|
||||
Aml *func = aml_arg(2);
|
||||
Aml *params = aml_arg(4);
|
||||
Aml *bnum = aml_derefof(aml_index(params, aml_int(0)));
|
||||
Aml *sunum = aml_derefof(aml_index(params, aml_int(1)));
|
||||
|
||||
method = aml_method("PDSM", 5, AML_SERIALIZED);
|
||||
|
||||
/* get supported functions */
|
||||
ifctx = aml_if(aml_equal(func, zero));
|
||||
{
|
||||
build_append_pci_dsm_func0_common(ifctx, ret);
|
||||
|
||||
aml_append(ifctx, aml_store(zero, caps));
|
||||
aml_append(ifctx,
|
||||
aml_store(aml_call2("AIDX", bnum, sunum), acpi_index));
|
||||
/*
|
||||
* advertise function 7 if device has acpi-index
|
||||
* acpi_index values:
|
||||
* 0: not present (default value)
|
||||
* FFFFFFFF: not supported (old QEMU without PIDX reg)
|
||||
* other: device's acpi-index
|
||||
*/
|
||||
ifctx1 = aml_if(aml_lnot(
|
||||
aml_or(aml_equal(acpi_index, zero),
|
||||
aml_equal(acpi_index, not_supp), NULL)
|
||||
));
|
||||
{
|
||||
/* have supported functions */
|
||||
aml_append(ifctx1, aml_or(caps, one, caps));
|
||||
/* support for function 7 */
|
||||
aml_append(ifctx1,
|
||||
aml_or(caps, aml_shiftleft(one, aml_int(7)), caps));
|
||||
}
|
||||
aml_append(ifctx, ifctx1);
|
||||
|
||||
aml_append(ifctx, aml_store(caps, aml_index(ret, zero)));
|
||||
aml_append(ifctx, aml_return(ret));
|
||||
}
|
||||
aml_append(method, ifctx);
|
||||
|
||||
/* handle specific functions requests */
|
||||
/*
|
||||
* PCI Firmware Specification 3.1
|
||||
* 4.6.7. _DSM for Naming a PCI or PCI Express Device Under
|
||||
* Operating Systems
|
||||
*/
|
||||
ifctx = aml_if(aml_equal(func, aml_int(7)));
|
||||
{
|
||||
Aml *pkg = aml_package(2);
|
||||
|
||||
aml_append(ifctx, aml_store(aml_call2("AIDX", bnum, sunum), acpi_index));
|
||||
aml_append(ifctx, aml_store(pkg, ret));
|
||||
/*
|
||||
* Windows calls func=7 without checking if it's available,
|
||||
* as workaround Microsoft has suggested to return invalid for func7
|
||||
* Package, so return 2 elements package but only initialize elements
|
||||
* when acpi_index is supported and leave them uninitialized, which
|
||||
* leads elements to being Uninitialized ObjectType and should trip
|
||||
* Windows into discarding result as an unexpected and prevent setting
|
||||
* bogus 'PCI Label' on the device.
|
||||
*/
|
||||
ifctx1 = aml_if(aml_lnot(aml_lor(
|
||||
aml_equal(acpi_index, zero), aml_equal(acpi_index, not_supp)
|
||||
)));
|
||||
{
|
||||
aml_append(ifctx1, aml_store(acpi_index, aml_index(ret, zero)));
|
||||
/*
|
||||
* optional, if not impl. should return null string
|
||||
*/
|
||||
aml_append(ifctx1, aml_store(aml_string("%s", ""),
|
||||
aml_index(ret, one)));
|
||||
}
|
||||
aml_append(ifctx, ifctx1);
|
||||
|
||||
aml_append(ifctx, aml_return(ret));
|
||||
}
|
||||
|
||||
aml_append(method, ifctx);
|
||||
return method;
|
||||
}
|
||||
|
||||
void build_acpi_pci_hotplug(Aml *table, AmlRegionSpace rs, uint64_t pcihp_addr)
|
||||
{
|
||||
Aml *scope;
|
||||
Aml *field;
|
||||
Aml *method;
|
||||
|
||||
scope = aml_scope("_SB.PCI0");
|
||||
|
||||
aml_append(scope,
|
||||
aml_operation_region("PCST", rs, aml_int(pcihp_addr), 0x08));
|
||||
field = aml_field("PCST", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
|
||||
aml_append(field, aml_named_field("PCIU", 32));
|
||||
aml_append(field, aml_named_field("PCID", 32));
|
||||
aml_append(scope, field);
|
||||
|
||||
aml_append(scope,
|
||||
aml_operation_region("SEJ", rs,
|
||||
aml_int(pcihp_addr + ACPI_PCIHP_SEJ_BASE), 0x04));
|
||||
field = aml_field("SEJ", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
|
||||
aml_append(field, aml_named_field("B0EJ", 32));
|
||||
aml_append(scope, field);
|
||||
|
||||
aml_append(scope,
|
||||
aml_operation_region("BNMR", rs,
|
||||
aml_int(pcihp_addr + ACPI_PCIHP_BNMR_BASE), 0x08));
|
||||
field = aml_field("BNMR", AML_DWORD_ACC, AML_NOLOCK, AML_WRITE_AS_ZEROS);
|
||||
aml_append(field, aml_named_field("BNUM", 32));
|
||||
aml_append(field, aml_named_field("PIDX", 32));
|
||||
aml_append(scope, field);
|
||||
|
||||
aml_append(scope, aml_mutex("BLCK", 0));
|
||||
|
||||
method = aml_method("PCEJ", 2, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF));
|
||||
aml_append(method, aml_store(aml_arg(0), aml_name("BNUM")));
|
||||
aml_append(method,
|
||||
aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("B0EJ")));
|
||||
aml_append(method, aml_release(aml_name("BLCK")));
|
||||
aml_append(method, aml_return(aml_int(0)));
|
||||
aml_append(scope, method);
|
||||
|
||||
method = aml_method("AIDX", 2, AML_NOTSERIALIZED);
|
||||
aml_append(method, aml_acquire(aml_name("BLCK"), 0xFFFF));
|
||||
aml_append(method, aml_store(aml_arg(0), aml_name("BNUM")));
|
||||
aml_append(method,
|
||||
aml_store(aml_shiftleft(aml_int(1), aml_arg(1)), aml_name("PIDX")));
|
||||
aml_append(method, aml_store(aml_name("PIDX"), aml_local(0)));
|
||||
aml_append(method, aml_release(aml_name("BLCK")));
|
||||
aml_append(method, aml_return(aml_local(0)));
|
||||
aml_append(scope, method);
|
||||
|
||||
aml_append(scope, aml_pci_pdsm());
|
||||
|
||||
aml_append(table, scope);
|
||||
}
|
||||
|
||||
/* Reserve PCIHP resources */
|
||||
void build_append_pcihp_resources(Aml *scope /* \\_SB.PCI0 */,
|
||||
uint64_t io_addr, uint64_t io_len)
|
||||
{
|
||||
Aml *dev, *crs;
|
||||
|
||||
dev = aml_device("PHPR");
|
||||
aml_append(dev, aml_name_decl("_HID", aml_string("PNP0A06")));
|
||||
aml_append(dev,
|
||||
aml_name_decl("_UID", aml_string("PCI Hotplug resources")));
|
||||
/* device present, functioning, decoding, not shown in UI */
|
||||
aml_append(dev, aml_name_decl("_STA", aml_int(0xB)));
|
||||
crs = aml_resource_template();
|
||||
aml_append(crs, aml_io(AML_DECODE16, io_addr, io_addr, 1, io_len));
|
||||
aml_append(dev, aml_name_decl("_CRS", crs));
|
||||
aml_append(scope, dev);
|
||||
}
|
||||
|
||||
bool build_append_notification_callback(Aml *parent_scope, const PCIBus *bus)
|
||||
{
|
||||
Aml *method;
|
||||
PCIBus *sec;
|
||||
QObject *bsel;
|
||||
int nr_notifiers = 0;
|
||||
GQueue *pcnt_bus_list = g_queue_new();
|
||||
|
||||
QLIST_FOREACH(sec, &bus->child, sibling) {
|
||||
Aml *br_scope = aml_scope("S%.02X", sec->parent_dev->devfn);
|
||||
if (pci_bus_is_root(sec)) {
|
||||
continue;
|
||||
}
|
||||
nr_notifiers = nr_notifiers +
|
||||
build_append_notification_callback(br_scope, sec);
|
||||
/*
|
||||
* add new child scope to parent
|
||||
* and keep track of bus that have PCNT,
|
||||
* bus list is used later to call children PCNTs from this level PCNT
|
||||
*/
|
||||
if (nr_notifiers) {
|
||||
g_queue_push_tail(pcnt_bus_list, sec);
|
||||
aml_append(parent_scope, br_scope);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Append PCNT method to notify about events on local and child buses.
|
||||
* ps: hostbridge might not have hotplug (bsel) enabled but might have
|
||||
* child bridges that do have bsel.
|
||||
*/
|
||||
method = aml_method("PCNT", 0, AML_NOTSERIALIZED);
|
||||
|
||||
/* If bus supports hotplug select it and notify about local events */
|
||||
bsel = object_property_get_qobject(OBJECT(bus), ACPI_PCIHP_PROP_BSEL, NULL);
|
||||
if (bsel) {
|
||||
uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
|
||||
|
||||
aml_append(method, aml_store(aml_int(bsel_val), aml_name("BNUM")));
|
||||
aml_append(method, aml_call2("DVNT", aml_name("PCIU"),
|
||||
aml_int(1))); /* Device Check */
|
||||
aml_append(method, aml_call2("DVNT", aml_name("PCID"),
|
||||
aml_int(3))); /* Eject Request */
|
||||
nr_notifiers++;
|
||||
}
|
||||
|
||||
/* Notify about child bus events in any case */
|
||||
while ((sec = g_queue_pop_head(pcnt_bus_list))) {
|
||||
aml_append(method, aml_name("^S%.02X.PCNT", sec->parent_dev->devfn));
|
||||
}
|
||||
|
||||
aml_append(parent_scope, method);
|
||||
qobject_unref(bsel);
|
||||
g_queue_free(pcnt_bus_list);
|
||||
return !!nr_notifiers;
|
||||
}
|
||||
|
||||
static Aml *aml_pci_device_dsm(void)
|
||||
{
|
||||
Aml *method;
|
||||
|
||||
method = aml_method("_DSM", 4, AML_SERIALIZED);
|
||||
{
|
||||
Aml *params = aml_local(0);
|
||||
Aml *pkg = aml_package(2);
|
||||
aml_append(pkg, aml_int(0));
|
||||
aml_append(pkg, aml_int(0));
|
||||
aml_append(method, aml_store(pkg, params));
|
||||
aml_append(method,
|
||||
aml_store(aml_name("BSEL"), aml_index(params, aml_int(0))));
|
||||
aml_append(method,
|
||||
aml_store(aml_name("ASUN"), aml_index(params, aml_int(1))));
|
||||
aml_append(method,
|
||||
aml_return(aml_call5("PDSM", aml_arg(0), aml_arg(1),
|
||||
aml_arg(2), aml_arg(3), params))
|
||||
);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
static Aml *aml_pci_static_endpoint_dsm(PCIDevice *pdev)
|
||||
{
|
||||
Aml *method;
|
||||
|
||||
g_assert(pdev->acpi_index != 0);
|
||||
method = aml_method("_DSM", 4, AML_SERIALIZED);
|
||||
{
|
||||
Aml *params = aml_local(0);
|
||||
Aml *pkg = aml_package(1);
|
||||
aml_append(pkg, aml_int(pdev->acpi_index));
|
||||
aml_append(method, aml_store(pkg, params));
|
||||
aml_append(method,
|
||||
aml_return(aml_call5("EDSM", aml_arg(0), aml_arg(1),
|
||||
aml_arg(2), aml_arg(3), params))
|
||||
);
|
||||
}
|
||||
return method;
|
||||
}
|
||||
|
||||
static void build_append_pcihp_notify_entry(Aml *method, int slot)
|
||||
{
|
||||
Aml *if_ctx;
|
||||
int32_t devfn = PCI_DEVFN(slot, 0);
|
||||
|
||||
if_ctx = aml_if(aml_and(aml_arg(0), aml_int(0x1U << slot), NULL));
|
||||
aml_append(if_ctx, aml_notify(aml_name("S%.02X", devfn), aml_arg(1)));
|
||||
aml_append(method, if_ctx);
|
||||
}
|
||||
|
||||
static bool is_devfn_ignored_generic(const int devfn, const PCIBus *bus)
|
||||
{
|
||||
const PCIDevice *pdev = bus->devices[devfn];
|
||||
|
||||
if (PCI_FUNC(devfn)) {
|
||||
if (IS_PCI_BRIDGE(pdev)) {
|
||||
/*
|
||||
* Ignore only hotplugged PCI bridges on !0 functions, but
|
||||
* allow describing cold plugged bridges on all functions
|
||||
*/
|
||||
if (DEVICE(pdev)->hotplugged) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_devfn_ignored_hotplug(const int devfn, const PCIBus *bus)
|
||||
{
|
||||
PCIDevice *pdev = bus->devices[devfn];
|
||||
if (pdev) {
|
||||
return is_devfn_ignored_generic(devfn, bus) ||
|
||||
!DEVICE_GET_CLASS(pdev)->hotpluggable ||
|
||||
/* Cold plugged bridges aren't themselves hot-pluggable */
|
||||
(IS_PCI_BRIDGE(pdev) && !DEVICE(pdev)->hotplugged);
|
||||
} else { /* non populated slots */
|
||||
/*
|
||||
* hotplug is supported only for non-multifunction device
|
||||
* so generate device description only for function 0
|
||||
*/
|
||||
if (PCI_FUNC(devfn) ||
|
||||
(pci_bus_is_express(bus) && PCI_SLOT(devfn) > 0)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void build_append_pcihp_slots(Aml *parent_scope, PCIBus *bus)
|
||||
{
|
||||
int devfn;
|
||||
Aml *dev, *notify_method = NULL, *method;
|
||||
QObject *bsel = object_property_get_qobject(OBJECT(bus),
|
||||
ACPI_PCIHP_PROP_BSEL, NULL);
|
||||
uint64_t bsel_val = qnum_get_uint(qobject_to(QNum, bsel));
|
||||
qobject_unref(bsel);
|
||||
|
||||
aml_append(parent_scope, aml_name_decl("BSEL", aml_int(bsel_val)));
|
||||
notify_method = aml_method("DVNT", 2, AML_NOTSERIALIZED);
|
||||
|
||||
for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
|
||||
int slot = PCI_SLOT(devfn);
|
||||
int adr = slot << 16 | PCI_FUNC(devfn);
|
||||
|
||||
if (is_devfn_ignored_hotplug(devfn, bus)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bus->devices[devfn]) {
|
||||
dev = aml_scope("S%.02X", devfn);
|
||||
} else {
|
||||
dev = aml_device("S%.02X", devfn);
|
||||
aml_append(dev, aml_name_decl("_ADR", aml_int(adr)));
|
||||
}
|
||||
|
||||
/*
|
||||
* Can't declare _SUN here for every device as it changes 'slot'
|
||||
* enumeration order in linux kernel, so use another variable for it
|
||||
*/
|
||||
aml_append(dev, aml_name_decl("ASUN", aml_int(slot)));
|
||||
aml_append(dev, aml_pci_device_dsm());
|
||||
|
||||
aml_append(dev, aml_name_decl("_SUN", aml_int(slot)));
|
||||
/* add _EJ0 to make slot hotpluggable */
|
||||
method = aml_method("_EJ0", 1, AML_NOTSERIALIZED);
|
||||
aml_append(method,
|
||||
aml_call2("PCEJ", aml_name("BSEL"), aml_name("_SUN"))
|
||||
);
|
||||
aml_append(dev, method);
|
||||
|
||||
build_append_pcihp_notify_entry(notify_method, slot);
|
||||
|
||||
/* device descriptor has been composed, add it into parent context */
|
||||
aml_append(parent_scope, dev);
|
||||
}
|
||||
aml_append(parent_scope, notify_method);
|
||||
}
|
||||
|
||||
void build_append_pci_bus_devices(Aml *parent_scope, PCIBus *bus)
|
||||
{
|
||||
int devfn;
|
||||
Aml *dev;
|
||||
|
||||
for (devfn = 0; devfn < ARRAY_SIZE(bus->devices); devfn++) {
|
||||
/* ACPI spec: 1.0b: Table 6-2 _ADR Object Bus Types, PCI type */
|
||||
int adr = PCI_SLOT(devfn) << 16 | PCI_FUNC(devfn);
|
||||
PCIDevice *pdev = bus->devices[devfn];
|
||||
|
||||
if (!pdev || is_devfn_ignored_generic(devfn, bus)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* start to compose PCI device descriptor */
|
||||
dev = aml_device("S%.02X", devfn);
|
||||
aml_append(dev, aml_name_decl("_ADR", aml_int(adr)));
|
||||
|
||||
call_dev_aml_func(DEVICE(bus->devices[devfn]), dev);
|
||||
/* add _DSM if device has acpi-index set */
|
||||
if (pdev->acpi_index &&
|
||||
!object_property_get_bool(OBJECT(pdev), "hotpluggable",
|
||||
&error_abort)) {
|
||||
aml_append(dev, aml_pci_static_endpoint_dsm(pdev));
|
||||
}
|
||||
|
||||
/* device descriptor has been composed, add it into parent context */
|
||||
aml_append(parent_scope, dev);
|
||||
}
|
||||
}
|
||||
|
||||
const VMStateDescription vmstate_acpi_pcihp_pci_status = {
|
||||
.name = "acpi_pcihp_pci_status",
|
||||
.version_id = 1,
|
||||
|
||||
+4
-1
@@ -567,7 +567,8 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
|
||||
|
||||
if (s->acpi_pci_hotplug.use_acpi_hotplug_bridge ||
|
||||
s->acpi_pci_hotplug.use_acpi_root_pci_hotplug) {
|
||||
acpi_pcihp_init(OBJECT(s), &s->acpi_pci_hotplug, bus, parent,
|
||||
object_property_set_link(OBJECT(s), "bus", OBJECT(bus), &error_abort);
|
||||
acpi_pcihp_init(OBJECT(s), &s->acpi_pci_hotplug, parent,
|
||||
ACPI_PCIHP_ADDR_PIIX4);
|
||||
qbus_set_hotplug_handler(BUS(pci_get_bus(PCI_DEVICE(s))), OBJECT(s));
|
||||
}
|
||||
@@ -611,6 +612,8 @@ static const Property piix4_pm_properties[] = {
|
||||
acpi_pci_hotplug.use_acpi_hotplug_bridge, true),
|
||||
DEFINE_PROP_BOOL(ACPI_PM_PROP_ACPI_PCI_ROOTHP, PIIX4PMState,
|
||||
acpi_pci_hotplug.use_acpi_root_pci_hotplug, true),
|
||||
DEFINE_PROP_LINK("bus", PIIX4PMState, acpi_pci_hotplug.root,
|
||||
TYPE_PCI_BUS, PCIBus *),
|
||||
DEFINE_PROP_BOOL("memory-hotplug-support", PIIX4PMState,
|
||||
acpi_memory_hotplug.is_enabled, true),
|
||||
DEFINE_PROP_BOOL("smm-compat", PIIX4PMState, smm_compat, false),
|
||||
|
||||
@@ -34,6 +34,8 @@ config ARM_VIRT
|
||||
select ACPI_HW_REDUCED
|
||||
select ACPI_APEI
|
||||
select ACPI_VIOT
|
||||
select ACPI_PCIHP
|
||||
select ACPI_PCI_BRIDGE
|
||||
select VIRTIO_MEM_SUPPORTED
|
||||
select ACPI_CXL
|
||||
select ACPI_HMAT
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/units.h"
|
||||
#include "hw/boards.h"
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "hw/arm/boot.h"
|
||||
#include "hw/arm/linux-boot-if.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/tswap.h"
|
||||
#include "exec/target_page.h"
|
||||
#include "system/kvm.h"
|
||||
#include "system/tcg.h"
|
||||
@@ -29,6 +30,7 @@
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/bswap.h"
|
||||
|
||||
/* Kernel boot protocol is specified in the kernel docs
|
||||
* Documentation/arm/Booting and Documentation/arm64/booting.txt
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
#include "hw/qdev-clock.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "exec/tswap.h"
|
||||
#include "qemu/units.h"
|
||||
#include "system/system.h"
|
||||
#include "target/arm/cpu-qom.h"
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include "hw/core/cpu.h"
|
||||
#include "hw/acpi/acpi-defs.h"
|
||||
#include "hw/acpi/acpi.h"
|
||||
#include "hw/acpi/pcihp.h"
|
||||
#include "hw/nvram/fw_cfg_acpi.h"
|
||||
#include "hw/acpi/bios-linker-loader.h"
|
||||
#include "hw/acpi/aml-build.h"
|
||||
@@ -144,12 +145,21 @@ static void acpi_dsdt_add_pci(Aml *scope, const MemMapEntry *memmap,
|
||||
int ecam_id = VIRT_ECAM_ID(vms->highmem_ecam);
|
||||
bool cxl_present = false;
|
||||
PCIBus *bus = vms->bus;
|
||||
bool acpi_pcihp = false;
|
||||
|
||||
if (vms->acpi_dev) {
|
||||
acpi_pcihp = object_property_get_bool(OBJECT(vms->acpi_dev),
|
||||
ACPI_PM_PROP_ACPI_PCIHP_BRIDGE,
|
||||
NULL);
|
||||
}
|
||||
|
||||
struct GPEXConfig cfg = {
|
||||
.mmio32 = memmap[VIRT_PCIE_MMIO],
|
||||
.pio = memmap[VIRT_PCIE_PIO],
|
||||
.ecam = memmap[ecam_id],
|
||||
.irq = irq,
|
||||
.bus = vms->bus,
|
||||
.pci_native_hotplug = !acpi_pcihp,
|
||||
};
|
||||
|
||||
if (vms->highmem_mmio) {
|
||||
@@ -897,6 +907,7 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
const int *irqmap = vms->irqmap;
|
||||
AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = vms->oem_id,
|
||||
.oem_table_id = vms->oem_table_id };
|
||||
Aml *pci0_scope;
|
||||
|
||||
acpi_table_begin(&table, table_data);
|
||||
dsdt = init_aml_allocator();
|
||||
@@ -950,6 +961,33 @@ build_dsdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms)
|
||||
|
||||
aml_append(dsdt, scope);
|
||||
|
||||
pci0_scope = aml_scope("\\_SB.PCI0");
|
||||
|
||||
aml_append(pci0_scope, build_pci_bridge_edsm());
|
||||
build_append_pci_bus_devices(pci0_scope, vms->bus);
|
||||
if (object_property_find(OBJECT(vms->bus), ACPI_PCIHP_PROP_BSEL)) {
|
||||
build_append_pcihp_slots(pci0_scope, vms->bus);
|
||||
}
|
||||
|
||||
if (vms->acpi_dev) {
|
||||
bool acpi_pcihp;
|
||||
|
||||
acpi_pcihp = object_property_get_bool(OBJECT(vms->acpi_dev),
|
||||
ACPI_PM_PROP_ACPI_PCIHP_BRIDGE,
|
||||
NULL);
|
||||
|
||||
if (acpi_pcihp) {
|
||||
build_acpi_pci_hotplug(dsdt, AML_SYSTEM_MEMORY,
|
||||
memmap[VIRT_ACPI_PCIHP].base);
|
||||
build_append_pcihp_resources(pci0_scope,
|
||||
memmap[VIRT_ACPI_PCIHP].base,
|
||||
memmap[VIRT_ACPI_PCIHP].size);
|
||||
|
||||
build_append_notification_callback(pci0_scope, vms->bus);
|
||||
}
|
||||
}
|
||||
aml_append(dsdt, pci0_scope);
|
||||
|
||||
/* copy AML table into ACPI tables blob */
|
||||
g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
|
||||
|
||||
@@ -1023,7 +1061,10 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables)
|
||||
}
|
||||
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
spcr_setup(tables_blob, tables->linker, vms);
|
||||
|
||||
if (ms->acpi_spcr_enabled) {
|
||||
spcr_setup(tables_blob, tables->linker, vms);
|
||||
}
|
||||
|
||||
acpi_add_table(table_offsets, tables_blob);
|
||||
build_dbg2(tables_blob, tables->linker, vms);
|
||||
|
||||
+23
-4
@@ -76,6 +76,7 @@
|
||||
#include "standard-headers/linux/input.h"
|
||||
#include "hw/arm/smmuv3.h"
|
||||
#include "hw/acpi/acpi.h"
|
||||
#include "hw/acpi/pcihp.h"
|
||||
#include "target/arm/cpu-qom.h"
|
||||
#include "target/arm/internals.h"
|
||||
#include "target/arm/multiprocessing.h"
|
||||
@@ -186,6 +187,7 @@ static const MemMapEntry base_memmap[] = {
|
||||
[VIRT_NVDIMM_ACPI] = { 0x09090000, NVDIMM_ACPI_IO_LEN},
|
||||
[VIRT_PVTIME] = { 0x090a0000, 0x00010000 },
|
||||
[VIRT_SECURE_GPIO] = { 0x090b0000, 0x00001000 },
|
||||
[VIRT_ACPI_PCIHP] = { 0x090c0000, ACPI_PCIHP_SIZE },
|
||||
[VIRT_MMIO] = { 0x0a000000, 0x00000200 },
|
||||
/* ...repeating for a total of NUM_VIRTIO_TRANSPORTS, each of that size */
|
||||
[VIRT_PLATFORM_BUS] = { 0x0c000000, 0x02000000 },
|
||||
@@ -686,8 +688,10 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
|
||||
{
|
||||
DeviceState *dev;
|
||||
MachineState *ms = MACHINE(vms);
|
||||
SysBusDevice *sbdev;
|
||||
int irq = vms->irqmap[VIRT_ACPI_GED];
|
||||
uint32_t event = ACPI_GED_PWR_DOWN_EVT;
|
||||
bool acpi_pcihp;
|
||||
|
||||
if (ms->ram_slots) {
|
||||
event |= ACPI_GED_MEM_HOTPLUG_EVT;
|
||||
@@ -699,11 +703,26 @@ static inline DeviceState *create_acpi_ged(VirtMachineState *vms)
|
||||
|
||||
dev = qdev_new(TYPE_ACPI_GED);
|
||||
qdev_prop_set_uint32(dev, "ged-event", event);
|
||||
sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
|
||||
object_property_set_link(OBJECT(dev), "bus", OBJECT(vms->bus), &error_abort);
|
||||
sbdev = SYS_BUS_DEVICE(dev);
|
||||
sysbus_realize_and_unref(sbdev, &error_fatal);
|
||||
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, vms->memmap[VIRT_ACPI_GED].base);
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 1, vms->memmap[VIRT_PCDIMM_ACPI].base);
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, qdev_get_gpio_in(vms->gic, irq));
|
||||
sysbus_mmio_map_name(sbdev, TYPE_ACPI_GED, vms->memmap[VIRT_ACPI_GED].base);
|
||||
sysbus_mmio_map_name(sbdev, ACPI_MEMHP_REGION_NAME,
|
||||
vms->memmap[VIRT_PCDIMM_ACPI].base);
|
||||
|
||||
acpi_pcihp = object_property_get_bool(OBJECT(dev),
|
||||
ACPI_PM_PROP_ACPI_PCIHP_BRIDGE, NULL);
|
||||
|
||||
if (acpi_pcihp) {
|
||||
int pcihp_region_index;
|
||||
|
||||
pcihp_region_index = sysbus_mmio_map_name(sbdev, ACPI_PCIHP_REGION_NAME,
|
||||
vms->memmap[VIRT_ACPI_PCIHP].base);
|
||||
assert(pcihp_region_index >= 0);
|
||||
}
|
||||
|
||||
sysbus_connect_irq(sbdev, 0, qdev_get_gpio_in(vms->gic, irq));
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "system/block-backend.h"
|
||||
#include "qapi/qapi-types-block.h"
|
||||
#include "qemu/bswap.h"
|
||||
#include "hw/block/block.h"
|
||||
#include "trace.h"
|
||||
|
||||
|
||||
@@ -13,7 +13,9 @@ system_ss.add(when: 'CONFIG_SSI_M25P80', if_true: files('m25p80_sfdp.c'))
|
||||
system_ss.add(when: 'CONFIG_SWIM', if_true: files('swim.c'))
|
||||
system_ss.add(when: 'CONFIG_XEN_BUS', if_true: files('xen-block.c'))
|
||||
|
||||
specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c', 'virtio-blk-common.c'))
|
||||
specific_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk.c', 'virtio-blk-common.c'))
|
||||
specific_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk.c'))
|
||||
system_ss.add(when: 'CONFIG_VIRTIO_BLK', if_true: files('virtio-blk-common.c'))
|
||||
specific_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('vhost-user-blk.c'))
|
||||
system_ss.add(when: 'CONFIG_VHOST_USER_BLK', if_true: files('virtio-blk-common.c'))
|
||||
|
||||
subdir('dataplane')
|
||||
|
||||
@@ -210,6 +210,7 @@ static int vhost_user_blk_stop(VirtIODevice *vdev)
|
||||
BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
|
||||
VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
|
||||
int ret;
|
||||
bool force_stop = false;
|
||||
|
||||
if (!s->started_vu) {
|
||||
return 0;
|
||||
@@ -220,7 +221,11 @@ static int vhost_user_blk_stop(VirtIODevice *vdev)
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = vhost_dev_stop(&s->dev, vdev, true);
|
||||
force_stop = s->skip_get_vring_base_on_force_shutdown &&
|
||||
qemu_force_shutdown_requested();
|
||||
|
||||
ret = force_stop ? vhost_dev_force_stop(&s->dev, vdev, true) :
|
||||
vhost_dev_stop(&s->dev, vdev, true);
|
||||
|
||||
if (k->set_guest_notifiers(qbus->parent, s->dev.nvqs, false) < 0) {
|
||||
error_report("vhost guest notifier cleanup failed: %d", ret);
|
||||
@@ -584,6 +589,8 @@ static const Property vhost_user_blk_properties[] = {
|
||||
VIRTIO_BLK_F_DISCARD, true),
|
||||
DEFINE_PROP_BIT64("write-zeroes", VHostUserBlk, parent_obj.host_features,
|
||||
VIRTIO_BLK_F_WRITE_ZEROES, true),
|
||||
DEFINE_PROP_BOOL("skip-get-vring-base-on-force-shutdown", VHostUserBlk,
|
||||
skip_get_vring_base_on_force_shutdown, false),
|
||||
};
|
||||
|
||||
static void vhost_user_blk_class_init(ObjectClass *klass, const void *data)
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "system/address-spaces.h"
|
||||
#include "exec/tswap.h"
|
||||
#include "system/dma.h"
|
||||
#include "system/runstate.h"
|
||||
#include "trace.h"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user