feat(rmm): add PCIe IO info to Boot manifest
- Add PCIe and SMMUv3 related information to DTS for
configurations with ENABLE_RME=1.
- Add entries for PCIe IO memory regions to Boot manifest
- Update RMMD_MANIFEST_VERSION_MINOR from 3 to 4.
- Read PCIe related information from DTB and write it to
Boot manifest.
- Rename structures that used to describe DRAM layout
and now describe both DRAM and PCIe IO memory regions:
- ns_dram_bank -> memory_bank
- ns_dram_info -> memory_info.
Change-Id: Ib75d1af86076f724f5c330074e231f1c2ba8e21d
Signed-off-by: AlexeiFedorov <Alexei.Fedorov@arm.com>
diff --git a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
index 43dc17b..662b8a4 100644
--- a/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
+++ b/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,7 +18,8 @@
struct hw_topology_t soc_topology;
struct uart_serial_config_t uart_serial_config;
struct cpu_timer_t cpu_timer;
-struct ns_dram_layout dram_layout;
+struct dram_layout_t dram_layout;
+struct pci_props_t pci_props;
/*
* Each NS DRAM bank entry is 'reg' node property which is
@@ -27,6 +28,7 @@
#define DRAM_ENTRY_SIZE (4UL * sizeof(uint32_t))
CASSERT(ARM_DRAM_NUM_BANKS == 2UL, ARM_DRAM_NUM_BANKS_mismatch);
+CASSERT(ARM_PCI_NUM_REGIONS == 2UL, ARM_PCI_NUM_REGIONS_mismatch);
#define ILLEGAL_ADDR ULL(~0)
@@ -352,8 +354,98 @@
return 0;
}
+/*
+ * Each PCIe memory region entry is 'ranges' node property which is
+ * an arbitrary number of (child-bus-address, parent-bus-address, length)
+ * triplets. E.g. with
+ * #address-cells = <3>
+ * #size-cells = <2>
+ * parent's #address-cells = <2>
+ * each entry occupies 7 32-bit words.
+ */
+int fconf_populate_pci_props(uintptr_t config)
+{
+ int node, parent, len, err;
+ int parent_ac, ac, sc, entry_len;
+ const uint32_t *reg, *ranges;
+
+ /* Necessary to work with libfdt APIs */
+ const void *hw_config_dtb = (const void *)config;
+
+ /* Find 'pci' node */
+ node = fdt_node_offset_by_prop_value(hw_config_dtb, -1, "device_type",
+ "pci", sizeof("pci"));
+ if (node < 0) {
+ WARN("FCONF: Unable to locate 'pci' node\n");
+ pci_props.ecam_base = 0UL;
+ pci_props.size = 0UL;
+ pci_props.num_ncoh_regions = 0UL;
+ /* Don't return error code if 'pci' node not found */
+ return 0;
+ }
+
+ reg = fdt_getprop(hw_config_dtb, node, "reg", &len);
+ if (reg == NULL) {
+ ERROR("FCONF failed to read 'reg' property\n");
+ return len;
+ }
+
+ err = fdt_get_reg_props_by_index(hw_config_dtb, node, 0,
+ (uintptr_t *)&pci_props.ecam_base,
+ (size_t *)&pci_props.size);
+ if (err < 0) {
+ ERROR("FCONF: Failed to read 'reg' property of 'pci' node\n");
+ return err;
+ }
+
+ parent = fdt_parent_offset(hw_config_dtb, node);
+ if (parent < 0) {
+ return -FDT_ERR_BADOFFSET;
+ }
+
+ parent_ac = fdt_address_cells(hw_config_dtb, parent);
+ ac = fdt_address_cells(hw_config_dtb, node);
+ sc = fdt_size_cells(hw_config_dtb, node);
+
+ entry_len = parent_ac + ac + sc;
+
+ ranges = fdt_getprop(hw_config_dtb, node, "ranges", &len);
+ if (ranges == NULL) {
+ ERROR("FCONF failed to read 'ranges' property\n");
+ return len;
+ }
+
+ /* 'ranges' length in 32-bit words */
+ len /= sizeof(uint32_t);
+ if ((len % entry_len) != 0) {
+ return -FDT_ERR_BADVALUE;
+ }
+
+ pci_props.num_ncoh_regions = (uint64_t)(len / entry_len);
+
+ if (pci_props.num_ncoh_regions > ARM_PCI_NUM_REGIONS) {
+ WARN("FCONF: 'ranges' reports more memory regions than supported\n");
+ pci_props.num_ncoh_regions = ARM_PCI_NUM_REGIONS;
+ }
+
+ for (unsigned int i = 0U; i < (unsigned int)pci_props.num_ncoh_regions; i++) {
+ unsigned int cell = i * entry_len + ac;
+
+ /* Read CPU address (parent-bus-address) space */
+ pci_props.ncoh_regions[i].base =
+ fdt_read_prop_cells(&ranges[cell], ac);
+
+ /* Read CPU address size */
+ pci_props.ncoh_regions[i].size =
+ fdt_read_prop_cells(&ranges[cell + parent_ac], sc);
+ }
+
+ return 0;
+}
+
FCONF_REGISTER_POPULATOR(HW_CONFIG, gicv3_config, fconf_populate_gicv3_config);
FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology);
FCONF_REGISTER_POPULATOR(HW_CONFIG, uart_config, fconf_populate_uart_config);
FCONF_REGISTER_POPULATOR(HW_CONFIG, cpu_timer, fconf_populate_cpu_timer);
FCONF_REGISTER_POPULATOR(HW_CONFIG, dram_layout, fconf_populate_dram_layout);
+FCONF_REGISTER_POPULATOR(HW_CONFIG, pci_props, fconf_populate_pci_props);
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index bdc2cac..19a340f 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2025, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -34,12 +34,11 @@
#define FVP_GICV2 1
#define FVP_GICV3 2
-/* Defines for RMM Console*/
+/* Defines for RMM Console */
#define FVP_RMM_CONSOLE_BASE UL(0x1c0c0000)
#define FVP_RMM_CONSOLE_BAUD UL(115200)
#define FVP_RMM_CONSOLE_CLK_IN_HZ UL(14745600)
#define FVP_RMM_CONSOLE_NAME "pl011"
-
#define FVP_RMM_CONSOLE_COUNT UL(1)
/*******************************************************************************
@@ -591,11 +590,78 @@
return sum;
}
-
+/*
+ * Boot Manifest structure illustration, with two DRAM banks,
+ * a single console and one device memory with two PCIe device
+ * non-coherent address ranges.
+ *
+ * +--------------------------------------------------+
+ * | offset | field | comment |
+ * +--------+--------------------+--------------------+
+ * | 0 | version | 0x00000004 |
+ * +--------+--------------------+--------------------+
+ * | 4 | padding | 0x00000000 |
+ * +--------+--------------------+--------------------+
+ * | 8 | plat_data | NULL |
+ * +--------+--------------------+--------------------+
+ * | 16 | num_banks | |
+ * +--------+--------------------+ |
+ * | 24 | banks | plat_dram +--+
+ * +--------+--------------------+ | |
+ * | 32 | checksum | | |
+ * +--------+--------------------+--------------------+ |
+ * | 40 | num_consoles | | |
+ * +--------+--------------------+ | |
+ * | 48 | consoles | plat_console +--|--+
+ * +--------+--------------------+ | | |
+ * | 56 | checksum | | | |
+ * +--------+--------------------+--------------------+ | |
+ * | 64 | num_banks | | | |
+ * +--------+--------------------+ | | |
+ * | 72 | banks | plat_ncoh_region +--|--|--+
+ * +--------+--------------------+ | | | |
+ * | 80 | checksum | | | | |
+ * +--------+--------------------+--------------------+ | | |
+ * | 88 | num_banks | | | | |
+ * +--------+--------------------+ | | | |
+ * | 96 | banks | plat_coh_region | | | |
+ * +--------+--------------------+ | | | |
+ * | 104 | checksum | | | | |
+ * +--------+--------------------+--------------------+<-+ | |
+ * | 112 | base 0 | | | |
+ * +--------+--------------------+ mem_bank[0] | | |
+ * | 120 | size 0 | | | |
+ * +--------+--------------------+--------------------+ | |
+ * | 128 | base 1 | | | |
+ * +--------+--------------------+ mem_bank[1] | | |
+ * | 136 | size 1 | | | |
+ * +--------+--------------------+--------------------+<----+ |
+ * | 144 | base | | |
+ * +--------+--------------------+ | |
+ * | 152 | map_pages | | |
+ * +--------+--------------------+ | |
+ * | 160 | name | | |
+ * +--------+--------------------+ consoles[0] | |
+ * | 168 | clk_in_hz | | |
+ * +--------+--------------------+ | |
+ * | 176 | baud_rate | | |
+ * +--------+--------------------+ | |
+ * | 184 | flags | | |
+ * +--------+--------------------+--------------------+<-------+
+ * | 192 | base 0 | |
+ * +--------+--------------------+ ncoh_region[0] |
+ * | 200 | size 0 | |
+ * +--------+--------------------+--------------------+
+ * | 208 | base 1 | |
+ * +--------+--------------------+ ncoh_region[1] |
+ * | 216 | size 1 | |
+ * +--------+--------------------+--------------------+
+ */
int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
{
uint64_t checksum, num_banks, num_consoles;
- struct ns_dram_bank *bank_ptr;
+ uint64_t num_ncoh_regions, num_coh_regions;
+ struct memory_bank *bank_ptr, *ncoh_region_ptr;
struct console_info *console_ptr;
assert(manifest != NULL);
@@ -607,71 +673,45 @@
/* Set number of consoles */
num_consoles = FVP_RMM_CONSOLE_COUNT;
+ /* Set number of device non-coherent address ranges based on DT */
+ num_ncoh_regions = FCONF_GET_PROPERTY(hw_config, pci_props, num_ncoh_regions);
+
manifest->version = RMMD_MANIFEST_VERSION;
manifest->padding = 0U; /* RES0 */
- manifest->plat_data = (uintptr_t)NULL;
+ manifest->plat_data = 0UL;
manifest->plat_dram.num_banks = num_banks;
manifest->plat_console.num_consoles = num_consoles;
+ manifest->plat_ncoh_region.num_banks = num_ncoh_regions;
- /*
- * Boot Manifest structure illustration, with two dram banks and
- * a single console.
- *
- * +----------------------------------------+
- * | offset | field | comment |
- * +--------+----------------+--------------+
- * | 0 | version | 0x00000003 |
- * +--------+----------------+--------------+
- * | 4 | padding | 0x00000000 |
- * +--------+----------------+--------------+
- * | 8 | plat_data | NULL |
- * +--------+----------------+--------------+
- * | 16 | num_banks | |
- * +--------+----------------+ |
- * | 24 | banks | plat_dram |
- * +--------+----------------+ |
- * | 32 | checksum | |
- * +--------+----------------+--------------+
- * | 40 | num_consoles | |
- * +--------+----------------+ |
- * | 48 | consoles | plat_console |
- * +--------+----------------+ |
- * | 56 | checksum | |
- * +--------+----------------+--------------+
- * | 64 | base 0 | |
- * +--------+----------------+ bank[0] |
- * | 72 | size 0 | |
- * +--------+----------------+--------------+
- * | 80 | base 1 | |
- * +--------+----------------+ bank[1] |
- * | 88 | size 1 | |
- * +--------+----------------+--------------+
- * | 96 | base | |
- * +--------+----------------+ |
- * | 104 | map_pages | |
- * +--------+----------------+ |
- * | 112 | name | |
- * +--------+----------------+ consoles[0] |
- * | 120 | clk_in_hz | |
- * +--------+----------------+ |
- * | 128 | baud_rate | |
- * +--------+----------------+ |
- * | 136 | flags | |
- * +--------+----------------+--------------+
- */
+ /* FVP does not support device coherent address ranges */
+ num_coh_regions = 0UL;
+ manifest->plat_coh_region.num_banks = num_coh_regions;
+ manifest->plat_coh_region.banks = NULL;
+ manifest->plat_coh_region.checksum = 0UL;
- bank_ptr = (struct ns_dram_bank *)
- (((uintptr_t)manifest) + sizeof(*manifest));
+ bank_ptr = (struct memory_bank *)
+ (((uintptr_t)manifest) + sizeof(struct rmm_manifest));
console_ptr = (struct console_info *)
- ((uintptr_t)bank_ptr + (num_banks * sizeof(*bank_ptr)));
-
+ ((uintptr_t)bank_ptr + (num_banks *
+ sizeof(struct memory_bank)));
+ ncoh_region_ptr = (struct memory_bank *)
+ ((uintptr_t)console_ptr + (num_consoles *
+ sizeof(struct console_info)));
manifest->plat_dram.banks = bank_ptr;
manifest->plat_console.consoles = console_ptr;
+ manifest->plat_ncoh_region.banks = ncoh_region_ptr;
/* Ensure the manifest is not larger than the shared buffer */
assert((sizeof(struct rmm_manifest) +
- (sizeof(struct console_info) * manifest->plat_console.num_consoles) +
- (sizeof(struct ns_dram_bank) * manifest->plat_dram.num_banks)) <= ARM_EL3_RMM_SHARED_SIZE);
+ (sizeof(struct memory_bank) *
+ manifest->plat_dram.num_banks) +
+ (sizeof(struct console_info) *
+ manifest->plat_console.num_consoles) +
+ (sizeof(struct memory_bank) *
+ manifest->plat_ncoh_region.num_banks) +
+ (sizeof(struct memory_bank) *
+ manifest->plat_coh_region.num_banks))
+ <= ARM_EL3_RMM_SHARED_SIZE);
/* Calculate checksum of plat_dram structure */
checksum = num_banks + (uint64_t)bank_ptr;
@@ -683,31 +723,56 @@
}
/* Update checksum */
- checksum += checksum_calc((uint64_t *)bank_ptr, sizeof(struct ns_dram_bank) * num_banks);
+ checksum += checksum_calc((uint64_t *)bank_ptr, sizeof(struct memory_bank) * num_banks);
/* Checksum must be 0 */
manifest->plat_dram.checksum = ~checksum + 1UL;
- /* Calculate the checksum of the plat_consoles structure */
+ /* Calculate the checksum of plat_consoles structure */
checksum = num_consoles + (uint64_t)console_ptr;
/* Zero out the console info struct */
- (void)memset((void *)console_ptr, '\0', sizeof(struct console_info) * num_consoles);
+ (void)memset((void *)console_ptr, '\0',
+ sizeof(struct console_info) * num_consoles);
console_ptr[0].base = FVP_RMM_CONSOLE_BASE;
console_ptr[0].map_pages = 1UL;
console_ptr[0].clk_in_hz = FVP_RMM_CONSOLE_CLK_IN_HZ;
console_ptr[0].baud_rate = FVP_RMM_CONSOLE_BAUD;
- (void)strlcpy(console_ptr[0].name, FVP_RMM_CONSOLE_NAME, RMM_CONSOLE_MAX_NAME_LEN - 1UL);
+ (void)strlcpy(console_ptr[0].name, FVP_RMM_CONSOLE_NAME,
+ RMM_CONSOLE_MAX_NAME_LEN - 1UL);
/* Update checksum */
checksum += checksum_calc((uint64_t *)console_ptr,
sizeof(struct console_info) * num_consoles);
-
/* Checksum must be 0 */
manifest->plat_console.checksum = ~checksum + 1UL;
+ /*
+ * Calculate the checksum of device non-coherent address ranges
+ * info structure
+ */
+ checksum = num_ncoh_regions + (uint64_t)ncoh_region_ptr;
+
+ /* Zero out the PCIe region info struct */
+ (void)memset((void *)ncoh_region_ptr, 0,
+ sizeof(struct memory_bank) * num_ncoh_regions);
+
+ for (unsigned long i = 0UL; i < num_ncoh_regions; i++) {
+ ncoh_region_ptr[i].base =
+ FCONF_GET_PROPERTY(hw_config, pci_props, ncoh_regions[i].base);
+ ncoh_region_ptr[i].size =
+ FCONF_GET_PROPERTY(hw_config, pci_props, ncoh_regions[i].size);
+ }
+
+ /* Update checksum */
+ checksum += checksum_calc((uint64_t *)ncoh_region_ptr,
+ sizeof(struct memory_bank) * num_ncoh_regions);
+
+ /* Checksum must be 0 */
+ manifest->plat_ncoh_region.checksum = ~checksum + 1UL;
+
return 0;
}
#endif /* ENABLE_RME */
diff --git a/plat/arm/board/fvp/include/fconf_hw_config_getter.h b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
index b7a1247..351f13d 100644
--- a/plat/arm/board/fvp/include/fconf_hw_config_getter.h
+++ b/plat/arm/board/fvp/include/fconf_hw_config_getter.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
+ * Copyright (c) 2020-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -18,6 +18,7 @@
#define hw_config__uart_serial_config_getter(prop) uart_serial_config.prop
#define hw_config__cpu_timer_getter(prop) cpu_timer.prop
#define hw_config__dram_layout_getter(prop) dram_layout.prop
+#define hw_config__pci_props_getter(prop) pci_props.prop
struct gicv3_config_t {
uint64_t gicd_base;
@@ -40,9 +41,16 @@
uint32_t clock_freq;
};
-struct ns_dram_layout {
+struct dram_layout_t {
uint64_t num_banks;
- struct ns_dram_bank dram_bank[ARM_DRAM_NUM_BANKS];
+ struct memory_bank dram_bank[ARM_DRAM_NUM_BANKS];
+};
+
+struct pci_props_t {
+ uint64_t ecam_base;
+ uint64_t size;
+ uint64_t num_ncoh_regions;
+ struct memory_bank ncoh_regions[ARM_PCI_NUM_REGIONS];
};
int fconf_populate_gicv3_config(uintptr_t config);
@@ -50,11 +58,13 @@
int fconf_populate_uart_config(uintptr_t config);
int fconf_populate_cpu_timer(uintptr_t config);
int fconf_populate_dram_layout(uintptr_t config);
+int fconf_populate_pci_props(uintptr_t config);
extern struct gicv3_config_t gicv3_config;
extern struct hw_topology_t soc_topology;
extern struct uart_serial_config_t uart_serial_config;
extern struct cpu_timer_t cpu_timer;
-extern struct ns_dram_layout dram_layout;
+extern struct dram_layout_t dram_layout;
+extern struct pci_props_t pci_props;
#endif /* FCONF_HW_CONFIG_GETTER_H */
diff --git a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
index 3ef9681..2402c05 100644
--- a/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
+++ b/plat/arm/board/neoverse_rd/platform/rdv3/rdv3_common.c
@@ -64,7 +64,7 @@
int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
{
uint64_t checksum, num_banks, num_consoles;
- struct ns_dram_bank *bank_ptr;
+ struct memory_bank *bank_ptr;
struct console_info *console_ptr;
assert(manifest != NULL);
@@ -129,7 +129,7 @@
* +--------+----------------+--------------+
*/
- bank_ptr = (struct ns_dram_bank *)
+ bank_ptr = (struct memory_bank *)
(((uintptr_t)manifest) + sizeof(*manifest));
console_ptr = (struct console_info *)
((uintptr_t)bank_ptr + (num_banks * sizeof(*bank_ptr)));
@@ -141,7 +141,7 @@
assert((sizeof(struct rmm_manifest) +
(sizeof(struct console_info) *
manifest->plat_console.num_consoles) +
- (sizeof(struct ns_dram_bank) * manifest->plat_dram.num_banks))
+ (sizeof(struct memory_bank) * manifest->plat_dram.num_banks))
<= ARM_EL3_RMM_SHARED_SIZE);
/* Calculate checksum of plat_dram structure */
@@ -156,7 +156,7 @@
/* Update checksum */
checksum += checksum_calc((uint64_t *)bank_ptr,
- sizeof(struct ns_dram_bank) * num_banks);
+ sizeof(struct memory_bank) * num_banks);
/* Checksum must be 0 */
manifest->plat_dram.checksum = ~checksum + 1UL;