diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2021-10-21 09:53:27 -0700 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2021-10-21 09:53:27 -0700 |
commit | 4c127fdbe81d66e7cafed90908d0fd1f6f2a6cd0 (patch) | |
tree | 0ffb5d0b94500657a423b29eb1cecfe8076854a7 | |
parent | e016b58f6ed2e07bde45da7d6792b6c93879a3cf (diff) | |
parent | f801789ff00f457044dcd91323316dbde42578d1 (diff) |
Merge remote-tracking branch 'remotes/rth/tags/pull-arm-20211021' into staging
Introduce cpu topology support
Generate DBG2 table
Switch to ssize_t for elf loader return type
Fixed sbsa cpu type error message typo
Only initialize required submodules for edk2
Dont create device-tree node for empty NUMA node
# gpg: Signature made Thu 21 Oct 2021 08:22:32 AM PDT
# gpg: using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg: issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [ultimate]
* remotes/rth/tags/pull-arm-20211021:
tests/data/acpi/virt: Update the empty expected file for PPTT
hw/arm/virt-acpi-build: Generate PPTT table
tests/data/acpi/virt: Add an empty expected file for PPTT
hw/acpi/aml-build: Add PPTT table
hw/acpi/aml-build: Add Processor hierarchy node structure
hw/arm/virt: Add cpu-map to device tree
device_tree: Add qemu_fdt_add_path
hw/arm/virt: Only describe cpu topology since virt-6.2
bios-tables-test: Generate reference table for virt/DBG2
hw/arm/virt_acpi_build: Generate DBG2 table
tests/acpi: Add void table for virt/DBG2 bios-tables-test
hw/elf_ops.h: switch to ssize_t for elf loader return type
hw/arm/sbsa-ref: Fixed cpu type error message typo.
roms/edk2: Only initialize required submodules
roms/edk2: Only init brotli submodule to build BaseTools
hw/arm/virt: Don't create device-tree node for empty NUMA node
tests/acpi: Generate reference blob for IORT rev E.b
hw/arm/virt-acpi-build: IORT upgrade up to revision E.b
tests/acpi: Get prepared for IORT E.b revision upgrade
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r-- | .gitlab-ci.d/edk2.yml | 6 | ||||
-rw-r--r-- | hw/acpi/aml-build.c | 89 | ||||
-rw-r--r-- | hw/arm/boot.c | 13 | ||||
-rw-r--r-- | hw/arm/sbsa-ref.c | 2 | ||||
-rw-r--r-- | hw/arm/virt-acpi-build.c | 117 | ||||
-rw-r--r-- | hw/arm/virt.c | 71 | ||||
-rw-r--r-- | hw/core/loader.c | 60 | ||||
-rw-r--r-- | include/hw/acpi/aml-build.h | 3 | ||||
-rw-r--r-- | include/hw/arm/virt.h | 4 | ||||
-rw-r--r-- | include/hw/elf_ops.h | 27 | ||||
-rw-r--r-- | include/hw/loader.h | 58 | ||||
-rw-r--r-- | include/sysemu/device_tree.h | 1 | ||||
-rw-r--r-- | roms/Makefile | 3 | ||||
-rw-r--r-- | roms/Makefile.edk2 | 7 | ||||
-rwxr-xr-x | scripts/make-release | 7 | ||||
-rw-r--r-- | softmmu/device_tree.c | 44 | ||||
-rw-r--r-- | tests/data/acpi/virt/DBG2 | bin | 0 -> 87 bytes | |||
-rw-r--r-- | tests/data/acpi/virt/IORT | bin | 124 -> 128 bytes | |||
-rw-r--r-- | tests/data/acpi/virt/IORT.memhp | bin | 124 -> 128 bytes | |||
-rw-r--r-- | tests/data/acpi/virt/IORT.numamem | bin | 124 -> 128 bytes | |||
-rw-r--r-- | tests/data/acpi/virt/IORT.pxb | bin | 124 -> 128 bytes | |||
-rw-r--r-- | tests/data/acpi/virt/PPTT | bin | 0 -> 76 bytes |
22 files changed, 403 insertions, 109 deletions
diff --git a/.gitlab-ci.d/edk2.yml b/.gitlab-ci.d/edk2.yml index 62497ba47f..13d0f8b019 100644 --- a/.gitlab-ci.d/edk2.yml +++ b/.gitlab-ci.d/edk2.yml @@ -50,7 +50,11 @@ build-edk2: GIT_DEPTH: 3 script: # Clone the required submodules and build EDK2 - git submodule update --init roms/edk2 - - git -C roms/edk2 submodule update --init + - git -C roms/edk2 submodule update --init -- + ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3 + BaseTools/Source/C/BrotliCompress/brotli + CryptoPkg/Library/OpensslLib/openssl + MdeModulePkg/Library/BrotliCustomDecompressLib/brotli - export JOBS=$(($(getconf _NPROCESSORS_ONLN) + 1)) - echo "=== Using ${JOBS} simultaneous jobs ===" - make -j${JOBS} -C roms efi 2>&1 1>edk2-stdout.log | tee -a edk2-stderr.log >&2 diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c index 76af0ebaf9..b3b3310df3 100644 --- a/hw/acpi/aml-build.c +++ b/hw/acpi/aml-build.c @@ -1964,6 +1964,95 @@ void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms, acpi_table_end(linker, &table); } +/* + * ACPI spec, Revision 6.3 + * 5.2.29.1 Processor hierarchy node structure (Type 0) + */ +static void build_processor_hierarchy_node(GArray *tbl, uint32_t flags, + uint32_t parent, uint32_t id, + uint32_t *priv_rsrc, + uint32_t priv_num) +{ + int i; + + build_append_byte(tbl, 0); /* Type 0 - processor */ + build_append_byte(tbl, 20 + priv_num * 4); /* Length */ + build_append_int_noprefix(tbl, 0, 2); /* Reserved */ + build_append_int_noprefix(tbl, flags, 4); /* Flags */ + build_append_int_noprefix(tbl, parent, 4); /* Parent */ + build_append_int_noprefix(tbl, id, 4); /* ACPI Processor ID */ + + /* Number of private resources */ + build_append_int_noprefix(tbl, priv_num, 4); + + /* Private resources[N] */ + if (priv_num > 0) { + assert(priv_rsrc); + for (i = 0; i < priv_num; i++) { + build_append_int_noprefix(tbl, priv_rsrc[i], 4); + } + } +} + +/* + * ACPI spec, Revision 6.3 + * 5.2.29 Processor Properties Topology Table (PPTT) + */ +void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + const char *oem_id, const char *oem_table_id) +{ + int pptt_start = table_data->len; + int uid = 0; + int socket; + AcpiTable table = { .sig = "PPTT", .rev = 2, + .oem_id = oem_id, .oem_table_id = oem_table_id }; + + acpi_table_begin(&table, table_data); + + for (socket = 0; socket < ms->smp.sockets; socket++) { + uint32_t socket_offset = table_data->len - pptt_start; + int core; + + build_processor_hierarchy_node( + table_data, + /* + * Physical package - represents the boundary + * of a physical package + */ + (1 << 0), + 0, socket, NULL, 0); + + for (core = 0; core < ms->smp.cores; core++) { + uint32_t core_offset = table_data->len - pptt_start; + int thread; + + if (ms->smp.threads > 1) { + build_processor_hierarchy_node( + table_data, + (0 << 0), /* not a physical package */ + socket_offset, core, NULL, 0); + + for (thread = 0; thread < ms->smp.threads; thread++) { + build_processor_hierarchy_node( + table_data, + (1 << 1) | /* ACPI Processor ID valid */ + (1 << 2) | /* Processor is a Thread */ + (1 << 3), /* Node is a Leaf */ + core_offset, uid++, NULL, 0); + } + } else { + build_processor_hierarchy_node( + table_data, + (1 << 1) | /* ACPI Processor ID valid */ + (1 << 3), /* Node is a Leaf */ + socket_offset, uid++, NULL, 0); + } + } + } + + acpi_table_end(linker, &table); +} + /* build rev1/rev3/rev5.1 FADT */ void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f, const char *oem_id, const char *oem_table_id) diff --git a/hw/arm/boot.c b/hw/arm/boot.c index 57efb61ee4..74ad397b1f 100644 --- a/hw/arm/boot.c +++ b/hw/arm/boot.c @@ -599,10 +599,23 @@ int arm_load_dtb(hwaddr addr, const struct arm_boot_info *binfo, } g_strfreev(node_path); + /* + * We drop all the memory nodes which correspond to empty NUMA nodes + * from the device tree, because the Linux NUMA binding document + * states they should not be generated. Linux will get the NUMA node + * IDs of the empty NUMA nodes from the distance map if they are needed. + * This means QEMU users may be obliged to provide command lines which + * configure distance maps when the empty NUMA node IDs are needed and + * Linux's default distance map isn't sufficient. + */ if (ms->numa_state != NULL && ms->numa_state->num_nodes > 0) { mem_base = binfo->loader_start; for (i = 0; i < ms->numa_state->num_nodes; i++) { mem_len = ms->numa_state->nodes[i].node_mem; + if (!mem_len) { + continue; + } + rc = fdt_add_memory_node(fdt, acells, mem_base, scells, mem_len, i); if (rc < 0) { diff --git a/hw/arm/sbsa-ref.c b/hw/arm/sbsa-ref.c index 509c5f09b4..358714bd3e 100644 --- a/hw/arm/sbsa-ref.c +++ b/hw/arm/sbsa-ref.c @@ -670,7 +670,7 @@ static void sbsa_ref_init(MachineState *machine) int n, sbsa_max_cpus; if (!cpu_type_valid(machine->cpu_type)) { - error_report("mach-virt: CPU type %s not supported", machine->cpu_type); + error_report("sbsa-ref: CPU type %s not supported", machine->cpu_type); exit(1); } diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index 6cec97352b..674f902652 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -241,19 +241,20 @@ static void acpi_dsdt_add_tpm(Aml *scope, VirtMachineState *vms) #endif #define ID_MAPPING_ENTRY_SIZE 20 -#define SMMU_V3_ENTRY_SIZE 60 -#define ROOT_COMPLEX_ENTRY_SIZE 32 +#define SMMU_V3_ENTRY_SIZE 68 +#define ROOT_COMPLEX_ENTRY_SIZE 36 #define IORT_NODE_OFFSET 48 static void build_iort_id_mapping(GArray *table_data, uint32_t input_base, uint32_t id_count, uint32_t out_ref) { - /* Identity RID mapping covering the whole input RID range */ + /* Table 4 ID mapping format */ build_append_int_noprefix(table_data, input_base, 4); /* Input base */ build_append_int_noprefix(table_data, id_count, 4); /* Number of IDs */ build_append_int_noprefix(table_data, input_base, 4); /* Output base */ build_append_int_noprefix(table_data, out_ref, 4); /* Output Reference */ - build_append_int_noprefix(table_data, 0, 4); /* Flags */ + /* Flags */ + build_append_int_noprefix(table_data, 0 /* Single mapping (disabled) */, 4); } struct AcpiIortIdMapping { @@ -298,7 +299,7 @@ static int iort_idmap_compare(gconstpointer a, gconstpointer b) /* * Input Output Remapping Table (IORT) * Conforms to "IO Remapping Table System Software on ARM Platforms", - * Document number: ARM DEN 0049B, October 2015 + * Document number: ARM DEN 0049E.b, Feb 2021 */ static void build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) @@ -307,10 +308,11 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) const uint32_t iort_node_offset = IORT_NODE_OFFSET; size_t node_size, smmu_offset = 0; AcpiIortIdMapping *idmap; + uint32_t id = 0; GArray *smmu_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping)); GArray *its_idmaps = g_array_new(false, true, sizeof(AcpiIortIdMapping)); - AcpiTable table = { .sig = "IORT", .rev = 0, .oem_id = vms->oem_id, + AcpiTable table = { .sig = "IORT", .rev = 3, .oem_id = vms->oem_id, .oem_table_id = vms->oem_table_id }; /* Table 2 The IORT */ acpi_table_begin(&table, table_data); @@ -358,12 +360,12 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) build_append_int_noprefix(table_data, IORT_NODE_OFFSET, 4); build_append_int_noprefix(table_data, 0, 4); /* Reserved */ - /* 3.1.1.3 ITS group node */ + /* Table 12 ITS Group Format */ build_append_int_noprefix(table_data, 0 /* ITS Group */, 1); /* Type */ node_size = 20 /* fixed header size */ + 4 /* 1 GIC ITS Identifier */; build_append_int_noprefix(table_data, node_size, 2); /* Length */ - build_append_int_noprefix(table_data, 0, 1); /* Revision */ - build_append_int_noprefix(table_data, 0, 4); /* Reserved */ + build_append_int_noprefix(table_data, 1, 1); /* Revision */ + build_append_int_noprefix(table_data, id++, 4); /* Identifier */ build_append_int_noprefix(table_data, 0, 4); /* Number of ID mappings */ build_append_int_noprefix(table_data, 0, 4); /* Reference to ID Array */ build_append_int_noprefix(table_data, 1, 4); /* Number of ITSs */ @@ -374,19 +376,19 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) int irq = vms->irqmap[VIRT_SMMU] + ARM_SPI_BASE; smmu_offset = table_data->len - table.table_offset; - /* 3.1.1.2 SMMUv3 */ + /* Table 9 SMMUv3 Format */ build_append_int_noprefix(table_data, 4 /* SMMUv3 */, 1); /* Type */ node_size = SMMU_V3_ENTRY_SIZE + ID_MAPPING_ENTRY_SIZE; build_append_int_noprefix(table_data, node_size, 2); /* Length */ - build_append_int_noprefix(table_data, 0, 1); /* Revision */ - build_append_int_noprefix(table_data, 0, 4); /* Reserved */ + build_append_int_noprefix(table_data, 4, 1); /* Revision */ + build_append_int_noprefix(table_data, id++, 4); /* Identifier */ build_append_int_noprefix(table_data, 1, 4); /* Number of ID mappings */ /* Reference to ID Array */ build_append_int_noprefix(table_data, SMMU_V3_ENTRY_SIZE, 4); /* Base address */ build_append_int_noprefix(table_data, vms->memmap[VIRT_SMMU].base, 8); /* Flags */ - build_append_int_noprefix(table_data, 1 /* COHACC OverrideNote */, 4); + build_append_int_noprefix(table_data, 1 /* COHACC Override */, 4); build_append_int_noprefix(table_data, 0, 4); /* Reserved */ build_append_int_noprefix(table_data, 0, 8); /* VATOS address */ /* Model */ @@ -395,35 +397,43 @@ build_iort(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) build_append_int_noprefix(table_data, irq + 1, 4); /* PRI */ build_append_int_noprefix(table_data, irq + 3, 4); /* GERR */ build_append_int_noprefix(table_data, irq + 2, 4); /* Sync */ + build_append_int_noprefix(table_data, 0, 4); /* Proximity domain */ + /* DeviceID mapping index (ignored since interrupts are GSIV based) */ + build_append_int_noprefix(table_data, 0, 4); /* output IORT node is the ITS group node (the first node) */ build_iort_id_mapping(table_data, 0, 0xFFFF, IORT_NODE_OFFSET); } - /* Table 16 Root Complex Node */ + /* Table 17 Root Complex Node */ build_append_int_noprefix(table_data, 2 /* Root complex */, 1); /* Type */ node_size = ROOT_COMPLEX_ENTRY_SIZE + ID_MAPPING_ENTRY_SIZE * rc_mapping_count; build_append_int_noprefix(table_data, node_size, 2); /* Length */ - build_append_int_noprefix(table_data, 0, 1); /* Revision */ - build_append_int_noprefix(table_data, 0, 4); /* Reserved */ + build_append_int_noprefix(table_data, 3, 1); /* Revision */ + build_append_int_noprefix(table_data, id++, 4); /* Identifier */ /* Number of ID mappings */ build_append_int_noprefix(table_data, rc_mapping_count, 4); /* Reference to ID Array */ build_append_int_noprefix(table_data, ROOT_COMPLEX_ENTRY_SIZE, 4); - /* Table 13 Memory access properties */ + /* Table 14 Memory access properties */ /* CCA: Cache Coherent Attribute */ build_append_int_noprefix(table_data, 1 /* fully coherent */, 4); build_append_int_noprefix(table_data, 0, 1); /* AH: Note Allocation Hints */ build_append_int_noprefix(table_data, 0, 2); /* Reserved */ - /* MAF: Note Memory Access Flags */ - build_append_int_noprefix(table_data, 0x3 /* CCA = CPM = DCAS = 1 */, 1); + /* Table 15 Memory Access Flags */ + build_append_int_noprefix(table_data, 0x3 /* CCA = CPM = DACS = 1 */, 1); build_append_int_noprefix(table_data, 0, 4); /* ATS Attribute */ /* MCFG pci_segment */ build_append_int_noprefix(table_data, 0, 4); /* PCI Segment number */ + /* Memory address size limit */ + build_append_int_noprefix(table_data, 64, 1); + + build_append_int_noprefix(table_data, 0, 3); /* Reserved */ + /* Output Reference */ if (vms->iommu == VIRT_IOMMU_SMMUV3) { AcpiIortIdMapping *range; @@ -616,6 +626,64 @@ build_gtdt(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) acpi_table_end(linker, &table); } +/* Debug Port Table 2 (DBG2) */ +static void +build_dbg2(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) +{ + AcpiTable table = { .sig = "DBG2", .rev = 0, .oem_id = vms->oem_id, + .oem_table_id = vms->oem_table_id }; + int dbg2devicelength; + const char name[] = "COM0"; + const int namespace_length = sizeof(name); + + acpi_table_begin(&table, table_data); + + dbg2devicelength = 22 + /* BaseAddressRegister[] offset */ + 12 + /* BaseAddressRegister[] */ + 4 + /* AddressSize[] */ + namespace_length /* NamespaceString[] */; + + /* OffsetDbgDeviceInfo */ + build_append_int_noprefix(table_data, 44, 4); + /* NumberDbgDeviceInfo */ + build_append_int_noprefix(table_data, 1, 4); + + /* Table 2. Debug Device Information structure format */ + build_append_int_noprefix(table_data, 0, 1); /* Revision */ + build_append_int_noprefix(table_data, dbg2devicelength, 2); /* Length */ + /* NumberofGenericAddressRegisters */ + build_append_int_noprefix(table_data, 1, 1); + /* NameSpaceStringLength */ + build_append_int_noprefix(table_data, namespace_length, 2); + build_append_int_noprefix(table_data, 38, 2); /* NameSpaceStringOffset */ + build_append_int_noprefix(table_data, 0, 2); /* OemDataLength */ + /* OemDataOffset (0 means no OEM data) */ + build_append_int_noprefix(table_data, 0, 2); + + /* Port Type */ + build_append_int_noprefix(table_data, 0x8000 /* Serial */, 2); + /* Port Subtype */ + build_append_int_noprefix(table_data, 0x3 /* ARM PL011 UART */, 2); + build_append_int_noprefix(table_data, 0, 2); /* Reserved */ + /* BaseAddressRegisterOffset */ + build_append_int_noprefix(table_data, 22, 2); + /* AddressSizeOffset */ + build_append_int_noprefix(table_data, 34, 2); + + /* BaseAddressRegister[] */ + build_append_gas(table_data, AML_AS_SYSTEM_MEMORY, 8, 0, 1, + vms->memmap[VIRT_UART].base); + + /* AddressSize[] */ + build_append_int_noprefix(table_data, + vms->memmap[VIRT_UART].size, 4); + + /* NamespaceString[] */ + g_array_append_vals(table_data, name, namespace_length); + + acpi_table_end(linker, &table); +}; + /* * ACPI spec, Revision 5.1 Errata A * 5.2.12 Multiple APIC Description Table (MADT) @@ -875,13 +943,19 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) dsdt = tables_blob->len; build_dsdt(tables_blob, tables->linker, vms); - /* FADT MADT GTDT MCFG SPCR pointed to by RSDT */ + /* FADT MADT PPTT GTDT MCFG SPCR DBG2 pointed to by RSDT */ acpi_add_table(table_offsets, tables_blob); build_fadt_rev5(tables_blob, tables->linker, vms, dsdt); acpi_add_table(table_offsets, tables_blob); build_madt(tables_blob, tables->linker, vms); + if (!vmc->no_cpu_topology) { + acpi_add_table(table_offsets, tables_blob); + build_pptt(tables_blob, tables->linker, ms, + vms->oem_id, vms->oem_table_id); + } + acpi_add_table(table_offsets, tables_blob); build_gtdt(tables_blob, tables->linker, vms); @@ -898,6 +972,9 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) acpi_add_table(table_offsets, tables_blob); build_spcr(tables_blob, tables->linker, vms); + acpi_add_table(table_offsets, tables_blob); + build_dbg2(tables_blob, tables->linker, vms); + if (vms->ras) { build_ghes_error_table(tables->hardware_errors, tables->linker); acpi_add_table(table_offsets, tables_blob); diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 4160d49688..ca433adb5b 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -351,20 +351,21 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) int cpu; int addr_cells = 1; const MachineState *ms = MACHINE(vms); + const VirtMachineClass *vmc = VIRT_MACHINE_GET_CLASS(vms); int smp_cpus = ms->smp.cpus; /* - * From Documentation/devicetree/bindings/arm/cpus.txt - * On ARM v8 64-bit systems value should be set to 2, - * that corresponds to the MPIDR_EL1 register size. - * If MPIDR_EL1[63:32] value is equal to 0 on all CPUs - * in the system, #address-cells can be set to 1, since - * MPIDR_EL1[63:32] bits are not used for CPUs - * identification. + * See Linux Documentation/devicetree/bindings/arm/cpus.yaml + * On ARM v8 64-bit systems value should be set to 2, + * that corresponds to the MPIDR_EL1 register size. + * If MPIDR_EL1[63:32] value is equal to 0 on all CPUs + * in the system, #address-cells can be set to 1, since + * MPIDR_EL1[63:32] bits are not used for CPUs + * identification. * - * Here we actually don't know whether our system is 32- or 64-bit one. - * The simplest way to go is to examine affinity IDs of all our CPUs. If - * at least one of them has Aff3 populated, we set #address-cells to 2. + * Here we actually don't know whether our system is 32- or 64-bit one. + * The simplest way to go is to examine affinity IDs of all our CPUs. If + * at least one of them has Aff3 populated, we set #address-cells to 2. */ for (cpu = 0; cpu < smp_cpus; cpu++) { ARMCPU *armcpu = ARM_CPU(qemu_get_cpu(cpu)); @@ -407,8 +408,57 @@ static void fdt_add_cpu_nodes(const VirtMachineState *vms) ms->possible_cpus->cpus[cs->cpu_index].props.node_id); } + if (!vmc->no_cpu_topology) { + qemu_fdt_setprop_cell(ms->fdt, nodename, "phandle", + qemu_fdt_alloc_phandle(ms->fdt)); + } + g_free(nodename); } + + if (!vmc->no_cpu_topology) { + /* + * Add vCPU topology description through fdt node cpu-map. + * + * See Linux Documentation/devicetree/bindings/cpu/cpu-topology.txt + * In a SMP system, the hierarchy of CPUs can be defined through + * four entities that are used to describe the layout of CPUs in + * the system: socket/cluster/core/thread. + * + * A socket node represents the boundary of system physical package + * and its child nodes must be one or more cluster nodes. A system + * can contain several layers of clustering within a single physical + * package and cluster nodes can be contained in parent cluster nodes. + * + * Given that cluster is not yet supported in the vCPU topology, + * we currently generate one cluster node within each socket node + * by default. + */ + qemu_fdt_add_subnode(ms->fdt, "/cpus/cpu-map"); + + for (cpu = smp_cpus - 1; cpu >= 0; cpu--) { + char *cpu_path = g_strdup_printf("/cpus/cpu@%d", cpu); + char *map_path; + + if (ms->smp.threads > 1) { + map_path = g_strdup_printf( + "/cpus/cpu-map/socket%d/cluster0/core%d/thread%d", + cpu / (ms->smp.cores * ms->smp.threads), + (cpu / ms->smp.threads) % ms->smp.cores, + cpu % ms->smp.threads); + } else { + map_path = g_strdup_printf( + "/cpus/cpu-map/socket%d/cluster0/core%d", + cpu / ms->smp.cores, + cpu % ms->smp.cores); + } + qemu_fdt_add_path(ms->fdt, map_path); + qemu_fdt_setprop_phandle(ms->fdt, map_path, "cpu", cpu_path); + + g_free(map_path); + g_free(cpu_path); + } + } } static void fdt_add_its_gic_node(VirtMachineState *vms) @@ -2816,6 +2866,7 @@ static void virt_machine_6_1_options(MachineClass *mc) virt_machine_6_2_options(mc); compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len); mc->smp_props.prefer_sockets = true; + vmc->no_cpu_topology = true; /* qemu ITS was introduced with 6.2 */ vmc->no_tcg_its = true; diff --git a/hw/core/loader.c b/hw/core/loader.c index c623318b73..c7f97fdce8 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -326,7 +326,7 @@ static void *load_at(int fd, off_t offset, size_t size) #define SZ 64 #include "hw/elf_ops.h" -const char *load_elf_strerror(int error) +const char *load_elf_strerror(ssize_t error) { switch (error) { case 0: @@ -402,12 +402,12 @@ fail: } /* return < 0 if error, otherwise the number of bytes loaded in memory */ -int load_elf(const char *filename, - uint64_t (*elf_note_fn)(void *, void *, bool), - uint64_t (*translate_fn)(void *, uint64_t), - void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, - uint64_t *highaddr, uint32_t *pflags, int big_endian, - int elf_machine, int clear_lsb, int data_swab) +ssize_t load_elf(const char *filename, + uint64_t (*elf_note_fn)(void *, void *, bool), + uint64_t (*translate_fn)(void *, uint64_t), + void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, + uint64_t *highaddr, uint32_t *pflags, int big_endian, + int elf_machine, int clear_lsb, int data_swab) { return load_elf_as(filename, elf_note_fn, translate_fn, translate_opaque, pentry, lowaddr, highaddr, pflags, big_endian, @@ -415,12 +415,13 @@ int load_elf(const char *filename, } /* return < 0 if error, otherwise the number of bytes loaded in memory */ -int load_elf_as(const char *filename, - uint64_t (*elf_note_fn)(void *, void *, bool), - uint64_t (*translate_fn)(void *, uint64_t), - void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, - uint64_t *highaddr, uint32_t *pflags, int big_endian, - int elf_machine, int clear_lsb, int data_swab, AddressSpace *as) +ssize_t load_elf_as(const char *filename, + uint64_t (*elf_note_fn)(void *, void *, bool), + uint64_t (*translate_fn)(void *, uint64_t), + void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, + uint64_t *highaddr, uint32_t *pflags, int big_endian, + int elf_machine, int clear_lsb, int data_swab, + AddressSpace *as) { return load_elf_ram(filename, elf_note_fn, translate_fn, translate_opaque, pentry, lowaddr, highaddr, pflags, big_endian, @@ -428,13 +429,13 @@ int load_elf_as(const char *filename, } /* return < 0 if error, otherwise the number of bytes loaded in memory */ -int load_elf_ram(const char *filename, - uint64_t (*elf_note_fn)(void *, void *, bool), - uint64_t (*translate_fn)(void *, uint64_t), - void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, - uint64_t *highaddr, uint32_t *pflags, int big_endian, - int elf_machine, int clear_lsb, int data_swab, - AddressSpace *as, bool load_rom) +ssize_t load_elf_ram(const char *filename, + uint64_t (*elf_note_fn)(void *, void *, bool), + uint64_t (*translate_fn)(void *, uint64_t), + void *translate_opaque, uint64_t *pentry, + uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags, + int big_endian, int elf_machine, int clear_lsb, + int data_swab, AddressSpace *as, bool load_rom) { return load_elf_ram_sym(filename, elf_note_fn, translate_fn, translate_opaque, @@ -444,16 +445,17 @@ int load_elf_ram(const char *filename, } /* return < 0 if error, otherwise the number of bytes loaded in memory */ -int load_elf_ram_sym(const char *filename, - uint64_t (*elf_note_fn)(void *, void *, bool), - uint64_t (*translate_fn)(void *, uint64_t), - void *translate_opaque, uint64_t *pentry, - uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags, - int big_endian, int elf_machine, - int clear_lsb, int data_swab, - AddressSpace *as, bool load_rom, symbol_fn_t sym_cb) +ssize_t load_elf_ram_sym(const char *filename, + uint64_t (*elf_note_fn)(void *, void *, bool), + uint64_t (*translate_fn)(void *, uint64_t), + void *translate_opaque, uint64_t *pentry, + uint64_t *lowaddr, uint64_t *highaddr, + uint32_t *pflags, int big_endian, int elf_machine, + int clear_lsb, int data_swab, + AddressSpace *as, bool load_rom, symbol_fn_t sym_cb) { - int fd, data_order, target_data_order, must_swab, ret = ELF_LOAD_FAILED; + int fd, data_order, target_data_order, must_swab; + ssize_t ret = ELF_LOAD_FAILED; uint8_t e_ident[EI_NIDENT]; fd = open(filename, O_RDONLY | O_BINARY); diff --git a/include/hw/acpi/aml-build.h b/include/hw/acpi/aml-build.h index 3cf6f2c1b9..8346003a22 100644 --- a/include/hw/acpi/aml-build.h +++ b/include/hw/acpi/aml-build.h @@ -489,6 +489,9 @@ void build_srat_memory(GArray *table_data, uint64_t base, void build_slit(GArray *table_data, BIOSLinker *linker, MachineState *ms, const char *oem_id, const char *oem_table_id); +void build_pptt(GArray *table_data, BIOSLinker *linker, MachineState *ms, + const char *oem_id, const char *oem_table_id); + void build_fadt(GArray *tbl, BIOSLinker *linker, const AcpiFadtData *f, const char *oem_id, const char *oem_table_id); diff --git a/include/hw/arm/virt.h b/include/hw/arm/virt.h index b461b8d261..dc6b66ffc8 100644 --- a/include/hw/arm/virt.h +++ b/include/hw/arm/virt.h @@ -125,11 +125,13 @@ struct VirtMachineClass { bool claim_edge_triggered_timers; bool smbios_old_sys_ver; bool no_highmem_ecam; - bool no_ged; /* Machines < 4.2 has no support for ACPI GED device */ + bool no_ged; /* Machines < 4.2 have no support for ACPI GED device */ bool kvm_no_adjvtime; bool no_kvm_steal_time; bool acpi_expose_flash; bool no_secure_gpio; + /* Machines < 6.2 have no support for describing cpu topology to guest */ + bool no_cpu_topology; }; struct VirtMachineState { diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h index 1c37cec4ae..995de8495c 100644 --- a/include/hw/elf_ops.h +++ b/include/hw/elf_ops.h @@ -312,25 +312,26 @@ static struct elf_note *glue(get_elf_note_type, SZ)(struct elf_note *nhdr, return nhdr; } -static int glue(load_elf, SZ)(const char *name, int fd, - uint64_t (*elf_note_fn)(void *, void *, bool), - uint64_t (*translate_fn)(void *, uint64_t), - void *translate_opaque, - int must_swab, uint64_t *pentry, - uint64_t *lowaddr, uint64_t *highaddr, - uint32_t *pflags, int elf_machine, - int clear_lsb, int data_swab, - AddressSpace *as, bool load_rom, - symbol_fn_t sym_cb) +static ssize_t glue(load_elf, SZ)(const char *name, int fd, + uint64_t (*elf_note_fn)(void *, void *, bool), + uint64_t (*translate_fn)(void *, uint64_t), + void *translate_opaque, + int must_swab, uint64_t *pentry, + uint64_t *lowaddr, uint64_t *highaddr, + uint32_t *pflags, int elf_machine, + int clear_lsb, int data_swab, + AddressSpace *as, bool load_rom, + symbol_fn_t sym_cb) { struct elfhdr ehdr; struct elf_phdr *phdr = NULL, *ph; - int size, i, total_size; + int size, i; + ssize_t total_size; elf_word mem_size, file_size, data_offset; uint64_t addr, low = (uint64_t)-1, high = 0; GMappedFile *mapped_file = NULL; uint8_t *data = NULL; - int ret = ELF_LOAD_FAILED; + ssize_t ret = ELF_LOAD_FAILED; if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr)) goto fail; @@ -482,7 +483,7 @@ static int glue(load_elf, SZ)(const char *name, int fd, } } - if (mem_size > INT_MAX - total_size) { + if (mem_size > SSIZE_MAX - total_size) { ret = ELF_LOAD_TOO_BIG; goto fail; } diff --git a/include/hw/loader.h b/include/hw/loader.h index 81104cb02f..4fa485bd61 100644 --- a/include/hw/loader.h +++ b/include/hw/loader.h @@ -90,7 +90,7 @@ int load_image_gzipped(const char *filename, hwaddr addr, uint64_t max_sz); #define ELF_LOAD_WRONG_ARCH -3 #define ELF_LOAD_WRONG_ENDIAN -4 #define ELF_LOAD_TOO_BIG -5 -const char *load_elf_strerror(int error); +const char *load_elf_strerror(ssize_t error); /** load_elf_ram_sym: * @filename: Path of ELF file @@ -128,48 +128,48 @@ const char *load_elf_strerror(int error); typedef void (*symbol_fn_t)(const char *st_name, int st_info, uint64_t st_value, uint64_t st_size); -int load_elf_ram_sym(const char *filename, - uint64_t (*elf_note_fn)(void *, void *, bool), - uint64_t (*translate_fn)(void *, uint64_t), - void *translate_opaque, uint64_t *pentry, - uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags, - int big_endian, int elf_machine, - int clear_lsb, int data_swab, - AddressSpace *as, bool load_rom, symbol_fn_t sym_cb); +ssize_t load_elf_ram_sym(const char *filename, + uint64_t (*elf_note_fn)(void *, void *, bool), + uint64_t (*translate_fn)(void *, uint64_t), + void *translate_opaque, uint64_t *pentry, + uint64_t *lowaddr, uint64_t *highaddr, + uint32_t *pflags, int big_endian, int elf_machine, + int clear_lsb, int data_swab, + AddressSpace *as, bool load_rom, symbol_fn_t sym_cb); /** load_elf_ram: * Same as load_elf_ram_sym(), but doesn't allow the caller to specify a * symbol callback function */ -int load_elf_ram(const char *filename, - uint64_t (*elf_note_fn)(void *, void *, bool), - uint64_t (*translate_fn)(void *, uint64_t), - void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, - uint64_t *highaddr, uint32_t *pflags, int big_endian, - int elf_machine, int clear_lsb, int data_swab, - AddressSpace *as, bool load_rom); +ssize_t load_elf_ram(const char *filename, + uint64_t (*elf_note_fn)(void *, void *, bool), + uint64_t (*translate_fn)(void *, uint64_t), + void *translate_opaque, uint64_t *pentry, + uint64_t *lowaddr, uint64_t *highaddr, uint32_t *pflags, + int big_endian, int elf_machine, int clear_lsb, + int data_swab, AddressSpace *as, bool load_rom); /** load_elf_as: * Same as load_elf_ram(), but always loads the elf as ROM */ -int load_elf_as(const char *filename, - uint64_t (*elf_note_fn)(void *, void *, bool), - uint64_t (*translate_fn)(void *, uint64_t), - void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, - uint64_t *highaddr, uint32_t *pflags, int big_endian, - int elf_machine, int clear_lsb, int data_swab, - AddressSpace *as); +ssize_t load_elf_as(const char *filename, + uint64_t (*elf_note_fn)(void *, void *, bool), + uint64_t (*translate_fn)(void *, uint64_t), + void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, + uint64_t *highaddr, uint32_t *pflags, int big_endian, + int elf_machine, int clear_lsb, int data_swab, + AddressSpace *as); /** load_elf: * Same as load_elf_as(), but doesn't allow the caller to specify an * AddressSpace. */ -int load_elf(const char *filename, - uint64_t (*elf_note_fn)(void *, void *, bool), - uint64_t (*translate_fn)(void *, uint64_t), - void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, - uint64_t *highaddr, uint32_t *pflags, int big_endian, - int elf_machine, int clear_lsb, int data_swab); +ssize_t load_elf(const char *filename, + uint64_t (*elf_note_fn)(void *, void *, bool), + uint64_t (*translate_fn)(void *, uint64_t), + void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr, + uint64_t *highaddr, uint32_t *pflags, int big_endian, + int elf_machine, int clear_lsb, int data_swab); /** load_elf_hdr: * @filename: Path of ELF file diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h index 8a2fe55622..ef060a9759 100644 --- a/include/sysemu/device_tree.h +++ b/include/sysemu/device_tree.h @@ -121,6 +121,7 @@ uint32_t qemu_fdt_get_phandle(void *fdt, const char *path); uint32_t qemu_fdt_alloc_phandle(void *fdt); int qemu_fdt_nop_node(void *fdt, const char *node_path); int qemu_fdt_add_subnode(void *fdt, const char *name); +int qemu_fdt_add_path(void *fdt, const char *path); #define qemu_fdt_setprop_cells(fdt, node_path, property, ...) \ do { \ diff --git a/roms/Makefile b/roms/Makefile index eeb5970348..b967b53bb7 100644 --- a/roms/Makefile +++ b/roms/Makefile @@ -143,7 +143,8 @@ build-efi-roms: build-pxe-roms # efirom # edk2-basetools: - cd edk2/BaseTools && git submodule update --init --force + cd edk2/BaseTools && git submodule update --init --force \ + Source/C/BrotliCompress/brotli $(MAKE) -C edk2/BaseTools \ PYTHON_COMMAND=$${EDK2_PYTHON_COMMAND:-python3} \ EXTRA_OPTFLAGS='$(EDK2_BASETOOLS_OPTFLAGS)' \ diff --git a/roms/Makefile.edk2 b/roms/Makefile.edk2 index a8ed325575..fdae0b511f 100644 --- a/roms/Makefile.edk2 +++ b/roms/Makefile.edk2 @@ -51,7 +51,12 @@ all: $(foreach flashdev,$(flashdevs),../pc-bios/edk2-$(flashdev).fd.bz2) \ # make-release/tarball scripts. submodules: if test -d edk2/.git; then \ - cd edk2 && git submodule update --init --force; \ + cd edk2 && git submodule update --init --force -- \ + ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3 \ + BaseTools/Source/C/BrotliCompress/brotli \ + CryptoPkg/Library/OpensslLib/openssl \ + MdeModulePkg/Library/BrotliCustomDecompressLib/brotli \ + ; \ fi # See notes on the ".NOTPARALLEL" target and the "+" indicator in diff --git a/scripts/make-release b/scripts/make-release index a2a8cda33c..05b14ecc95 100755 --- a/scripts/make-release +++ b/scripts/make-release @@ -27,7 +27,12 @@ git submodule update --init # don't necessarily have much control over how a submodule handles its # submodule dependencies, so we continue to handle these on a case-by-case # basis for now. -(cd roms/edk2 && git submodule update --init) +(cd roms/edk2 && \ + git submodule update --init -- \ + ArmPkg/Library/ArmSoftFloatLib/berkeley-softfloat-3 \ + BaseTools/Source/C/BrotliCompress/brotli \ + CryptoPkg/Library/OpensslLib/openssl \ + MdeModulePkg/Library/BrotliCustomDecompressLib/brotli) popd tar --exclude=.git -cjf ${destination}.tar.bz2 ${destination} rm -rf ${destination} diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c index b621f63fba..3965c834ca 100644 --- a/softmmu/device_tree.c +++ b/softmmu/device_tree.c @@ -540,8 +540,8 @@ int qemu_fdt_add_subnode(void *fdt, const char *name) retval = fdt_add_subnode(fdt, parent, basename); if (retval < 0) { - error_report("FDT: Failed to create subnode %s: %s", name, - fdt_strerror(retval)); + error_report("%s: Failed to create subnode %s: %s", + __func__, name, fdt_strerror(retval)); exit(1); } @@ -549,6 +549,46 @@ int qemu_fdt_add_subnode(void *fdt, const char *name) return retval; } +/* + * qemu_fdt_add_path: Like qemu_fdt_add_subnode(), but will add + * all missing subnodes from the given path. + */ +int qemu_fdt_add_path(void *fdt, const char *path) +{ + const char *name; + const char *p = path; + int namelen, retval; + int parent = 0; + + if (path[0] != '/') { + return -1; + } + + while (p) { + name = p + 1; + p = strchr(name, '/'); + namelen = p != NULL ? p - name : strlen(name); + + retval = fdt_subnode_offset_namelen(fdt, parent, name, namelen); + if (retval < 0 && retval != -FDT_ERR_NOTFOUND) { + error_report("%s: Unexpected error in finding subnode %.*s: %s", + __func__, namelen, name, fdt_strerror(retval)); + exit(1); + } else if (retval == -FDT_ERR_NOTFOUND) { + retval = fdt_add_subnode_namelen(fdt, parent, name, namelen); + if (retval < 0) { + error_report("%s: Failed to create subnode %.*s: %s", + __func__, namelen, name, fdt_strerror(retval)); + exit(1); + } + } + + parent = retval; + } + + return retval; +} + void qemu_fdt_dumpdtb(void *fdt, int size) { const char *dumpdtb = current_machine->dumpdtb; diff --git a/tests/data/acpi/virt/DBG2 b/tests/data/acpi/virt/DBG2 Binary files differnew file mode 100644 index 0000000000..86e6314f7b --- /dev/null +++ b/tests/data/acpi/virt/DBG2 diff --git a/tests/data/acpi/virt/IORT b/tests/data/acpi/virt/IORT Binary files differindex 521acefe9b..7efd0ce8a6 100644 --- a/tests/data/acpi/virt/IORT +++ b/tests/data/acpi/virt/IORT diff --git a/tests/data/acpi/virt/IORT.memhp b/tests/data/acpi/virt/IORT.memhp Binary files differindex 521acefe9b..7efd0ce8a6 100644 --- a/tests/data/acpi/virt/IORT.memhp +++ b/tests/data/acpi/virt/IORT.memhp diff --git a/tests/data/acpi/virt/IORT.numamem b/tests/data/acpi/virt/IORT.numamem Binary files differindex 521acefe9b..7efd0ce8a6 100644 --- a/tests/data/acpi/virt/IORT.numamem +++ b/tests/data/acpi/virt/IORT.numamem diff --git a/tests/data/acpi/virt/IORT.pxb b/tests/data/acpi/virt/IORT.pxb Binary files differindex 521acefe9b..7efd0ce8a6 100644 --- a/tests/data/acpi/virt/IORT.pxb +++ b/tests/data/acpi/virt/IORT.pxb diff --git a/tests/data/acpi/virt/PPTT b/tests/data/acpi/virt/PPTT Binary files differnew file mode 100644 index 0000000000..7a1258ecf1 --- /dev/null +++ b/tests/data/acpi/virt/PPTT |