diff options
-rw-r--r-- | docs/getting_started/docs-build.rst | 29 | ||||
-rw-r--r-- | docs/getting_started/porting-guide.rst | 13 | ||||
-rw-r--r-- | drivers/arm/tzc/tzc_dmc620.c | 35 | ||||
-rw-r--r-- | include/drivers/arm/tzc_dmc620.h | 10 | ||||
-rw-r--r-- | include/plat/common/platform.h | 5 | ||||
-rw-r--r-- | plat/arm/board/arm_fpga/aarch64/fpga_helpers.S | 63 | ||||
-rw-r--r-- | plat/arm/board/arm_fpga/fpga_bl31_setup.c | 51 | ||||
-rw-r--r-- | plat/arm/board/arm_fpga/fpga_def.h | 1 | ||||
-rw-r--r-- | plat/arm/board/arm_fpga/fpga_private.h | 15 | ||||
-rw-r--r-- | plat/arm/board/arm_fpga/fpga_topology.c | 70 | ||||
-rw-r--r-- | plat/arm/board/arm_fpga/include/platform_def.h | 9 | ||||
-rw-r--r-- | plat/arm/common/arm_bl31_setup.c | 20 | ||||
-rw-r--r-- | plat/arm/common/arm_common.c | 19 | ||||
-rw-r--r-- | plat/common/plat_bl_common.c | 7 | ||||
-rw-r--r-- | plat/nvidia/tegra/common/tegra_platform.c | 22 | ||||
-rw-r--r-- | services/arm_arch_svc/arm_arch_svc_setup.c | 3 |
16 files changed, 292 insertions, 80 deletions
diff --git a/docs/getting_started/docs-build.rst b/docs/getting_started/docs-build.rst index 91b1b3a397..87c677fcde 100644 --- a/docs/getting_started/docs-build.rst +++ b/docs/getting_started/docs-build.rst @@ -67,7 +67,7 @@ Output from the build process will be placed in: :: - docs/build/html/ + docs/build/html We also support building documentation in other formats. From the ``docs`` directory of the project, run the following command to see the supported @@ -79,6 +79,31 @@ top-level Makefile for |TF-A| itself. make help +Building rendered documentation from a container +------------------------------------------------ + +There may be cases where you can not either install or upgrade required +dependencies to generate the documents, so in this case, one way to +create the documentation is through a docker container. The first step is +to check if `docker`_ is installed in your host, otherwise check main docker +page for installation instructions. Once installed, run the following script +from project root directory + +.. code:: shell + + docker run --rm -v $PWD:/TF sphinxdoc/sphinx \ + bash -c 'cd /TF && \ + pip3 install plantuml -r ./docs/requirements.txt && make doc' + +The above command fetches the ``sphinxdoc/sphinx`` container from `docker +hub`_, launches the container, installs documentation requirements and finally +creates the documentation. Once done, exit the container and output from the +build process will be placed in: + +:: + + docs/build/html + -------------- *Copyright (c) 2019, Arm Limited. All rights reserved.* @@ -86,3 +111,5 @@ top-level Makefile for |TF-A| itself. .. _Sphinx: http://www.sphinx-doc.org/en/master/ .. _pip homepage: https://pip.pypa.io/en/stable/ .. _Dia: https://wiki.gnome.org/Apps/Dia +.. _docker: https://www.docker.com/ +.. _docker hub: https://hub.docker.com/repository/docker/sphinxdoc/sphinx diff --git a/docs/getting_started/porting-guide.rst b/docs/getting_started/porting-guide.rst index c98f3cc041..7aaeae2f4e 100644 --- a/docs/getting_started/porting-guide.rst +++ b/docs/getting_started/porting-guide.rst @@ -1130,6 +1130,7 @@ This function returns soc version which mainly consist of below fields soc_version[30:24] = JEP-106 continuation code for the SiP soc_version[23:16] = JEP-106 identification code with parity bit for the SiP + soc_version[15:0] = Implementation defined SoC ID Function : plat_get_soc_revision() ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -1145,6 +1146,18 @@ This function returns soc revision in below format soc_revision[0:30] = SOC revision of specific SOC +Function : plat_is_smccc_feature_available() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t + Return : int32_t + +This function returns SMC_ARCH_CALL_SUCCESS if the platform supports +the SMCCC function specified in the argument; otherwise returns +SMC_ARCH_CALL_NOT_SUPPORTED. + Modifications specific to a Boot Loader stage --------------------------------------------- diff --git a/drivers/arm/tzc/tzc_dmc620.c b/drivers/arm/tzc/tzc_dmc620.c index 64ec5abee7..7e307ee504 100644 --- a/drivers/arm/tzc/tzc_dmc620.c +++ b/drivers/arm/tzc/tzc_dmc620.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -17,7 +17,7 @@ /* Helper macro for getting dmc_base addr of a dmc_inst */ #define DMC_BASE(plat_data, dmc_inst) \ - ((uintptr_t)(plat_data->dmc_base[dmc_inst])) + ((uintptr_t)((plat_data)->dmc_base[(dmc_inst)])) /* Pointer to the tzc_dmc620_config_data structure populated by the platform */ static const tzc_dmc620_config_data_t *g_plat_config_data; @@ -31,8 +31,7 @@ static const tzc_dmc620_config_data_t *g_plat_config_data; static void tzc_dmc620_validate_plat_driver_data( const tzc_dmc620_driver_data_t *plat_driver_data) { - uint8_t dmc_inst, dmc_count; - unsigned int dmc_id; + unsigned int dmc_inst, dmc_count, dmc_id; uintptr_t base; assert(plat_driver_data != NULL); @@ -59,7 +58,7 @@ static void tzc_dmc620_configure_region(int region_no, { uint32_t min_31_00, min_47_32; uint32_t max_31_00, max_47_32; - uint8_t dmc_inst, dmc_count; + unsigned int dmc_inst, dmc_count; uintptr_t base; const tzc_dmc620_driver_data_t *plat_driver_data; @@ -67,19 +66,19 @@ static void tzc_dmc620_configure_region(int region_no, assert(plat_driver_data != NULL); /* Do range checks on regions. */ - assert((region_no >= 0U) && (region_no <= DMC620_ACC_ADDR_COUNT)); + assert((region_no >= 0) && (region_no <= DMC620_ACC_ADDR_COUNT)); /* region_base and (region_top + 1) must be 4KB aligned */ assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U); dmc_count = plat_driver_data->dmc_count; for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { - min_31_00 = (region_base & MASK_31_16) | sec_attr; - min_47_32 = (region_base & MASK_47_32) - >> DMC620_ACC_ADDR_WIDTH; - max_31_00 = (region_top & MASK_31_16); - max_47_32 = (region_top & MASK_47_32) - >> DMC620_ACC_ADDR_WIDTH; + min_31_00 = (uint32_t)((region_base & MASK_31_16) | sec_attr); + min_47_32 = (uint32_t)((region_base & MASK_47_32) + >> DMC620_ACC_ADDR_WIDTH); + max_31_00 = (uint32_t)(region_top & MASK_31_16); + max_47_32 = (uint32_t)((region_top & MASK_47_32) + >> DMC620_ACC_ADDR_WIDTH); /* Extract the base address of the DMC-620 instance */ base = DMC_BASE(plat_driver_data, dmc_inst); @@ -100,7 +99,7 @@ static void tzc_dmc620_configure_region(int region_no, */ static void tzc_dmc620_set_action(void) { - uint8_t dmc_inst, dmc_count; + unsigned int dmc_inst, dmc_count; uintptr_t base; const tzc_dmc620_driver_data_t *plat_driver_data; @@ -123,7 +122,7 @@ static void tzc_dmc620_set_action(void) */ static void tzc_dmc620_verify_complete(void) { - uint8_t dmc_inst, dmc_count; + unsigned int dmc_inst, dmc_count; uintptr_t base; const tzc_dmc620_driver_data_t *plat_driver_data; @@ -133,8 +132,9 @@ static void tzc_dmc620_verify_complete(void) /* Extract the base address of the DMC-620 instance */ base = DMC_BASE(plat_driver_data, dmc_inst); while ((mmio_read_32(base + DMC620_MEMC_STATUS) & - DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO) + DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO) { continue; + } } } @@ -145,7 +145,7 @@ static void tzc_dmc620_verify_complete(void) */ void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data) { - int i; + uint8_t i; /* Check if valid pointer is passed */ assert(plat_config_data != NULL); @@ -164,11 +164,12 @@ void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data) g_plat_config_data = plat_config_data; INFO("Configuring DMC-620 TZC settings\n"); - for (i = 0U; i < g_plat_config_data->acc_addr_count; i++) + for (i = 0U; i < g_plat_config_data->acc_addr_count; i++) { tzc_dmc620_configure_region(i, g_plat_config_data->plat_acc_addr_data[i].region_base, g_plat_config_data->plat_acc_addr_data[i].region_top, g_plat_config_data->plat_acc_addr_data[i].sec_attr); + } tzc_dmc620_set_action(); tzc_dmc620_verify_complete(); diff --git a/include/drivers/arm/tzc_dmc620.h b/include/drivers/arm/tzc_dmc620.h index e0e6760b28..26c444d101 100644 --- a/include/drivers/arm/tzc_dmc620.h +++ b/include/drivers/arm/tzc_dmc620.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -32,16 +32,16 @@ /* Address offsets of access address next registers */ #define DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no) \ (DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE + \ - (region_no * DMC620_ACC_ADDR_NEXT_SIZE)) + ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE)) #define DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no) \ (DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE + \ - (region_no * DMC620_ACC_ADDR_NEXT_SIZE)) + ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE)) #define DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no) \ (DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE + \ - (region_no * DMC620_ACC_ADDR_NEXT_SIZE)) + ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE)) #define DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no) \ (DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE + \ - (region_no * DMC620_ACC_ADDR_NEXT_SIZE)) + ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE)) /* Number of TZC address regions in DMC-620 */ #define DMC620_ACC_ADDR_COUNT U(8) diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index 658b423801..2c1a180c83 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -341,4 +341,9 @@ int32_t plat_get_soc_version(void); */ int32_t plat_get_soc_revision(void); +/* + * Optional function to check for SMCCC function availability for platform + */ +int32_t plat_is_smccc_feature_available(u_register_t fid); + #endif /* PLATFORM_H */ diff --git a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S index aeed3108ed..20120c9c3c 100644 --- a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S +++ b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S @@ -7,6 +7,8 @@ #include <arch.h> #include <asm_macros.S> #include <common/bl_common.h> +#include "../fpga_private.h" + #include <platform_def.h> .globl plat_get_my_entrypoint @@ -14,10 +16,10 @@ .globl plat_is_my_cpu_primary .globl platform_mem_init .globl plat_my_core_pos - .globl plat_fpga_calc_core_pos .globl plat_crash_console_init .globl plat_crash_console_putc .globl plat_crash_console_flush + .globl plat_fpga_calc_core_pos /* ----------------------------------------------------------------------- * Indicate a cold boot for every CPU - warm boot is unsupported for the @@ -34,23 +36,59 @@ endfunc plat_get_my_entrypoint * ----------------------------------------------------------------------- */ func plat_secondary_cold_boot_setup + + /* + * Wait for the primary processor to initialise the .BSS segment + * to avoid a race condition that would erase fpga_valid_mpids + * if it is populated before the C runtime is ready. + * + * We cannot use the current spin-lock implementation until the + * runtime is up and we should not rely on sevl/wfe instructions as + * it is optional whether they are implemented or not, so we use + * a global variable as lock and wait for the primary processor to + * finish the C runtime bring-up. + */ + + ldr w0, =C_RUNTIME_READY_KEY + adrp x1, secondary_core_spinlock + add x1, x1, :lo12:secondary_core_spinlock +1: + wfe + ldr w2, [x1] + cmp w2, w0 + b.ne 1b + /* Prevent reordering of the store into fpga_valid_mpids below */ + dmb ish + + mov x10, x30 + bl plat_my_core_pos + mov x30, x10 + + adrp x4, fpga_valid_mpids + add x4, x4, :lo12:fpga_valid_mpids + mov x5, #VALID_MPID + strb w5, [x4, x0] + /* * Poll the CPU's hold entry until it indicates to jump * to the entrypoint address. */ - bl plat_my_core_pos - lsl x0, x0, #PLAT_FPGA_HOLD_ENTRY_SHIFT - ldr x1, =hold_base - ldr x2, =fpga_sec_entrypoint + + adrp x1, hold_base + add x1, x1, :lo12:hold_base poll_hold_entry: - ldr x3, [x1, x0] + ldr x3, [x1, x0, LSL #PLAT_FPGA_HOLD_ENTRY_SHIFT] cmp x3, #PLAT_FPGA_HOLD_STATE_GO b.ne 1f + + adrp x2, fpga_sec_entrypoint + add x2, x2, :lo12:fpga_sec_entrypoint ldr x3, [x2] br x3 1: wfe b poll_hold_entry + endfunc plat_secondary_cold_boot_setup /* ----------------------------------------------------------------------- @@ -73,12 +111,16 @@ func platform_mem_init endfunc platform_mem_init func plat_my_core_pos + ldr x1, =(MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT)) mrs x0, mpidr_el1 + and x0, x0, x1 b plat_fpga_calc_core_pos + endfunc plat_my_core_pos /* ----------------------------------------------------------------------- - * unsigned int plat_fpga_calc_core_pos(u_register_t mpidr) + * unsigned int plat_fpga_calc_core_pos (uint32_t mpid) + * Clobber registers: x0 to x5 * ----------------------------------------------------------------------- */ func plat_fpga_calc_core_pos @@ -88,6 +130,7 @@ func plat_fpga_calc_core_pos * * If not set, shift MPIDR to left to make it look as if in a * multi-threaded implementation. + * */ tst x0, #MPIDR_MT_MASK lsl x3, x0, #MPIDR_AFFINITY_BITS @@ -98,11 +141,13 @@ func plat_fpga_calc_core_pos ubfx x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS ubfx x2, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS - /* Compute linear position */ mov x4, #FPGA_MAX_CPUS_PER_CLUSTER - madd x1, x2, x4, x1 mov x5, #FPGA_MAX_PE_PER_CPU + + /* Compute linear position */ + madd x1, x2, x4, x1 madd x0, x1, x5, x0 + ret endfunc plat_fpga_calc_core_pos diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c index e4b9767d40..6eeff451cc 100644 --- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c +++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c @@ -7,23 +7,23 @@ #include <assert.h> #include <common/fdt_wrappers.h> +#include <drivers/delay_timer.h> #include <drivers/generic_delay_timer.h> -#include <lib/mmio.h> #include <libfdt.h> +#include "fpga_private.h" #include <plat/common/platform.h> #include <platform_def.h> -#include "fpga_private.h" - static entry_point_info_t bl33_image_ep_info; +volatile uint32_t secondary_core_spinlock; uintptr_t plat_get_ns_image_entrypoint(void) { #ifdef PRELOADED_BL33_BASE return PRELOADED_BL33_BASE; #else - return 0; + return 0ULL; #endif } @@ -35,6 +35,17 @@ uint32_t fpga_get_spsr_for_bl33_entry(void) void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3) { + /* Add this core to the VALID mpids list */ + fpga_valid_mpids[plat_my_core_pos()] = VALID_MPID; + + /* + * Notify the secondary CPUs that the C runtime is ready + * so they can announce themselves. + */ + secondary_core_spinlock = C_RUNTIME_READY_KEY; + dsbish(); + sev(); + fpga_console_init(); bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); @@ -54,11 +65,37 @@ void bl31_plat_arch_setup(void) void bl31_platform_setup(void) { - /* Initialize the GIC driver, cpu and distributor interfaces */ - plat_fpga_gic_init(); - /* Write frequency to CNTCRL and initialize timer */ generic_delay_timer_init(); + + /* + * Before doing anything else, wait for some time to ensure that + * the secondary CPUs have populated the fpga_valid_mpids array. + * As the number of secondary cores is unknown and can even be 0, + * it is not possible to rely on any signal from them, so use a + * delay instead. + */ + mdelay(5); + + /* + * On the event of a cold reset issued by, for instance, a reset pin + * assertion, we cannot guarantee memory to be initialized to zero. + * In such scenario, if the secondary cores reached + * plat_secondary_cold_boot_setup before the primary one initialized + * .BSS, we could end up having a race condition if the spinlock + * was not cleared before. + * + * Similarly, if there were a reset before the spinlock had been + * cleared, the secondary cores would find the lock opened before + * .BSS is cleared, causing another race condition. + * + * So clean the spinlock as soon as we think it is safe to reduce the + * chances of any race condition on a reset. + */ + secondary_core_spinlock = 0UL; + + /* Initialize the GIC driver, cpu and distributor interfaces */ + plat_fpga_gic_init(); } entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) diff --git a/plat/arm/board/arm_fpga/fpga_def.h b/plat/arm/board/arm_fpga/fpga_def.h index 5f1951f792..2884ea6d4f 100644 --- a/plat/arm/board/arm_fpga/fpga_def.h +++ b/plat/arm/board/arm_fpga/fpga_def.h @@ -18,6 +18,7 @@ * that are present will still be indexed appropriately regardless of any empty * entries in the array used to represent the topology. */ + #define FPGA_MAX_CLUSTER_COUNT 4 #define FPGA_MAX_CPUS_PER_CLUSTER 8 #define FPGA_MAX_PE_PER_CPU 4 diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h index 7545bd17eb..46287adea7 100644 --- a/plat/arm/board/arm_fpga/fpga_private.h +++ b/plat/arm/board/arm_fpga/fpga_private.h @@ -7,12 +7,23 @@ #ifndef FPGA_PRIVATE_H #define FPGA_PRIVATE_H -unsigned int plat_fpga_calc_core_pos(u_register_t mpidr); +#include "../fpga_def.h" +#include <platform_def.h> + +#define C_RUNTIME_READY_KEY (0xaa55aa55) +#define VALID_MPID (1U) + +#ifndef __ASSEMBLER__ + +extern unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT]; void fpga_console_init(void); void plat_fpga_gic_init(void); void fpga_pwr_gic_on_finish(void); void fpga_pwr_gic_off(void); +unsigned int plat_fpga_calc_core_pos(uint32_t mpid); + +#endif /* __ASSEMBLER__ */ -#endif +#endif /* FPGA_PRIVATE_H */ diff --git a/plat/arm/board/arm_fpga/fpga_topology.c b/plat/arm/board/arm_fpga/fpga_topology.c index a2908d7278..7fead869b5 100644 --- a/plat/arm/board/arm_fpga/fpga_topology.c +++ b/plat/arm/board/arm_fpga/fpga_topology.c @@ -5,15 +5,20 @@ */ #include <arch_helpers.h> +#include <common/debug.h> +#include <lib/spinlock.h> #include "fpga_private.h" +#include <plat/common/platform.h> #include <platform_def.h> -static unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2]; +unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2]; +unsigned char fpga_valid_mpids[PLATFORM_CORE_COUNT]; const unsigned char *plat_get_power_domain_tree_desc(void) { - int i; + unsigned int i; + /* * The highest level is the system level. The next level is constituted * by clusters and then cores in clusters. @@ -21,12 +26,26 @@ const unsigned char *plat_get_power_domain_tree_desc(void) * This description of the power domain topology is aligned with the CPU * indices returned by the plat_core_pos_by_mpidr() and plat_my_core_pos() * APIs. + * + * A description of the topology tree can be found at + * https://trustedfirmware-a.readthedocs.io/en/latest/design/psci-pd-tree.html#design */ - fpga_power_domain_tree_desc[0] = 1; - fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT; - for (i = 0; i < FPGA_MAX_CLUSTER_COUNT; i++) { - fpga_power_domain_tree_desc[i + 2] = FPGA_MAX_CPUS_PER_CLUSTER * FPGA_MAX_PE_PER_CPU; + if (fpga_power_domain_tree_desc[0] == 0U) { + /* + * As fpga_power_domain_tree_desc[0] == 0, assume that the + * Power Domain Topology Tree has not been initialized, so + * perform the initialization here. + */ + + fpga_power_domain_tree_desc[0] = 1U; + fpga_power_domain_tree_desc[1] = FPGA_MAX_CLUSTER_COUNT; + + for (i = 0U; i < FPGA_MAX_CLUSTER_COUNT; i++) { + fpga_power_domain_tree_desc[2 + i] = + (FPGA_MAX_CPUS_PER_CLUSTER * + FPGA_MAX_PE_PER_CPU); + } } return fpga_power_domain_tree_desc; @@ -34,40 +53,25 @@ const unsigned char *plat_get_power_domain_tree_desc(void) int plat_core_pos_by_mpidr(u_register_t mpidr) { - unsigned int cluster_id, cpu_id, thread_id; + unsigned int core_pos; - /* - * The image running on the FPGA may or may not implement - * multithreading, and it shouldn't be assumed this is consistent - * across all CPUs. - * This ensures that any passed mpidr values reflect the status of the - * primary CPU's MT bit. - */ + mpidr &= (MPID_MASK & ~(MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT)); mpidr |= (read_mpidr_el1() & MPIDR_MT_MASK); - mpidr &= MPID_MASK; - if (mpidr & MPIDR_MT_MASK) { - thread_id = MPIDR_AFFLVL0_VAL(mpidr); - cpu_id = MPIDR_AFFLVL1_VAL(mpidr); - cluster_id = MPIDR_AFFLVL2_VAL(mpidr); - } else { - thread_id = 0; - cpu_id = MPIDR_AFFLVL0_VAL(mpidr); - cluster_id = MPIDR_AFFLVL1_VAL(mpidr); + if ((MPIDR_AFFLVL2_VAL(mpidr) >= FPGA_MAX_CLUSTER_COUNT) || + (MPIDR_AFFLVL1_VAL(mpidr) >= FPGA_MAX_CPUS_PER_CLUSTER) || + (MPIDR_AFFLVL0_VAL(mpidr) >= FPGA_MAX_PE_PER_CPU)) { + ERROR ("Invalid mpidr: 0x%08x\n", (uint32_t)mpidr); + panic(); } - if (cluster_id >= FPGA_MAX_CLUSTER_COUNT) { - return -1; - } - - if (cpu_id >= FPGA_MAX_CPUS_PER_CLUSTER) { - return -1; - } + /* Calculate the core position, based on the maximum topology. */ + core_pos = plat_fpga_calc_core_pos(mpidr); - if (thread_id >= FPGA_MAX_PE_PER_CPU) { + /* Check whether this core is actually present. */ + if (fpga_valid_mpids[core_pos] != VALID_MPID) { return -1; } - /* Calculate the correct core, catering for multi-threaded images */ - return (int) plat_fpga_calc_core_pos(mpidr); + return core_pos; } diff --git a/plat/arm/board/arm_fpga/include/platform_def.h b/plat/arm/board/arm_fpga/include/platform_def.h index 31fc9870cc..411b936da1 100644 --- a/plat/arm/board/arm_fpga/include/platform_def.h +++ b/plat/arm/board/arm_fpga/include/platform_def.h @@ -21,11 +21,12 @@ #define CACHE_WRITEBACK_SHIFT U(6) #define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) -#define PLATFORM_CORE_COUNT \ - (FPGA_MAX_CLUSTER_COUNT * FPGA_MAX_CPUS_PER_CLUSTER * FPGA_MAX_PE_PER_CPU) +#define PLATFORM_CORE_COUNT \ + (FPGA_MAX_CLUSTER_COUNT * \ + FPGA_MAX_CPUS_PER_CLUSTER * \ + FPGA_MAX_PE_PER_CPU) -#define PLAT_NUM_PWR_DOMAINS (FPGA_MAX_CLUSTER_COUNT + \ - PLATFORM_CORE_COUNT) + 1 +#define PLAT_NUM_PWR_DOMAINS (FPGA_MAX_CLUSTER_COUNT + PLATFORM_CORE_COUNT + 1) #if !ENABLE_PIE #define BL31_BASE UL(0x80000000) diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c index ded8f895eb..58ccf0e511 100644 --- a/plat/arm/common/arm_bl31_setup.c +++ b/plat/arm/common/arm_bl31_setup.c @@ -114,6 +114,18 @@ void __init arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_confi SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); bl32_image_ep_info.pc = BL32_BASE; bl32_image_ep_info.spsr = arm_get_spsr_for_bl32_entry(); + +#if defined(SPD_spmd) + /* SPM (hafnium in secure world) expects SPM Core manifest base address + * in x0, which in !RESET_TO_BL31 case loaded after base of non shared + * SRAM(after 4KB offset of SRAM). But in RESET_TO_BL31 case all non + * shared SRAM is allocated to BL31, so to avoid overwriting of manifest + * keep it in the last page. + */ + bl32_image_ep_info.args.arg0 = ARM_TRUSTED_SRAM_BASE + + PLAT_ARM_TRUSTED_SRAM_SIZE - PAGE_SIZE; +#endif + # endif /* BL32_BASE */ /* Populate entry point information for BL33 */ @@ -130,6 +142,14 @@ void __init arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_confi bl33_image_ep_info.spsr = arm_get_spsr_for_bl33_entry(); SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); +#if defined(SPD_spmd) && !(ARM_LINUX_KERNEL_AS_BL33) + /* + * Hafnium in normal world expects its manifest address in x0, which + * is loaded at base of DRAM. + */ + bl33_image_ep_info.args.arg0 = (u_register_t)ARM_DRAM1_BASE; +#endif + # if ARM_LINUX_KERNEL_AS_BL33 /* * According to the file ``Documentation/arm64/booting.txt`` of the diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c index 60c777ed83..e2b99a3d6d 100644 --- a/plat/arm/common/arm_common.c +++ b/plat/arm/common/arm_common.c @@ -13,7 +13,9 @@ #include <common/debug.h> #include <common/romlib.h> #include <lib/mmio.h> +#include <lib/smccc.h> #include <lib/xlat_tables/xlat_tables_compat.h> +#include <services/arm_arch_svc.h> #include <plat/arm/common/plat_arm.h> #include <plat/common/platform.h> @@ -235,6 +237,23 @@ int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode) } #endif +/***************************************************************************** + * plat_is_smccc_feature_available() - This function checks whether SMCCC + * feature is availabile for platform. + * @fid: SMCCC function id + * + * Return SMC_OK if SMCCC feature is available and SMC_ARCH_CALL_NOT_SUPPORTED + * otherwise. + *****************************************************************************/ +int32_t plat_is_smccc_feature_available(u_register_t fid) +{ + switch (fid) { + case SMCCC_ARCH_SOC_ID: + default: + return SMC_ARCH_CALL_NOT_SUPPORTED; + } +} + /* * Weak function to get ARM platform SOC-ID, Always return SOC-ID=0 * ToDo: Get proper SOC-ID for every ARM platform and define this diff --git a/plat/common/plat_bl_common.c b/plat/common/plat_bl_common.c index d38fc6f75b..89b77ba6ce 100644 --- a/plat/common/plat_bl_common.c +++ b/plat/common/plat_bl_common.c @@ -11,6 +11,7 @@ #include <common/debug.h> #include <lib/xlat_tables/xlat_tables_compat.h> #include <plat/common/platform.h> +#include <services/arm_arch_svc.h> #include <smccc_helpers.h> #include <tools_share/firmware_encrypted.h> @@ -25,6 +26,7 @@ #pragma weak bl2_plat_handle_post_image_load #pragma weak plat_try_next_boot_source #pragma weak plat_get_enc_key_info +#pragma weak plat_is_smccc_feature_available #pragma weak plat_get_soc_version #pragma weak plat_get_soc_revision @@ -38,6 +40,11 @@ int32_t plat_get_soc_revision(void) return SMC_ARCH_CALL_NOT_SUPPORTED; } +int32_t plat_is_smccc_feature_available(u_register_t fid __unused) +{ + return SMC_ARCH_CALL_NOT_SUPPORTED; +} + void bl2_el3_plat_prepare_exit(void) { } diff --git a/plat/nvidia/tegra/common/tegra_platform.c b/plat/nvidia/tegra/common/tegra_platform.c index e4338b9638..080413575a 100644 --- a/plat/nvidia/tegra/common/tegra_platform.c +++ b/plat/nvidia/tegra/common/tegra_platform.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause @@ -8,6 +8,8 @@ #include <arch_helpers.h> #include <assert.h> #include <lib/mmio.h> +#include <lib/smccc.h> +#include <services/arm_arch_svc.h> #include <tegra_def.h> #include <tegra_platform.h> #include <tegra_private.h> @@ -286,3 +288,21 @@ int32_t plat_get_soc_revision(void) { return (int32_t)((tegra_get_chipid_major() << 8) | tegra_get_chipid_minor()); } + +/***************************************************************************** + * plat_smccc_feature_available() - This function checks whether SMCCC feature + * is availabile for the platform or not. + * @fid: SMCCC function id + * + * Return SMC_ARCH_CALL_SUCCESS if SMCCC feature is available and + * SMC_ARCH_CALL_NOT_SUPPORTED otherwise. + *****************************************************************************/ +int32_t plat_smccc_feature_available(u_register_t fid) +{ + switch (fid) { + case SMCCC_ARCH_SOC_ID: + return SMC_ARCH_CALL_SUCCESS; + default: + return SMC_ARCH_CALL_NOT_SUPPORTED; + } +} diff --git a/services/arm_arch_svc/arm_arch_svc_setup.c b/services/arm_arch_svc/arm_arch_svc_setup.c index 588656d57f..37bfc62e2b 100644 --- a/services/arm_arch_svc/arm_arch_svc_setup.c +++ b/services/arm_arch_svc/arm_arch_svc_setup.c @@ -24,8 +24,9 @@ static int32_t smccc_arch_features(u_register_t arg1) switch (arg1) { case SMCCC_VERSION: case SMCCC_ARCH_FEATURES: + return SMC_ARCH_CALL_SUCCESS; case SMCCC_ARCH_SOC_ID: - return SMC_OK; + return plat_is_smccc_feature_available(arg1); #if WORKAROUND_CVE_2017_5715 case SMCCC_ARCH_WORKAROUND_1: if (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES) |