diff options
Diffstat (limited to 'plat')
-rw-r--r-- | plat/arm/board/fvp/fvp_common.c | 70 | ||||
-rw-r--r-- | plat/arm/board/fvp/fvp_pm.c | 5 | ||||
-rw-r--r-- | plat/arm/common/aarch64/arm_ehf.c | 24 | ||||
-rw-r--r-- | plat/arm/common/aarch64/arm_helpers.S | 29 | ||||
-rw-r--r-- | plat/arm/common/aarch64/arm_sdei.c | 33 | ||||
-rw-r--r-- | plat/arm/common/arm_common.c | 57 | ||||
-rw-r--r-- | plat/arm/common/arm_common.mk | 8 | ||||
-rw-r--r-- | plat/arm/common/arm_gicv2.c | 1 | ||||
-rw-r--r-- | plat/arm/common/arm_pm.c | 22 | ||||
-rw-r--r-- | plat/arm/common/arm_tzc400.c | 22 | ||||
-rw-r--r-- | plat/arm/css/common/css_pm.c | 2 | ||||
-rw-r--r-- | plat/common/aarch64/plat_common.c | 26 | ||||
-rw-r--r-- | plat/common/plat_gicv2.c | 10 | ||||
-rw-r--r-- | plat/common/plat_gicv3.c | 8 | ||||
-rw-r--r-- | plat/common/plat_psci_common.c | 9 |
15 files changed, 284 insertions, 42 deletions
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c index 57cc3d513..6729863d7 100644 --- a/plat/arm/board/fvp/fvp_common.c +++ b/plat/arm/board/fvp/fvp_common.c @@ -6,6 +6,7 @@ #include <arm_config.h> #include <arm_def.h> +#include <arm_spm_def.h> #include <assert.h> #include <cci.h> #include <ccn.h> @@ -13,6 +14,7 @@ #include <gicv2.h> #include <mmio.h> #include <plat_arm.h> +#include <secure_partition.h> #include <v2m_def.h> #include "../fvp_def.h" @@ -89,6 +91,9 @@ const mmap_region_t plat_arm_mmap[] = { /* To access the Root of Trust Public Key registers. */ MAP_DEVICE2, #endif +#if ENABLE_SPM + ARM_SP_IMAGE_MMAP, +#endif #if ARM_BL31_IN_DRAM ARM_MAP_BL31_SEC_DRAM, #endif @@ -114,9 +119,23 @@ const mmap_region_t plat_arm_mmap[] = { MAP_DEVICE0, MAP_DEVICE1, ARM_V2M_MAP_MEM_PROTECT, +#if ENABLE_SPM + ARM_SPM_BUF_EL3_MMAP, +#endif + {0} +}; + +#if ENABLE_SPM && defined(IMAGE_BL31) +const mmap_region_t plat_arm_secure_partition_mmap[] = { + V2M_MAP_IOFPGA_EL0, /* for the UART */ + ARM_SP_IMAGE_MMAP, + ARM_SP_IMAGE_NS_BUF_MMAP, + ARM_SP_IMAGE_RW_MMAP, + ARM_SPM_BUF_EL0_MMAP, {0} }; #endif +#endif #ifdef IMAGE_BL32 const mmap_region_t plat_arm_mmap[] = { #ifdef AARCH32 @@ -156,6 +175,57 @@ static unsigned int get_interconnect_master(void) } #endif +#if ENABLE_SPM && defined(IMAGE_BL31) +/* + * Boot information passed to a secure partition during initialisation. Linear + * indices in MP information will be filled at runtime. + */ +static secure_partition_mp_info_t sp_mp_info[] = { + [0] = {0x80000000, 0}, + [1] = {0x80000001, 0}, + [2] = {0x80000002, 0}, + [3] = {0x80000003, 0}, + [4] = {0x80000100, 0}, + [5] = {0x80000101, 0}, + [6] = {0x80000102, 0}, + [7] = {0x80000103, 0}, +}; + +const secure_partition_boot_info_t plat_arm_secure_partition_boot_info = { + .h.type = PARAM_SP_IMAGE_BOOT_INFO, + .h.version = VERSION_1, + .h.size = sizeof(secure_partition_boot_info_t), + .h.attr = 0, + .sp_mem_base = ARM_SP_IMAGE_BASE, + .sp_mem_limit = ARM_SP_IMAGE_LIMIT, + .sp_image_base = ARM_SP_IMAGE_BASE, + .sp_stack_base = PLAT_SP_IMAGE_STACK_BASE, + .sp_heap_base = ARM_SP_IMAGE_HEAP_BASE, + .sp_ns_comm_buf_base = ARM_SP_IMAGE_NS_BUF_BASE, + .sp_shared_buf_base = PLAT_SPM_BUF_BASE, + .sp_image_size = ARM_SP_IMAGE_SIZE, + .sp_pcpu_stack_size = PLAT_SP_IMAGE_STACK_PCPU_SIZE, + .sp_heap_size = ARM_SP_IMAGE_HEAP_SIZE, + .sp_ns_comm_buf_size = ARM_SP_IMAGE_NS_BUF_SIZE, + .sp_shared_buf_size = PLAT_SPM_BUF_SIZE, + .num_sp_mem_regions = ARM_SP_IMAGE_NUM_MEM_REGIONS, + .num_cpus = PLATFORM_CORE_COUNT, + .mp_info = &sp_mp_info[0], +}; + +const struct mmap_region *plat_get_secure_partition_mmap(void *cookie) +{ + return plat_arm_secure_partition_mmap; +} + +const struct secure_partition_boot_info *plat_get_secure_partition_boot_info( + void *cookie) +{ + return &plat_arm_secure_partition_boot_info; +} + +#endif + /******************************************************************************* * A single boot loader stack is expected to work on both the Foundation FVP * models and the two flavours of the Base FVP models (AEMv8 & Cortex). The diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c index faeb1b777..13bd8f237 100644 --- a/plat/arm/board/fvp/fvp_pm.c +++ b/plat/arm/board/fvp/fvp_pm.c @@ -14,6 +14,7 @@ #include <plat_arm.h> #include <platform.h> #include <psci.h> +#include <spe.h> #include <v2m_def.h> #include "drivers/pwrc/fvp_pwrc.h" #include "fvp_def.h" @@ -57,7 +58,7 @@ static void fvp_cluster_pwrdwn_common(void) * On power down we need to disable statistical profiling extensions * before exiting coherency. */ - arm_disable_spe(); + spe_disable(); #endif /* Disable coherency if this cluster is to be turned off */ @@ -398,7 +399,7 @@ plat_psci_ops_t plat_arm_psci_pm_ops = { .system_off = fvp_system_off, .system_reset = fvp_system_reset, .validate_power_state = fvp_validate_power_state, - .validate_ns_entrypoint = arm_validate_ns_entrypoint, + .validate_ns_entrypoint = arm_validate_psci_entrypoint, .translate_power_state_by_mpidr = fvp_translate_power_state_by_mpidr, .get_node_hw_state = fvp_node_hw_state, .get_sys_suspend_power_state = fvp_get_sys_suspend_power_state, diff --git a/plat/arm/common/aarch64/arm_ehf.c b/plat/arm/common/aarch64/arm_ehf.c new file mode 100644 index 000000000..785b7bb54 --- /dev/null +++ b/plat/arm/common/aarch64/arm_ehf.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <ehf.h> +#include <platform_def.h> + +/* + * Enumeration of priority levels on ARM platforms. + */ +ehf_pri_desc_t arm_exceptions[] = { +#if SDEI_SUPPORT + /* Critical priority SDEI */ + EHF_PRI_DESC(ARM_PRI_BITS, PLAT_SDEI_CRITICAL_PRI), + + /* Normal priority SDEI */ + EHF_PRI_DESC(ARM_PRI_BITS, PLAT_SDEI_NORMAL_PRI), +#endif +}; + +/* Plug in ARM exceptions to Exception Handling Framework. */ +EHF_REGISTER_PRIORITIES(arm_exceptions, ARRAY_SIZE(arm_exceptions), ARM_PRI_BITS); diff --git a/plat/arm/common/aarch64/arm_helpers.S b/plat/arm/common/aarch64/arm_helpers.S index b53e60dba..9d3a10819 100644 --- a/plat/arm/common/aarch64/arm_helpers.S +++ b/plat/arm/common/aarch64/arm_helpers.S @@ -12,7 +12,6 @@ .globl plat_crash_console_putc .globl plat_crash_console_flush .globl platform_mem_init - .globl arm_disable_spe /* ----------------------------------------------------- @@ -88,34 +87,6 @@ func platform_mem_init ret endfunc platform_mem_init - /* ----------------------------------------------------- - * void arm_disable_spe (void); - * ----------------------------------------------------- - */ -#if ENABLE_SPE_FOR_LOWER_ELS -func arm_disable_spe - /* Detect if SPE is implemented */ - mrs x0, id_aa64dfr0_el1 - ubfx x0, x0, #ID_AA64DFR0_PMS_SHIFT, #ID_AA64DFR0_PMS_LENGTH - cmp x0, #0x1 - b.ne 1f - - /* Drain buffered data */ - .arch armv8.2-a+profile - psb csync - dsb nsh - - /* Disable Profiling Buffer */ - mrs x0, pmblimitr_el1 - bic x0, x0, #1 - msr pmblimitr_el1, x0 - isb - .arch armv8-a -1: - ret -endfunc arm_disable_spe -#endif - /* * Need to use coherent stack when ARM Cryptocell is used to autheticate images * since Cryptocell uses DMA to transfer data and it is not coherent with the diff --git a/plat/arm/common/aarch64/arm_sdei.c b/plat/arm/common/aarch64/arm_sdei.c new file mode 100644 index 000000000..514800c3e --- /dev/null +++ b/plat/arm/common/aarch64/arm_sdei.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* SDEI configuration for ARM platforms */ + +#include <ehf.h> +#include <platform_def.h> +#include <sdei.h> + +/* Private event mappings */ +static sdei_ev_map_t arm_private_sdei[] = { + /* Event 0 */ + SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI), + + /* Dynamic private events */ + SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), +}; + +/* Shared event mappings */ +static sdei_ev_map_t arm_shared_sdei[] = { + /* Dynamic shared events */ + SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), +}; + +/* Export ARM SDEI events */ +REGISTER_SDEI_MAP(arm_private_sdei, arm_shared_sdei); diff --git a/plat/arm/common/arm_common.c b/plat/arm/common/arm_common.c index 420a38651..bf6397377 100644 --- a/plat/arm/common/arm_common.c +++ b/plat/arm/common/arm_common.c @@ -11,6 +11,7 @@ #include <mmio.h> #include <plat_arm.h> #include <platform_def.h> +#include <secure_partition.h> extern const mmap_region_t plat_arm_mmap[]; @@ -79,6 +80,14 @@ void arm_setup_page_tables(uintptr_t total_base, MT_DEVICE | MT_RW | MT_SECURE); #endif +#if ENABLE_SPM && defined(IMAGE_BL31) + /* The address of the following region is calculated by the linker. */ + mmap_add_region(SP_IMAGE_XLAT_TABLES_START, + SP_IMAGE_XLAT_TABLES_START, + SP_IMAGE_XLAT_TABLES_SIZE, + MT_MEMORY | MT_RW | MT_SECURE); +#endif + /* Now (re-)map the platform-specific memory regions */ mmap_add(plat_arm_get_mmap()); @@ -195,3 +204,51 @@ unsigned int plat_get_syscnt_freq2(void) } #endif /* ARM_SYS_CNTCTL_BASE */ + +#if SDEI_SUPPORT +/* + * Translate SDEI entry point to PA, and perform standard ARM entry point + * validation on it. + */ +int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode) +{ + uint64_t par, pa; + uint32_t scr_el3; + + /* Doing Non-secure address translation requires SCR_EL3.NS set */ + scr_el3 = read_scr_el3(); + write_scr_el3(scr_el3 | SCR_NS_BIT); + isb(); + + assert((client_mode == MODE_EL2) || (client_mode == MODE_EL1)); + if (client_mode == MODE_EL2) { + /* + * Translate entry point to Physical Address using the EL2 + * translation regime. + */ + ats1e2r(ep); + } else { + /* + * Translate entry point to Physical Address using the EL1&0 + * translation regime, including stage 2. + */ + ats12e1r(ep); + } + isb(); + par = read_par_el1(); + + /* Restore original SCRL_EL3 */ + write_scr_el3(scr_el3); + isb(); + + /* If the translation resulted in fault, return failure */ + if ((par & PAR_F_MASK) != 0) + return -1; + + /* Extract Physical Address from PAR */ + pa = (par & (PAR_ADDR_MASK << PAR_ADDR_SHIFT)); + + /* Perform NS entry point validation on the physical address */ + return arm_validate_ns_entrypoint(pa); +} +#endif diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index 44eb43f62..17acae52f 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -184,6 +184,14 @@ BL31_SOURCES += plat/arm/common/arm_sip_svc.c \ lib/pmf/pmf_smc.c endif +ifeq (${EL3_EXCEPTION_HANDLING},1) +BL31_SOURCES += plat/arm/common/aarch64/arm_ehf.c +endif + +ifeq (${SDEI_SUPPORT},1) +BL31_SOURCES += plat/arm/common/aarch64/arm_sdei.c +endif + ifneq (${TRUSTED_BOARD_BOOT},0) # Include common TBB sources diff --git a/plat/arm/common/arm_gicv2.c b/plat/arm/common/arm_gicv2.c index b081fa8d9..5644c6040 100644 --- a/plat/arm/common/arm_gicv2.c +++ b/plat/arm/common/arm_gicv2.c @@ -51,6 +51,7 @@ void plat_arm_gic_init(void) { gicv2_distif_init(); gicv2_pcpu_distif_init(); + gicv2_set_pe_target_mask(plat_my_core_pos()); gicv2_cpuif_enable(); } diff --git a/plat/arm/common/arm_pm.c b/plat/arm/common/arm_pm.c index 5e7e047a5..44ac5b5d6 100644 --- a/plat/arm/common/arm_pm.c +++ b/plat/arm/common/arm_pm.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -112,7 +112,7 @@ int arm_validate_power_state(unsigned int power_state, /******************************************************************************* * ARM standard platform handler called to check the validity of the non secure - * entrypoint. + * entrypoint. Returns 0 if the entrypoint is valid, or -1 otherwise. ******************************************************************************/ int arm_validate_ns_entrypoint(uintptr_t entrypoint) { @@ -121,15 +121,23 @@ int arm_validate_ns_entrypoint(uintptr_t entrypoint) * secure DRAM. */ if ((entrypoint >= ARM_NS_DRAM1_BASE) && (entrypoint < - (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) - return PSCI_E_SUCCESS; + (ARM_NS_DRAM1_BASE + ARM_NS_DRAM1_SIZE))) { + return 0; + } #ifndef AARCH32 if ((entrypoint >= ARM_DRAM2_BASE) && (entrypoint < - (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) - return PSCI_E_SUCCESS; + (ARM_DRAM2_BASE + ARM_DRAM2_SIZE))) { + return 0; + } #endif - return PSCI_E_INVALID_ADDRESS; + return -1; +} + +int arm_validate_psci_entrypoint(uintptr_t entrypoint) +{ + return arm_validate_ns_entrypoint(entrypoint) == 0 ? PSCI_E_SUCCESS : + PSCI_E_INVALID_ADDRESS; } /****************************************************************************** diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c index e19ca673f..23c031734 100644 --- a/plat/arm/common/arm_tzc400.c +++ b/plat/arm/common/arm_tzc400.c @@ -1,10 +1,11 @@ /* - * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ #include <arm_def.h> +#include <arm_spm_def.h> #include <debug.h> #include <platform_def.h> #include <tzc400.h> @@ -56,9 +57,26 @@ void arm_tzc400_setup(void) ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS, PLAT_ARM_TZC_NS_DEV_ACCESS); -#else + +#if ENABLE_SPM + /* + * Region 4 set to cover Non-Secure access to the communication buffer + * shared with the Secure world. + */ + tzc400_configure_region(PLAT_ARM_TZC_FILTERS, + 4, + ARM_SP_IMAGE_NS_BUF_BASE, + (ARM_SP_IMAGE_NS_BUF_BASE + + ARM_SP_IMAGE_NS_BUF_SIZE) - 1, + TZC_REGION_S_NONE, + PLAT_ARM_TZC_NS_DEV_ACCESS); +#endif + +#else /* if defined(EL3_PAYLOAD_BASE) */ + /* Allow secure access only to DRAM for EL3 payloads. */ tzc400_configure_region0(TZC_REGION_S_RDWR, 0); + #endif /* EL3_PAYLOAD_BASE */ /* diff --git a/plat/arm/css/common/css_pm.c b/plat/arm/css/common/css_pm.c index 4104dd73f..4a615e1c9 100644 --- a/plat/arm/css/common/css_pm.c +++ b/plat/arm/css/common/css_pm.c @@ -299,7 +299,7 @@ plat_psci_ops_t plat_arm_psci_pm_ops = { .system_off = css_system_off, .system_reset = css_system_reset, .validate_power_state = css_validate_power_state, - .validate_ns_entrypoint = arm_validate_ns_entrypoint, + .validate_ns_entrypoint = arm_validate_psci_entrypoint, .translate_power_state_by_mpidr = css_translate_power_state_by_mpidr, .get_node_hw_state = css_node_hw_state, .get_sys_suspend_power_state = css_get_sys_suspend_power_state, diff --git a/plat/common/aarch64/plat_common.c b/plat/common/aarch64/plat_common.c index 05084e196..a87e7c673 100644 --- a/plat/common/aarch64/plat_common.c +++ b/plat/common/aarch64/plat_common.c @@ -3,6 +3,8 @@ * * SPDX-License-Identifier: BSD-3-Clause */ + +#include <arch_helpers.h> #include <assert.h> #include <console.h> #include <platform.h> @@ -20,6 +22,11 @@ #pragma weak plat_get_syscnt_freq2 #endif /* ERROR_DEPRECATED */ +#if SDEI_SUPPORT +#pragma weak plat_sdei_handle_masked_trigger +#pragma weak plat_sdei_validate_entry_point +#endif + void bl31_plat_enable_mmu(uint32_t flags) { enable_mmu_el3(flags); @@ -64,3 +71,22 @@ unsigned int plat_get_syscnt_freq2(void) return (unsigned int)freq; } #endif /* ERROR_DEPRECATED */ + +#if SDEI_SUPPORT +/* + * Function that handles spurious SDEI interrupts while events are masked. + */ +void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr) +{ + WARN("Spurious SDEI interrupt %u on masked PE %lx\n", intr, mpidr); +} + +/* + * Default Function to validate SDEI entry point, which returns success. + * Platforms may override this with their own validation mechanism. + */ +int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode) +{ + return 0; +} +#endif diff --git a/plat/common/plat_gicv2.c b/plat/common/plat_gicv2.c index 05fabcab1..38e1a61e7 100644 --- a/plat/common/plat_gicv2.c +++ b/plat/common/plat_gicv2.c @@ -277,3 +277,13 @@ unsigned int plat_ic_set_priority_mask(unsigned int mask) { return gicv2_set_pmr(mask); } + +unsigned int plat_ic_get_interrupt_id(unsigned int raw) +{ + unsigned int id = (raw & INT_ID_MASK); + + if (id == GIC_SPURIOUS_INTERRUPT) + id = INTR_ID_UNAVAILABLE; + + return id; +} diff --git a/plat/common/plat_gicv3.c b/plat/common/plat_gicv3.c index 52ceb6a7c..030eea723 100644 --- a/plat/common/plat_gicv3.c +++ b/plat/common/plat_gicv3.c @@ -271,6 +271,14 @@ unsigned int plat_ic_set_priority_mask(unsigned int mask) { return gicv3_set_pmr(mask); } + +unsigned int plat_ic_get_interrupt_id(unsigned int raw) +{ + unsigned int id = (raw & INT_ID_MASK); + + return (gicv3_is_intr_id_special_identifier(id) ? + INTR_ID_UNAVAILABLE : id); +} #endif #ifdef IMAGE_BL32 diff --git a/plat/common/plat_psci_common.c b/plat/common/plat_psci_common.c index 95adb051c..0e818d0de 100644 --- a/plat/common/plat_psci_common.c +++ b/plat/common/plat_psci_common.c @@ -18,6 +18,13 @@ /* Ticks elapsed in one second by a signal of 1 MHz */ #define MHZ_TICKS_PER_SEC 1000000 +/* Maximum time-stamp value read from architectural counters */ +#ifdef AARCH32 +#define MAX_TS UINT32_MAX +#else +#define MAX_TS UINT64_MAX +#endif + /* Following are used as ID's to capture time-stamp */ #define PSCI_STAT_ID_ENTER_LOW_PWR 0 #define PSCI_STAT_ID_EXIT_LOW_PWR 1 @@ -45,7 +52,7 @@ static u_register_t calc_stat_residency(unsigned long long pwrupts, assert(residency_div); if (pwrupts < pwrdnts) - res = UINT64_MAX - pwrdnts + pwrupts; + res = MAX_TS - pwrdnts + pwrupts; else res = pwrupts - pwrdnts; |