mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
pc,pci,virtio: features, fixes A huge acpi refactoring. Fixes, cleanups all over the place. Signed-off-by: Michael S. Tsirkin <mst@redhat.com> # gpg: Signature made Tue 05 Oct 2021 02:31:11 PM PDT # 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] * remotes/mst/tags/for_upstream: (47 commits) hw/i386/amd_iommu: Add description/category to TYPE_AMD_IOMMU_PCI hw/i386/amd_iommu: Rename SysBus specific functions as amdvi_sysbus_X() hw/i386/amd_iommu: Rename amdviPCI TypeInfo nvdimm: release the correct device list virtio-balloon: Fix page-poison subsection name bios-tables-test: Update ACPI DSDT table golden blobs for q35 hw/i386/acpi: fix conflicting IO address range for acpi pci hotplug in q35 bios-tables-test: allow changes in DSDT ACPI tables for q35 acpi: AcpiGenericAddress no longer used to map/access fields of MMIO, drop packed attribute acpi: remove no longer used build_header() acpi: build_facs: use build_append_int_noprefix() API to compose table acpi: arm/virt: build_gtdt: use acpi_table_begin()/acpi_table_end() instead of build_header() acpi: arm/virt: build_spcr: use acpi_table_begin()/acpi_table_end() instead of build_header() acpi: arm/virt: build_spcr: fix invalid cast acpi: arm/virt: convert build_iort() to endian agnostic build_append_FOO() API acpi: arm: virt: build_iort: use acpi_table_begin()/acpi_table_end() instead of build_header() acpi: arm: virt: build_dsdt: use acpi_table_begin()/acpi_table_end() instead of build_header() acpi: build_dsdt_microvm: use acpi_table_begin()/acpi_table_end() instead of build_header() acpi: arm/virt: madt: use build_append_int_noprefix() API to compose MADT table acpi: x86: madt: use build_append_int_noprefix() API to compose MADT table ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
@@ -3,7 +3,8 @@
|
||||
#include "hw/i386/acpi-build.h"
|
||||
|
||||
void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
||||
const CPUArchIdList *apic_ids, GArray *entry)
|
||||
const CPUArchIdList *apic_ids, GArray *entry,
|
||||
bool force_enabled)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
+118
-75
@@ -52,6 +52,19 @@ static void build_append_byte(GArray *array, uint8_t val)
|
||||
g_array_append_val(array, val);
|
||||
}
|
||||
|
||||
static void build_append_padded_str(GArray *array, const char *str,
|
||||
size_t maxlen, char pad)
|
||||
{
|
||||
size_t i;
|
||||
size_t len = strlen(str);
|
||||
|
||||
g_assert(len <= maxlen);
|
||||
g_array_append_vals(array, str, len);
|
||||
for (i = maxlen - len; i > 0; i--) {
|
||||
g_array_append_val(array, pad);
|
||||
}
|
||||
}
|
||||
|
||||
static void build_append_array(GArray *array, GArray *val)
|
||||
{
|
||||
g_array_append_vals(array, val->data, val->len);
|
||||
@@ -1692,27 +1705,53 @@ Aml *aml_object_type(Aml *object)
|
||||
return var;
|
||||
}
|
||||
|
||||
void
|
||||
build_header(BIOSLinker *linker, GArray *table_data,
|
||||
AcpiTableHeader *h, const char *sig, int len, uint8_t rev,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
void acpi_table_begin(AcpiTable *desc, GArray *array)
|
||||
{
|
||||
unsigned tbl_offset = (char *)h - table_data->data;
|
||||
unsigned checksum_offset = (char *)&h->checksum - table_data->data;
|
||||
memcpy(&h->signature, sig, 4);
|
||||
h->length = cpu_to_le32(len);
|
||||
h->revision = rev;
|
||||
|
||||
strpadcpy((char *)h->oem_id, sizeof h->oem_id, oem_id, ' ');
|
||||
strpadcpy((char *)h->oem_table_id, sizeof h->oem_table_id,
|
||||
oem_table_id, ' ');
|
||||
desc->array = array;
|
||||
desc->table_offset = array->len;
|
||||
|
||||
/*
|
||||
* ACPI spec 1.0b
|
||||
* 5.2.3 System Description Table Header
|
||||
*/
|
||||
g_assert(strlen(desc->sig) == 4);
|
||||
g_array_append_vals(array, desc->sig, 4); /* Signature */
|
||||
/*
|
||||
* reserve space for Length field, which will be patched by
|
||||
* acpi_table_end() when the table creation is finished.
|
||||
*/
|
||||
build_append_int_noprefix(array, 0, 4); /* Length */
|
||||
build_append_int_noprefix(array, desc->rev, 1); /* Revision */
|
||||
build_append_int_noprefix(array, 0, 1); /* Checksum */
|
||||
build_append_padded_str(array, desc->oem_id, 6, ' '); /* OEMID */
|
||||
/* OEM Table ID */
|
||||
build_append_padded_str(array, desc->oem_table_id, 8, ' ');
|
||||
build_append_int_noprefix(array, 1, 4); /* OEM Revision */
|
||||
g_array_append_vals(array, ACPI_BUILD_APPNAME8, 4); /* Creator ID */
|
||||
build_append_int_noprefix(array, 1, 4); /* Creator Revision */
|
||||
}
|
||||
|
||||
void acpi_table_end(BIOSLinker *linker, AcpiTable *desc)
|
||||
{
|
||||
/*
|
||||
* ACPI spec 1.0b
|
||||
* 5.2.3 System Description Table Header
|
||||
* Table 5-2 DESCRIPTION_HEADER Fields
|
||||
*/
|
||||
const unsigned checksum_offset = 9;
|
||||
uint32_t table_len = desc->array->len - desc->table_offset;
|
||||
uint32_t table_len_le = cpu_to_le32(table_len);
|
||||
gchar *len_ptr = &desc->array->data[desc->table_offset + 4];
|
||||
|
||||
/* patch "Length" field that has been reserved by acpi_table_begin()
|
||||
* to the actual length, i.e. accumulated table length from
|
||||
* acpi_table_begin() till acpi_table_end()
|
||||
*/
|
||||
memcpy(len_ptr, &table_len_le, sizeof table_len_le);
|
||||
|
||||
h->oem_revision = cpu_to_le32(1);
|
||||
memcpy(h->asl_compiler_id, ACPI_BUILD_APPNAME8, 4);
|
||||
h->asl_compiler_revision = cpu_to_le32(1);
|
||||
/* Checksum to be filled in by Guest linker */
|
||||
bios_linker_loader_add_checksum(linker, ACPI_BUILD_TABLE_FILE,
|
||||
tbl_offset, len, checksum_offset);
|
||||
desc->table_offset, table_len, desc->table_offset + checksum_offset);
|
||||
}
|
||||
|
||||
void *acpi_data_push(GArray *table_data, unsigned size)
|
||||
@@ -1822,73 +1861,81 @@ build_rsdp(GArray *tbl, BIOSLinker *linker, AcpiRsdpData *rsdp_data)
|
||||
32);
|
||||
}
|
||||
|
||||
/* Build rsdt table */
|
||||
/*
|
||||
* ACPI 1.0 Root System Description Table (RSDT)
|
||||
*/
|
||||
void
|
||||
build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
int i;
|
||||
unsigned rsdt_entries_offset;
|
||||
AcpiRsdtDescriptorRev1 *rsdt;
|
||||
int rsdt_start = table_data->len;
|
||||
const unsigned table_data_len = (sizeof(uint32_t) * table_offsets->len);
|
||||
const unsigned rsdt_entry_size = sizeof(rsdt->table_offset_entry[0]);
|
||||
const size_t rsdt_len = sizeof(*rsdt) + table_data_len;
|
||||
AcpiTable table = { .sig = "RSDT", .rev = 1,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
rsdt = acpi_data_push(table_data, rsdt_len);
|
||||
rsdt_entries_offset = (char *)rsdt->table_offset_entry - table_data->data;
|
||||
acpi_table_begin(&table, table_data);
|
||||
for (i = 0; i < table_offsets->len; ++i) {
|
||||
uint32_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i);
|
||||
uint32_t rsdt_entry_offset = rsdt_entries_offset + rsdt_entry_size * i;
|
||||
uint32_t rsdt_entry_offset = table.array->len;
|
||||
|
||||
/* rsdt->table_offset_entry to be filled by Guest linker */
|
||||
/* reserve space for entry */
|
||||
build_append_int_noprefix(table.array, 0, 4);
|
||||
|
||||
/* mark position of RSDT entry to be filled by Guest linker */
|
||||
bios_linker_loader_add_pointer(linker,
|
||||
ACPI_BUILD_TABLE_FILE, rsdt_entry_offset, rsdt_entry_size,
|
||||
ACPI_BUILD_TABLE_FILE, rsdt_entry_offset, 4,
|
||||
ACPI_BUILD_TABLE_FILE, ref_tbl_offset);
|
||||
|
||||
}
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + rsdt_start),
|
||||
"RSDT", rsdt_len, 1, oem_id, oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
/* Build xsdt table */
|
||||
/*
|
||||
* ACPI 2.0 eXtended System Description Table (XSDT)
|
||||
*/
|
||||
void
|
||||
build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
int i;
|
||||
unsigned xsdt_entries_offset;
|
||||
AcpiXsdtDescriptorRev2 *xsdt;
|
||||
int xsdt_start = table_data->len;
|
||||
const unsigned table_data_len = (sizeof(uint64_t) * table_offsets->len);
|
||||
const unsigned xsdt_entry_size = sizeof(xsdt->table_offset_entry[0]);
|
||||
const size_t xsdt_len = sizeof(*xsdt) + table_data_len;
|
||||
AcpiTable table = { .sig = "XSDT", .rev = 1,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
acpi_table_begin(&table, table_data);
|
||||
|
||||
xsdt = acpi_data_push(table_data, xsdt_len);
|
||||
xsdt_entries_offset = (char *)xsdt->table_offset_entry - table_data->data;
|
||||
for (i = 0; i < table_offsets->len; ++i) {
|
||||
uint64_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i);
|
||||
uint64_t xsdt_entry_offset = xsdt_entries_offset + xsdt_entry_size * i;
|
||||
uint64_t xsdt_entry_offset = table.array->len;
|
||||
|
||||
/* xsdt->table_offset_entry to be filled by Guest linker */
|
||||
/* reserve space for entry */
|
||||
build_append_int_noprefix(table.array, 0, 8);
|
||||
|
||||
/* mark position of RSDT entry to be filled by Guest linker */
|
||||
bios_linker_loader_add_pointer(linker,
|
||||
ACPI_BUILD_TABLE_FILE, xsdt_entry_offset, xsdt_entry_size,
|
||||
ACPI_BUILD_TABLE_FILE, xsdt_entry_offset, 8,
|
||||
ACPI_BUILD_TABLE_FILE, ref_tbl_offset);
|
||||
}
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + xsdt_start),
|
||||
"XSDT", xsdt_len, 1, oem_id, oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
|
||||
/*
|
||||
* ACPI spec, Revision 4.0
|
||||
* 5.2.16.2 Memory Affinity Structure
|
||||
*/
|
||||
void build_srat_memory(GArray *table_data, uint64_t base,
|
||||
uint64_t len, int node, MemoryAffinityFlags flags)
|
||||
{
|
||||
numamem->type = ACPI_SRAT_MEMORY;
|
||||
numamem->length = sizeof(*numamem);
|
||||
numamem->proximity = cpu_to_le32(node);
|
||||
numamem->flags = cpu_to_le32(flags);
|
||||
numamem->base_addr = cpu_to_le64(base);
|
||||
numamem->range_length = cpu_to_le64(len);
|
||||
build_append_int_noprefix(table_data, 1, 1); /* Type */
|
||||
build_append_int_noprefix(table_data, 40, 1); /* Length */
|
||||
build_append_int_noprefix(table_data, node, 4); /* Proximity Domain */
|
||||
build_append_int_noprefix(table_data, 0, 2); /* Reserved */
|
||||
build_append_int_noprefix(table_data, base, 4); /* Base Address Low */
|
||||
/* Base Address High */
|
||||
build_append_int_noprefix(table_data, base >> 32, 4);
|
||||
build_append_int_noprefix(table_data, len, 4); /* Length Low */
|
||||
build_append_int_noprefix(table_data, len >> 32, 4); /* Length High */
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
|
||||
build_append_int_noprefix(table_data, flags, 4); /* Flags */
|
||||
build_append_int_noprefix(table_data, 0, 8); /* Reserved */
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1898,11 +1945,12 @@ void build_srat_memory(AcpiSratMemoryAffinity *numamem, uint64_t base,
|
||||
void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
int slit_start, i, j;
|
||||
slit_start = table_data->len;
|
||||
int i, j;
|
||||
int nb_numa_nodes = ms->numa_state->num_nodes;
|
||||
AcpiTable table = { .sig = "SLIT", .rev = 1,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
acpi_data_push(table_data, sizeof(AcpiTableHeader));
|
||||
acpi_table_begin(&table, table_data);
|
||||
|
||||
build_append_int_noprefix(table_data, nb_numa_nodes, 8);
|
||||
for (i = 0; i < nb_numa_nodes; i++) {
|
||||
@@ -1913,11 +1961,7 @@ void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms,
|
||||
1);
|
||||
}
|
||||
}
|
||||
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + slit_start),
|
||||
"SLIT",
|
||||
table_data->len - slit_start, 1, oem_id, oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
/* build rev1/rev3/rev5.1 FADT */
|
||||
@@ -1925,9 +1969,10 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
int off;
|
||||
int fadt_start = tbl->len;
|
||||
AcpiTable table = { .sig = "FACP", .rev = f->rev,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
acpi_data_push(tbl, sizeof(AcpiTableHeader));
|
||||
acpi_table_begin(&table, tbl);
|
||||
|
||||
/* FACS address to be filled by Guest linker at runtime */
|
||||
off = tbl->len;
|
||||
@@ -1991,7 +2036,7 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
|
||||
build_append_int_noprefix(tbl, f->flags, 4); /* Flags */
|
||||
|
||||
if (f->rev == 1) {
|
||||
goto build_hdr;
|
||||
goto done;
|
||||
}
|
||||
|
||||
build_append_gas_from_struct(tbl, &f->reset_reg); /* RESET_REG */
|
||||
@@ -2028,7 +2073,7 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
|
||||
build_append_gas(tbl, AML_AS_SYSTEM_MEMORY, 0 , 0, 0, 0); /* X_GPE1_BLK */
|
||||
|
||||
if (f->rev <= 4) {
|
||||
goto build_hdr;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* SLEEP_CONTROL_REG */
|
||||
@@ -2039,9 +2084,8 @@ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f,
|
||||
/* TODO: extra fields need to be added to support revisions above rev5 */
|
||||
assert(f->rev == 5);
|
||||
|
||||
build_hdr:
|
||||
build_header(linker, tbl, (void *)(tbl->data + fadt_start),
|
||||
"FACP", tbl->len - fadt_start, f->rev, oem_id, oem_table_id);
|
||||
done:
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TPM
|
||||
@@ -2054,13 +2098,14 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
uint8_t start_method_params[12] = {};
|
||||
unsigned log_addr_offset, tpm2_start;
|
||||
unsigned log_addr_offset;
|
||||
uint64_t control_area_start_address;
|
||||
TPMIf *tpmif = tpm_find();
|
||||
uint32_t start_method;
|
||||
AcpiTable table = { .sig = "TPM2", .rev = 4,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
tpm2_start = table_data->len;
|
||||
acpi_data_push(table_data, sizeof(AcpiTableHeader));
|
||||
acpi_table_begin(&table, table_data);
|
||||
|
||||
/* Platform Class */
|
||||
build_append_int_noprefix(table_data, TPM2_ACPI_CLASS_CLIENT, 2);
|
||||
@@ -2098,9 +2143,7 @@ void build_tpm2(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
|
||||
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
|
||||
log_addr_offset, 8,
|
||||
ACPI_BUILD_TPMLOG_FILE, 0);
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + tpm2_start),
|
||||
"TPM2", table_data->len - tpm2_start, 4, oem_id, oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+2
-15
@@ -669,21 +669,8 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
|
||||
|
||||
/* build _MAT object */
|
||||
assert(adevc && adevc->madt_cpu);
|
||||
adevc->madt_cpu(adev, i, arch_ids, madt_buf);
|
||||
switch (madt_buf->data[0]) {
|
||||
case ACPI_APIC_PROCESSOR: {
|
||||
AcpiMadtProcessorApic *apic = (void *)madt_buf->data;
|
||||
apic->flags = cpu_to_le32(1);
|
||||
break;
|
||||
}
|
||||
case ACPI_APIC_LOCAL_X2APIC: {
|
||||
AcpiMadtProcessorX2Apic *apic = (void *)madt_buf->data;
|
||||
apic->flags = cpu_to_le32(1);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
adevc->madt_cpu(adev, i, arch_ids, madt_buf,
|
||||
true); /* set enabled flag */
|
||||
aml_append(dev, aml_name_decl("_MAT",
|
||||
aml_buffer(madt_buf->len, (uint8_t *)madt_buf->data)));
|
||||
g_array_free(madt_buf, true);
|
||||
|
||||
+4
-6
@@ -362,18 +362,16 @@ static void build_ghes_v2(GArray *table_data, int source_id, BIOSLinker *linker)
|
||||
void acpi_build_hest(GArray *table_data, BIOSLinker *linker,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
uint64_t hest_start = table_data->len;
|
||||
AcpiTable table = { .sig = "HEST", .rev = 1,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
/* Hardware Error Source Table header*/
|
||||
acpi_data_push(table_data, sizeof(AcpiTableHeader));
|
||||
acpi_table_begin(&table, table_data);
|
||||
|
||||
/* Error Source Count */
|
||||
build_append_int_noprefix(table_data, ACPI_GHES_ERROR_SOURCE_COUNT, 4);
|
||||
|
||||
build_ghes_v2(table_data, ACPI_HEST_SRC_ID_SEA, linker);
|
||||
|
||||
build_header(linker, table_data, (void *)(table_data->data + hest_start),
|
||||
"HEST", table_data->len - hest_start, 1, oem_id, oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
void acpi_ghes_add_fw_cfg(AcpiGhesState *ags, FWCfgState *s,
|
||||
|
||||
+6
-8
@@ -200,6 +200,8 @@ static void hmat_build_table_structs(GArray *table_data, NumaState *numa_state)
|
||||
HMAT_LB_Info *hmat_lb;
|
||||
NumaHmatCacheOptions *hmat_cache;
|
||||
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
|
||||
|
||||
for (i = 0; i < numa_state->num_nodes; i++) {
|
||||
flags = 0;
|
||||
|
||||
@@ -256,14 +258,10 @@ static void hmat_build_table_structs(GArray *table_data, NumaState *numa_state)
|
||||
void build_hmat(GArray *table_data, BIOSLinker *linker, NumaState *numa_state,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
int hmat_start = table_data->len;
|
||||
|
||||
/* reserve space for HMAT header */
|
||||
acpi_data_push(table_data, 40);
|
||||
AcpiTable table = { .sig = "HMAT", .rev = 2,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
acpi_table_begin(&table, table_data);
|
||||
hmat_build_table_structs(table_data, numa_state);
|
||||
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + hmat_start),
|
||||
"HMAT", table_data->len - hmat_start, 2, oem_id, oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
+34
-42
@@ -44,22 +44,6 @@ static const uint8_t nvdimm_nfit_spa_uuid[] =
|
||||
UUID_LE(0x66f0d379, 0xb4f3, 0x4074, 0xac, 0x43, 0x0d, 0x33,
|
||||
0x18, 0xb7, 0x8c, 0xdb);
|
||||
|
||||
/*
|
||||
* NVDIMM Firmware Interface Table
|
||||
* @signature: "NFIT"
|
||||
*
|
||||
* It provides information that allows OSPM to enumerate NVDIMM present in
|
||||
* the platform and associate system physical address ranges created by the
|
||||
* NVDIMMs.
|
||||
*
|
||||
* It is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)
|
||||
*/
|
||||
struct NvdimmNfitHeader {
|
||||
ACPI_TABLE_HEADER_DEF
|
||||
uint32_t reserved;
|
||||
} QEMU_PACKED;
|
||||
typedef struct NvdimmNfitHeader NvdimmNfitHeader;
|
||||
|
||||
/*
|
||||
* define NFIT structures according to ACPI 6.0: 5.2.25 NVDIMM Firmware
|
||||
* Interface Table (NFIT).
|
||||
@@ -355,10 +339,10 @@ nvdimm_build_structure_caps(GArray *structures, uint32_t capabilities)
|
||||
|
||||
static GArray *nvdimm_build_device_structure(NVDIMMState *state)
|
||||
{
|
||||
GSList *device_list = nvdimm_get_device_list();
|
||||
GSList *device_list, *list = nvdimm_get_device_list();
|
||||
GArray *structures = g_array_new(false, true /* clear */, 1);
|
||||
|
||||
for (; device_list; device_list = device_list->next) {
|
||||
for (device_list = list; device_list; device_list = device_list->next) {
|
||||
DeviceState *dev = device_list->data;
|
||||
|
||||
/* build System Physical Address Range Structure. */
|
||||
@@ -373,7 +357,7 @@ static GArray *nvdimm_build_device_structure(NVDIMMState *state)
|
||||
/* build NVDIMM Control Region Structure. */
|
||||
nvdimm_build_structure_dcr(structures, dev);
|
||||
}
|
||||
g_slist_free(device_list);
|
||||
g_slist_free(list);
|
||||
|
||||
if (state->persistence) {
|
||||
nvdimm_build_structure_caps(structures, state->persistence);
|
||||
@@ -401,25 +385,33 @@ void nvdimm_plug(NVDIMMState *state)
|
||||
nvdimm_build_fit_buffer(state);
|
||||
}
|
||||
|
||||
/*
|
||||
* NVDIMM Firmware Interface Table
|
||||
* @signature: "NFIT"
|
||||
*
|
||||
* It provides information that allows OSPM to enumerate NVDIMM present in
|
||||
* the platform and associate system physical address ranges created by the
|
||||
* NVDIMMs.
|
||||
*
|
||||
* It is defined in ACPI 6.0: 5.2.25 NVDIMM Firmware Interface Table (NFIT)
|
||||
*/
|
||||
|
||||
static void nvdimm_build_nfit(NVDIMMState *state, GArray *table_offsets,
|
||||
GArray *table_data, BIOSLinker *linker,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
NvdimmFitBuffer *fit_buf = &state->fit_buf;
|
||||
unsigned int header;
|
||||
AcpiTable table = { .sig = "NFIT", .rev = 1,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
acpi_add_table(table_offsets, table_data);
|
||||
|
||||
/* NFIT header. */
|
||||
header = table_data->len;
|
||||
acpi_data_push(table_data, sizeof(NvdimmNfitHeader));
|
||||
acpi_table_begin(&table, table_data);
|
||||
/* Reserved */
|
||||
build_append_int_noprefix(table_data, 0, 4);
|
||||
/* NVDIMM device structures. */
|
||||
g_array_append_vals(table_data, fit_buf->fit->data, fit_buf->fit->len);
|
||||
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + header), "NFIT",
|
||||
sizeof(NvdimmNfitHeader) + fit_buf->fit->len, 1, oem_id,
|
||||
oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
#define NVDIMM_DSM_MEMORY_SIZE 4096
|
||||
@@ -1282,14 +1274,15 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data,
|
||||
NVDIMMState *nvdimm_state,
|
||||
uint32_t ram_slots, const char *oem_id)
|
||||
{
|
||||
int mem_addr_offset;
|
||||
Aml *ssdt, *sb_scope, *dev;
|
||||
int mem_addr_offset, nvdimm_ssdt;
|
||||
AcpiTable table = { .sig = "SSDT", .rev = 1,
|
||||
.oem_id = oem_id, .oem_table_id = "NVDIMM" };
|
||||
|
||||
acpi_add_table(table_offsets, table_data);
|
||||
|
||||
acpi_table_begin(&table, table_data);
|
||||
ssdt = init_aml_allocator();
|
||||
acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
|
||||
|
||||
sb_scope = aml_scope("\\_SB");
|
||||
|
||||
dev = aml_device("NVDR");
|
||||
@@ -1318,8 +1311,6 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data,
|
||||
aml_append(sb_scope, dev);
|
||||
aml_append(ssdt, sb_scope);
|
||||
|
||||
nvdimm_ssdt = table_data->len;
|
||||
|
||||
/* copy AML table into ACPI tables blob and patch header there */
|
||||
g_array_append_vals(table_data, ssdt->buf->data, ssdt->buf->len);
|
||||
mem_addr_offset = build_append_named_dword(table_data,
|
||||
@@ -1331,18 +1322,20 @@ static void nvdimm_build_ssdt(GArray *table_offsets, GArray *table_data,
|
||||
bios_linker_loader_add_pointer(linker,
|
||||
ACPI_BUILD_TABLE_FILE, mem_addr_offset, sizeof(uint32_t),
|
||||
NVDIMM_DSM_MEM_FILE, 0);
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + nvdimm_ssdt),
|
||||
"SSDT", table_data->len - nvdimm_ssdt, 1, oem_id, "NVDIMM");
|
||||
free_aml_allocator();
|
||||
/*
|
||||
* must be executed as the last so that pointer patching command above
|
||||
* would be executed by guest before it recalculated checksum which were
|
||||
* scheduled by acpi_table_end()
|
||||
*/
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
void nvdimm_build_srat(GArray *table_data)
|
||||
{
|
||||
GSList *device_list = nvdimm_get_device_list();
|
||||
GSList *device_list, *list = nvdimm_get_device_list();
|
||||
|
||||
for (; device_list; device_list = device_list->next) {
|
||||
AcpiSratMemoryAffinity *numamem = NULL;
|
||||
for (device_list = list; device_list; device_list = device_list->next) {
|
||||
DeviceState *dev = device_list->data;
|
||||
Object *obj = OBJECT(dev);
|
||||
uint64_t addr, size;
|
||||
@@ -1352,11 +1345,10 @@ void nvdimm_build_srat(GArray *table_data)
|
||||
addr = object_property_get_uint(obj, PC_DIMM_ADDR_PROP, &error_abort);
|
||||
size = object_property_get_uint(obj, PC_DIMM_SIZE_PROP, &error_abort);
|
||||
|
||||
numamem = acpi_data_push(table_data, sizeof *numamem);
|
||||
build_srat_memory(numamem, addr, size, node,
|
||||
build_srat_memory(table_data, addr, size, node,
|
||||
MEM_AFFINITY_ENABLED | MEM_AFFINITY_NON_VOLATILE);
|
||||
}
|
||||
g_slist_free(device_list);
|
||||
g_slist_free(list);
|
||||
}
|
||||
|
||||
void nvdimm_build_acpi(GArray *table_offsets, GArray *table_data,
|
||||
|
||||
+9
-9
@@ -28,19 +28,20 @@
|
||||
#include "hw/acpi/pci.h"
|
||||
#include "hw/pci/pcie_host.h"
|
||||
|
||||
/*
|
||||
* PCI Firmware Specification, Revision 3.0
|
||||
* 4.1.2 MCFG Table Description.
|
||||
*/
|
||||
void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
int mcfg_start = table_data->len;
|
||||
AcpiTable table = { .sig = "MCFG", .rev = 1,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
acpi_table_begin(&table, table_data);
|
||||
|
||||
/*
|
||||
* PCI Firmware Specification, Revision 3.0
|
||||
* 4.1.2 MCFG Table Description.
|
||||
*/
|
||||
acpi_data_push(table_data, sizeof(AcpiTableHeader));
|
||||
/* Reserved */
|
||||
build_append_int_noprefix(table_data, 0, 8);
|
||||
|
||||
/*
|
||||
* Memory Mapped Enhanced Configuration Space Base Address Allocation
|
||||
* Structure
|
||||
@@ -56,6 +57,5 @@ void build_mcfg(GArray *table_data, BIOSLinker *linker, AcpiMcfgInfo *info,
|
||||
/* Reserved */
|
||||
build_append_int_noprefix(table_data, 0, 4);
|
||||
|
||||
build_header(linker, table_data, (void *)(table_data->data + mcfg_start),
|
||||
"MCFG", table_data->len - mcfg_start, 1, oem_id, oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
+6
-7
@@ -29,6 +29,8 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
|
||||
Aml *ssdt, *dev, *scope, *method, *addr, *if_ctx;
|
||||
uint32_t vgia_offset;
|
||||
QemuUUID guid_le;
|
||||
AcpiTable table = { .sig = "SSDT", .rev = 1,
|
||||
.oem_id = oem_id, .oem_table_id = "VMGENID" };
|
||||
|
||||
/* Fill in the GUID values. These need to be converted to little-endian
|
||||
* first, since that's what the guest expects
|
||||
@@ -42,12 +44,10 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
|
||||
g_array_insert_vals(guid, VMGENID_GUID_OFFSET, guid_le.data,
|
||||
ARRAY_SIZE(guid_le.data));
|
||||
|
||||
/* Put this in a separate SSDT table */
|
||||
/* Put VMGNEID into a separate SSDT table */
|
||||
acpi_table_begin(&table, table_data);
|
||||
ssdt = init_aml_allocator();
|
||||
|
||||
/* Reserve space for header */
|
||||
acpi_data_push(ssdt->buf, sizeof(AcpiTableHeader));
|
||||
|
||||
/* Storage for the GUID address */
|
||||
vgia_offset = table_data->len +
|
||||
build_append_named_dword(ssdt->buf, "VGIA");
|
||||
@@ -116,9 +116,8 @@ void vmgenid_build_acpi(VmGenIdState *vms, GArray *table_data, GArray *guid,
|
||||
ACPI_BUILD_TABLE_FILE, vgia_offset, sizeof(uint32_t),
|
||||
VMGENID_GUID_FW_CFG_FILE, 0);
|
||||
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + table_data->len - ssdt->buf->len),
|
||||
"SSDT", ssdt->buf->len, 1, oem_id, "VMGENID");
|
||||
/* must be called after above command to ensure correct table checksum */
|
||||
acpi_table_end(linker, &table);
|
||||
free_aml_allocator();
|
||||
}
|
||||
|
||||
|
||||
+318
-233
File diff suppressed because it is too large
Load Diff
+4
-1
@@ -37,7 +37,9 @@
|
||||
#include "hw/virtio/virtio.h"
|
||||
#include "hw/virtio/virtio-pci.h"
|
||||
|
||||
GlobalProperty hw_compat_6_1[] = {};
|
||||
GlobalProperty hw_compat_6_1[] = {
|
||||
{ "vhost-user-vsock-device", "seqpacket", "off" },
|
||||
};
|
||||
const size_t hw_compat_6_1_len = G_N_ELEMENTS(hw_compat_6_1);
|
||||
|
||||
GlobalProperty hw_compat_6_0[] = {
|
||||
@@ -46,6 +48,7 @@ GlobalProperty hw_compat_6_0[] = {
|
||||
{ "nvme-ns", "eui64-default", "off"},
|
||||
{ "e1000", "init-vet", "off" },
|
||||
{ "e1000e", "init-vet", "off" },
|
||||
{ "vhost-vsock-device", "seqpacket", "off" },
|
||||
};
|
||||
const size_t hw_compat_6_0_len = G_N_ELEMENTS(hw_compat_6_0);
|
||||
|
||||
|
||||
+164
-128
@@ -345,13 +345,23 @@ static void acpi_align_size(GArray *blob, unsigned align)
|
||||
g_array_set_size(blob, ROUND_UP(acpi_data_len(blob), align));
|
||||
}
|
||||
|
||||
/* FACS */
|
||||
/*
|
||||
* ACPI spec 1.0b,
|
||||
* 5.2.6 Firmware ACPI Control Structure
|
||||
*/
|
||||
static void
|
||||
build_facs(GArray *table_data)
|
||||
{
|
||||
AcpiFacsDescriptorRev1 *facs = acpi_data_push(table_data, sizeof *facs);
|
||||
memcpy(&facs->signature, "FACS", 4);
|
||||
facs->length = cpu_to_le32(sizeof(*facs));
|
||||
const char *sig = "FACS";
|
||||
const uint8_t reserved[40] = {};
|
||||
|
||||
g_array_append_vals(table_data, sig, 4); /* Signature */
|
||||
build_append_int_noprefix(table_data, 64, 4); /* Length */
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Hardware Signature */
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Firmware Waking Vector */
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Global Lock */
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Flags */
|
||||
g_array_append_vals(table_data, reserved, 40); /* Reserved */
|
||||
}
|
||||
|
||||
static void build_append_pcihp_notify_entry(Aml *method, int slot)
|
||||
@@ -1405,12 +1415,12 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
#endif
|
||||
int i;
|
||||
VMBusBridge *vmbus_bridge = vmbus_bridge_find();
|
||||
AcpiTable table = { .sig = "DSDT", .rev = 1, .oem_id = x86ms->oem_id,
|
||||
.oem_table_id = x86ms->oem_table_id };
|
||||
|
||||
acpi_table_begin(&table, table_data);
|
||||
dsdt = init_aml_allocator();
|
||||
|
||||
/* Reserve space for header */
|
||||
acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader));
|
||||
|
||||
build_dbg_aml(dsdt);
|
||||
if (misc->is_piix4) {
|
||||
sb_scope = aml_scope("_SB");
|
||||
@@ -1867,70 +1877,87 @@ build_dsdt(GArray *table_data, BIOSLinker *linker,
|
||||
|
||||
/* copy AML table into ACPI tables blob and patch header there */
|
||||
g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + table_data->len - dsdt->buf->len),
|
||||
"DSDT", dsdt->buf->len, 1, x86ms->oem_id, x86ms->oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
free_aml_allocator();
|
||||
}
|
||||
|
||||
/*
|
||||
* IA-PC HPET (High Precision Event Timers) Specification (Revision: 1.0a)
|
||||
* 3.2.4The ACPI 2.0 HPET Description Table (HPET)
|
||||
*/
|
||||
static void
|
||||
build_hpet(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
||||
const char *oem_table_id)
|
||||
{
|
||||
Acpi20Hpet *hpet;
|
||||
int hpet_start = table_data->len;
|
||||
AcpiTable table = { .sig = "HPET", .rev = 1,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
hpet = acpi_data_push(table_data, sizeof(*hpet));
|
||||
acpi_table_begin(&table, table_data);
|
||||
/* Note timer_block_id value must be kept in sync with value advertised by
|
||||
* emulated hpet
|
||||
*/
|
||||
hpet->timer_block_id = cpu_to_le32(0x8086a201);
|
||||
hpet->addr.address = cpu_to_le64(HPET_BASE);
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + hpet_start),
|
||||
"HPET", sizeof(*hpet), 1, oem_id, oem_table_id);
|
||||
/* Event Timer Block ID */
|
||||
build_append_int_noprefix(table_data, 0x8086a201, 4);
|
||||
/* BASE_ADDRESS */
|
||||
build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 0, 0, 0, HPET_BASE);
|
||||
/* HPET Number */
|
||||
build_append_int_noprefix(table_data, 0, 1);
|
||||
/* Main Counter Minimum Clock_tick in Periodic Mode */
|
||||
build_append_int_noprefix(table_data, 0, 2);
|
||||
/* Page Protection And OEM Attribute */
|
||||
build_append_int_noprefix(table_data, 0, 1);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TPM
|
||||
/*
|
||||
* TCPA Description Table
|
||||
*
|
||||
* Following Level 00, Rev 00.37 of specs:
|
||||
* http://www.trustedcomputinggroup.org/resources/tcg_acpi_specification
|
||||
* 7.1.2 ACPI Table Layout
|
||||
*/
|
||||
static void
|
||||
build_tpm_tcpa(GArray *table_data, BIOSLinker *linker, GArray *tcpalog,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
int tcpa_start = table_data->len;
|
||||
Acpi20Tcpa *tcpa = acpi_data_push(table_data, sizeof *tcpa);
|
||||
unsigned log_addr_size = sizeof(tcpa->log_area_start_address);
|
||||
unsigned log_addr_offset =
|
||||
(char *)&tcpa->log_area_start_address - table_data->data;
|
||||
unsigned log_addr_offset;
|
||||
AcpiTable table = { .sig = "TCPA", .rev = 2,
|
||||
.oem_id = oem_id, .oem_table_id = oem_table_id };
|
||||
|
||||
tcpa->platform_class = cpu_to_le16(TPM_TCPA_ACPI_CLASS_CLIENT);
|
||||
tcpa->log_area_minimum_length = cpu_to_le32(TPM_LOG_AREA_MINIMUM_SIZE);
|
||||
acpi_data_push(tcpalog, le32_to_cpu(tcpa->log_area_minimum_length));
|
||||
acpi_table_begin(&table, table_data);
|
||||
/* Platform Class */
|
||||
build_append_int_noprefix(table_data, TPM_TCPA_ACPI_CLASS_CLIENT, 2);
|
||||
/* Log Area Minimum Length (LAML) */
|
||||
build_append_int_noprefix(table_data, TPM_LOG_AREA_MINIMUM_SIZE, 4);
|
||||
/* Log Area Start Address (LASA) */
|
||||
log_addr_offset = table_data->len;
|
||||
build_append_int_noprefix(table_data, 0, 8);
|
||||
|
||||
/* allocate/reserve space for TPM log area */
|
||||
acpi_data_push(tcpalog, TPM_LOG_AREA_MINIMUM_SIZE);
|
||||
bios_linker_loader_alloc(linker, ACPI_BUILD_TPMLOG_FILE, tcpalog, 1,
|
||||
false /* high memory */);
|
||||
|
||||
/* log area start address to be filled by Guest linker */
|
||||
bios_linker_loader_add_pointer(linker,
|
||||
ACPI_BUILD_TABLE_FILE, log_addr_offset, log_addr_size,
|
||||
ACPI_BUILD_TPMLOG_FILE, 0);
|
||||
bios_linker_loader_add_pointer(linker, ACPI_BUILD_TABLE_FILE,
|
||||
log_addr_offset, 8, ACPI_BUILD_TPMLOG_FILE, 0);
|
||||
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + tcpa_start),
|
||||
"TCPA", sizeof(*tcpa), 2, oem_id, oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define HOLE_640K_START (640 * KiB)
|
||||
#define HOLE_640K_END (1 * MiB)
|
||||
|
||||
/*
|
||||
* ACPI spec, Revision 3.0
|
||||
* 5.2.15 System Resource Affinity Table (SRAT)
|
||||
*/
|
||||
static void
|
||||
build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
{
|
||||
AcpiSystemResourceAffinityTable *srat;
|
||||
AcpiSratMemoryAffinity *numamem;
|
||||
|
||||
int i;
|
||||
int srat_start, numa_start, slots;
|
||||
int numa_mem_start, slots;
|
||||
uint64_t mem_len, mem_base, next_base;
|
||||
MachineClass *mc = MACHINE_GET_CLASS(machine);
|
||||
X86MachineState *x86ms = X86_MACHINE(machine);
|
||||
@@ -1941,45 +1968,53 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
ram_addr_t hotpluggable_address_space_size =
|
||||
object_property_get_int(OBJECT(pcms), PC_MACHINE_DEVMEM_REGION_SIZE,
|
||||
NULL);
|
||||
AcpiTable table = { .sig = "SRAT", .rev = 1, .oem_id = x86ms->oem_id,
|
||||
.oem_table_id = x86ms->oem_table_id };
|
||||
|
||||
srat_start = table_data->len;
|
||||
|
||||
srat = acpi_data_push(table_data, sizeof *srat);
|
||||
srat->reserved1 = cpu_to_le32(1);
|
||||
acpi_table_begin(&table, table_data);
|
||||
build_append_int_noprefix(table_data, 1, 4); /* Reserved */
|
||||
build_append_int_noprefix(table_data, 0, 8); /* Reserved */
|
||||
|
||||
for (i = 0; i < apic_ids->len; i++) {
|
||||
int node_id = apic_ids->cpus[i].props.node_id;
|
||||
uint32_t apic_id = apic_ids->cpus[i].arch_id;
|
||||
|
||||
if (apic_id < 255) {
|
||||
AcpiSratProcessorAffinity *core;
|
||||
|
||||
core = acpi_data_push(table_data, sizeof *core);
|
||||
core->type = ACPI_SRAT_PROCESSOR_APIC;
|
||||
core->length = sizeof(*core);
|
||||
core->local_apic_id = apic_id;
|
||||
core->proximity_lo = node_id;
|
||||
memset(core->proximity_hi, 0, 3);
|
||||
core->local_sapic_eid = 0;
|
||||
core->flags = cpu_to_le32(1);
|
||||
/* 5.2.15.1 Processor Local APIC/SAPIC Affinity Structure */
|
||||
build_append_int_noprefix(table_data, 0, 1); /* Type */
|
||||
build_append_int_noprefix(table_data, 16, 1); /* Length */
|
||||
/* Proximity Domain [7:0] */
|
||||
build_append_int_noprefix(table_data, node_id, 1);
|
||||
build_append_int_noprefix(table_data, apic_id, 1); /* APIC ID */
|
||||
/* Flags, Table 5-36 */
|
||||
build_append_int_noprefix(table_data, 1, 4);
|
||||
build_append_int_noprefix(table_data, 0, 1); /* Local SAPIC EID */
|
||||
/* Proximity Domain [31:8] */
|
||||
build_append_int_noprefix(table_data, 0, 3);
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
|
||||
} else {
|
||||
AcpiSratProcessorX2ApicAffinity *core;
|
||||
|
||||
core = acpi_data_push(table_data, sizeof *core);
|
||||
core->type = ACPI_SRAT_PROCESSOR_x2APIC;
|
||||
core->length = sizeof(*core);
|
||||
core->x2apic_id = cpu_to_le32(apic_id);
|
||||
core->proximity_domain = cpu_to_le32(node_id);
|
||||
core->flags = cpu_to_le32(1);
|
||||
/*
|
||||
* ACPI spec, Revision 4.0
|
||||
* 5.2.16.3 Processor Local x2APIC Affinity Structure
|
||||
*/
|
||||
build_append_int_noprefix(table_data, 2, 1); /* Type */
|
||||
build_append_int_noprefix(table_data, 24, 1); /* Length */
|
||||
build_append_int_noprefix(table_data, 0, 2); /* Reserved */
|
||||
/* Proximity Domain */
|
||||
build_append_int_noprefix(table_data, node_id, 4);
|
||||
build_append_int_noprefix(table_data, apic_id, 4); /* X2APIC ID */
|
||||
/* Flags, Table 5-39 */
|
||||
build_append_int_noprefix(table_data, 1 /* Enabled */, 4);
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Clock Domain */
|
||||
build_append_int_noprefix(table_data, 0, 4); /* Reserved */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* the memory map is a bit tricky, it contains at least one hole
|
||||
* from 640k-1M and possibly another one from 3.5G-4G.
|
||||
*/
|
||||
next_base = 0;
|
||||
numa_start = table_data->len;
|
||||
numa_mem_start = table_data->len;
|
||||
|
||||
for (i = 1; i < nb_numa_nodes + 1; ++i) {
|
||||
mem_base = next_base;
|
||||
@@ -1991,8 +2026,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
next_base > HOLE_640K_START) {
|
||||
mem_len -= next_base - HOLE_640K_START;
|
||||
if (mem_len > 0) {
|
||||
numamem = acpi_data_push(table_data, sizeof *numamem);
|
||||
build_srat_memory(numamem, mem_base, mem_len, i - 1,
|
||||
build_srat_memory(table_data, mem_base, mem_len, i - 1,
|
||||
MEM_AFFINITY_ENABLED);
|
||||
}
|
||||
|
||||
@@ -2010,8 +2044,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
next_base > x86ms->below_4g_mem_size) {
|
||||
mem_len -= next_base - x86ms->below_4g_mem_size;
|
||||
if (mem_len > 0) {
|
||||
numamem = acpi_data_push(table_data, sizeof *numamem);
|
||||
build_srat_memory(numamem, mem_base, mem_len, i - 1,
|
||||
build_srat_memory(table_data, mem_base, mem_len, i - 1,
|
||||
MEM_AFFINITY_ENABLED);
|
||||
}
|
||||
mem_base = 1ULL << 32;
|
||||
@@ -2020,8 +2053,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
}
|
||||
|
||||
if (mem_len > 0) {
|
||||
numamem = acpi_data_push(table_data, sizeof *numamem);
|
||||
build_srat_memory(numamem, mem_base, mem_len, i - 1,
|
||||
build_srat_memory(table_data, mem_base, mem_len, i - 1,
|
||||
MEM_AFFINITY_ENABLED);
|
||||
}
|
||||
}
|
||||
@@ -2030,10 +2062,15 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
nvdimm_build_srat(table_data);
|
||||
}
|
||||
|
||||
slots = (table_data->len - numa_start) / sizeof *numamem;
|
||||
/*
|
||||
* TODO: this part is not in ACPI spec and current linux kernel boots fine
|
||||
* without these entries. But I recall there were issues the last time I
|
||||
* tried to remove it with some ancient guest OS, however I can't remember
|
||||
* what that was so keep this around for now
|
||||
*/
|
||||
slots = (table_data->len - numa_mem_start) / 40 /* mem affinity len */;
|
||||
for (; slots < nb_numa_nodes + 2; slots++) {
|
||||
numamem = acpi_data_push(table_data, sizeof *numamem);
|
||||
build_srat_memory(numamem, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
|
||||
build_srat_memory(table_data, 0, 0, 0, MEM_AFFINITY_NOFLAGS);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2045,17 +2082,12 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
* providing _PXM method if necessary.
|
||||
*/
|
||||
if (hotpluggable_address_space_size) {
|
||||
numamem = acpi_data_push(table_data, sizeof *numamem);
|
||||
build_srat_memory(numamem, machine->device_memory->base,
|
||||
build_srat_memory(table_data, machine->device_memory->base,
|
||||
hotpluggable_address_space_size, nb_numa_nodes - 1,
|
||||
MEM_AFFINITY_HOTPLUGGABLE | MEM_AFFINITY_ENABLED);
|
||||
}
|
||||
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + srat_start),
|
||||
"SRAT",
|
||||
table_data->len - srat_start, 1, x86ms->oem_id,
|
||||
x86ms->oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2064,8 +2096,9 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine)
|
||||
static void
|
||||
insert_scope(PCIBus *bus, PCIDevice *dev, void *opaque)
|
||||
{
|
||||
const size_t device_scope_size = 6 /* device scope structure */ +
|
||||
2 /* 1 path entry */;
|
||||
GArray *scope_blob = opaque;
|
||||
AcpiDmarDeviceScope *scope = NULL;
|
||||
|
||||
if (object_dynamic_cast(OBJECT(dev), TYPE_PCI_BRIDGE)) {
|
||||
/* Dmar Scope Type: 0x02 for PCI Bridge */
|
||||
@@ -2076,8 +2109,7 @@ insert_scope(PCIBus *bus, PCIDevice *dev, void *opaque)
|
||||
}
|
||||
|
||||
/* length */
|
||||
build_append_int_noprefix(scope_blob,
|
||||
sizeof(*scope) + sizeof(scope->path[0]), 1);
|
||||
build_append_int_noprefix(scope_blob, device_scope_size, 1);
|
||||
/* reserved */
|
||||
build_append_int_noprefix(scope_blob, 0, 2);
|
||||
/* enumeration_id */
|
||||
@@ -2109,26 +2141,26 @@ dmar_host_bridges(Object *obj, void *opaque)
|
||||
}
|
||||
|
||||
/*
|
||||
* VT-d spec 8.1 DMA Remapping Reporting Structure
|
||||
* (version Oct. 2014 or later)
|
||||
* Intel ® Virtualization Technology for Directed I/O
|
||||
* Architecture Specification. Revision 3.3
|
||||
* 8.1 DMA Remapping Reporting Structure
|
||||
*/
|
||||
static void
|
||||
build_dmar_q35(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
||||
const char *oem_table_id)
|
||||
{
|
||||
int dmar_start = table_data->len;
|
||||
|
||||
AcpiTableDmar *dmar;
|
||||
AcpiDmarHardwareUnit *drhd;
|
||||
AcpiDmarRootPortATS *atsr;
|
||||
uint8_t dmar_flags = 0;
|
||||
uint8_t rsvd10[10] = {};
|
||||
/* Root complex IOAPIC uses one path only */
|
||||
const size_t ioapic_scope_size = 6 /* device scope structure */ +
|
||||
2 /* 1 path entry */;
|
||||
X86IOMMUState *iommu = x86_iommu_get_default();
|
||||
AcpiDmarDeviceScope *scope = NULL;
|
||||
/* Root complex IOAPIC use one path[0] only */
|
||||
size_t ioapic_scope_size = sizeof(*scope) + sizeof(scope->path[0]);
|
||||
IntelIOMMUState *intel_iommu = INTEL_IOMMU_DEVICE(iommu);
|
||||
GArray *scope_blob = g_array_new(false, true, 1);
|
||||
|
||||
AcpiTable table = { .sig = "DMAR", .rev = 1, .oem_id = oem_id,
|
||||
.oem_table_id = oem_table_id };
|
||||
|
||||
/*
|
||||
* A PCI bus walk, for each PCI host bridge.
|
||||
* Insert scope for each PCI bridge and endpoint device which
|
||||
@@ -2142,43 +2174,52 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
||||
dmar_flags |= 0x1; /* Flags: 0x1: INT_REMAP */
|
||||
}
|
||||
|
||||
dmar = acpi_data_push(table_data, sizeof(*dmar));
|
||||
dmar->host_address_width = intel_iommu->aw_bits - 1;
|
||||
dmar->flags = dmar_flags;
|
||||
acpi_table_begin(&table, table_data);
|
||||
/* Host Address Width */
|
||||
build_append_int_noprefix(table_data, intel_iommu->aw_bits - 1, 1);
|
||||
build_append_int_noprefix(table_data, dmar_flags, 1); /* Flags */
|
||||
g_array_append_vals(table_data, rsvd10, sizeof(rsvd10)); /* Reserved */
|
||||
|
||||
/* DMAR Remapping Hardware Unit Definition structure */
|
||||
drhd = acpi_data_push(table_data, sizeof(*drhd) + ioapic_scope_size);
|
||||
drhd->type = cpu_to_le16(ACPI_DMAR_TYPE_HARDWARE_UNIT);
|
||||
drhd->length =
|
||||
cpu_to_le16(sizeof(*drhd) + ioapic_scope_size + scope_blob->len);
|
||||
drhd->flags = 0; /* Don't include all pci device */
|
||||
drhd->pci_segment = cpu_to_le16(0);
|
||||
drhd->address = cpu_to_le64(Q35_HOST_BRIDGE_IOMMU_ADDR);
|
||||
/* 8.3 DMAR Remapping Hardware Unit Definition structure */
|
||||
build_append_int_noprefix(table_data, 0, 2); /* Type */
|
||||
/* Length */
|
||||
build_append_int_noprefix(table_data,
|
||||
16 + ioapic_scope_size + scope_blob->len, 2);
|
||||
/* Flags */
|
||||
build_append_int_noprefix(table_data, 0 /* Don't include all pci device */ ,
|
||||
1);
|
||||
build_append_int_noprefix(table_data, 0 , 1); /* Reserved */
|
||||
build_append_int_noprefix(table_data, 0 , 2); /* Segment Number */
|
||||
/* Register Base Address */
|
||||
build_append_int_noprefix(table_data, Q35_HOST_BRIDGE_IOMMU_ADDR , 8);
|
||||
|
||||
/* Scope definition for the root-complex IOAPIC. See VT-d spec
|
||||
* 8.3.1 (version Oct. 2014 or later). */
|
||||
scope = &drhd->scope[0];
|
||||
scope->entry_type = 0x03; /* Type: 0x03 for IOAPIC */
|
||||
scope->length = ioapic_scope_size;
|
||||
scope->enumeration_id = ACPI_BUILD_IOAPIC_ID;
|
||||
scope->bus = Q35_PSEUDO_BUS_PLATFORM;
|
||||
scope->path[0].device = PCI_SLOT(Q35_PSEUDO_DEVFN_IOAPIC);
|
||||
scope->path[0].function = PCI_FUNC(Q35_PSEUDO_DEVFN_IOAPIC);
|
||||
build_append_int_noprefix(table_data, 0x03 /* IOAPIC */, 1); /* Type */
|
||||
build_append_int_noprefix(table_data, ioapic_scope_size, 1); /* Length */
|
||||
build_append_int_noprefix(table_data, 0, 2); /* Reserved */
|
||||
/* Enumeration ID */
|
||||
build_append_int_noprefix(table_data, ACPI_BUILD_IOAPIC_ID, 1);
|
||||
/* Start Bus Number */
|
||||
build_append_int_noprefix(table_data, Q35_PSEUDO_BUS_PLATFORM, 1);
|
||||
/* Path, {Device, Function} pair */
|
||||
build_append_int_noprefix(table_data, PCI_SLOT(Q35_PSEUDO_DEVFN_IOAPIC), 1);
|
||||
build_append_int_noprefix(table_data, PCI_FUNC(Q35_PSEUDO_DEVFN_IOAPIC), 1);
|
||||
|
||||
/* Add scope found above */
|
||||
g_array_append_vals(table_data, scope_blob->data, scope_blob->len);
|
||||
g_array_free(scope_blob, true);
|
||||
|
||||
if (iommu->dt_supported) {
|
||||
atsr = acpi_data_push(table_data, sizeof(*atsr));
|
||||
atsr->type = cpu_to_le16(ACPI_DMAR_TYPE_ATSR);
|
||||
atsr->length = cpu_to_le16(sizeof(*atsr));
|
||||
atsr->flags = ACPI_DMAR_ATSR_ALL_PORTS;
|
||||
atsr->pci_segment = cpu_to_le16(0);
|
||||
/* 8.5 Root Port ATS Capability Reporting Structure */
|
||||
build_append_int_noprefix(table_data, 2, 2); /* Type */
|
||||
build_append_int_noprefix(table_data, 8, 2); /* Length */
|
||||
build_append_int_noprefix(table_data, 1 /* ALL_PORTS */, 1); /* Flags */
|
||||
build_append_int_noprefix(table_data, 0, 1); /* Reserved */
|
||||
build_append_int_noprefix(table_data, 0, 2); /* Segment Number */
|
||||
}
|
||||
|
||||
build_header(linker, table_data, (void *)(table_data->data + dmar_start),
|
||||
"DMAR", table_data->len - dmar_start, 1, oem_id, oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2192,10 +2233,10 @@ static void
|
||||
build_waet(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
||||
const char *oem_table_id)
|
||||
{
|
||||
int waet_start = table_data->len;
|
||||
AcpiTable table = { .sig = "WAET", .rev = 1, .oem_id = oem_id,
|
||||
.oem_table_id = oem_table_id };
|
||||
|
||||
/* WAET header */
|
||||
acpi_data_push(table_data, sizeof(AcpiTableHeader));
|
||||
acpi_table_begin(&table, table_data);
|
||||
/*
|
||||
* Set "ACPI PM timer good" flag.
|
||||
*
|
||||
@@ -2204,9 +2245,7 @@ build_waet(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
||||
* Which avoids costly VMExits caused by guest re-reading it unnecessarily.
|
||||
*/
|
||||
build_append_int_noprefix(table_data, 1 << 1 /* ACPI PM timer good */, 4);
|
||||
|
||||
build_header(linker, table_data, (void *)(table_data->data + waet_start),
|
||||
"WAET", table_data->len - waet_start, 1, oem_id, oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -2312,12 +2351,12 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
||||
const char *oem_table_id)
|
||||
{
|
||||
int ivhd_table_len = 24;
|
||||
int iommu_start = table_data->len;
|
||||
AMDVIState *s = AMD_IOMMU_DEVICE(x86_iommu_get_default());
|
||||
GArray *ivhd_blob = g_array_new(false, true, 1);
|
||||
AcpiTable table = { .sig = "IVRS", .rev = 1, .oem_id = oem_id,
|
||||
.oem_table_id = oem_table_id };
|
||||
|
||||
/* IVRS header */
|
||||
acpi_data_push(table_data, sizeof(AcpiTableHeader));
|
||||
acpi_table_begin(&table, table_data);
|
||||
/* IVinfo - IO virtualization information common to all
|
||||
* IOMMU units in a system
|
||||
*/
|
||||
@@ -2402,10 +2441,7 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker, const char *oem_id,
|
||||
0x48, /* special device */
|
||||
8);
|
||||
}
|
||||
|
||||
build_header(linker, table_data, (void *)(table_data->data + iommu_start),
|
||||
"IVRS", table_data->len - iommu_start, 1, oem_id,
|
||||
oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
typedef
|
||||
|
||||
+81
-79
@@ -34,9 +34,13 @@
|
||||
#include "acpi-common.h"
|
||||
|
||||
void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
||||
const CPUArchIdList *apic_ids, GArray *entry)
|
||||
const CPUArchIdList *apic_ids, GArray *entry,
|
||||
bool force_enabled)
|
||||
{
|
||||
uint32_t apic_id = apic_ids->cpus[uid].arch_id;
|
||||
/* Flags – Local APIC Flags */
|
||||
uint32_t flags = apic_ids->cpus[uid].cpu != NULL || force_enabled ?
|
||||
1 /* Enabled */ : 0;
|
||||
|
||||
/* ACPI spec says that LAPIC entry for non present
|
||||
* CPU may be omitted from MADT or it must be marked
|
||||
@@ -45,82 +49,84 @@ void pc_madt_cpu_entry(AcpiDeviceIf *adev, int uid,
|
||||
* should be put in MADT but kept disabled.
|
||||
*/
|
||||
if (apic_id < 255) {
|
||||
AcpiMadtProcessorApic *apic = acpi_data_push(entry, sizeof *apic);
|
||||
|
||||
apic->type = ACPI_APIC_PROCESSOR;
|
||||
apic->length = sizeof(*apic);
|
||||
apic->processor_id = uid;
|
||||
apic->local_apic_id = apic_id;
|
||||
if (apic_ids->cpus[uid].cpu != NULL) {
|
||||
apic->flags = cpu_to_le32(1);
|
||||
} else {
|
||||
apic->flags = cpu_to_le32(0);
|
||||
}
|
||||
/* Rev 1.0b, Table 5-13 Processor Local APIC Structure */
|
||||
build_append_int_noprefix(entry, 0, 1); /* Type */
|
||||
build_append_int_noprefix(entry, 8, 1); /* Length */
|
||||
build_append_int_noprefix(entry, uid, 1); /* ACPI Processor ID */
|
||||
build_append_int_noprefix(entry, apic_id, 1); /* APIC ID */
|
||||
build_append_int_noprefix(entry, flags, 4); /* Flags */
|
||||
} else {
|
||||
AcpiMadtProcessorX2Apic *apic = acpi_data_push(entry, sizeof *apic);
|
||||
|
||||
apic->type = ACPI_APIC_LOCAL_X2APIC;
|
||||
apic->length = sizeof(*apic);
|
||||
apic->uid = cpu_to_le32(uid);
|
||||
apic->x2apic_id = cpu_to_le32(apic_id);
|
||||
if (apic_ids->cpus[uid].cpu != NULL) {
|
||||
apic->flags = cpu_to_le32(1);
|
||||
} else {
|
||||
apic->flags = cpu_to_le32(0);
|
||||
}
|
||||
/* Rev 4.0, 5.2.12.12 Processor Local x2APIC Structure */
|
||||
build_append_int_noprefix(entry, 9, 1); /* Type */
|
||||
build_append_int_noprefix(entry, 16, 1); /* Length */
|
||||
build_append_int_noprefix(entry, 0, 2); /* Reserved */
|
||||
build_append_int_noprefix(entry, apic_id, 4); /* X2APIC ID */
|
||||
build_append_int_noprefix(entry, flags, 4); /* Flags */
|
||||
build_append_int_noprefix(entry, uid, 4); /* ACPI Processor UID */
|
||||
}
|
||||
}
|
||||
|
||||
static void build_ioapic(GArray *entry, uint8_t id, uint32_t addr, uint32_t irq)
|
||||
{
|
||||
/* Rev 1.0b, 5.2.8.2 IO APIC */
|
||||
build_append_int_noprefix(entry, 1, 1); /* Type */
|
||||
build_append_int_noprefix(entry, 12, 1); /* Length */
|
||||
build_append_int_noprefix(entry, id, 1); /* IO APIC ID */
|
||||
build_append_int_noprefix(entry, 0, 1); /* Reserved */
|
||||
build_append_int_noprefix(entry, addr, 4); /* IO APIC Address */
|
||||
build_append_int_noprefix(entry, irq, 4); /* System Vector Base */
|
||||
}
|
||||
|
||||
static void
|
||||
build_xrupt_override(GArray *entry, uint8_t src, uint32_t gsi, uint16_t flags)
|
||||
{
|
||||
/* Rev 1.0b, 5.2.8.3.1 Interrupt Source Overrides */
|
||||
build_append_int_noprefix(entry, 2, 1); /* Type */
|
||||
build_append_int_noprefix(entry, 10, 1); /* Length */
|
||||
build_append_int_noprefix(entry, 0, 1); /* Bus */
|
||||
build_append_int_noprefix(entry, src, 1); /* Source */
|
||||
/* Global System Interrupt Vector */
|
||||
build_append_int_noprefix(entry, gsi, 4);
|
||||
build_append_int_noprefix(entry, flags, 2); /* Flags */
|
||||
}
|
||||
|
||||
/*
|
||||
* ACPI spec, Revision 1.0b
|
||||
* 5.2.8 Multiple APIC Description Table
|
||||
*/
|
||||
void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
|
||||
X86MachineState *x86ms, AcpiDeviceIf *adev,
|
||||
const char *oem_id, const char *oem_table_id)
|
||||
{
|
||||
int i;
|
||||
bool x2apic_mode = false;
|
||||
MachineClass *mc = MACHINE_GET_CLASS(x86ms);
|
||||
const CPUArchIdList *apic_ids = mc->possible_cpu_arch_ids(MACHINE(x86ms));
|
||||
int madt_start = table_data->len;
|
||||
AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(adev);
|
||||
bool x2apic_mode = false;
|
||||
AcpiTable table = { .sig = "APIC", .rev = 1, .oem_id = oem_id,
|
||||
.oem_table_id = oem_table_id };
|
||||
|
||||
AcpiMultipleApicTable *madt;
|
||||
AcpiMadtIoApic *io_apic;
|
||||
AcpiMadtIntsrcovr *intsrcovr;
|
||||
int i;
|
||||
|
||||
madt = acpi_data_push(table_data, sizeof *madt);
|
||||
madt->local_apic_address = cpu_to_le32(APIC_DEFAULT_ADDRESS);
|
||||
madt->flags = cpu_to_le32(1);
|
||||
acpi_table_begin(&table, table_data);
|
||||
/* Local APIC Address */
|
||||
build_append_int_noprefix(table_data, APIC_DEFAULT_ADDRESS, 4);
|
||||
build_append_int_noprefix(table_data, 1 /* PCAT_COMPAT */, 4); /* Flags */
|
||||
|
||||
for (i = 0; i < apic_ids->len; i++) {
|
||||
adevc->madt_cpu(adev, i, apic_ids, table_data);
|
||||
adevc->madt_cpu(adev, i, apic_ids, table_data, false);
|
||||
if (apic_ids->cpus[i].arch_id > 254) {
|
||||
x2apic_mode = true;
|
||||
}
|
||||
}
|
||||
|
||||
io_apic = acpi_data_push(table_data, sizeof *io_apic);
|
||||
io_apic->type = ACPI_APIC_IO;
|
||||
io_apic->length = sizeof(*io_apic);
|
||||
io_apic->io_apic_id = ACPI_BUILD_IOAPIC_ID;
|
||||
io_apic->address = cpu_to_le32(IO_APIC_DEFAULT_ADDRESS);
|
||||
io_apic->interrupt = cpu_to_le32(0);
|
||||
|
||||
build_ioapic(table_data, ACPI_BUILD_IOAPIC_ID, IO_APIC_DEFAULT_ADDRESS, 0);
|
||||
if (x86ms->ioapic2) {
|
||||
AcpiMadtIoApic *io_apic2;
|
||||
io_apic2 = acpi_data_push(table_data, sizeof *io_apic);
|
||||
io_apic2->type = ACPI_APIC_IO;
|
||||
io_apic2->length = sizeof(*io_apic);
|
||||
io_apic2->io_apic_id = ACPI_BUILD_IOAPIC_ID + 1;
|
||||
io_apic2->address = cpu_to_le32(IO_APIC_SECONDARY_ADDRESS);
|
||||
io_apic2->interrupt = cpu_to_le32(IO_APIC_SECONDARY_IRQBASE);
|
||||
build_ioapic(table_data, ACPI_BUILD_IOAPIC_ID + 1,
|
||||
IO_APIC_SECONDARY_ADDRESS, IO_APIC_SECONDARY_IRQBASE);
|
||||
}
|
||||
|
||||
if (x86ms->apic_xrupt_override) {
|
||||
intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
|
||||
intsrcovr->type = ACPI_APIC_XRUPT_OVERRIDE;
|
||||
intsrcovr->length = sizeof(*intsrcovr);
|
||||
intsrcovr->source = 0;
|
||||
intsrcovr->gsi = cpu_to_le32(2);
|
||||
intsrcovr->flags = cpu_to_le16(0); /* conforms to bus specifications */
|
||||
build_xrupt_override(table_data, 0, 2,
|
||||
0 /* Flags: Conforms to the specifications of the bus */);
|
||||
}
|
||||
|
||||
for (i = 1; i < 16; i++) {
|
||||
@@ -128,36 +134,32 @@ void acpi_build_madt(GArray *table_data, BIOSLinker *linker,
|
||||
/* No need for a INT source override structure. */
|
||||
continue;
|
||||
}
|
||||
intsrcovr = acpi_data_push(table_data, sizeof *intsrcovr);
|
||||
intsrcovr->type = ACPI_APIC_XRUPT_OVERRIDE;
|
||||
intsrcovr->length = sizeof(*intsrcovr);
|
||||
intsrcovr->source = i;
|
||||
intsrcovr->gsi = cpu_to_le32(i);
|
||||
intsrcovr->flags = cpu_to_le16(0xd); /* active high, level triggered */
|
||||
build_xrupt_override(table_data, i, i,
|
||||
0xd /* Flags: Active high, Level Triggered */);
|
||||
}
|
||||
|
||||
if (x2apic_mode) {
|
||||
AcpiMadtLocalX2ApicNmi *local_nmi;
|
||||
|
||||
local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
|
||||
local_nmi->type = ACPI_APIC_LOCAL_X2APIC_NMI;
|
||||
local_nmi->length = sizeof(*local_nmi);
|
||||
local_nmi->uid = 0xFFFFFFFF; /* all processors */
|
||||
local_nmi->flags = cpu_to_le16(0);
|
||||
local_nmi->lint = 1; /* ACPI_LINT1 */
|
||||
/* Rev 4.0, 5.2.12.13 Local x2APIC NMI Structure*/
|
||||
build_append_int_noprefix(table_data, 0xA, 1); /* Type */
|
||||
build_append_int_noprefix(table_data, 12, 1); /* Length */
|
||||
build_append_int_noprefix(table_data, 0, 2); /* Flags */
|
||||
/* ACPI Processor UID */
|
||||
build_append_int_noprefix(table_data, 0xFFFFFFFF /* all processors */,
|
||||
4);
|
||||
/* Local x2APIC LINT# */
|
||||
build_append_int_noprefix(table_data, 1 /* ACPI_LINT1 */, 1);
|
||||
build_append_int_noprefix(table_data, 0, 3); /* Reserved */
|
||||
} else {
|
||||
AcpiMadtLocalNmi *local_nmi;
|
||||
|
||||
local_nmi = acpi_data_push(table_data, sizeof *local_nmi);
|
||||
local_nmi->type = ACPI_APIC_LOCAL_NMI;
|
||||
local_nmi->length = sizeof(*local_nmi);
|
||||
local_nmi->processor_id = 0xff; /* all processors */
|
||||
local_nmi->flags = cpu_to_le16(0);
|
||||
local_nmi->lint = 1; /* ACPI_LINT1 */
|
||||
/* Rev 1.0b, 5.2.8.3.3 Local APIC NMI */
|
||||
build_append_int_noprefix(table_data, 4, 1); /* Type */
|
||||
build_append_int_noprefix(table_data, 6, 1); /* Length */
|
||||
/* ACPI Processor ID */
|
||||
build_append_int_noprefix(table_data, 0xFF /* all processors */, 1);
|
||||
build_append_int_noprefix(table_data, 0, 2); /* Flags */
|
||||
/* Local APIC INTI# */
|
||||
build_append_int_noprefix(table_data, 1 /* ACPI_LINT1 */, 1);
|
||||
}
|
||||
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + madt_start), "APIC",
|
||||
table_data->len - madt_start, 1, oem_id, oem_table_id);
|
||||
acpi_table_end(linker, &table);
|
||||
}
|
||||
|
||||
|
||||
@@ -113,16 +113,16 @@ build_dsdt_microvm(GArray *table_data, BIOSLinker *linker,
|
||||
Aml *dsdt, *sb_scope, *scope, *pkg;
|
||||
bool ambiguous;
|
||||
Object *isabus;
|
||||
AcpiTable table = { .sig = "DSDT", .rev = 2, .oem_id = x86ms->oem_id,
|
||||
.oem_table_id = x86ms->oem_table_id };
|
||||
|
||||
isabus = object_resolve_path_type("", TYPE_ISA_BUS, &ambiguous);
|
||||
assert(isabus);
|
||||
assert(!ambiguous);
|
||||
|
||||
acpi_table_begin(&table, table_data);
|
||||
dsdt = init_aml_allocator();
|
||||
|
||||
/* Reserve space for header */
|
||||
acpi_data_push(dsdt->buf, sizeof(AcpiTableHeader));
|
||||
|
||||
sb_scope = aml_scope("_SB");
|
||||
fw_cfg_add_acpi_dsdt(sb_scope, x86ms->fw_cfg);
|
||||
isa_build_aml(ISA_BUS(isabus), sb_scope);
|
||||
@@ -144,11 +144,10 @@ build_dsdt_microvm(GArray *table_data, BIOSLinker *linker,
|
||||
aml_append(scope, aml_name_decl("_S5", pkg));
|
||||
aml_append(dsdt, scope);
|
||||
|
||||
/* copy AML table into ACPI tables blob and patch header there */
|
||||
/* copy AML bytecode into ACPI tables blob */
|
||||
g_array_append_vals(table_data, dsdt->buf->data, dsdt->buf->len);
|
||||
build_header(linker, table_data,
|
||||
(void *)(table_data->data + table_data->len - dsdt->buf->len),
|
||||
"DSDT", dsdt->buf->len, 2, x86ms->oem_id, x86ms->oem_table_id);
|
||||
|
||||
acpi_table_end(linker, &table);
|
||||
free_aml_allocator();
|
||||
}
|
||||
|
||||
|
||||
+25
-16
@@ -1526,7 +1526,7 @@ static void amdvi_init(AMDVIState *s)
|
||||
AMDVI_MAX_PH_ADDR | AMDVI_MAX_GVA_ADDR | AMDVI_MAX_VA_ADDR);
|
||||
}
|
||||
|
||||
static void amdvi_reset(DeviceState *dev)
|
||||
static void amdvi_sysbus_reset(DeviceState *dev)
|
||||
{
|
||||
AMDVIState *s = AMD_IOMMU_DEVICE(dev);
|
||||
|
||||
@@ -1534,7 +1534,7 @@ static void amdvi_reset(DeviceState *dev)
|
||||
amdvi_init(s);
|
||||
}
|
||||
|
||||
static void amdvi_realize(DeviceState *dev, Error **errp)
|
||||
static void amdvi_sysbus_realize(DeviceState *dev, Error **errp)
|
||||
{
|
||||
int ret = 0;
|
||||
AMDVIState *s = AMD_IOMMU_DEVICE(dev);
|
||||
@@ -1585,27 +1585,27 @@ static void amdvi_realize(DeviceState *dev, Error **errp)
|
||||
amdvi_init(s);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_amdvi = {
|
||||
static const VMStateDescription vmstate_amdvi_sysbus = {
|
||||
.name = "amd-iommu",
|
||||
.unmigratable = 1
|
||||
};
|
||||
|
||||
static void amdvi_instance_init(Object *klass)
|
||||
static void amdvi_sysbus_instance_init(Object *klass)
|
||||
{
|
||||
AMDVIState *s = AMD_IOMMU_DEVICE(klass);
|
||||
|
||||
object_initialize(&s->pci, sizeof(s->pci), TYPE_AMD_IOMMU_PCI);
|
||||
}
|
||||
|
||||
static void amdvi_class_init(ObjectClass *klass, void* data)
|
||||
static void amdvi_sysbus_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
X86IOMMUClass *dc_class = X86_IOMMU_DEVICE_CLASS(klass);
|
||||
|
||||
dc->reset = amdvi_reset;
|
||||
dc->vmsd = &vmstate_amdvi;
|
||||
dc->reset = amdvi_sysbus_reset;
|
||||
dc->vmsd = &vmstate_amdvi_sysbus;
|
||||
dc->hotpluggable = false;
|
||||
dc_class->realize = amdvi_realize;
|
||||
dc_class->realize = amdvi_sysbus_realize;
|
||||
dc_class->int_remap = amdvi_int_remap;
|
||||
/* Supported by the pc-q35-* machine types */
|
||||
dc->user_creatable = true;
|
||||
@@ -1613,18 +1613,27 @@ static void amdvi_class_init(ObjectClass *klass, void* data)
|
||||
dc->desc = "AMD IOMMU (AMD-Vi) DMA Remapping device";
|
||||
}
|
||||
|
||||
static const TypeInfo amdvi = {
|
||||
static const TypeInfo amdvi_sysbus = {
|
||||
.name = TYPE_AMD_IOMMU_DEVICE,
|
||||
.parent = TYPE_X86_IOMMU_DEVICE,
|
||||
.instance_size = sizeof(AMDVIState),
|
||||
.instance_init = amdvi_instance_init,
|
||||
.class_init = amdvi_class_init
|
||||
.instance_init = amdvi_sysbus_instance_init,
|
||||
.class_init = amdvi_sysbus_class_init
|
||||
};
|
||||
|
||||
static const TypeInfo amdviPCI = {
|
||||
static void amdvi_pci_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
dc->desc = "AMD IOMMU (AMD-Vi) DMA Remapping device";
|
||||
}
|
||||
|
||||
static const TypeInfo amdvi_pci = {
|
||||
.name = TYPE_AMD_IOMMU_PCI,
|
||||
.parent = TYPE_PCI_DEVICE,
|
||||
.instance_size = sizeof(AMDVIPCIState),
|
||||
.class_init = amdvi_pci_class_init,
|
||||
.interfaces = (InterfaceInfo[]) {
|
||||
{ INTERFACE_CONVENTIONAL_PCI_DEVICE },
|
||||
{ },
|
||||
@@ -1645,11 +1654,11 @@ static const TypeInfo amdvi_iommu_memory_region_info = {
|
||||
.class_init = amdvi_iommu_memory_region_class_init,
|
||||
};
|
||||
|
||||
static void amdviPCI_register_types(void)
|
||||
static void amdvi_register_types(void)
|
||||
{
|
||||
type_register_static(&amdviPCI);
|
||||
type_register_static(&amdvi);
|
||||
type_register_static(&amdvi_pci);
|
||||
type_register_static(&amdvi_sysbus);
|
||||
type_register_static(&amdvi_iommu_memory_region_info);
|
||||
}
|
||||
|
||||
type_init(amdviPCI_register_types);
|
||||
type_init(amdvi_register_types);
|
||||
|
||||
@@ -81,7 +81,9 @@ static uint64_t vuv_get_features(VirtIODevice *vdev,
|
||||
{
|
||||
VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
|
||||
|
||||
return vhost_get_features(&vvc->vhost_dev, user_feature_bits, features);
|
||||
features = vhost_get_features(&vvc->vhost_dev, user_feature_bits, features);
|
||||
|
||||
return vhost_vsock_common_get_features(vdev, features, errp);
|
||||
}
|
||||
|
||||
static const VMStateDescription vuv_vmstate = {
|
||||
|
||||
@@ -18,6 +18,30 @@
|
||||
#include "qemu/iov.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
const int feature_bits[] = {
|
||||
VIRTIO_VSOCK_F_SEQPACKET,
|
||||
VHOST_INVALID_FEATURE_BIT
|
||||
};
|
||||
|
||||
uint64_t vhost_vsock_common_get_features(VirtIODevice *vdev, uint64_t features,
|
||||
Error **errp)
|
||||
{
|
||||
VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
|
||||
|
||||
if (vvc->seqpacket != ON_OFF_AUTO_OFF) {
|
||||
virtio_add_feature(&features, VIRTIO_VSOCK_F_SEQPACKET);
|
||||
}
|
||||
|
||||
features = vhost_get_features(&vvc->vhost_dev, feature_bits, features);
|
||||
|
||||
if (vvc->seqpacket == ON_OFF_AUTO_ON &&
|
||||
!virtio_has_feature(features, VIRTIO_VSOCK_F_SEQPACKET)) {
|
||||
error_setg(errp, "vhost-vsock backend doesn't support seqpacket");
|
||||
}
|
||||
|
||||
return features;
|
||||
}
|
||||
|
||||
int vhost_vsock_common_start(VirtIODevice *vdev)
|
||||
{
|
||||
VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
|
||||
@@ -231,11 +255,18 @@ void vhost_vsock_common_unrealize(VirtIODevice *vdev)
|
||||
virtio_cleanup(vdev);
|
||||
}
|
||||
|
||||
static Property vhost_vsock_common_properties[] = {
|
||||
DEFINE_PROP_ON_OFF_AUTO("seqpacket", VHostVSockCommon, seqpacket,
|
||||
ON_OFF_AUTO_AUTO),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
static void vhost_vsock_common_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
|
||||
|
||||
device_class_set_props(dc, vhost_vsock_common_properties);
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
vdc->guest_notifier_mask = vhost_vsock_common_guest_notifier_mask;
|
||||
vdc->guest_notifier_pending = vhost_vsock_common_guest_notifier_pending;
|
||||
|
||||
+1
-10
@@ -21,11 +21,6 @@
|
||||
#include "hw/virtio/vhost-vsock.h"
|
||||
#include "monitor/monitor.h"
|
||||
|
||||
const int feature_bits[] = {
|
||||
VIRTIO_VSOCK_F_SEQPACKET,
|
||||
VHOST_INVALID_FEATURE_BIT
|
||||
};
|
||||
|
||||
static void vhost_vsock_get_config(VirtIODevice *vdev, uint8_t *config)
|
||||
{
|
||||
VHostVSock *vsock = VHOST_VSOCK(vdev);
|
||||
@@ -113,11 +108,7 @@ static uint64_t vhost_vsock_get_features(VirtIODevice *vdev,
|
||||
uint64_t requested_features,
|
||||
Error **errp)
|
||||
{
|
||||
VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
|
||||
|
||||
virtio_add_feature(&requested_features, VIRTIO_VSOCK_F_SEQPACKET);
|
||||
return vhost_get_features(&vvc->vhost_dev, feature_bits,
|
||||
requested_features);
|
||||
return vhost_vsock_common_get_features(vdev, requested_features, errp);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_virtio_vhost_vsock = {
|
||||
|
||||
@@ -852,7 +852,7 @@ static const VMStateDescription vmstate_virtio_balloon_free_page_hint = {
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_virtio_balloon_page_poison = {
|
||||
.name = "vitio-balloon-device/page-poison",
|
||||
.name = "virtio-balloon-device/page-poison",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = virtio_balloon_page_poison_support,
|
||||
|
||||
+14
-17
@@ -984,28 +984,23 @@ static int virtqueue_split_read_next_desc(VirtIODevice *vdev, VRingDesc *desc,
|
||||
return VIRTQUEUE_READ_DESC_MORE;
|
||||
}
|
||||
|
||||
/* Called within rcu_read_lock(). */
|
||||
static void virtqueue_split_get_avail_bytes(VirtQueue *vq,
|
||||
unsigned int *in_bytes, unsigned int *out_bytes,
|
||||
unsigned max_in_bytes, unsigned max_out_bytes)
|
||||
unsigned max_in_bytes, unsigned max_out_bytes,
|
||||
VRingMemoryRegionCaches *caches)
|
||||
{
|
||||
VirtIODevice *vdev = vq->vdev;
|
||||
unsigned int max, idx;
|
||||
unsigned int total_bufs, in_total, out_total;
|
||||
VRingMemoryRegionCaches *caches;
|
||||
MemoryRegionCache indirect_desc_cache = MEMORY_REGION_CACHE_INVALID;
|
||||
int64_t len = 0;
|
||||
int rc;
|
||||
|
||||
RCU_READ_LOCK_GUARD();
|
||||
|
||||
idx = vq->last_avail_idx;
|
||||
total_bufs = in_total = out_total = 0;
|
||||
|
||||
max = vq->vring.num;
|
||||
caches = vring_get_region_caches(vq);
|
||||
if (!caches) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
while ((rc = virtqueue_num_heads(vq, idx)) > 0) {
|
||||
MemoryRegionCache *desc_cache = &caches->desc;
|
||||
@@ -1124,32 +1119,28 @@ static int virtqueue_packed_read_next_desc(VirtQueue *vq,
|
||||
return VIRTQUEUE_READ_DESC_MORE;
|
||||
}
|
||||
|
||||
/* Called within rcu_read_lock(). */
|
||||
static void virtqueue_packed_get_avail_bytes(VirtQueue *vq,
|
||||
unsigned int *in_bytes,
|
||||
unsigned int *out_bytes,
|
||||
unsigned max_in_bytes,
|
||||
unsigned max_out_bytes)
|
||||
unsigned max_out_bytes,
|
||||
VRingMemoryRegionCaches *caches)
|
||||
{
|
||||
VirtIODevice *vdev = vq->vdev;
|
||||
unsigned int max, idx;
|
||||
unsigned int total_bufs, in_total, out_total;
|
||||
MemoryRegionCache *desc_cache;
|
||||
VRingMemoryRegionCaches *caches;
|
||||
MemoryRegionCache indirect_desc_cache = MEMORY_REGION_CACHE_INVALID;
|
||||
int64_t len = 0;
|
||||
VRingPackedDesc desc;
|
||||
bool wrap_counter;
|
||||
|
||||
RCU_READ_LOCK_GUARD();
|
||||
idx = vq->last_avail_idx;
|
||||
wrap_counter = vq->last_avail_wrap_counter;
|
||||
total_bufs = in_total = out_total = 0;
|
||||
|
||||
max = vq->vring.num;
|
||||
caches = vring_get_region_caches(vq);
|
||||
if (!caches) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
unsigned int num_bufs = total_bufs;
|
||||
@@ -1250,6 +1241,8 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
|
||||
uint16_t desc_size;
|
||||
VRingMemoryRegionCaches *caches;
|
||||
|
||||
RCU_READ_LOCK_GUARD();
|
||||
|
||||
if (unlikely(!vq->vring.desc)) {
|
||||
goto err;
|
||||
}
|
||||
@@ -1268,10 +1261,12 @@ void virtqueue_get_avail_bytes(VirtQueue *vq, unsigned int *in_bytes,
|
||||
|
||||
if (virtio_vdev_has_feature(vq->vdev, VIRTIO_F_RING_PACKED)) {
|
||||
virtqueue_packed_get_avail_bytes(vq, in_bytes, out_bytes,
|
||||
max_in_bytes, max_out_bytes);
|
||||
max_in_bytes, max_out_bytes,
|
||||
caches);
|
||||
} else {
|
||||
virtqueue_split_get_avail_bytes(vq, in_bytes, out_bytes,
|
||||
max_in_bytes, max_out_bytes);
|
||||
max_in_bytes, max_out_bytes,
|
||||
caches);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -1703,6 +1698,8 @@ static unsigned int virtqueue_packed_drop_all(VirtQueue *vq)
|
||||
VirtIODevice *vdev = vq->vdev;
|
||||
VRingPackedDesc desc;
|
||||
|
||||
RCU_READ_LOCK_GUARD();
|
||||
|
||||
caches = vring_get_region_caches(vq);
|
||||
if (!caches) {
|
||||
return 0;
|
||||
|
||||
+1
-527
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user