diff options
33 files changed, 421 insertions, 51 deletions
diff --git a/docs/components/el3-spmc.rst b/docs/components/el3-spmc.rst index b461eeff4..d2042f7b0 100644 --- a/docs/components/el3-spmc.rst +++ b/docs/components/el3-spmc.rst @@ -84,15 +84,18 @@ Platform Guide - plat_spmc_shmem_begin - plat_spmc_shmem_reclaim + - plat_spmc_rxtx_validate SPMC provides platform hooks related to memory management interfaces. +Platforms enabling ``SPMC_AT_EL3`` must implement all the hooks. These hooks can be used for platform specific implementations such as managing access control, programming TZ Controllers or MPUs, and validating ownership and security state of memory regions supplied -through FFA_MEM_SHARE and FFA_MEM_LEND requests. +during FF-A ABI calls such as FFA_RXTX_MAP, FFA_MEM_SHARE and +FFA_MEM_LEND requests. Platform implementations are expected to ensure that memory regions -accepted for sharing or lending comply with the platform security model +provided for FF-A ABI calls comply with the platform security model and enforce any ownership, access control, and security-state checks required by the platform. diff --git a/docs/plat/nxp/nbxv3.rst b/docs/plat/nxp/nbxv3.rst index 44d65faf2..d0e977fda 100644 --- a/docs/plat/nxp/nbxv3.rst +++ b/docs/plat/nxp/nbxv3.rst @@ -87,6 +87,38 @@ U-Boot + kernel + ramdisk. Smaller manifests provision faster over the JTAG semihosting link. The schema is documented in ``plat/nxp/soc-lx2160a/nbxv3/MANIFEST.md``. +RCW build stamp (PBL -> BL2) +---------------------------- + +The RCW carries no version which prevents the software identification. +On this board, this identification is set into one of the LX2160A DCFG +general-purpose scratch registers, ``SCRATCHRW13``. + +The PBI command block embedded in the PBL writes it while the boot +Service Processor processes the RCW, and the DCFG +``SCRATCHRW`` registers survive the hand-off to BL2 (they are cleared +only by a power-on reset). + +The 32-bit word is packed, all-BCD:: + + 31 28 27 24 23 16 15 8 7 0 + +-------+-------+-------+-------+-------+ + |CARRIER| TAG | YY | MM | DD | all BCD + +-------+-------+-------+-------+-------+ + +- **CARRIER** identifies the carrier board the CPU module is plugged into. +- **TAG** is a fixed marker, ``0xB`` +- **YY / MM / DD** are the RCW build date in BCD + +The first boot lines based on the RCW shall be some of the following:: + + NOTICE Iliad nbxv32 RCW v.20260820 + NOTICE Iliad nbxv3 (bring-up, no IO) RCW v.20260820 + +This pairs with the ``MEM_PLL_RAT`` probe: that register tells BL2 +*whether* a production RCW is live, while ``SCRATCHRW13`` tells it +*which* one, and on *which* carrier. + Board policy deviations from the LX2160A reference boards --------------------------------------------------------- @@ -106,12 +138,19 @@ Board policy deviations from the LX2160A reference boards Building -------- +The ``fip_ddr`` target packs the Synopsys DDR PHY training firmware. +Get it using a NXP clone of ``ddr-phy-binary`` repository into the TF-A +root so the default ``DDR_PHY_BIN_PATH`` (``./ddr-phy-binary/lx2160a``) +resolves:: + + git clone https://github.com/NXP/ddr-phy-binary + Production XIP BL2 + FIP (embedded in the PBL at NOR offset 0x9000): .. code:: shell make PLAT=nbxv3 BOOT_MODE=flexspi_nor RCW=$RCW_BIN BL33=$UBOOT_BIN \ - pbl fip fip-ddr + pbl fip fip_ddr Bootstrap BL2 (build, loaded by OpenOCD into OCRAM, resolves staged images over ARM semihosting): diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index 06edd7ff4..5d6b644f2 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -492,6 +492,8 @@ struct ffa_mtd; int plat_spmc_shmem_datastore_get(uint8_t **datastore, size_t *size); int plat_spmc_shmem_begin(struct ffa_mtd *desc); int plat_spmc_shmem_reclaim(struct ffa_mtd *desc); +bool plat_spmc_rxtx_validate(uintptr_t rx_address, uintptr_t tx_address, + size_t buffer_size); #endif /******************************************************************************* diff --git a/plat/altera/soc/agilex3/platform.mk b/plat/altera/soc/agilex3/platform.mk index 84613a417..a4b3c175e 100644 --- a/plat/altera/soc/agilex3/platform.mk +++ b/plat/altera/soc/agilex3/platform.mk @@ -141,6 +141,11 @@ SOCFPGA_SECURE_VAB_AUTH := 0 $(call assert_boolean,SOCFPGA_SECURE_VAB_AUTH) $(eval $(call add_define,SOCFPGA_SECURE_VAB_AUTH)) +# Configs for UART0/1 Configuration +SOCFPGA_UART_CONFIG := 0 +$(call assert_boolean,SOCFPGA_UART_CONFIG) +$(eval $(call add_define,SOCFPGA_UART_CONFIG)) + PROGRAMMABLE_RESET_ADDRESS := 0 RESET_TO_BL2 := 1 BL2_INV_DCACHE := 0 diff --git a/plat/altera/soc/common/include/platform_def.h b/plat/altera/soc/common/include/platform_def.h index e13662b6b..0eb2b4c27 100644 --- a/plat/altera/soc/common/include/platform_def.h +++ b/plat/altera/soc/common/include/platform_def.h @@ -154,8 +154,13 @@ /******************************************************************************* * UART related constants ******************************************************************************/ +#if SOCFPGA_UART_CONFIG +#define CRASH_CONSOLE_BASE PLAT_UART1_BASE +#define PLAT_INTEL_UART_BASE PLAT_UART1_BASE +#else #define CRASH_CONSOLE_BASE PLAT_UART0_BASE #define PLAT_INTEL_UART_BASE PLAT_UART0_BASE +#endif #define PLAT_BAUDRATE (115200) #define PLAT_UART_CLOCK (100000000) diff --git a/plat/altera/soc/common/soc/socfpga_handoff.c b/plat/altera/soc/common/soc/socfpga_handoff.c index bf5f2bed2..f1d140d1a 100644 --- a/plat/altera/soc/common/soc/socfpga_handoff.c +++ b/plat/altera/soc/common/soc/socfpga_handoff.c @@ -9,6 +9,7 @@ #include <string.h> #include "socfpga_handoff.h" +#include "socfpga_private.h" #define SWAP_UINT32(x) (((x) >> 24) | (((x) & 0x00FF0000) >> 8) | \ (((x) & 0x0000FF00) << 8) | ((x) << 24)) diff --git a/plat/altera/soc/common/soc/socfpga_mailbox.c b/plat/altera/soc/common/soc/socfpga_mailbox.c index 95415245a..df77fc489 100644 --- a/plat/altera/soc/common/soc/socfpga_mailbox.c +++ b/plat/altera/soc/common/soc/socfpga_mailbox.c @@ -90,7 +90,14 @@ static int write_mailbox_cmd_buffer(uint32_t *cin, uint32_t cout, do { if (is_mailbox_cmdbuf_full(*cin)) { + /* + * Intermediate doorbell: Buffer is full. Trigger the + * hardware CIN update and notify SDM, then wait for + * buffer space. + * Only trigger once per fill event. + */ if (!(*is_doorbell_triggered)) { + mmio_write_32(MBOX_OFFSET + MBOX_CIN, *cin); mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U); *is_doorbell_triggered = true; @@ -99,7 +106,6 @@ static int write_mailbox_cmd_buffer(uint32_t *cin, uint32_t cout, } else { mmio_write_32(MBOX_ENTRY_TO_ADDR(CMD, (*cin)++), data); *cin %= MBOX_CMD_BUFFER_SIZE; - mmio_write_32(MBOX_OFFSET + MBOX_CIN, *cin); break; } } while (--timeout != 0U); @@ -154,6 +160,14 @@ static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args, } } + /* + * Final doorbell: Notify SDM that command is complete. + * This is required even if an early doorbell was triggered during + * buffer-full handling, because there is at least one data written + * after SDM consumed the first batch. + * Update CIN before the doorbell so SDM reads complete data. + */ + mmio_write_32(MBOX_OFFSET + MBOX_CIN, cmd_free_offset); mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U); #if SIP_SVC_V3 diff --git a/plat/amd/versal2/aarch64/common.c b/plat/amd/versal2/aarch64/common.c index eb8d2d905..daa060350 100644 --- a/plat/amd/versal2/aarch64/common.c +++ b/plat/amd/versal2/aarch64/common.c @@ -157,3 +157,17 @@ void config_setup(void) /* Configure IPI data */ soc_ipi_config_table_init(); } + +/* + * Versal2-specific implementations of PMC_TAP accessors. + * PMC_TAP is mapped in DEVICE2 at runtime on Versal2, so direct read is safe. + */ +uint32_t get_pmc_tap_idcode(void) +{ + return mmio_read_32(PMC_TAP_IDCODE); +} + +uint32_t get_pmc_tap_version(void) +{ + return mmio_read_32(PMC_TAP_VERSION); +} diff --git a/plat/amd/versal2/include/def.h b/plat/amd/versal2/include/def.h index 2d755f0aa..09dfeff13 100644 --- a/plat/amd/versal2/include/def.h +++ b/plat/amd/versal2/include/def.h @@ -44,6 +44,7 @@ /* For platform detection */ #define PMC_TAP U(0xF11A0000) +#define PMC_TAP_IDCODE PMC_TAP #define PMC_TAP_VERSION (PMC_TAP + 0x4U) # define PMC_VERSION GENMASK(7U, 0U) # define PS_VERSION GENMASK(15U, 8U) @@ -55,6 +56,8 @@ #define PSXC_VSLGEN2_IDCODE U(0x04DB0093) #define PSXC_2VM3654_IDCODE U(0x04D98093) +#define PLAT_SOC_NAME "Versal Gen 2" + /* Global timer reset */ #define PSX_CRF U(0xEC200000) #define ACPU0_CLK_CTRL U(0x10C) diff --git a/plat/amd/versal2/pm_service/pm_svc_main.c b/plat/amd/versal2/pm_service/pm_svc_main.c index 8875f6516..f52700621 100644 --- a/plat/amd/versal2/pm_service/pm_svc_main.c +++ b/plat/amd/versal2/pm_service/pm_svc_main.c @@ -364,11 +364,6 @@ static uintptr_t eemi_psci_debugfs_handler(uint32_t api_id, const uint32_t *pm_a switch (api_val) { - case (uint32_t)PM_SELF_SUSPEND: - ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2], - pm_arg[3], security_flag); - SMC_RET1(handle, (u_register_t)ret); - case (uint32_t)PM_FORCE_POWERDOWN: ret = pm_force_powerdown(pm_arg[0], (uint8_t)pm_arg[1], security_flag); SMC_RET1(handle, (u_register_t)ret); diff --git a/plat/arm/board/fvp/fvp_el3_spmc.c b/plat/arm/board/fvp/fvp_el3_spmc.c index 76b4910ab..251d93f85 100644 --- a/plat/arm/board/fvp/fvp_el3_spmc.c +++ b/plat/arm/board/fvp/fvp_el3_spmc.c @@ -39,3 +39,13 @@ int plat_spmc_shmem_reclaim(struct ffa_mtd *desc) { return 0; } + +/* + * Allow the platform to validate the memory regions supplied for the + * RX/TX buffers. + */ +bool plat_spmc_rxtx_validate(uintptr_t rx_address, uintptr_t tx_address, + size_t buffer_size) +{ + return true; +} diff --git a/plat/arm/board/juno/juno_el3_spmc.c b/plat/arm/board/juno/juno_el3_spmc.c index c3acaf295..333c0cd8e 100644 --- a/plat/arm/board/juno/juno_el3_spmc.c +++ b/plat/arm/board/juno/juno_el3_spmc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2026, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -37,6 +37,16 @@ int plat_spmc_shmem_reclaim(struct ffa_mtd *desc) return 0; } +/* + * Allow the platform to validate the memory regions supplied for the + * RX/TX buffers. + */ +bool plat_spmc_rxtx_validate(uintptr_t rx_address, uintptr_t tx_address, + size_t buffer_size) +{ + return true; +} + int plat_spmd_handle_group0_interrupt(uint32_t intid) { /* @@ -46,4 +56,3 @@ int plat_spmd_handle_group0_interrupt(uint32_t intid) (void)intid; return -1; } - diff --git a/plat/arm/board/neoverse_rd/platform/rdn2/rdn2_plat.c b/plat/arm/board/neoverse_rd/platform/rdn2/rdn2_plat.c index 6310e361e..3ecf92580 100644 --- a/plat/arm/board/neoverse_rd/platform/rdn2/rdn2_plat.c +++ b/plat/arm/board/neoverse_rd/platform/rdn2/rdn2_plat.c @@ -225,6 +225,16 @@ int plat_spmc_shmem_reclaim(struct ffa_mtd *desc) return 0; } +/* + * Allow the platform to validate the memory regions supplied for the + * RX/TX buffers. + */ +bool plat_spmc_rxtx_validate(uintptr_t rx_address, uintptr_t tx_address, + size_t buffer_size) +{ + return true; +} + int plat_spmd_handle_group0_interrupt(uint32_t intid) { /* diff --git a/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/plat/hisilicon/hikey960/hikey960_bl31_setup.c index c189f91aa..f98186889 100644 --- a/plat/hisilicon/hikey960/hikey960_bl31_setup.c +++ b/plat/hisilicon/hikey960/hikey960_bl31_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2024, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2017-2026, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -211,6 +211,16 @@ int plat_spmc_shmem_reclaim(struct ffa_mtd *desc) return 0; } +/* + * Allow the platform to validate the memory regions supplied for the + * RX/TX buffers. + */ +bool plat_spmc_rxtx_validate(uintptr_t rx_address, uintptr_t tx_address, + size_t buffer_size) +{ + return true; +} + #endif void bl31_platform_setup(void) diff --git a/plat/intel/soc/agilex/platform.mk b/plat/intel/soc/agilex/platform.mk index 184cc842d..ff3f382cb 100644 --- a/plat/intel/soc/agilex/platform.mk +++ b/plat/intel/soc/agilex/platform.mk @@ -1,7 +1,7 @@ # # Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved. # Copyright (c) 2019-2023, Intel Corporation. All rights reserved. -# Copyright (c) 2024-2025, Altera Corporation. All rights reserved. +# Copyright (c) 2024-2026, Altera Corporation. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -112,6 +112,11 @@ SOCFPGA_SECURE_VAB_AUTH := 0 $(call assert_boolean,SOCFPGA_SECURE_VAB_AUTH) $(eval $(call add_define,SOCFPGA_SECURE_VAB_AUTH)) +# Configs for UART0/1 Configuration +SOCFPGA_UART_CONFIG := 0 +$(call assert_boolean,SOCFPGA_UART_CONFIG) +$(eval $(call add_define,SOCFPGA_UART_CONFIG)) + PROGRAMMABLE_RESET_ADDRESS := 0 RESET_TO_BL2 := 1 BL2_INV_DCACHE := 0 diff --git a/plat/intel/soc/agilex5/platform.mk b/plat/intel/soc/agilex5/platform.mk index 546263bbe..3a3f2167f 100644 --- a/plat/intel/soc/agilex5/platform.mk +++ b/plat/intel/soc/agilex5/platform.mk @@ -1,7 +1,7 @@ # # Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. # Copyright (c) 2019-2023, Intel Corporation. All rights reserved. -# Copyright (c) 2024-2025, Altera Corporation. All rights reserved. +# Copyright (c) 2024-2026, Altera Corporation. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -142,6 +142,11 @@ SOCFPGA_SECURE_VAB_AUTH := 0 $(call assert_boolean,SOCFPGA_SECURE_VAB_AUTH) $(eval $(call add_define,SOCFPGA_SECURE_VAB_AUTH)) +# Configs for UART0/1 Configuration +SOCFPGA_UART_CONFIG := 0 +$(call assert_boolean,SOCFPGA_UART_CONFIG) +$(eval $(call add_define,SOCFPGA_UART_CONFIG)) + PROGRAMMABLE_RESET_ADDRESS := 0 RESET_TO_BL2 := 1 BL2_INV_DCACHE := 0 diff --git a/plat/intel/soc/common/include/platform_def.h b/plat/intel/soc/common/include/platform_def.h index 6325d3521..ec3fab0d8 100644 --- a/plat/intel/soc/common/include/platform_def.h +++ b/plat/intel/soc/common/include/platform_def.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2019-2023, Intel Corporation. All rights reserved. - * Copyright (c) 2024-2025, Altera Corporation. All rights reserved. + * Copyright (c) 2024-2026, Altera Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -152,8 +152,13 @@ /******************************************************************************* * UART related constants ******************************************************************************/ +#if SOCFPGA_UART_CONFIG +#define CRASH_CONSOLE_BASE PLAT_UART1_BASE +#define PLAT_INTEL_UART_BASE PLAT_UART1_BASE +#else #define CRASH_CONSOLE_BASE PLAT_UART0_BASE #define PLAT_INTEL_UART_BASE PLAT_UART0_BASE +#endif #define PLAT_BAUDRATE (115200) #define PLAT_UART_CLOCK (100000000) diff --git a/plat/intel/soc/common/soc/socfpga_mailbox.c b/plat/intel/soc/common/soc/socfpga_mailbox.c index cf494d681..aecc5d2f5 100644 --- a/plat/intel/soc/common/soc/socfpga_mailbox.c +++ b/plat/intel/soc/common/soc/socfpga_mailbox.c @@ -90,7 +90,14 @@ static int write_mailbox_cmd_buffer(uint32_t *cin, uint32_t cout, do { if (is_mailbox_cmdbuf_full(*cin)) { + /* + * Intermediate doorbell: Buffer is full. Trigger the + * hardware CIN update and notify SDM, then wait for + * buffer space. + * Only trigger once per fill event. + */ if (!(*is_doorbell_triggered)) { + mmio_write_32(MBOX_OFFSET + MBOX_CIN, *cin); mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U); *is_doorbell_triggered = true; @@ -99,7 +106,6 @@ static int write_mailbox_cmd_buffer(uint32_t *cin, uint32_t cout, } else { mmio_write_32(MBOX_ENTRY_TO_ADDR(CMD, (*cin)++), data); *cin %= MBOX_CMD_BUFFER_SIZE; - mmio_write_32(MBOX_OFFSET + MBOX_CIN, *cin); break; } } while (--timeout != 0U); @@ -154,6 +160,14 @@ static int fill_mailbox_circular_buffer(uint32_t header_cmd, uint32_t *args, } } + /* + * Final doorbell: Notify SDM that command is complete. + * This is required even if an early doorbell was triggered during + * buffer-full handling, because there is at least one data written + * after SDM consumed the first batch. + * Update CIN before the doorbell so SDM reads complete data. + */ + mmio_write_32(MBOX_OFFSET + MBOX_CIN, cmd_free_offset); mmio_write_32(MBOX_OFFSET + MBOX_DOORBELL_TO_SDM, 1U); #if SIP_SVC_V3 diff --git a/plat/intel/soc/n5x/platform.mk b/plat/intel/soc/n5x/platform.mk index 41969f269..93f05afb1 100644 --- a/plat/intel/soc/n5x/platform.mk +++ b/plat/intel/soc/n5x/platform.mk @@ -1,6 +1,6 @@ # # Copyright (c) 2019-2023, Intel Corporation. All rights reserved. -# Copyright (c) 2024-2025, Altera Corporation. All rights reserved. +# Copyright (c) 2024-2026, Altera Corporation. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -54,6 +54,11 @@ $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33) $(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33)) $(eval $(call add_define,ARM_PRELOADED_DTB_BASE)) +# Configs for UART0/1 Configuration +SOCFPGA_UART_CONFIG := 0 +$(call assert_boolean,SOCFPGA_UART_CONFIG) +$(eval $(call add_define,SOCFPGA_UART_CONFIG)) + # Configs for Boot Source SOCFPGA_BOOT_SOURCE_SDMMC ?= 0 SOCFPGA_BOOT_SOURCE_QSPI ?= 0 diff --git a/plat/intel/soc/stratix10/platform.mk b/plat/intel/soc/stratix10/platform.mk index 4ac15b2dc..6f459b1fb 100644 --- a/plat/intel/soc/stratix10/platform.mk +++ b/plat/intel/soc/stratix10/platform.mk @@ -1,7 +1,7 @@ # # Copyright (c) 2019-2023, ARM Limited and Contributors. All rights reserved. # Copyright (c) 2019-2023, Intel Corporation. All rights reserved. -# Copyright (c) 2024-2025, Altera Corporation. All rights reserved. +# Copyright (c) 2024-2026, Altera Corporation. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -85,6 +85,11 @@ $(call assert_boolean,ARM_LINUX_KERNEL_AS_BL33) $(eval $(call add_define,ARM_LINUX_KERNEL_AS_BL33)) $(eval $(call add_define,ARM_PRELOADED_DTB_BASE)) +# Configs for UART0/1 Configuration +SOCFPGA_UART_CONFIG := 0 +$(call assert_boolean,SOCFPGA_UART_CONFIG) +$(eval $(call add_define,SOCFPGA_UART_CONFIG)) + # Configs for Boot Source SOCFPGA_BOOT_SOURCE_SDMMC ?= 0 SOCFPGA_BOOT_SOURCE_QSPI ?= 0 diff --git a/plat/nxp/soc-lx2160a/nbxv3/plat_soc_hooks.c b/plat/nxp/soc-lx2160a/nbxv3/plat_soc_hooks.c index 1a328e592..6d3e6016d 100644 --- a/plat/nxp/soc-lx2160a/nbxv3/plat_soc_hooks.c +++ b/plat/nxp/soc-lx2160a/nbxv3/plat_soc_hooks.c @@ -5,6 +5,8 @@ * Platform overrides for the LX2160A shared soc.c weak hooks. */ +#include <stdint.h> + #include <common/debug.h> #include <lib/mmio.h> #include <nxp_smmu.h> @@ -14,6 +16,51 @@ #include <soc.h> /* + * RCW build stamp, written by the PBI into DCFG SCRATCHRW13: + * + * 31 28 27 24 23 16 15 8 7 0 + * +-------+-------+-------+-------+-------+ + * |CARRIER| TAG | YY | MM | DD | all BCD + * +-------+-------+-------+-------+-------+ + * + * e.g. 0x2B260820 -> "Iliad nbxv32 RCW v.20260820". + */ +#define NBXV3_DCFG_SCRATCHRW13_OFFSET 0x230U +#define NBXV3_STAMP_TAG 0xBU +#define NBXV3_STAMP_TAG_SHIFT 24U +#define NBXV3_STAMP_CARRIER_SHIFT 28U +#define NBXV3_STAMP_DATE_MASK 0x00FFFFFFU +#define NBXV3_STAMP_BRINGUP 0xFU + +static void nbxv3_print_rcw_stamp(void) +{ + uint32_t stamp = mmio_read_32(NXP_DCFG_ADDR + + NBXV3_DCFG_SCRATCHRW13_OFFSET); + uint32_t carrier; + + if (stamp == 0U) { + NOTICE("Iliad nbxv3 RCW v.<none> (PBL missing build stamp)\n"); + return; + } + + if (((stamp >> NBXV3_STAMP_TAG_SHIFT) & 0xFU) != NBXV3_STAMP_TAG) { + NOTICE("Iliad nbxv3 RCW v.<unknown format 0x%08X>\n", stamp); + return; + } + + carrier = stamp >> NBXV3_STAMP_CARRIER_SHIFT; + + if (carrier == NBXV3_STAMP_BRINGUP) { + NOTICE("Iliad nbxv3 (bring-up, no IO) RCW v.20%06X\n", + stamp & NBXV3_STAMP_DATE_MASK); + return; + } + + NOTICE("Iliad nbxv3%u RCW v.20%06X\n", carrier, + stamp & NBXV3_STAMP_DATE_MASK); +} + +/* * Called near the end of soc_early_init() * * nbxv3-specific platform overrides go here. @@ -22,6 +69,8 @@ void plat_soc_early_init_hook(void) { nbxv3_mode_t mode = nbxv3_runtime_mode(); + nbxv3_print_rcw_stamp(); + NOTICE("nbxv3: runtime mode = %s\n", nbxv3_mode_name(mode)); switch (mode) { diff --git a/plat/qemu/common/qemu_common.c b/plat/qemu/common/qemu_common.c index 31974c98f..f49601b7e 100644 --- a/plat/qemu/common/qemu_common.c +++ b/plat/qemu/common/qemu_common.c @@ -202,6 +202,16 @@ int plat_spmc_shmem_reclaim(struct ffa_mtd *desc) { return 0; } + +/* + * Allow the platform to validate the memory regions supplied for the + * RX/TX buffers. + */ +bool plat_spmc_rxtx_validate(uintptr_t rx_address, uintptr_t tx_address, + size_t buffer_size) +{ + return true; +} #endif #if defined(SPD_spmd) diff --git a/plat/xilinx/common/include/plat_common.h b/plat/xilinx/common/include/plat_common.h index 2092cdfab..34f5e25f8 100644 --- a/plat/xilinx/common/include/plat_common.h +++ b/plat/xilinx/common/include/plat_common.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2023-2026, Advanced Micro Devices, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -26,4 +26,21 @@ #define ARM_IRQ_SEC_SGI_6 14U #define ARM_IRQ_SEC_SGI_7 15U +/******************************************************************************* + * PMC_TAP accessor functions - platform-specific implementations, and shared + * PMC_TAP register layout constants + ******************************************************************************/ + +/* IDCODE[27:12] = FAMILY + SUB_FAMILY + DEVICE_CODE + SVD (stable part number) */ +#define PMC_TAP_IDCODE_SVD_SHIFT U(12) + +#ifndef __ASSEMBLER__ + +#include <stdint.h> + +uint32_t get_pmc_tap_idcode(void); +uint32_t get_pmc_tap_version(void); + +#endif /* __ASSEMBLER__ */ + #endif /* PLAT_COMMON_H */ diff --git a/plat/xilinx/common/pm_service/pm_svc_main.c b/plat/xilinx/common/pm_service/pm_svc_main.c index ef13ae3d1..7e15e0c1b 100644 --- a/plat/xilinx/common/pm_service/pm_svc_main.c +++ b/plat/xilinx/common/pm_service/pm_svc_main.c @@ -369,11 +369,6 @@ static uintptr_t eemi_psci_debugfs_handler(uint32_t api_id, const uint32_t *pm_a switch (api_id) { - case (uint32_t)PM_SELF_SUSPEND: - ret = pm_self_suspend(pm_arg[0], pm_arg[1], pm_arg[2], - pm_arg[3], security_flag); - SMC_RET1(handle, (u_register_t)ret); - case (uint32_t)PM_FORCE_POWERDOWN: ret = pm_force_powerdown(pm_arg[0], (uint8_t)pm_arg[1], security_flag); SMC_RET1(handle, (u_register_t)ret); diff --git a/plat/xilinx/common/versal.c b/plat/xilinx/common/versal.c index c2c25535b..ec95cecec 100644 --- a/plat/xilinx/common/versal.c +++ b/plat/xilinx/common/versal.c @@ -1,15 +1,18 @@ /* - * Copyright (c) 2023, Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2023-2026, Advanced Micro Devices, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ +#include <stdio.h> + #include <common/debug.h> #include <lib/mmio.h> #include <lib/smccc.h> #include <plat/common/platform.h> #include <services/arm_arch_svc.h> +#include <plat_common.h> #include <plat_private.h> #include <plat_startup.h> #include <pm_api_sys.h> @@ -46,11 +49,16 @@ int32_t plat_is_smccc_feature_available(u_register_t fid) */ int32_t plat_get_soc_version(void) { - uint32_t manfid; - - manfid = SOC_ID_SET_JEP_106(JEDEC_XILINX_BKID, JEDEC_XILINX_MFID); + uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_XILINX_BKID, JEDEC_XILINX_MFID); + /* + * IDCODE[27:12] = FAMILY + SUB_FAMILY + DEVICE_CODE + SVD - stable + * 16-bit SoC part-number that does not change across steppings. + */ + uint32_t soc_id = (get_pmc_tap_idcode() >> PMC_TAP_IDCODE_SVD_SHIFT) & + SOC_ID_IMPL_DEF_MASK; + uint32_t result = manfid | soc_id; - return (int32_t)(manfid | (platform_version & SOC_ID_IMPL_DEF_MASK)); + return (int32_t)result; } /** @@ -63,5 +71,41 @@ int32_t plat_get_soc_version(void) */ int32_t plat_get_soc_revision(void) { - return (int32_t)(platform_id & SOC_ID_REV_MASK); + /* + * VERSION[30:0] carries PMC_VERSION[7:0], PS_VERSION[15:8], + * RTL_VERSION[23:16], PLATFORM[27:24], and PLATFORM_VERSION[30:28]. + * PS_VERSION and PMC_VERSION change across silicon steppings. + */ + uint32_t result = get_pmc_tap_version() & SOC_ID_REV_MASK; + + return (int32_t)result; +} + +/** + * plat_get_soc_name() - SoC name for all Versal-family platforms. + * + * PLAT_SOC_NAME is defined per platform in its *_def.h: + * versal_def.h -> "Versal" + * versal_net_def.h -> "Versal NET" + * def.h (versal2) -> "Versal Gen 2" + * + * PMC_TAP.IDCODE is appended so Linux can identify the exact SoC variant. + * This file is compiled for all three platforms via platform.mk. + * + * @soc_name: Buffer to store the SoC name string. + * + * Return: SMC_ARCH_CALL_SUCCESS on success. + */ +int32_t plat_get_soc_name(char *soc_name) +{ + int32_t ret = SMC_ARCH_CALL_SUCCESS; + int rc = snprintf(soc_name, SMCCC_SOC_NAME_LEN, PLAT_SOC_NAME " %08x", + get_pmc_tap_idcode()); + + /* snprintf return value should be checked to detect truncation */ + if (rc < 0 || rc >= (int)SMCCC_SOC_NAME_LEN) { + ret = SMC_ARCH_CALL_NOT_SUPPORTED; + } + + return ret; } diff --git a/plat/xilinx/versal/aarch64/versal_common.c b/plat/xilinx/versal/aarch64/versal_common.c index 27a67640a..a61f329e5 100644 --- a/plat/xilinx/versal/aarch64/versal_common.c +++ b/plat/xilinx/versal/aarch64/versal_common.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved. - * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2022-2026, Advanced Micro Devices, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -19,6 +19,8 @@ uint32_t platform_id, platform_version; uint32_t cpu_clock; +static uint32_t platform_idcode, platform_version_raw; + /* * Table of regions to map using the MMU. * This doesn't include TZRAM as the 'mem_layout' argument passed to @@ -46,9 +48,9 @@ void versal_config_setup(void) void board_detection(void) { +#if (TFA_NO_PM == 0) uint32_t plat_info[2]; -#if (TFA_NO_PM == 0) if (pm_get_chipid(plat_info) != PM_RET_SUCCESS) { /* If the call is failed we cannot proceed with further * setup. TF-A to panic in this situation. @@ -56,12 +58,15 @@ void board_detection(void) NOTICE("Failed to read the chip information"); panic(); } + platform_idcode = plat_info[0]; + platform_version_raw = plat_info[1]; #else - plat_info[1] = mmio_read_32(PMC_TAP_VERSION); + platform_idcode = mmio_read_32(PMC_TAP_IDCODE); + platform_version_raw = mmio_read_32(PMC_TAP_VERSION); #endif - platform_id = FIELD_GET(PLATFORM_MASK, plat_info[1]); - platform_version = FIELD_GET(PLATFORM_VERSION_MASK, plat_info[1]); + platform_id = FIELD_GET(PLATFORM_MASK, platform_version_raw); + platform_version = FIELD_GET(PLATFORM_VERSION_MASK, platform_version_raw); if (platform_id == VERSAL_COSIM) { platform_id = VERSAL_QEMU; @@ -113,3 +118,17 @@ uint32_t get_uart_clk(void) return uart_clock; } + +/* + * Versal-specific implementations of PMC_TAP accessors. + * PMC_TAP is not mapped at EL3 runtime on Versal, so we use cached values. + */ +uint32_t get_pmc_tap_idcode(void) +{ + return platform_idcode; +} + +uint32_t get_pmc_tap_version(void) +{ + return platform_version_raw; +} diff --git a/plat/xilinx/versal/include/versal_def.h b/plat/xilinx/versal/include/versal_def.h index 1f56b101a..a274e6c79 100644 --- a/plat/xilinx/versal/include/versal_def.h +++ b/plat/xilinx/versal/include/versal_def.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2019-2022, Xilinx, Inc. All rights reserved. - * Copyright (c) 2022-2024, Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2022-2026, Advanced Micro Devices, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -43,7 +43,9 @@ #define VERSAL_QEMU 3U #define VERSAL_COSIM 7U +#define PMC_TAP_IDCODE U(0xF11A0000) #define PMC_TAP_VERSION U(0xF11A0004) +#define PLAT_SOC_NAME "Versal" /* Firmware Image Package */ #define VERSAL_PRIMARY_CPU 0 diff --git a/plat/xilinx/versal_net/aarch64/versal_net_common.c b/plat/xilinx/versal_net/aarch64/versal_net_common.c index 79e44c348..6f7a87022 100644 --- a/plat/xilinx/versal_net/aarch64/versal_net_common.c +++ b/plat/xilinx/versal_net/aarch64/versal_net_common.c @@ -1,7 +1,7 @@ /* * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2018-2022, Xilinx, Inc. All rights reserved. - * Copyright (c) 2022-2025, Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2022-2026, Advanced Micro Devices, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -184,3 +184,18 @@ void get_boot_mode(uint32_t *mode) return; } #endif + +/* + * Versal NET-specific implementations of PMC_TAP accessors. + * PMC_TAP is mapped in DEVICE2 at runtime on Versal NET, so direct read + * is safe. + */ +uint32_t get_pmc_tap_idcode(void) +{ + return mmio_read_32(PMC_TAP_IDCODE); +} + +uint32_t get_pmc_tap_version(void) +{ + return mmio_read_32(PMC_TAP_VERSION); +} diff --git a/plat/xilinx/versal_net/include/versal_net_def.h b/plat/xilinx/versal_net/include/versal_net_def.h index 54f9cc993..e667b068d 100644 --- a/plat/xilinx/versal_net/include/versal_net_def.h +++ b/plat/xilinx/versal_net/include/versal_net_def.h @@ -1,7 +1,7 @@ /* * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. * Copyright (c) 2021-2022, Xilinx, Inc. All rights reserved. - * Copyright (c) 2022-2023, Advanced Micro Devices, Inc. All rights reserved. + * Copyright (c) 2022-2026, Advanced Micro Devices, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -42,9 +42,11 @@ /* For platform detection */ #define PMC_TAP U(0xF11A0000) +#define PMC_TAP_IDCODE PMC_TAP #define PMC_TAP_VERSION (PMC_TAP + 0x4U) # define PLATFORM_MASK GENMASK(27U, 24U) # define PLATFORM_VERSION_MASK GENMASK(31U, 28U) +#define PLAT_SOC_NAME "Versal NET" /* Global timer reset */ #define PSX_CRF U(0xEC200000) diff --git a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c index f6f7fcafe..c34345039 100644 --- a/plat/xilinx/zynqmp/aarch64/zynqmp_common.c +++ b/plat/xilinx/zynqmp/aarch64/zynqmp_common.c @@ -6,6 +6,7 @@ */ #include <stdbool.h> +#include <stdio.h> #include <string.h> #include <common/debug.h> @@ -41,20 +42,27 @@ const mmap_region_t *plat_get_mmap(void) return plat_zynqmp_mmap; } -static uint32_t zynqmp_get_silicon_ver(void) +static uint32_t zynqmp_get_csu_version(void) { static uint32_t ver; if (ver == 0U) { - ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + - ZYNQMP_CSU_VERSION_OFFSET); - ver &= ZYNQMP_SILICON_VER_MASK; - ver >>= ZYNQMP_SILICON_VER_SHIFT; + ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); } return ver; } +static uint32_t zynqmp_get_silicon_ver(void) +{ + uint32_t ver = zynqmp_get_csu_version(); + + ver &= ZYNQMP_SILICON_VER_MASK; + ver >>= ZYNQMP_SILICON_VER_SHIFT; + + return ver; +} + uint32_t get_uart_clk(void) { unsigned int ver = zynqmp_get_silicon_ver(); @@ -287,9 +295,7 @@ static char *zynqmp_get_silicon_idcode_name(void) static unsigned int zynqmp_get_rtl_ver(void) { - uint32_t ver; - - ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); + uint32_t ver = zynqmp_get_csu_version(); ver &= ZYNQMP_RTL_VER_MASK; ver >>= ZYNQMP_RTL_VER_SHIFT; @@ -332,21 +338,50 @@ int32_t plat_is_smccc_feature_available(u_register_t fid) int32_t plat_get_soc_version(void) { - uint32_t chip_id = zynqmp_get_silicon_ver(); + uint32_t idcode = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); uint32_t manfid = SOC_ID_SET_JEP_106(JEDEC_XILINX_BKID, JEDEC_XILINX_MFID); - uint32_t result = (manfid | (chip_id & 0xFFFFU)); + /* + * IDCODE[27:12] = FAMILY(7) + SUB_FAMILY(2) + DEVICE_CODE(4) + SVD(3) + * = stable 16-bit SoC part-number, does not change across steppings. + */ + uint32_t soc_id = (idcode >> ZYNQMP_CSU_IDCODE_SVD_SHIFT) & + SOC_ID_IMPL_DEF_MASK; + uint32_t result = manfid | soc_id; return (int32_t)result; } int32_t plat_get_soc_revision(void) { - return (int32_t)mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); + /* + * CSU_VERSION[30:0] carries PS_VER[3:0], RTL_VER[11:4], and + * SILICON_VER[15:12]. PS_VER and RTL_VER change across silicon + * steppings, satisfying the SMCCC revision stability requirement. + */ + uint32_t ver = zynqmp_get_csu_version(); + uint32_t result = ver & SOC_ID_REV_MASK; + + return (int32_t)result; +} + +int32_t plat_get_soc_name(char *soc_name) +{ + uint32_t idcode = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_IDCODE_OFFSET); + int32_t ret = SMC_ARCH_CALL_SUCCESS; + int rc = snprintf(soc_name, SMCCC_SOC_NAME_LEN, PLAT_SOC_NAME " %08x", + idcode); + + /* snprintf return value should be checked to detect truncation */ + if (rc < 0 || rc >= (int)SMCCC_SOC_NAME_LEN) { + ret = SMC_ARCH_CALL_NOT_SUPPORTED; + } + + return ret; } static uint32_t zynqmp_get_ps_ver(void) { - uint32_t ver = mmio_read_32(ZYNQMP_CSU_BASEADDR + ZYNQMP_CSU_VERSION_OFFSET); + uint32_t ver = zynqmp_get_csu_version(); ver &= ZYNQMP_PS_VER_MASK; ver >>= ZYNQMP_PS_VER_SHIFT; diff --git a/plat/xilinx/zynqmp/include/zynqmp_def.h b/plat/xilinx/zynqmp/include/zynqmp_def.h index cd3bbbc64..f0bff0a43 100644 --- a/plat/xilinx/zynqmp/include/zynqmp_def.h +++ b/plat/xilinx/zynqmp/include/zynqmp_def.h @@ -1,5 +1,6 @@ /* * Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2026, Advanced Micro Devices, Inc. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -201,6 +202,7 @@ #define ZYNQMP_CSU_BASEADDR U(0xFFCA0000) #define ZYNQMP_CSU_IDCODE_OFFSET U(0x40) +#define PLAT_SOC_NAME "ZynqMP" #define ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT U(0) #define ZYNQMP_CSU_IDCODE_XILINX_ID_MASK (U(0xFFF) << ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT) diff --git a/services/std_svc/spm/el3_spmc/spmc_main.c b/services/std_svc/spm/el3_spmc/spmc_main.c index c8d6c95cb..3ac40bd83 100644 --- a/services/std_svc/spm/el3_spmc/spmc_main.c +++ b/services/std_svc/spm/el3_spmc/spmc_main.c @@ -997,6 +997,13 @@ static uint64_t rxtx_map_handler(uint32_t smc_fid, /* Obtain the RX/TX buffer pair descriptor. */ mbox = spmc_get_mbox_desc(secure_origin); + /* Validate the memory ranges provided. */ + if (!plat_spmc_rxtx_validate(rx_address, tx_address, buf_size)) { + WARN("Invalid memory ranges provided for the RX/TX buffers.\n"); + return spmc_ffa_error_return(handle, + FFA_ERROR_INVALID_PARAMETER); + } + spin_lock(&mbox->lock); /* Check if buffers have already been mapped. */ diff --git a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c index 3ec787d12..08e542998 100644 --- a/services/std_svc/spm/el3_spmc/spmc_shared_mem.c +++ b/services/std_svc/spm/el3_spmc/spmc_shared_mem.c @@ -247,6 +247,7 @@ emad_advance(const struct ffa_emad_v1_0 *emad, size_t offset) static struct ffa_comp_mrd * spmc_shmem_obj_get_comp_mrd(struct spmc_shmem_obj *obj, uint32_t ffa_version) { + size_t desc_len = obj->desc_filled; size_t emad_size; /* * The comp_mrd_offset field of the emad descriptor remains consistent @@ -263,6 +264,12 @@ spmc_shmem_obj_get_comp_mrd(struct spmc_shmem_obj *obj, uint32_t ffa_version) return NULL; } + if (desc_len < sizeof(struct ffa_comp_mrd) || + emad->comp_mrd_offset > desc_len - sizeof(struct ffa_comp_mrd)) { + WARN("Composite memory region descriptor offset is out of bounds.\n"); + return NULL; + } + return (struct ffa_comp_mrd *) ((uint8_t *)(&obj->desc) + emad->comp_mrd_offset); } @@ -1030,7 +1037,7 @@ static int spmc_shmem_check_state_obj(struct spmc_shmem_obj *obj, * transmitted descriptors. */ if ((obj->desc.handle != inflight_obj->desc.handle) && - (obj->desc_size == obj->desc_filled)) { + (inflight_obj->desc_size == inflight_obj->desc_filled)) { other_mrd = spmc_shmem_obj_get_comp_mrd(inflight_obj, FFA_VERSION_COMPILED); if (other_mrd == NULL) { @@ -1919,6 +1926,13 @@ long spmc_ffa_mem_frag_rx(uint32_t smc_fid, goto err_unlock_shmem; } + if (obj->desc_filled != obj->desc_size) { + WARN("%s: incomplete object desc filled %zu < size %zu\n", + __func__, obj->desc_filled, obj->desc_size); + ret = FFA_ERROR_INVALID_PARAMETER; + goto err_unlock_shmem; + } + desc_sender_id = (uint32_t)obj->desc.sender_id << 16; if (sender_id != 0U && sender_id != desc_sender_id) { WARN("%s: invalid sender_id 0x%x != 0x%x\n", __func__, |
