bool pcihp_bridge_en;
} AcpiBuildPciBusHotplugState;
+typedef struct FwCfgTPMConfig {
+ uint32_t tpmppi_address;
+ uint8_t tpm_version;
+ uint8_t tpmppi_version;
+} QEMU_PACKED FwCfgTPMConfig;
+
static void init_common_fadt_data(Object *o, AcpiFadtData *data)
{
uint32_t io = object_property_get_uint(o, ACPI_PM_PROP_PM_IO_BASE, NULL);
/* FACS */
static void
-build_facs(GArray *table_data, BIOSLinker *linker)
+build_facs(GArray *table_data)
{
AcpiFacsDescriptorRev1 *facs = acpi_data_push(table_data, sizeof *facs);
memcpy(&facs->signature, "FACS", 4);
uint32_t nr_mem = machine->ram_slots;
int root_bus_limit = 0xFF;
PCIBus *bus = NULL;
+ TPMIf *tpm = tpm_find();
int i;
dsdt = init_aml_allocator();
build_legacy_cpu_hotplug_aml(dsdt, machine, pm->cpu_hp_io_base);
} else {
CPUHotplugFeatures opts = {
- .apci_1_compatible = true, .has_legacy_cphp = true
+ .acpi_1_compatible = true, .has_legacy_cphp = true
};
build_cpus_aml(dsdt, machine, opts, pm->cpu_hp_io_base,
"\\_SB.PCI0", "\\_GPE._E02");
aml_append(scope, method);
}
- if (pcms->acpi_nvdimm_state.is_enabled) {
+ if (machine->nvdimms_state->is_enabled) {
method = aml_method("_E04", 0, AML_NOTSERIALIZED);
aml_append(method, aml_notify(aml_name("\\_SB.NVDR"),
aml_int(0x80)));
/* Scan all PCI buses. Generate tables to support hotplug. */
build_append_pci_bus_devices(scope, bus, pm->pcihp_bridge_en);
- if (TPM_IS_TIS(tpm_find())) {
- dev = aml_device("ISA.TPM");
- aml_append(dev, aml_name_decl("_HID", aml_eisaid("PNP0C31")));
+ if (TPM_IS_TIS(tpm)) {
+ if (misc->tpm_version == TPM_VERSION_2_0) {
+ dev = aml_device("TPM");
+ aml_append(dev, aml_name_decl("_HID",
+ aml_string("MSFT0101")));
+ } else {
+ dev = aml_device("ISA.TPM");
+ aml_append(dev, aml_name_decl("_HID",
+ aml_eisaid("PNP0C31")));
+ }
+
aml_append(dev, aml_name_decl("_STA", aml_int(0xF)));
crs = aml_resource_template();
aml_append(crs, aml_memory32_fixed(TPM_TIS_ADDR_BASE,
*/
/* aml_append(crs, aml_irq_no_flags(TPM_TIS_IRQ)); */
aml_append(dev, aml_name_decl("_CRS", crs));
+
+ tpm_build_ppi_acpi(tpm, dev);
+
aml_append(scope, dev);
}
}
}
- if (TPM_IS_CRB(tpm_find())) {
+ if (TPM_IS_CRB(tpm)) {
dev = aml_device("TPM");
aml_append(dev, aml_name_decl("_HID", aml_string("MSFT0101")));
crs = aml_resource_template();
aml_append(method, aml_return(aml_int(0x0f)));
aml_append(dev, method);
+ tpm_build_ppi_acpi(tpm, dev);
+
aml_append(sb_scope, dev);
}
#define HOLE_640K_START (640 * KiB)
#define HOLE_640K_END (1 * MiB)
-static void build_srat_hotpluggable_memory(GArray *table_data, uint64_t base,
- uint64_t len, int default_node)
-{
- MemoryDeviceInfoList *info_list = qmp_memory_device_list();
- MemoryDeviceInfoList *info;
- MemoryDeviceInfo *mi;
- PCDIMMDeviceInfo *di;
- uint64_t end = base + len, cur, size;
- bool is_nvdimm;
- AcpiSratMemoryAffinity *numamem;
- MemoryAffinityFlags flags;
-
- for (cur = base, info = info_list;
- cur < end;
- cur += size, info = info->next) {
- numamem = acpi_data_push(table_data, sizeof *numamem);
-
- if (!info) {
- build_srat_memory(numamem, cur, end - cur, default_node,
- MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
- break;
- }
-
- mi = info->value;
- is_nvdimm = (mi->type == MEMORY_DEVICE_INFO_KIND_NVDIMM);
- di = !is_nvdimm ? mi->u.dimm.data : mi->u.nvdimm.data;
-
- if (cur < di->addr) {
- build_srat_memory(numamem, cur, di->addr - cur, default_node,
- MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
- numamem = acpi_data_push(table_data, sizeof *numamem);
- }
-
- size = di->size;
-
- flags = MEM_AFFINITY_ENABLED;
- if (di->hotpluggable) {
- flags |= MEM_AFFINITY_HOTPLUGGABLE;
- }
- if (is_nvdimm) {
- flags |= MEM_AFFINITY_NON_VOLATILE;
- }
-
- build_srat_memory(numamem, di->addr, size, di->node, flags);
- }
-
- qapi_free_MemoryDeviceInfoList(info_list);
-}
-
static void
build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
{
mem_len = next_base - pcms->below_4g_mem_size;
next_base = mem_base + mem_len;
}
- numamem = acpi_data_push(table_data, sizeof *numamem);
- build_srat_memory(numamem, mem_base, mem_len, i - 1,
- MEM_AFFINITY_ENABLED);
+
+ if (mem_len > 0) {
+ numamem = acpi_data_push(table_data, sizeof *numamem);
+ build_srat_memory(numamem, mem_base, mem_len, i - 1,
+ MEM_AFFINITY_ENABLED);
+ }
}
slots = (table_data->len - numa_start) / sizeof *numamem;
for (; slots < pcms->numa_nodes + 2; slots++) {
* providing _PXM method if necessary.
*/
if (hotplugabble_address_space_size) {
- build_srat_hotpluggable_memory(table_data, machine->device_memory->base,
- hotplugabble_address_space_size,
- pcms->numa_nodes - 1);
+ numamem = acpi_data_push(table_data, sizeof *numamem);
+ build_srat_memory(numamem, machine->device_memory->base,
+ hotplugabble_address_space_size, pcms->numa_nodes - 1,
+ MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
}
build_header(linker, table_data,
IntelIOMMUState *intel_iommu = INTEL_IOMMU_DEVICE(iommu);
assert(iommu);
- if (iommu->intr_supported) {
+ if (x86_iommu_ir_supported(iommu)) {
dmar_flags |= 0x1; /* Flags: 0x1: INT_REMAP */
}
* IVRS table as specified in AMD IOMMU Specification v2.62, Section 5.2
* accessible here http://support.amd.com/TechDocs/48882_IOMMU.pdf
*/
+#define IOAPIC_SB_DEVID (uint64_t)PCI_BUILD_BDF(0, PCI_DEVFN(0x14, 0))
+
static void
build_amd_iommu(GArray *table_data, BIOSLinker *linker)
{
+ int ivhd_table_len = 28;
int iommu_start = table_data->len;
AMDVIState *s = AMD_IOMMU_DEVICE(x86_iommu_get_default());
(1UL << 6) | /* PrefSup */
(1UL << 7), /* PPRSup */
1);
+
+ /*
+ * When interrupt remapping is supported, we add a special IVHD device
+ * for type IO-APIC.
+ */
+ if (x86_iommu_ir_supported(x86_iommu_get_default())) {
+ ivhd_table_len += 8;
+ }
/* IVHD length */
- build_append_int_noprefix(table_data, 0x24, 2);
+ build_append_int_noprefix(table_data, ivhd_table_len, 2);
/* DeviceID */
build_append_int_noprefix(table_data, s->devid, 2);
/* Capability offset */
build_append_int_noprefix(table_data,
(48UL << 30) | /* HATS */
(48UL << 28) | /* GATS */
- (1UL << 2), /* GTSup */
+ (1UL << 2) | /* GTSup */
+ (1UL << 6), /* GASup */
4);
/*
* Type 1 device entry reporting all devices
*/
build_append_int_noprefix(table_data, 0x0000001, 4);
+ /*
+ * Add a special IVHD device type.
+ * Refer to spec - Table 95: IVHD device entry type codes
+ *
+ * Linux IOMMU driver checks for the special IVHD device (type IO-APIC).
+ * See Linux kernel commit 'c2ff5cf5294bcbd7fa50f7d860e90a66db7e5059'
+ */
+ if (x86_iommu_ir_supported(x86_iommu_get_default())) {
+ build_append_int_noprefix(table_data,
+ (0x1ull << 56) | /* type IOAPIC */
+ (IOAPIC_SB_DEVID << 40) | /* IOAPIC devid */
+ 0x48, /* special device */
+ 8);
+ }
+
build_header(linker, table_data, (void *)(table_data->data + iommu_start),
"IVRS", table_data->len - iommu_start, 1, NULL, NULL);
}
-static GArray *
-build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
-{
- AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
- unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
- unsigned rsdt_pa_offset =
- (char *)&rsdp->rsdt_physical_address - rsdp_table->data;
-
- bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
- true /* fseg memory */);
-
- memcpy(&rsdp->signature, "RSD PTR ", 8);
- memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
- /* Address to be filled by Guest linker */
- bios_linker_loader_add_pointer(linker,
- ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size,
- ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset);
-
- /* Checksum to be filled by Guest linker */
- bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
- (char *)rsdp - rsdp_table->data, sizeof *rsdp,
- (char *)&rsdp->checksum - rsdp_table->data);
-
- return rsdp_table;
-}
-
typedef
struct AcpiBuildState {
/* Copy of table in RAM (for patching). */
* requirements.
*/
facs = tables_blob->len;
- build_facs(tables_blob, tables->linker);
+ build_facs(tables_blob);
/* DSDT is pointed to by FADT */
dsdt = tables_blob->len;
build_dmar_q35(tables_blob, tables->linker);
}
}
- if (pcms->acpi_nvdimm_state.is_enabled) {
+ if (machine->nvdimms_state->is_enabled) {
nvdimm_build_acpi(table_offsets, tables_blob, tables->linker,
- &pcms->acpi_nvdimm_state, machine->ram_slots);
+ machine->nvdimms_state, machine->ram_slots);
}
/* Add tables supplied by user (if any) */
slic_oem.id, slic_oem.table_id);
/* RSDP is in FSEG memory, so allocate it separately */
- build_rsdp(tables->rsdp, tables->linker, rsdt);
+ {
+ AcpiRsdpData rsdp_data = {
+ .revision = 0,
+ .oem_id = ACPI_BUILD_APPNAME6,
+ .xsdt_tbl_offset = NULL,
+ .rsdt_tbl_offset = &rsdt,
+ };
+ build_rsdp(tables->rsdp, tables->linker, &rsdp_data);
+ if (!pcmc->rsdp_in_ram) {
+ /* We used to allocate some extra space for RSDP revision 2 but
+ * only used the RSDP revision 0 space. The extra bytes were
+ * zeroed out and not used.
+ * Here we continue wasting those extra 16 bytes to make sure we
+ * don't break migration for machine types 2.2 and older due to
+ * RSDP blob size mismatch.
+ */
+ build_append_int_noprefix(tables->rsdp, 0, 16);
+ }
+ }
/* We'll expose it all to Guest so we want to reduce
* chance of size changes.
AcpiBuildTables tables;
AcpiBuildState *build_state;
Object *vmgenid_dev;
+ TPMIf *tpm;
+ static FwCfgTPMConfig tpm_config;
if (!pcms->fw_cfg) {
ACPI_BUILD_DPRINTF("No fw cfg. Bailing out.\n");
fw_cfg_add_file(pcms->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
tables.tcpalog->data, acpi_data_len(tables.tcpalog));
+ tpm = tpm_find();
+ if (tpm && object_property_get_bool(OBJECT(tpm), "ppi", &error_abort)) {
+ tpm_config = (FwCfgTPMConfig) {
+ .tpmppi_address = cpu_to_le32(TPM_PPI_ADDR_BASE),
+ .tpm_version = tpm_get_version(tpm),
+ .tpmppi_version = TPM_PPI_VERSION_1_30
+ };
+ fw_cfg_add_file(pcms->fw_cfg, "etc/tpm/config",
+ &tpm_config, sizeof tpm_config);
+ }
+
vmgenid_dev = find_vmgenid_dev();
if (vmgenid_dev) {
vmgenid_add_fw_cfg(VMGENID(vmgenid_dev), pcms->fw_cfg,