From bef44f60edaa763031bce6144c0267aefbb1f2bf Mon Sep 17 00:00:00 2001 From: AlexeiFedorov Date: Mon, 14 Oct 2024 15:23:34 +0100 Subject: [PATCH] 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 --- common/fdt_wrappers.c | 2 +- docs/components/rmm-el3-comms-spec.rst | 130 ++++++------ fdts/fvp-base-psci-common.dtsi | 36 +++- include/common/fdt_wrappers.h | 2 + include/plat/arm/common/arm_def.h | 3 + include/services/rmm_core_manifest.h | 45 +++-- .../board/fvp/fconf/fconf_hw_config_getter.c | 96 ++++++++- plat/arm/board/fvp/fvp_common.c | 191 ++++++++++++------ .../fvp/include/fconf_hw_config_getter.h | 18 +- .../neoverse_rd/platform/rdv3/rdv3_common.c | 8 +- 10 files changed, 375 insertions(+), 156 deletions(-) diff --git a/common/fdt_wrappers.c b/common/fdt_wrappers.c index b213ffa47..863835154 100644 --- a/common/fdt_wrappers.c +++ b/common/fdt_wrappers.c @@ -277,7 +277,7 @@ int fdtw_write_inplace_bytes(void *dtb, int node, const char *prop, 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]); diff --git a/docs/components/rmm-el3-comms-spec.rst b/docs/components/rmm-el3-comms-spec.rst index 79e1d2cdf..f1ca031f7 100644 --- a/docs/components/rmm-el3-comms-spec.rst +++ b/docs/components/rmm-el3-comms-spec.rst @@ -53,7 +53,7 @@ are explained below: 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 -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: @@ -182,12 +182,12 @@ platform information. This Boot Manifest is versioned independently of the Boot Interface, to help 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. -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 document. These data are optional and can be NULL. - plat_dram : Structure encoding the NS DRAM information on the platform. This @@ -720,61 +720,65 @@ _____ RMM-EL3 Boot Manifest structure ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The RMM-EL3 Boot Manifest v0.3 structure contains platform boot information passed -from EL3 to RMM. The size of the Boot Manifest is 64 bytes. +The RMM-EL3 Boot Manifest v0.4 structure contains platform boot information passed +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 table: -+--------------+--------+----------------+----------------------------------------+ -| Name | Offset | Type | Description | -+==============+========+================+========================================+ -| version | 0 | uint32_t | Boot Manifest version | -+--------------+--------+----------------+----------------------------------------+ -| padding | 4 | uint32_t | Reserved, set to 0 | -+--------------+--------+----------------+----------------------------------------+ -| plat_data | 8 | uintptr_t | Pointer to Platform Data section | -+--------------+--------+----------------+----------------------------------------+ -| plat_dram | 16 | ns_dram_info | NS DRAM Layout Info structure | -+--------------+--------+----------------+----------------------------------------+ -| plat_console | 40 | console_list | List of consoles available to RMM | -+--------------+--------+----------------+----------------------------------------+ ++--------------------+--------+-------------------+----------------------------------------------+ +| Name | Offset | Type | Description | ++====================+========+===================+==============================================+ +| version | 0 | uint32_t | Boot Manifest version | ++--------------------+--------+-------------------+----------------------------------------------+ +| padding | 4 | uint32_t | Reserved, set to 0 | ++--------------------+--------+-------------------+----------------------------------------------+ +| plat_data | 8 | uintptr_t | Pointer to Platform Data section | ++--------------------+--------+-------------------+----------------------------------------------+ +| plat_dram | 16 | memory_info | NS DRAM Layout Info structure | ++--------------------+--------+-------------------+----------------------------------------------+ +| 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 -DRAM layout. The members of this structure are shown in the table below: +Memory Info structure contains information about platform memory layout. +The members of this structure are shown in the table below: +-----------+--------+----------------+----------------------------------------+ | 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 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 | -+===========+========+================+========================================+ -| base | 0 | uintptr_t | Base address | -+-----------+--------+----------------+----------------------------------------+ -| size | 8 | uint64_t | Size of bank in bytes | -+-----------+--------+----------------+----------------------------------------+ ++-----------+--------+----------------+--------------------------------------------+ +| Name | Offset | Type | Description | ++===========+========+================+============================================+ +| base | 0 | uintptr_t | Base address | ++-----------+--------+----------------+--------------------------------------------+ +| size | 8 | uint64_t | Size of memory bank/device region in bytes | ++-----------+--------+----------------+--------------------------------------------+ .. _console_list_struct: @@ -784,15 +788,15 @@ Console List structure Console List structure contains information about the available consoles for RMM. The members of this structure are shown in the table below: -+--------------+--------+----------------+----------------------------------------+ -| Name | Offset | Type | Description | -+==============+========+================+========================================+ -| num_consoles | 0 | uint64_t | Number of consoles | -+--------------+--------+----------------+----------------------------------------+ -| consoles | 8 | console_info * | Pointer to 'console_info'[] array | -+--------------+--------+----------------+----------------------------------------+ -| checksum | 16 | uint64_t | Checksum | -+--------------+--------+----------------+----------------------------------------+ ++--------------+--------+----------------+-------------------------------------+ +| Name | Offset | Type | Description | ++==============+========+================+=====================================+ +| num_consoles | 0 | uint64_t | Number of consoles | ++--------------+--------+----------------+-------------------------------------+ +| consoles | 8 | console_info * | Pointer to 'console_info'[] array | ++--------------+--------+----------------+-------------------------------------+ +| checksum | 16 | uint64_t | Checksum | ++--------------+--------+----------------+-------------------------------------+ Checksum is calculated as two's complement sum of 'num_consoles', 'consoles' 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. -+-----------+--------+---------------+----------------------------------------+ -| Name | Offset | Type | Description | -+===========+========+===============+========================================+ -| base | 0 | uintptr_t | Console Base address | -+-----------+--------+---------------+----------------------------------------+ -| map_pages | 8 | uint64_t | Num of pages to map for console MMIO | -+-----------+--------+---------------+----------------------------------------+ -| name | 16 | char[] | Name of console | -+-----------+--------+---------------+----------------------------------------+ -| clk_in_hz | 24 | uint64_t | UART clock (in hz) for console | -+-----------+--------+---------------+----------------------------------------+ -| baud_rate | 32 | uint64_t | Baud rate | -+-----------+--------+---------------+----------------------------------------+ -| flags | 40 | uint64_t | Additional flags (RES0) | -+-----------+--------+---------------+----------------------------------------+ ++-----------+--------+---------------+-----------------------------------------+ +| Name | Offset | Type | Description | ++===========+========+===============+=========================================+ +| base | 0 | uintptr_t | Console Base address | ++-----------+--------+---------------+-----------------------------------------+ +| map_pages | 8 | uint64_t | Num of pages to map for console MMIO | ++-----------+--------+---------------+-----------------------------------------+ +| name | 16 | char[8] | Name of console | ++-----------+--------+---------------+-----------------------------------------+ +| clk_in_hz | 24 | uint64_t | UART clock (in Hz) for console | ++-----------+--------+---------------+-----------------------------------------+ +| baud_rate | 32 | uint64_t | Baud rate | ++-----------+--------+---------------+-----------------------------------------+ +| flags | 40 | uint64_t | Additional flags (RES0) | ++-----------+--------+---------------+-----------------------------------------+ .. _el3_token_sign_request_struct: 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 | diff --git a/fdts/fvp-base-psci-common.dtsi b/fdts/fvp-base-psci-common.dtsi index 583bba70e..ff3a6ba27 100644 --- a/fdts/fvp-base-psci-common.dtsi +++ b/fdts/fvp-base-psci-common.dtsi @@ -7,7 +7,7 @@ * * 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 @@ -249,4 +249,38 @@ <0 0 44 &gic 0 GIC_SPI 44 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 = , + , + , + ; + interrupt-names = "eventq", "gerror", "priq", "cmdq-sync"; + dma-coherent; + #iommu-cells = <1>; + msi-parent = <&its 0x10000>; + }; +#endif /* ENABLE_RME */ }; diff --git a/include/common/fdt_wrappers.h b/include/common/fdt_wrappers.h index de08f1db5..7f6af59c8 100644 --- a/include/common/fdt_wrappers.h +++ b/include/common/fdt_wrappers.h @@ -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); +uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells); + static inline uint32_t fdt_blob_size(const void *dtb) { const uint32_t *dtb_header = (const uint32_t *)dtb; diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index 55b44b185..073c157e5 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -246,6 +246,9 @@ MEASURED_BOOT /* Number of DRAM banks */ #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_SGI_0 8 diff --git a/include/services/rmm_core_manifest.h b/include/services/rmm_core_manifest.h index 6b57267d8..2d6e71f09 100644 --- a/include/services/rmm_core_manifest.h +++ b/include/services/rmm_core_manifest.h @@ -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 */ @@ -14,7 +14,7 @@ #include #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) @@ -37,29 +37,29 @@ #define RMMD_GET_MANIFEST_VERSION_MINOR(_version) \ (_version & 0xFFFF) -/* NS DRAM bank structure */ -struct ns_dram_bank { +/* Memory bank/device region structure */ +struct memory_bank { 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); -CASSERT(offsetof(struct ns_dram_bank, size) == 8UL, +CASSERT(offsetof(struct memory_bank, size) == 8UL, rmm_manifest_size_unaligned); -/* NS DRAM layout info structure */ -struct ns_dram_info { - uint64_t num_banks; /* Number of NS DRAM banks */ - struct ns_dram_bank *banks; /* Pointer to ns_dram_bank[] */ - uint64_t checksum; /* Checksum of ns_dram_info data */ +/* Memory/device region layout info structure */ +struct memory_info { + uint64_t num_banks; /* Number of memory banks/device regions */ + struct memory_bank *banks; /* Pointer to memory_bank[] */ + 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); -CASSERT(offsetof(struct ns_dram_info, banks) == 8UL, +CASSERT(offsetof(struct memory_info, banks) == 8UL, rmm_manifest_dram_data_unaligned); -CASSERT(offsetof(struct ns_dram_info, checksum) == 16UL, +CASSERT(offsetof(struct memory_info, checksum) == 16UL, rmm_manifest_checksum_unaligned); /* Console info structure */ @@ -98,13 +98,18 @@ CASSERT(offsetof(struct console_list, consoles) == 8UL, CASSERT(offsetof(struct console_list, checksum) == 16UL, rmm_manifest_console_list_checksum); -/* Boot manifest core structure as per v0.3 */ +/* Boot manifest core structure as per v0.4 */ struct rmm_manifest { uint32_t version; /* Manifest version */ uint32_t padding; /* RES0 */ uintptr_t plat_data; /* Manifest platform data */ - struct ns_dram_info plat_dram; /* Platform NS DRAM data (v0.2) */ - struct console_list plat_console; /* Platform console list (v0.3) */ + /* Platform NS DRAM data (v0.2) */ + 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, @@ -115,5 +120,9 @@ CASSERT(offsetof(struct rmm_manifest, plat_dram) == 16UL, rmm_manifest_plat_dram_unaligned); CASSERT(offsetof(struct rmm_manifest, plat_console) == 40UL, 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 */ 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 43dc17bc8..662b8a464 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 gicv3_config_t gicv3_config; 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 @@ struct ns_dram_layout dram_layout; #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 @@ int fconf_populate_dram_layout(uintptr_t config) 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 bdc2cacfb..19a340f2a 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 @@ static uint64_t checksum_calc(uint64_t *buffer, size_t size) 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 @@ int plat_rmmd_load_manifest(struct rmm_manifest *manifest) /* 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 @@ int plat_rmmd_load_manifest(struct rmm_manifest *manifest) } /* 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 b7a124726..351f13d82 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 @@ struct cpu_timer_t { 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_topology(uintptr_t config); 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 3ef9681e1..2402c0556 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 @@ static uint64_t checksum_calc(uint64_t *buffer, size_t size) 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 @@ 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)); console_ptr = (struct console_info *) ((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) + (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 @@ int plat_rmmd_load_manifest(struct rmm_manifest *manifest) /* 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;