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>
This commit is contained in:
AlexeiFedorov 2024-10-14 15:23:34 +01:00 committed by Jean-Philippe Brucker
parent 665a8fdf3a
commit bef44f60ed
10 changed files with 375 additions and 156 deletions

View file

@ -277,7 +277,7 @@ int fdtw_write_inplace_bytes(void *dtb, int node, const char *prop,
return err; return err;
} }
static uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells) uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells)
{ {
uint64_t reg = fdt32_to_cpu(prop[0]); uint64_t reg = fdt32_to_cpu(prop[0]);

View file

@ -53,7 +53,7 @@ are explained below:
consistency with the versioning schemes used in other parts of RMM. consistency with the versioning schemes used in other parts of RMM.
This document specifies the 0.4 version of Boot Interface ABI and RMM-EL3 This document specifies the 0.4 version of Boot Interface ABI and RMM-EL3
services specification and the 0.3 version of the Boot Manifest. services specification and the 0.4 version of the Boot Manifest.
.. _rmm_el3_boot_interface: .. _rmm_el3_boot_interface:
@ -182,12 +182,12 @@ platform information.
This Boot Manifest is versioned independently of the Boot Interface, to help This Boot Manifest is versioned independently of the Boot Interface, to help
evolve the former independent of the latter. evolve the former independent of the latter.
The current version for the Boot Manifest is ``v0.3`` and the rules explained The current version for the Boot Manifest is ``v0.4`` and the rules explained
in :ref:`rmm_el3_ifc_versioning` apply on this version as well. in :ref:`rmm_el3_ifc_versioning` apply on this version as well.
The Boot Manifest v0.3 has the following fields: The Boot Manifest v0.4 has the following fields:
- version : Version of the Manifest (v0.3) - version : Version of the Manifest (v0.4)
- plat_data : Pointer to the platform specific data and not specified by this - plat_data : Pointer to the platform specific data and not specified by this
document. These data are optional and can be NULL. document. These data are optional and can be NULL.
- plat_dram : Structure encoding the NS DRAM information on the platform. This - plat_dram : Structure encoding the NS DRAM information on the platform. This
@ -720,61 +720,65 @@ _____
RMM-EL3 Boot Manifest structure RMM-EL3 Boot Manifest structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The RMM-EL3 Boot Manifest v0.3 structure contains platform boot information passed The RMM-EL3 Boot Manifest v0.4 structure contains platform boot information passed
from EL3 to RMM. The size of the Boot Manifest is 64 bytes. from EL3 to RMM. The size of the Boot Manifest is 112 bytes.
The members of the RMM-EL3 Boot Manifest structure are shown in the following The members of the RMM-EL3 Boot Manifest structure are shown in the following
table: table:
+--------------+--------+----------------+----------------------------------------+ +--------------------+--------+-------------------+----------------------------------------------+
| Name | Offset | Type | Description | | Name | Offset | Type | Description |
+==============+========+================+========================================+ +====================+========+===================+==============================================+
| version | 0 | uint32_t | Boot Manifest version | | version | 0 | uint32_t | Boot Manifest version |
+--------------+--------+----------------+----------------------------------------+ +--------------------+--------+-------------------+----------------------------------------------+
| padding | 4 | uint32_t | Reserved, set to 0 | | padding | 4 | uint32_t | Reserved, set to 0 |
+--------------+--------+----------------+----------------------------------------+ +--------------------+--------+-------------------+----------------------------------------------+
| plat_data | 8 | uintptr_t | Pointer to Platform Data section | | plat_data | 8 | uintptr_t | Pointer to Platform Data section |
+--------------+--------+----------------+----------------------------------------+ +--------------------+--------+-------------------+----------------------------------------------+
| plat_dram | 16 | ns_dram_info | NS DRAM Layout Info structure | | plat_dram | 16 | memory_info | NS DRAM Layout Info structure |
+--------------+--------+----------------+----------------------------------------+ +--------------------+--------+-------------------+----------------------------------------------+
| plat_console | 40 | console_list | List of consoles available to RMM | | plat_console | 40 | console_list | List of consoles available to RMM |
+--------------+--------+----------------+----------------------------------------+ +--------------------+--------+-------------------+----------------------------------------------+
| plat_ncoh_region | 64 | memory_info | Device non-coherent ranges Info structure |
+--------------------+--------+-------------------+----------------------------------------------+
| plat_coh_region | 88 | memory_info | Device coherent ranges Info structure |
+--------------------+--------+-------------------+----------------------------------------------+
.. _ns_dram_info_struct: .. _memory_info_struct:
NS DRAM Layout Info structure Memory Info structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
NS DRAM Layout Info structure contains information about platform Non-secure Memory Info structure contains information about platform memory layout.
DRAM layout. The members of this structure are shown in the table below: The members of this structure are shown in the table below:
+-----------+--------+----------------+----------------------------------------+ +-----------+--------+----------------+----------------------------------------+
| Name | Offset | Type | Description | | Name | Offset | Type | Description |
+===========+========+================+========================================+ +===========+========+================+========================================+
| num_banks | 0 | uint64_t | Number of NS DRAM banks | | num_banks | 0 | uint64_t | Number of memory banks/device regions |
+-----------+--------+----------------+----------------------------------------+ +-----------+--------+----------------+----------------------------------------+
| banks | 8 | ns_dram_bank * | Pointer to 'ns_dram_bank'[] array | | banks | 8 | memory_bank * | Pointer to 'memory_bank'[] array |
+-----------+--------+----------------+----------------------------------------+ +-----------+--------+----------------+----------------------------------------+
| checksum | 16 | uint64_t | Checksum | | checksum | 16 | uint64_t | Checksum |
+-----------+--------+----------------+----------------------------------------+ +-----------+--------+----------------+----------------------------------------+
Checksum is calculated as two's complement sum of 'num_banks', 'banks' pointer Checksum is calculated as two's complement sum of 'num_banks', 'banks' pointer
and DRAM banks data array pointed by it. and memory banks data array pointed by it.
.. _ns_dram_bank_struct: .. _memory_bank_struct:
NS DRAM Bank structure Memory Bank/Device region structure
~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
NS DRAM Bank structure contains information about each Non-secure DRAM bank: Memory Bank structure contains information about each memory bank/device region:
+-----------+--------+----------------+----------------------------------------+ +-----------+--------+----------------+--------------------------------------------+
| Name | Offset | Type | Description | | Name | Offset | Type | Description |
+===========+========+================+========================================+ +===========+========+================+============================================+
| base | 0 | uintptr_t | Base address | | base | 0 | uintptr_t | Base address |
+-----------+--------+----------------+----------------------------------------+ +-----------+--------+----------------+--------------------------------------------+
| size | 8 | uint64_t | Size of bank in bytes | | size | 8 | uint64_t | Size of memory bank/device region in bytes |
+-----------+--------+----------------+----------------------------------------+ +-----------+--------+----------------+--------------------------------------------+
.. _console_list_struct: .. _console_list_struct:
@ -784,15 +788,15 @@ Console List structure
Console List structure contains information about the available consoles for RMM. Console List structure contains information about the available consoles for RMM.
The members of this structure are shown in the table below: The members of this structure are shown in the table below:
+--------------+--------+----------------+----------------------------------------+ +--------------+--------+----------------+-------------------------------------+
| Name | Offset | Type | Description | | Name | Offset | Type | Description |
+==============+========+================+========================================+ +==============+========+================+=====================================+
| num_consoles | 0 | uint64_t | Number of consoles | | num_consoles | 0 | uint64_t | Number of consoles |
+--------------+--------+----------------+----------------------------------------+ +--------------+--------+----------------+-------------------------------------+
| consoles | 8 | console_info * | Pointer to 'console_info'[] array | | consoles | 8 | console_info * | Pointer to 'console_info'[] array |
+--------------+--------+----------------+----------------------------------------+ +--------------+--------+----------------+-------------------------------------+
| checksum | 16 | uint64_t | Checksum | | checksum | 16 | uint64_t | Checksum |
+--------------+--------+----------------+----------------------------------------+ +--------------+--------+----------------+-------------------------------------+
Checksum is calculated as two's complement sum of 'num_consoles', 'consoles' Checksum is calculated as two's complement sum of 'num_consoles', 'consoles'
pointer and the consoles array pointed by it. pointer and the consoles array pointed by it.
@ -804,28 +808,28 @@ Console Info structure
Console Info structure contains information about each Console available to RMM. Console Info structure contains information about each Console available to RMM.
+-----------+--------+---------------+----------------------------------------+ +-----------+--------+---------------+-----------------------------------------+
| Name | Offset | Type | Description | | Name | Offset | Type | Description |
+===========+========+===============+========================================+ +===========+========+===============+=========================================+
| base | 0 | uintptr_t | Console Base address | | base | 0 | uintptr_t | Console Base address |
+-----------+--------+---------------+----------------------------------------+ +-----------+--------+---------------+-----------------------------------------+
| map_pages | 8 | uint64_t | Num of pages to map for console MMIO | | map_pages | 8 | uint64_t | Num of pages to map for console MMIO |
+-----------+--------+---------------+----------------------------------------+ +-----------+--------+---------------+-----------------------------------------+
| name | 16 | char[] | Name of console | | name | 16 | char[8] | Name of console |
+-----------+--------+---------------+----------------------------------------+ +-----------+--------+---------------+-----------------------------------------+
| clk_in_hz | 24 | uint64_t | UART clock (in hz) for console | | clk_in_hz | 24 | uint64_t | UART clock (in Hz) for console |
+-----------+--------+---------------+----------------------------------------+ +-----------+--------+---------------+-----------------------------------------+
| baud_rate | 32 | uint64_t | Baud rate | | baud_rate | 32 | uint64_t | Baud rate |
+-----------+--------+---------------+----------------------------------------+ +-----------+--------+---------------+-----------------------------------------+
| flags | 40 | uint64_t | Additional flags (RES0) | | flags | 40 | uint64_t | Additional flags (RES0) |
+-----------+--------+---------------+----------------------------------------+ +-----------+--------+---------------+-----------------------------------------+
.. _el3_token_sign_request_struct: .. _el3_token_sign_request_struct:
EL3 Token Sign Request structure EL3 Token Sign Request structure
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This structure represents a realm attestation toekn signing request. This structure represents a realm attestation token signing request.
+-------------+--------+---------------+-----------------------------------------+ +-------------+--------+---------------+-----------------------------------------+
| Name | Offset | Type | Description | | Name | Offset | Type | Description |

View file

@ -7,7 +7,7 @@
* *
* RTSM_VE_AEMv8A.lisa * RTSM_VE_AEMv8A.lisa
* *
* Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2017-2025, ARM Limited and Contributors. All rights reserved.
*/ */
#include <dt-bindings/interrupt-controller/arm-gic.h> #include <dt-bindings/interrupt-controller/arm-gic.h>
@ -249,4 +249,38 @@
<0 0 44 &gic 0 GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>, <0 0 44 &gic 0 GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>,
<0 0 46 &gic 0 GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>; <0 0 46 &gic 0 GIC_SPI 46 IRQ_TYPE_LEVEL_HIGH>;
}; };
#if (ENABLE_RME == 1)
pci: pci@40000000 {
#address-cells = <3>;
#size-cells = <2>;
#interrupt-cells = <1>;
compatible = "pci-host-ecam-generic";
device_type = "pci";
reg = <0x0 0x40000000 0x0 0x10000000>;
ranges = <0x2000000 0x0 0x50000000 0x0 0x50000000 0x0 0x10000000>,
<0x2000000 0x40 0x00000000 0x40 0x00000000 0x40 0x00000000>;
interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 2 &gic 0 0 GIC_SPI 169 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 3 &gic 0 0 GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>,
<0 0 0 4 &gic 0 0 GIC_SPI 171 IRQ_TYPE_LEVEL_HIGH>;
interrupt-map-mask = <0x0 0x0 0x0 0x7>;
msi-map = <0x0 &its 0x0 0x10000>;
iommu-map = <0x0 &smmu 0x0 0x10000>;
dma-coherent;
};
smmu: iommu@2b400000 {
compatible = "arm,smmu-v3";
reg = <0x0 0x2b400000 0x0 0x100000>;
interrupts = <GIC_SPI 74 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 79 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 75 IRQ_TYPE_EDGE_RISING>,
<GIC_SPI 77 IRQ_TYPE_EDGE_RISING>;
interrupt-names = "eventq", "gerror", "priq", "cmdq-sync";
dma-coherent;
#iommu-cells = <1>;
msi-parent = <&its 0x10000>;
};
#endif /* ENABLE_RME */
}; };

View file

@ -49,6 +49,8 @@ int fdtw_for_each_cpu(const void *fdt,
int fdtw_find_or_add_subnode(void *fdt, int parentoffset, const char *name); int fdtw_find_or_add_subnode(void *fdt, int parentoffset, const char *name);
uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells);
static inline uint32_t fdt_blob_size(const void *dtb) static inline uint32_t fdt_blob_size(const void *dtb)
{ {
const uint32_t *dtb_header = (const uint32_t *)dtb; const uint32_t *dtb_header = (const uint32_t *)dtb;

View file

@ -246,6 +246,9 @@ MEASURED_BOOT
/* Number of DRAM banks */ /* Number of DRAM banks */
#define ARM_DRAM_NUM_BANKS 2UL #define ARM_DRAM_NUM_BANKS 2UL
/* Number of PCIe memory regions */
#define ARM_PCI_NUM_REGIONS 2UL
#define ARM_IRQ_SEC_PHY_TIMER 29 #define ARM_IRQ_SEC_PHY_TIMER 29
#define ARM_IRQ_SEC_SGI_0 8 #define ARM_IRQ_SEC_SGI_0 8

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2022-2024, Arm Limited. All rights reserved. * Copyright (c) 2022-2025, Arm Limited. All rights reserved.
* *
* SPDX-License-Identifier: BSD-3-Clause * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -14,7 +14,7 @@
#include <lib/cassert.h> #include <lib/cassert.h>
#define RMMD_MANIFEST_VERSION_MAJOR U(0) #define RMMD_MANIFEST_VERSION_MAJOR U(0)
#define RMMD_MANIFEST_VERSION_MINOR U(3) #define RMMD_MANIFEST_VERSION_MINOR U(4)
#define RMM_CONSOLE_MAX_NAME_LEN U(8) #define RMM_CONSOLE_MAX_NAME_LEN U(8)
@ -37,29 +37,29 @@
#define RMMD_GET_MANIFEST_VERSION_MINOR(_version) \ #define RMMD_GET_MANIFEST_VERSION_MINOR(_version) \
(_version & 0xFFFF) (_version & 0xFFFF)
/* NS DRAM bank structure */ /* Memory bank/device region structure */
struct ns_dram_bank { struct memory_bank {
uintptr_t base; /* Base address */ uintptr_t base; /* Base address */
uint64_t size; /* Size of bank */ uint64_t size; /* Size of memory bank/device region */
}; };
CASSERT(offsetof(struct ns_dram_bank, base) == 0UL, CASSERT(offsetof(struct memory_bank, base) == 0UL,
rmm_manifest_base_unaligned); rmm_manifest_base_unaligned);
CASSERT(offsetof(struct ns_dram_bank, size) == 8UL, CASSERT(offsetof(struct memory_bank, size) == 8UL,
rmm_manifest_size_unaligned); rmm_manifest_size_unaligned);
/* NS DRAM layout info structure */ /* Memory/device region layout info structure */
struct ns_dram_info { struct memory_info {
uint64_t num_banks; /* Number of NS DRAM banks */ uint64_t num_banks; /* Number of memory banks/device regions */
struct ns_dram_bank *banks; /* Pointer to ns_dram_bank[] */ struct memory_bank *banks; /* Pointer to memory_bank[] */
uint64_t checksum; /* Checksum of ns_dram_info data */ uint64_t checksum; /* Checksum of memory_info data */
}; };
CASSERT(offsetof(struct ns_dram_info, num_banks) == 0UL, CASSERT(offsetof(struct memory_info, num_banks) == 0UL,
rmm_manifest_num_banks_unaligned); rmm_manifest_num_banks_unaligned);
CASSERT(offsetof(struct ns_dram_info, banks) == 8UL, CASSERT(offsetof(struct memory_info, banks) == 8UL,
rmm_manifest_dram_data_unaligned); rmm_manifest_dram_data_unaligned);
CASSERT(offsetof(struct ns_dram_info, checksum) == 16UL, CASSERT(offsetof(struct memory_info, checksum) == 16UL,
rmm_manifest_checksum_unaligned); rmm_manifest_checksum_unaligned);
/* Console info structure */ /* Console info structure */
@ -98,13 +98,18 @@ CASSERT(offsetof(struct console_list, consoles) == 8UL,
CASSERT(offsetof(struct console_list, checksum) == 16UL, CASSERT(offsetof(struct console_list, checksum) == 16UL,
rmm_manifest_console_list_checksum); rmm_manifest_console_list_checksum);
/* Boot manifest core structure as per v0.3 */ /* Boot manifest core structure as per v0.4 */
struct rmm_manifest { struct rmm_manifest {
uint32_t version; /* Manifest version */ uint32_t version; /* Manifest version */
uint32_t padding; /* RES0 */ uint32_t padding; /* RES0 */
uintptr_t plat_data; /* Manifest platform data */ uintptr_t plat_data; /* Manifest platform data */
struct ns_dram_info plat_dram; /* Platform NS DRAM data (v0.2) */ /* Platform NS DRAM data (v0.2) */
struct console_list plat_console; /* Platform console list (v0.3) */ struct memory_info plat_dram;
/* Platform console list (v0.3) */
struct console_list plat_console;
/* Platform device address ranges (v0.4) */
struct memory_info plat_ncoh_region;
struct memory_info plat_coh_region;
}; };
CASSERT(offsetof(struct rmm_manifest, version) == 0UL, CASSERT(offsetof(struct rmm_manifest, version) == 0UL,
@ -115,5 +120,9 @@ CASSERT(offsetof(struct rmm_manifest, plat_dram) == 16UL,
rmm_manifest_plat_dram_unaligned); rmm_manifest_plat_dram_unaligned);
CASSERT(offsetof(struct rmm_manifest, plat_console) == 40UL, CASSERT(offsetof(struct rmm_manifest, plat_console) == 40UL,
rmm_manifest_plat_console_unaligned); rmm_manifest_plat_console_unaligned);
CASSERT(offsetof(struct rmm_manifest, plat_ncoh_region) == 64UL,
rmm_manifest_plat_ncoh_region_unaligned);
CASSERT(offsetof(struct rmm_manifest, plat_coh_region) == 88UL,
rmm_manifest_plat_coh_region_unaligned);
#endif /* RMM_CORE_MANIFEST_H */ #endif /* RMM_CORE_MANIFEST_H */

View file

@ -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 * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -18,7 +18,8 @@ struct gicv3_config_t gicv3_config;
struct hw_topology_t soc_topology; struct hw_topology_t soc_topology;
struct uart_serial_config_t uart_serial_config; struct uart_serial_config_t uart_serial_config;
struct cpu_timer_t cpu_timer; 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 * Each NS DRAM bank entry is 'reg' node property which is
@ -27,6 +28,7 @@ struct ns_dram_layout dram_layout;
#define DRAM_ENTRY_SIZE (4UL * sizeof(uint32_t)) #define DRAM_ENTRY_SIZE (4UL * sizeof(uint32_t))
CASSERT(ARM_DRAM_NUM_BANKS == 2UL, ARM_DRAM_NUM_BANKS_mismatch); 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) #define ILLEGAL_ADDR ULL(~0)
@ -352,8 +354,98 @@ int fconf_populate_dram_layout(uintptr_t config)
return 0; 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, gicv3_config, fconf_populate_gicv3_config);
FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology); 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, uart_config, fconf_populate_uart_config);
FCONF_REGISTER_POPULATOR(HW_CONFIG, cpu_timer, fconf_populate_cpu_timer); 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, dram_layout, fconf_populate_dram_layout);
FCONF_REGISTER_POPULATOR(HW_CONFIG, pci_props, fconf_populate_pci_props);

View file

@ -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 * SPDX-License-Identifier: BSD-3-Clause
*/ */
@ -34,12 +34,11 @@
#define FVP_GICV2 1 #define FVP_GICV2 1
#define FVP_GICV3 2 #define FVP_GICV3 2
/* Defines for RMM Console*/ /* Defines for RMM Console */
#define FVP_RMM_CONSOLE_BASE UL(0x1c0c0000) #define FVP_RMM_CONSOLE_BASE UL(0x1c0c0000)
#define FVP_RMM_CONSOLE_BAUD UL(115200) #define FVP_RMM_CONSOLE_BAUD UL(115200)
#define FVP_RMM_CONSOLE_CLK_IN_HZ UL(14745600) #define FVP_RMM_CONSOLE_CLK_IN_HZ UL(14745600)
#define FVP_RMM_CONSOLE_NAME "pl011" #define FVP_RMM_CONSOLE_NAME "pl011"
#define FVP_RMM_CONSOLE_COUNT UL(1) #define FVP_RMM_CONSOLE_COUNT UL(1)
/******************************************************************************* /*******************************************************************************
@ -591,11 +590,78 @@ static uint64_t checksum_calc(uint64_t *buffer, size_t size)
return sum; 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) int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
{ {
uint64_t checksum, num_banks, num_consoles; 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; struct console_info *console_ptr;
assert(manifest != NULL); assert(manifest != NULL);
@ -607,71 +673,45 @@ int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
/* Set number of consoles */ /* Set number of consoles */
num_consoles = FVP_RMM_CONSOLE_COUNT; 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->version = RMMD_MANIFEST_VERSION;
manifest->padding = 0U; /* RES0 */ manifest->padding = 0U; /* RES0 */
manifest->plat_data = (uintptr_t)NULL; manifest->plat_data = 0UL;
manifest->plat_dram.num_banks = num_banks; manifest->plat_dram.num_banks = num_banks;
manifest->plat_console.num_consoles = num_consoles; manifest->plat_console.num_consoles = num_consoles;
manifest->plat_ncoh_region.num_banks = num_ncoh_regions;
/* /* FVP does not support device coherent address ranges */
* Boot Manifest structure illustration, with two dram banks and num_coh_regions = 0UL;
* a single console. manifest->plat_coh_region.num_banks = num_coh_regions;
* manifest->plat_coh_region.banks = NULL;
* +----------------------------------------+ manifest->plat_coh_region.checksum = 0UL;
* | 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 | |
* +--------+----------------+--------------+
*/
bank_ptr = (struct ns_dram_bank *) bank_ptr = (struct memory_bank *)
(((uintptr_t)manifest) + sizeof(*manifest)); (((uintptr_t)manifest) + sizeof(struct rmm_manifest));
console_ptr = (struct console_info *) 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_dram.banks = bank_ptr;
manifest->plat_console.consoles = console_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 */ /* Ensure the manifest is not larger than the shared buffer */
assert((sizeof(struct rmm_manifest) + assert((sizeof(struct rmm_manifest) +
(sizeof(struct console_info) * manifest->plat_console.num_consoles) + (sizeof(struct memory_bank) *
(sizeof(struct ns_dram_bank) * manifest->plat_dram.num_banks)) <= ARM_EL3_RMM_SHARED_SIZE); 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 */ /* Calculate checksum of plat_dram structure */
checksum = num_banks + (uint64_t)bank_ptr; checksum = num_banks + (uint64_t)bank_ptr;
@ -683,31 +723,56 @@ int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
} }
/* Update checksum */ /* 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 */ /* Checksum must be 0 */
manifest->plat_dram.checksum = ~checksum + 1UL; 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; checksum = num_consoles + (uint64_t)console_ptr;
/* Zero out the console info struct */ /* 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].base = FVP_RMM_CONSOLE_BASE;
console_ptr[0].map_pages = 1UL; console_ptr[0].map_pages = 1UL;
console_ptr[0].clk_in_hz = FVP_RMM_CONSOLE_CLK_IN_HZ; console_ptr[0].clk_in_hz = FVP_RMM_CONSOLE_CLK_IN_HZ;
console_ptr[0].baud_rate = FVP_RMM_CONSOLE_BAUD; 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 */ /* Update checksum */
checksum += checksum_calc((uint64_t *)console_ptr, checksum += checksum_calc((uint64_t *)console_ptr,
sizeof(struct console_info) * num_consoles); sizeof(struct console_info) * num_consoles);
/* Checksum must be 0 */ /* Checksum must be 0 */
manifest->plat_console.checksum = ~checksum + 1UL; 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; return 0;
} }
#endif /* ENABLE_RME */ #endif /* ENABLE_RME */

View file

@ -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 * 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__uart_serial_config_getter(prop) uart_serial_config.prop
#define hw_config__cpu_timer_getter(prop) cpu_timer.prop #define hw_config__cpu_timer_getter(prop) cpu_timer.prop
#define hw_config__dram_layout_getter(prop) dram_layout.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 { struct gicv3_config_t {
uint64_t gicd_base; uint64_t gicd_base;
@ -40,9 +41,16 @@ struct cpu_timer_t {
uint32_t clock_freq; uint32_t clock_freq;
}; };
struct ns_dram_layout { struct dram_layout_t {
uint64_t num_banks; 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); int fconf_populate_gicv3_config(uintptr_t config);
@ -50,11 +58,13 @@ int fconf_populate_topology(uintptr_t config);
int fconf_populate_uart_config(uintptr_t config); int fconf_populate_uart_config(uintptr_t config);
int fconf_populate_cpu_timer(uintptr_t config); int fconf_populate_cpu_timer(uintptr_t config);
int fconf_populate_dram_layout(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 gicv3_config_t gicv3_config;
extern struct hw_topology_t soc_topology; extern struct hw_topology_t soc_topology;
extern struct uart_serial_config_t uart_serial_config; extern struct uart_serial_config_t uart_serial_config;
extern struct cpu_timer_t cpu_timer; 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 */ #endif /* FCONF_HW_CONFIG_GETTER_H */

View file

@ -64,7 +64,7 @@ static uint64_t checksum_calc(uint64_t *buffer, size_t size)
int plat_rmmd_load_manifest(struct rmm_manifest *manifest) int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
{ {
uint64_t checksum, num_banks, num_consoles; uint64_t checksum, num_banks, num_consoles;
struct ns_dram_bank *bank_ptr; struct memory_bank *bank_ptr;
struct console_info *console_ptr; struct console_info *console_ptr;
assert(manifest != NULL); assert(manifest != NULL);
@ -129,7 +129,7 @@ int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
* +--------+----------------+--------------+ * +--------+----------------+--------------+
*/ */
bank_ptr = (struct ns_dram_bank *) bank_ptr = (struct memory_bank *)
(((uintptr_t)manifest) + sizeof(*manifest)); (((uintptr_t)manifest) + sizeof(*manifest));
console_ptr = (struct console_info *) console_ptr = (struct console_info *)
((uintptr_t)bank_ptr + (num_banks * sizeof(*bank_ptr))); ((uintptr_t)bank_ptr + (num_banks * sizeof(*bank_ptr)));
@ -141,7 +141,7 @@ int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
assert((sizeof(struct rmm_manifest) + assert((sizeof(struct rmm_manifest) +
(sizeof(struct console_info) * (sizeof(struct console_info) *
manifest->plat_console.num_consoles) + 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); <= ARM_EL3_RMM_SHARED_SIZE);
/* Calculate checksum of plat_dram structure */ /* Calculate checksum of plat_dram structure */
@ -156,7 +156,7 @@ int plat_rmmd_load_manifest(struct rmm_manifest *manifest)
/* Update checksum */ /* Update checksum */
checksum += checksum_calc((uint64_t *)bank_ptr, checksum += checksum_calc((uint64_t *)bank_ptr,
sizeof(struct ns_dram_bank) * num_banks); sizeof(struct memory_bank) * num_banks);
/* Checksum must be 0 */ /* Checksum must be 0 */
manifest->plat_dram.checksum = ~checksum + 1UL; manifest->plat_dram.checksum = ~checksum + 1UL;