diff options
25 files changed, 845 insertions, 64 deletions
diff --git a/docs/change-log-upcoming.rst b/docs/change-log-upcoming.rst index 72dfb50e8..f089a5ed6 100644 --- a/docs/change-log-upcoming.rst +++ b/docs/change-log-upcoming.rst @@ -40,6 +40,7 @@ New Features - CPU Support - Example: "cortex-a55: Workaround for erratum 1221012" + - Use Speculation Barrier instruction for v8.5+ cores - Drivers - Example: "console: Allow the console to register multiple times" @@ -55,6 +56,8 @@ New Features - Platforms - Example: "arm/common: Introduce wrapper functions to setup secure watchdog" - plat/arm: Add support for the new `dualroot` chain of trust. + - plat/arm/fvp: Add support for fconf in BL31 and SP_MIN. Populate power + domain desciptor dynamically by leveraging fconf APIs. - PSCI - Example: "Adding new optional PSCI hook ``pwr_domain_on_finish_late``" @@ -63,6 +66,7 @@ New Features - Example: "UBSAN support and handlers" - Add support for optional firmware encryption feature (experimental). - Introduce a new `dualroot` chain of trust. + - aarch32: stop speculative execution past exception returns. - SPCI - Introduced the SPM Dispatcher (SPMD) component as a new standard service. diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst index e53f71471..50cafcfa0 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -146,6 +146,12 @@ Common build options is on hardware that does not implement AArch32, or at least not at EL1 and higher ELs). Default value is 1. +- ``CTX_INCLUDE_EL2_REGS`` : This boolean option provides context save/restore + operations when entering/exiting an EL2 execution context. This is of primary + interest when Armv8.4-SecEL2 extension is implemented. Default is 0 (disabled). + This option must be equal to 1 (enabled) when ``SPD=spmd`` and + ``SPMD_SPM_AT_SEL2`` is set. + - ``CTX_INCLUDE_FPREGS``: Boolean option that, when set to 1, will cause the FP registers to be included when saving and restoring the CPU context. Default is 0. @@ -536,8 +542,8 @@ Common build options - ``SEPARATE_CODE_AND_RODATA``: Whether code and read-only data should be isolated on separate memory pages. This is a trade-off between security and memory usage. See "Isolating code and read-only data on separate memory - pages" section in :ref:`Firmware Design`. This flag is disabled by default and - affects all BL images. + pages" section in :ref:`Firmware Design`. This flag is disabled by default + and affects all BL images. - ``SEPARATE_NOBITS_REGION``: Setting this option to ``1`` allows the NOBITS sections of BL31 (.bss, stacks, page tables, and coherent memory) to be @@ -550,7 +556,9 @@ Common build options This build option is only valid if ``ARCH=aarch64``. The value should be the path to the directory containing the SPD source, relative to ``services/spd/``; the directory is expected to contain a makefile called - ``<spd-value>.mk``. + ``<spd-value>.mk``. The SPM Dispatcher standard service is located in + services/std_svc/spmd and enabled by ``SPD=spmd``. The SPM Dispatcher + cannot be enabled when the ``SPM_MM`` option is enabled. - ``SPIN_ON_BL1_EXIT``: This option introduces an infinite loop in BL1. It can take either 0 (no loop) or 1 (add a loop). 0 is the default. This loop stops @@ -558,13 +566,23 @@ Common build options firmware images have been loaded in memory, and the MMU and caches are turned off. Refer to the "Debugging options" section for more details. +- ``SPMD_SPM_AT_SEL2`` : this boolean option is used jointly with the SPM + Dispatcher option (``SPD=spmd``). When enabled (1) it indicates the SPMC + component runs at the S-EL2 execution state provided by the Armv8.4-SecEL2 + extension. This is the default when enabling the SPM Dispatcher. When + disabled (0) it indicates the SPMC component runs at the S-EL1 execution + state. This latter configuration supports pre-Armv8.4 platforms (aka not + implementing the Armv8.4-SecEL2 extension). + - ``SPM_MM`` : Boolean option to enable the Management Mode (MM)-based Secure - Partition Manager (SPM) implementation. The default value is ``0``. + Partition Manager (SPM) implementation. The default value is ``0`` + (disabled). This option cannot be enabled (``1``) when SPM Dispatcher is + enabled (``SPD=spmd``). - ``SP_LAYOUT_FILE``: Platform provided path to JSON file containing the - description of secure partitions. Build system will parse this file and - package all secure partition blobs in FIP. This file not necessarily be - part of TF-A tree. Only avaialbe when ``SPD=spmd``. + description of secure partitions. The build system will parse this file and + package all secure partition blobs into the FIP. This file is not + necessarily part of TF-A tree. Only available when ``SPD=spmd``. - ``SP_MIN_WITH_SECURE_FIQ``: Boolean flag to indicate the SP_MIN handles secure interrupts (caught through the FIQ line). Platforms can enable diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c index 4ae55fcc7..40cd4554f 100644 --- a/drivers/st/ddr/stm32mp1_ram.c +++ b/drivers/st/ddr/stm32mp1_ram.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved + * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ @@ -250,8 +250,9 @@ static int stm32mp1_ddr_setup(void) VERBOSE("%s : ram size(%x, %x)\n", __func__, (uint32_t)priv->info.base, (uint32_t)priv->info.size); - write_sctlr(read_sctlr() & ~SCTLR_C_BIT); - dcsw_op_all(DC_OP_CISW); + if (stm32mp_map_ddr_non_cacheable() != 0) { + panic(); + } uret = ddr_test_data_bus(); if (uret != 0U) { @@ -274,7 +275,9 @@ static int stm32mp1_ddr_setup(void) panic(); } - write_sctlr(read_sctlr() | SCTLR_C_BIT); + if (stm32mp_unmap_ddr() != 0) { + panic(); + } return 0; } diff --git a/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S new file mode 100644 index 000000000..f350455d5 --- /dev/null +++ b/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <common/bl_common.h> +#include <platform_def.h> + + .globl plat_get_my_entrypoint + .globl plat_secondary_cold_boot_setup + .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 + +/* ----------------------------------------------------------------------- + * Indicate a cold boot for every CPU - warm boot is unsupported for the + * holding pen PSCI implementation. + * ----------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + mov x0, #0 + ret +endfunc plat_get_my_entrypoint + +/* ----------------------------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * ----------------------------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* + * 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 +poll_hold_entry: + ldr x3, [x1, x0] + cmp x3, #PLAT_FPGA_HOLD_STATE_GO + b.ne 1f + ldr x3, [x2] + br x3 +1: + wfe + b poll_hold_entry +endfunc plat_secondary_cold_boot_setup + +/* ----------------------------------------------------------------------- + * unsigned int plat_is_my_cpu_primary (void); + * + * Find out whether the current cpu is the primary cpu + * ----------------------------------------------------------------------- + */ +func plat_is_my_cpu_primary + mrs x0, mpidr_el1 + mov_imm x1, MPIDR_AFFINITY_MASK + and x0, x0, x1 + cmp x0, #FPGA_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + +func platform_mem_init + ret +endfunc platform_mem_init + +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_fpga_calc_core_pos +endfunc plat_my_core_pos + +/* ----------------------------------------------------------------------- + * unsigned int plat_fpga_calc_core_pos(u_register_t mpidr) + * ----------------------------------------------------------------------- + */ +func plat_fpga_calc_core_pos + /* + * Check for MT bit in MPIDR, which may be either value for images + * running on the FPGA. + * + * 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 + csel x3, x3, x0, eq + + /* Extract individual affinity fields from MPIDR */ + ubfx x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS + 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 + madd x0, x1, x5, x0 + ret +endfunc plat_fpga_calc_core_pos + +func plat_crash_console_init + mov_imm x0, PLAT_FPGA_CRASH_UART_BASE + mov_imm x1, PLAT_FPGA_CRASH_UART_CLK_IN_HZ + mov_imm x2, PLAT_FPGA_CONSOLE_BAUDRATE + b console_pl011_core_init +endfunc plat_crash_console_init + +func plat_crash_console_putc + mov_imm x1, PLAT_FPGA_CRASH_UART_BASE + b console_pl011_core_putc +endfunc plat_crash_console_putc + +func plat_crash_console_flush + mov_imm x0, PLAT_FPGA_CRASH_UART_BASE + b console_pl011_core_flush +endfunc plat_crash_console_flush diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c new file mode 100644 index 000000000..d499379ee --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <lib/mmio.h> +#include <drivers/generic_delay_timer.h> + +#include <plat/common/platform.h> +#include <platform_def.h> + +#include "fpga_private.h" + +static entry_point_info_t bl33_image_ep_info; + +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + return 0; +#endif +} + +uint32_t fpga_get_spsr_for_bl33_entry(void) +{ + return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + fpga_console_init(); + + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + bl33_image_ep_info.spsr = fpga_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + + /* Set x0-x3 for the primary CPU as expected by the kernel */ + bl33_image_ep_info.args.arg0 = (u_register_t)FPGA_PRELOADED_DTB_BASE; + bl33_image_ep_info.args.arg1 = 0U; + bl33_image_ep_info.args.arg2 = 0U; + bl33_image_ep_info.args.arg3 = 0U; +} + +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(); + mmio_write_32(FPGA_TIMER_BASE, ((1 << 8) | 1UL)); +} + +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + next_image_info = &bl33_image_ep_info; + + /* Only expecting BL33: the kernel will run in EL2NS */ + assert(type == NON_SECURE); + + /* None of the images can have 0x0 as the entrypoint */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return FPGA_TIMER_FREQUENCY; +} + +void bl31_plat_enable_mmu(uint32_t flags) +{ + /* TODO: determine if MMU needs to be enabled */ +} diff --git a/plat/arm/board/arm_fpga/fpga_console.c b/plat/arm/board/arm_fpga/fpga_console.c new file mode 100644 index 000000000..b4ebf3424 --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_console.c @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <drivers/console.h> +#include <drivers/arm/pl011.h> + +#include <platform_def.h> + +static console_t console; + +void fpga_console_init(void) +{ + (void)console_pl011_register(PLAT_FPGA_BOOT_UART_BASE, + PLAT_FPGA_BOOT_UART_CLK_IN_HZ, + PLAT_FPGA_CONSOLE_BAUDRATE, + &console); + + console_set_scope(&console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME); +} diff --git a/plat/arm/board/arm_fpga/fpga_def.h b/plat/arm/board/arm_fpga/fpga_def.h new file mode 100644 index 000000000..56ee1663d --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_def.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <lib/utils_def.h> + +#ifndef FPGA_DEF_H +#define FPGA_DEF_H + +/* + * These are set to large values to account for images describing systems with + * larger cluster configurations. + * + * For cases where the number of clusters, cores or threads is smaller than a + * maximum value below, this does not affect the PSCI functionality as any PEs + * 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 2 +#define FPGA_MAX_CPUS_PER_CLUSTER 8 +#define FPGA_MAX_PE_PER_CPU 4 + +#define FPGA_PRIMARY_CPU 0x0 + +/******************************************************************************* + * FPGA image memory map related constants + ******************************************************************************/ + +/* UART base address and clock frequency, as configured by the image */ +#define PLAT_FPGA_BOOT_UART_BASE 0x7ff80000 +#define PLAT_FPGA_BOOT_UART_CLK_IN_HZ 10000000 + +#define PLAT_FPGA_CRASH_UART_BASE PLAT_FPGA_BOOT_UART_BASE +#define PLAT_FPGA_CRASH_UART_CLK_IN_HZ PLAT_FPGA_BOOT_UART_CLK_IN_HZ + +#define FPGA_TIMER_FREQUENCY 10000000 +#define FPGA_TIMER_BASE 0x2a830000 + +#endif diff --git a/plat/arm/board/arm_fpga/fpga_gicv3.c b/plat/arm/board/arm_fpga/fpga_gicv3.c new file mode 100644 index 000000000..be1684e4b --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_gicv3.c @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <drivers/arm/gicv3.h> +#include <drivers/arm/gic_common.h> + +#include <plat/common/platform.h> +#include <platform_def.h> + +static const interrupt_prop_t fpga_interrupt_props[] = { + PLATFORM_G1S_PROPS(INTR_GROUP1S), + PLATFORM_G0_PROPS(INTR_GROUP0) +}; + +static uintptr_t fpga_rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +static unsigned int fpga_mpidr_to_core_pos(unsigned long mpidr) +{ + return (unsigned int)plat_core_pos_by_mpidr(mpidr); +} + +static const gicv3_driver_data_t fpga_gicv3_driver_data = { + .gicd_base = GICD_BASE, + .gicr_base = GICR_BASE, + .interrupt_props = fpga_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(fpga_interrupt_props), + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = fpga_rdistif_base_addrs, + .mpidr_to_core_pos = fpga_mpidr_to_core_pos +}; + +void plat_fpga_gic_init(void) +{ + gicv3_driver_init(&fpga_gicv3_driver_data); + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void fpga_pwr_gic_on_finish(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +void fpga_pwr_gic_off(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); + gicv3_rdistif_off(plat_my_core_pos()); +} diff --git a/plat/arm/board/arm_fpga/fpga_pm.c b/plat/arm/board/arm_fpga/fpga_pm.c new file mode 100644 index 000000000..4c372179f --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_pm.c @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> + +#include <lib/psci/psci.h> +#include <plat/arm/common/plat_arm.h> +#include <plat/common/platform.h> + +#include "fpga_private.h" +#include <platform_def.h> + +/* + * This is a basic PSCI implementation that allows secondary CPUs to be + * released from their initial state and continue to the warm boot entrypoint. + * + * The secondary CPUs are placed in a holding pen and released by calls + * to fpga_pwr_domain_on(mpidr), which updates the hold entry for the CPU + * specified by the mpidr argument - the (polling) target CPU will then branch + * to the BL31 warm boot sequence at the entrypoint address. + * + * Additionally, the secondary CPUs are kept in a low-power wfe() state + * (placed there at the end of each poll) and woken when necessary through + * calls to sev() in fpga_pwr_domain_on(mpidr), once the hold state for the + * relevant CPU has been updated. + * + * Hotplug is currently implemented using a wfi-loop, which removes the + * dependencies on any power controllers or other mechanism that is specific + * to the running system as specified by the FPGA image. + */ + +uint64_t hold_base[PLATFORM_CORE_COUNT]; +uintptr_t fpga_sec_entrypoint; + +/* + * Calls to the CPU specified by the mpidr will set its hold entry to a value + * indicating that it should stop polling and branch off to the warm entrypoint. + */ +static int fpga_pwr_domain_on(u_register_t mpidr) +{ + unsigned int pos = plat_core_pos_by_mpidr(mpidr); + unsigned long current_mpidr = read_mpidr_el1(); + + if (mpidr == current_mpidr) { + return PSCI_E_ALREADY_ON; + } + hold_base[pos] = PLAT_FPGA_HOLD_STATE_GO; + flush_dcache_range((uintptr_t)&hold_base[pos], sizeof(uint64_t)); + sev(); /* Wake any CPUs from wfe */ + + return PSCI_E_SUCCESS; +} + +void fpga_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + fpga_pwr_gic_on_finish(); +} + +static void fpga_pwr_domain_off(const psci_power_state_t *target_state) +{ + fpga_pwr_gic_off(); + + while (1) { + wfi(); + } +} + +static void fpga_cpu_standby(plat_local_state_t cpu_state) +{ + /* + * Enter standby state + * dsb is good practice before using wfi to enter low power states + */ + u_register_t scr = read_scr_el3(); + write_scr_el3(scr|SCR_IRQ_BIT); + dsb(); + wfi(); + write_scr_el3(scr); +} + +plat_psci_ops_t plat_fpga_psci_pm_ops = { + .pwr_domain_on = fpga_pwr_domain_on, + .pwr_domain_on_finish = fpga_pwr_domain_on_finish, + .pwr_domain_off = fpga_pwr_domain_off, + .cpu_standby = fpga_cpu_standby +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + fpga_sec_entrypoint = sec_entrypoint; + flush_dcache_range((uint64_t)&fpga_sec_entrypoint, + sizeof(fpga_sec_entrypoint)); + *psci_ops = &plat_fpga_psci_pm_ops; + return 0; +} diff --git a/plat/arm/board/arm_fpga/fpga_private.h b/plat/arm/board/arm_fpga/fpga_private.h new file mode 100644 index 000000000..7545bd17e --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_private.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FPGA_PRIVATE_H +#define FPGA_PRIVATE_H + +unsigned int plat_fpga_calc_core_pos(u_register_t mpidr); + +void fpga_console_init(void); + +void plat_fpga_gic_init(void); +void fpga_pwr_gic_on_finish(void); +void fpga_pwr_gic_off(void); + +#endif diff --git a/plat/arm/board/arm_fpga/fpga_topology.c b/plat/arm/board/arm_fpga/fpga_topology.c new file mode 100644 index 000000000..a705429ac --- /dev/null +++ b/plat/arm/board/arm_fpga/fpga_topology.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> + +#include "fpga_private.h" +#include <platform_def.h> + +static unsigned char fpga_power_domain_tree_desc[FPGA_MAX_CLUSTER_COUNT + 2]; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + int i; + /* + * The highest level is the system level. The next level is constituted + * by clusters and then cores in clusters. + * + * 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. + */ + 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; + } + + return fpga_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id, thread_id; + + mpidr &= MPIDR_AFFINITY_MASK; + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) { + return -1; + } + + if (mpidr & MPIDR_MT_MASK) { + thread_id = MPIDR_AFFLVL0_VAL(mpidr); + } else { + thread_id = 0; + } + + cpu_id = MPIDR_AFFLVL1_VAL(mpidr); + cluster_id = MPIDR_AFFLVL2_VAL(mpidr); + + if (cluster_id >= FPGA_MAX_CLUSTER_COUNT) { + return -1; + } else if (cpu_id >= FPGA_MAX_CPUS_PER_CLUSTER) { + return -1; + } else if (thread_id >= FPGA_MAX_PE_PER_CPU) { + return -1; + } + + /* + * 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 |= (read_mpidr_el1() & MPIDR_MT_MASK); + + /* Calculate the correct core, catering for multi-threaded images */ + return (int) plat_fpga_calc_core_pos(mpidr); +} diff --git a/plat/arm/board/arm_fpga/include/plat_macros.S b/plat/arm/board/arm_fpga/include/plat_macros.S new file mode 100644 index 000000000..44cddeb36 --- /dev/null +++ b/plat/arm/board/arm_fpga/include/plat_macros.S @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MACROS_S +#define PLAT_MACROS_S + +.macro plat_crash_print_regs +.endm + +#endif diff --git a/plat/arm/board/arm_fpga/include/platform_def.h b/plat/arm/board/arm_fpga/include/platform_def.h new file mode 100644 index 000000000..5c8aff691 --- /dev/null +++ b/plat/arm/board/arm_fpga/include/platform_def.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include <arch.h> +#include <plat/common/common_def.h> +#include <platform_def.h> +#include "../fpga_def.h" + +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" + +#define PLATFORM_LINKER_ARCH aarch64 + +#define PLATFORM_STACK_SIZE UL(0x800) + +#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 PLAT_NUM_PWR_DOMAINS (FPGA_MAX_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + 1 + +#if !ENABLE_PIE +#define BL31_BASE UL(0x80000000) +#define BL31_LIMIT UL(0x80100000) +#else +#define BL31_BASE UL(0x0) +#define BL31_LIMIT UL(0x01000000) +#endif + +#define GICD_BASE 0x30000000 +#define GICR_BASE 0x30040000 + +#define PLAT_SDEI_NORMAL_PRI 0x70 + +#define ARM_IRQ_SEC_PHY_TIMER 29 + +#define ARM_IRQ_SEC_SGI_0 8 +#define ARM_IRQ_SEC_SGI_1 9 +#define ARM_IRQ_SEC_SGI_2 10 +#define ARM_IRQ_SEC_SGI_3 11 +#define ARM_IRQ_SEC_SGI_4 12 +#define ARM_IRQ_SEC_SGI_5 13 +#define ARM_IRQ_SEC_SGI_6 14 +#define ARM_IRQ_SEC_SGI_7 15 + +/* + * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLATFORM_G1S_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define PLATFORM_G0_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, PLAT_SDEI_NORMAL_PRI, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +#define PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 2 + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 + +#define PLAT_FPGA_HOLD_ENTRY_SHIFT 3 +#define PLAT_FPGA_HOLD_STATE_WAIT 0 +#define PLAT_FPGA_HOLD_STATE_GO 1 + +#define PLAT_FPGA_CONSOLE_BAUDRATE 38400 + +#endif diff --git a/plat/arm/board/arm_fpga/platform.mk b/plat/arm/board/arm_fpga/platform.mk new file mode 100644 index 000000000..b4f38fab4 --- /dev/null +++ b/plat/arm/board/arm_fpga/platform.mk @@ -0,0 +1,93 @@ +# +# Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +RESET_TO_BL31 := 1 +ifeq (${RESET_TO_BL31}, 0) +$(error "This is a BL31-only port; RESET_TO_BL31 must be enabled") +endif + +ifeq (${ENABLE_PIE}, 1) +override SEPARATE_CODE_AND_RODATA := 1 +endif + +CTX_INCLUDE_AARCH32_REGS := 0 +ifeq (${CTX_INCLUDE_AARCH32_REGS}, 1) +$(error "This is an AArch64-only port; CTX_INCLUDE_AARCH32_REGS must be disabled") +endif + +ifeq (${TRUSTED_BOARD_BOOT}, 1) +$(error "TRUSTED_BOARD_BOOT must be disabled") +endif + +ifndef PRELOADED_BL33_BASE +$(error "PRELOADED_BL33_BASE is not set") +endif + +ifndef FPGA_PRELOADED_DTB_BASE +$(error "FPGA_PRELOADED_DTB_BASE is not set") +else +$(eval $(call add_define,FPGA_PRELOADED_DTB_BASE)) +endif + +# Treating this as a memory-constrained port for now +USE_COHERENT_MEM := 0 + +# This can be overridden depending on CPU(s) used in the FPGA image +HW_ASSISTED_COHERENCY := 1 + +FPGA_CPU_LIBS := lib/cpus/${ARCH}/aem_generic.S + +# select a different set of CPU files, depending on whether we compile for +# hardware assisted coherency cores or not +ifeq (${HW_ASSISTED_COHERENCY}, 0) +# Cores used without DSU + FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a35.S \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S \ + lib/cpus/aarch64/cortex_a72.S \ + lib/cpus/aarch64/cortex_a73.S +else +# AArch64-only cores + FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a76.S \ + lib/cpus/aarch64/cortex_a76ae.S \ + lib/cpus/aarch64/cortex_a77.S \ + lib/cpus/aarch64/neoverse_n1.S \ + lib/cpus/aarch64/neoverse_e1.S \ + lib/cpus/aarch64/neoverse_zeus.S \ + lib/cpus/aarch64/cortex_hercules.S \ + lib/cpus/aarch64/cortex_hercules_ae.S \ + lib/cpus/aarch64/cortex_a65.S \ + lib/cpus/aarch64/cortex_a65ae.S +# AArch64/AArch32 cores + FPGA_CPU_LIBS += lib/cpus/aarch64/cortex_a55.S \ + lib/cpus/aarch64/cortex_a75.S +endif + +FPGA_GIC_SOURCES := drivers/arm/gic/v3/gicv3_helpers.c \ + drivers/arm/gic/v3/gicdv3_helpers.c \ + drivers/arm/gic/v3/gicrv3_helpers.c \ + drivers/arm/gic/v3/gicv3_main.c \ + drivers/arm/gic/v3/gic600.c \ + drivers/arm/gic/common/gic_common.c \ + plat/common/plat_gicv3.c \ + plat/arm/board/arm_fpga/fpga_gicv3.c + +PLAT_INCLUDES := -Iplat/arm/board/arm_fpga/include + +PLAT_BL_COMMON_SOURCES := plat/arm/board/arm_fpga/${ARCH}/fpga_helpers.S + +BL31_SOURCES += drivers/delay_timer/delay_timer.c \ + drivers/delay_timer/generic_delay_timer.c \ + drivers/arm/pl011/${ARCH}/pl011_console.S \ + plat/common/plat_psci_common.c \ + plat/arm/board/arm_fpga/fpga_pm.c \ + plat/arm/board/arm_fpga/fpga_topology.c \ + plat/arm/board/arm_fpga/fpga_console.c \ + plat/arm/board/arm_fpga/fpga_bl31_setup.c \ + ${FPGA_CPU_LIBS} \ + ${FPGA_GIC_SOURCES} + +all: bl31 diff --git a/plat/arm/css/sgi/sgi_bl31_setup.c b/plat/arm/css/sgi/sgi_bl31_setup.c index fcb7e1f9f..a4aed004d 100644 --- a/plat/arm/css/sgi/sgi_bl31_setup.c +++ b/plat/arm/css/sgi/sgi_bl31_setup.c @@ -75,7 +75,7 @@ scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id) { if (sgi_plat_info.platform_id == RD_N1E1_EDGE_SID_VER_PART_NUM || sgi_plat_info.platform_id == RD_DANIEL_SID_VER_PART_NUM) { - if (channel_id >= sizeof(rd_n1e1_edge_scmi_plat_info)) + if (channel_id >= ARRAY_SIZE(rd_n1e1_edge_scmi_plat_info)) panic(); return &rd_n1e1_edge_scmi_plat_info[channel_id]; } diff --git a/plat/common/plat_psci_common.c b/plat/common/plat_psci_common.c index bed8890a7..c32e59f9c 100644 --- a/plat/common/plat_psci_common.c +++ b/plat/common/plat_psci_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2019, 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 @@ -63,7 +63,6 @@ static u_register_t calc_stat_residency(unsigned long long pwrupts, /* * Capture timestamp before entering a low power state. - * No cache maintenance is required when capturing the timestamp. * Cache maintenance may be needed when reading these timestamps. */ void plat_psci_stat_accounting_start( @@ -71,12 +70,11 @@ void plat_psci_stat_accounting_start( { assert(state_info != NULL); PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_ENTER_LOW_PWR, - PMF_NO_CACHE_MAINT); + PMF_CACHE_MAINT); } /* * Capture timestamp after exiting a low power state. - * No cache maintenance is required when capturing the timestamp. * Cache maintenance may be needed when reading these timestamps. */ void plat_psci_stat_accounting_stop( @@ -84,7 +82,7 @@ void plat_psci_stat_accounting_stop( { assert(state_info != NULL); PMF_CAPTURE_TIMESTAMP(psci_svc, PSCI_STAT_ID_EXIT_LOW_PWR, - PMF_NO_CACHE_MAINT); + PMF_CACHE_MAINT); } /* diff --git a/plat/st/common/include/stm32mp_common.h b/plat/st/common/include/stm32mp_common.h index 4f8567979..27ddab0c8 100644 --- a/plat/st/common/include/stm32mp_common.h +++ b/plat/st/common/include/stm32mp_common.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved + * Copyright (C) 2018-2020, STMicroelectronics - All Rights Reserved * * SPDX-License-Identifier: BSD-3-Clause */ @@ -87,4 +87,8 @@ void stm32mp_io_setup(void); */ int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer); +/* Functions to map DDR in MMU with non-cacheable attribute, and unmap it */ +int stm32mp_map_ddr_non_cacheable(void); +int stm32mp_unmap_ddr(void); + #endif /* STM32MP_COMMON_H */ diff --git a/plat/st/common/stm32mp_common.c b/plat/st/common/stm32mp_common.c index afa87f487..9af156457 100644 --- a/plat/st/common/stm32mp_common.c +++ b/plat/st/common/stm32mp_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -12,6 +12,7 @@ #include <arch_helpers.h> #include <common/debug.h> #include <drivers/st/stm32mp_clkfunc.h> +#include <lib/xlat_tables/xlat_tables_v2.h> #include <plat/common/platform.h> uintptr_t plat_get_ns_image_entrypoint(void) @@ -151,3 +152,16 @@ int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer) return 0; } + +int stm32mp_map_ddr_non_cacheable(void) +{ + return mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, + STM32MP_DDR_MAX_SIZE, + MT_NON_CACHEABLE | MT_RW | MT_NS); +} + +int stm32mp_unmap_ddr(void) +{ + return mmap_remove_dynamic_region(STM32MP_DDR_BASE, + STM32MP_DDR_MAX_SIZE); +} diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c index 024dbe076..652765ce1 100644 --- a/plat/st/stm32mp1/bl2_plat_setup.c +++ b/plat/st/stm32mp1/bl2_plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -130,6 +130,7 @@ void bl2_el3_early_platform_setup(u_register_t arg0, void bl2_platform_setup(void) { int ret; + uint32_t ddr_ns_size; if (dt_pmic_status() > 0) { initialize_pmic(); @@ -141,8 +142,24 @@ void bl2_platform_setup(void) panic(); } + ddr_ns_size = stm32mp_get_ddr_ns_size(); + assert(ddr_ns_size > 0U); + + /* Map non secure DDR for BL33 load, now with cacheable attribute */ + ret = mmap_add_dynamic_region(STM32MP_DDR_BASE, STM32MP_DDR_BASE, + ddr_ns_size, MT_MEMORY | MT_RW | MT_NS); + assert(ret == 0); + #ifdef AARCH32_SP_OPTEE INFO("BL2 runs OP-TEE setup\n"); + + /* Map secure DDR for OP-TEE paged area */ + ret = mmap_add_dynamic_region(STM32MP_DDR_BASE + ddr_ns_size, + STM32MP_DDR_BASE + ddr_ns_size, + STM32MP_DDR_S_SIZE, + MT_MEMORY | MT_RW | MT_SECURE); + assert(ret == 0); + /* Initialize tzc400 after DDR initialization */ stm32mp1_security_setup(); #else @@ -166,14 +183,6 @@ void bl2_el3_plat_arch_setup(void) MT_CODE | MT_SECURE); #ifdef AARCH32_SP_OPTEE - /* OP-TEE image needs post load processing: keep RAM read/write */ - mmap_add_region(STM32MP_DDR_BASE + dt_get_ddr_size() - - STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE, - STM32MP_DDR_BASE + dt_get_ddr_size() - - STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE, - STM32MP_DDR_S_SIZE, - MT_MEMORY | MT_RW | MT_SECURE); - mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE, STM32MP_OPTEE_SIZE, MT_MEMORY | MT_RW | MT_SECURE); @@ -181,19 +190,12 @@ void bl2_el3_plat_arch_setup(void) /* Prevent corruption of preloaded BL32 */ mmap_add_region(BL32_BASE, BL32_BASE, BL32_LIMIT - BL32_BASE, - MT_MEMORY | MT_RO | MT_SECURE); - + MT_RO_DATA | MT_SECURE); #endif - /* Map non secure DDR for BL33 load and DDR training area restore */ - mmap_add_region(STM32MP_DDR_BASE, - STM32MP_DDR_BASE, - STM32MP_DDR_MAX_SIZE, - MT_MEMORY | MT_RW | MT_NS); - /* Prevent corruption of preloaded Device Tree */ mmap_add_region(DTB_BASE, DTB_BASE, DTB_LIMIT - DTB_BASE, - MT_MEMORY | MT_RO | MT_SECURE); + MT_RO_DATA | MT_SECURE); configure_mmu(); @@ -351,8 +353,7 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); assert(paged_mem_params != NULL); paged_mem_params->image_info.image_base = STM32MP_DDR_BASE + - (dt_get_ddr_size() - STM32MP_DDR_S_SIZE - - STM32MP_DDR_SHMEM_SIZE); + stm32mp_get_ddr_ns_size(); paged_mem_params->image_info.image_max_size = STM32MP_DDR_S_SIZE; diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h index e38fca012..2da64acbc 100644 --- a/plat/st/stm32mp1/include/stm32mp1_private.h +++ b/plat/st/stm32mp1/include/stm32mp1_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -21,4 +21,5 @@ void stm32mp1_syscfg_init(void); void stm32mp1_syscfg_enable_io_compensation(void); void stm32mp1_syscfg_disable_io_compensation(void); +uint32_t stm32mp_get_ddr_ns_size(void); #endif /* STM32MP1_PRIVATE_H */ diff --git a/plat/st/stm32mp1/plat_image_load.c b/plat/st/stm32mp1/plat_image_load.c index a52db6cac..6d7af741a 100644 --- a/plat/st/stm32mp1/plat_image_load.c +++ b/plat/st/stm32mp1/plat_image_load.c @@ -1,9 +1,11 @@ /* - * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ +#include <platform_def.h> + #include <common/desc_image_load.h> #include <plat/common/platform.h> @@ -21,6 +23,13 @@ void plat_flush_next_bl_params(void) ******************************************************************************/ bl_load_info_t *plat_get_bl_image_load_info(void) { + bl_mem_params_node_t *bl33 = get_bl_mem_params_node(BL33_IMAGE_ID); + uint32_t ddr_ns_size = stm32mp_get_ddr_ns_size(); + + /* Max size is non-secure DDR end address minus image_base */ + bl33->image_info.image_max_size = STM32MP_DDR_BASE + ddr_ns_size - + bl33->image_info.image_base; + return get_bl_load_info_from_mem_params_desc(); } diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk index bd1a16bf7..5ce7a9c4f 100644 --- a/plat/st/stm32mp1/platform.mk +++ b/plat/st/stm32mp1/platform.mk @@ -11,6 +11,11 @@ USE_COHERENT_MEM := 0 STM32_TF_VERSION ?= 0 +# Enable dynamic memory mapping +PLAT_XLAT_TABLES_DYNAMIC := 1 +$(eval $(call assert_boolean,PLAT_XLAT_TABLES_DYNAMIC)) +$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC)) + # Not needed for Cortex-A7 WORKAROUND_CVE_2017_5715:= 0 @@ -152,8 +157,6 @@ STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed STM32_TF_STM32 := $(addprefix ${BUILD_PLAT}/tf-a-, $(patsubst %.dtb,%.stm32,$(DTB_FILE_NAME))) STM32_TF_LINKERFILE := ${BUILD_PLAT}/stm32mp1.ld -BL2_CFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC=1 - # Variables for use with stm32image STM32IMAGEPATH ?= tools/stm32image STM32IMAGE ?= ${STM32IMAGEPATH}/stm32image${BIN_EXT} diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h index 5dc520625..fc776ae8b 100644 --- a/plat/st/stm32mp1/stm32mp1_def.h +++ b/plat/st/stm32mp1/stm32mp1_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -62,6 +62,9 @@ #ifdef AARCH32_SP_OPTEE #define STM32MP_DDR_S_SIZE U(0x01E00000) /* 30 MB */ #define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */ +#else +#define STM32MP_DDR_S_SIZE U(0) +#define STM32MP_DDR_SHMEM_SIZE U(0) #endif /* DDR power initializations */ diff --git a/plat/st/stm32mp1/stm32mp1_private.c b/plat/st/stm32mp1/stm32mp1_private.c index e2dcd2af7..ac4519575 100644 --- a/plat/st/stm32mp1/stm32mp1_private.c +++ b/plat/st/stm32mp1/stm32mp1_private.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -365,3 +365,24 @@ uint32_t stm32_iwdg_shadow_update(uint32_t iwdg_inst, uint32_t flags) return BSEC_OK; } #endif + +/* Get the non-secure DDR size */ +uint32_t stm32mp_get_ddr_ns_size(void) +{ + static uint32_t ddr_ns_size; + uint32_t ddr_size; + + if (ddr_ns_size != 0U) { + return ddr_ns_size; + } + + ddr_size = dt_get_ddr_size(); + if ((ddr_size <= (STM32MP_DDR_S_SIZE + STM32MP_DDR_SHMEM_SIZE)) || + (ddr_size > STM32MP_DDR_MAX_SIZE)) { + panic(); + } + + ddr_ns_size = ddr_size - (STM32MP_DDR_S_SIZE + STM32MP_DDR_SHMEM_SIZE); + + return ddr_ns_size; +} diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c index 61db2e7c7..3a29ba966 100644 --- a/plat/st/stm32mp1/stm32mp1_security.c +++ b/plat/st/stm32mp1/stm32mp1_security.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -35,29 +35,30 @@ static void init_tzc400(void) { unsigned long long region_base, region_top; unsigned long long ddr_base = STM32MP_DDR_BASE; - unsigned long long ddr_size = (unsigned long long)dt_get_ddr_size(); - unsigned long long ddr_top = ddr_base + (ddr_size - 1U); + unsigned long long ddr_ns_size = + (unsigned long long)stm32mp_get_ddr_ns_size(); + unsigned long long ddr_ns_top = ddr_base + (ddr_ns_size - 1U); tzc400_init(STM32MP1_TZC_BASE); tzc400_disable_filters(); -#ifdef AARCH32_SP_OPTEE /* * Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the * same configuration to all filters in the TZC. */ region_base = ddr_base; - region_top = ddr_top - STM32MP_DDR_S_SIZE - STM32MP_DDR_SHMEM_SIZE; + region_top = ddr_ns_top; tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1, region_base, region_top, TZC_REGION_S_NONE, TZC_REGION_NSEC_ALL_ACCESS_RDWR); +#ifdef AARCH32_SP_OPTEE /* Region 2 set to cover all secure DRAM. */ region_base = region_top + 1U; - region_top = ddr_top - STM32MP_DDR_SHMEM_SIZE; + region_top += STM32MP_DDR_S_SIZE; tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 2, region_base, region_top, @@ -66,24 +67,12 @@ static void init_tzc400(void) /* Region 3 set to cover non-secure shared memory DRAM. */ region_base = region_top + 1U; - region_top = ddr_top; + region_top += STM32MP_DDR_SHMEM_SIZE; tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 3, region_base, region_top, TZC_REGION_S_NONE, TZC_REGION_NSEC_ALL_ACCESS_RDWR); -#else - /* - * Region 1 set to cover all DRAM at 0xC000_0000. Apply the - * same configuration to all filters in the TZC. - */ - region_base = ddr_base; - region_top = ddr_top; - tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, 1, - region_base, - region_top, - TZC_REGION_S_NONE, - TZC_REGION_NSEC_ALL_ACCESS_RDWR); #endif /* Raise an exception if a NS device tries to access secure memory */ |