diff options
124 files changed, 4533 insertions, 399 deletions
@@ -125,21 +125,30 @@ OC := ${CROSS_COMPILE}objcopy OD := ${CROSS_COMPILE}objdump NM := ${CROSS_COMPILE}nm PP := ${CROSS_COMPILE}gcc -E +DTC ?= dtc + +ifeq (${ARM_ARCH_MAJOR},7) +target32-directive = -target arm-none-eabi +# Will set march32-directive from platform configuration +else +target32-directive = -target armv8a-none-eabi +march32-directive = -march=armv8-a +endif ifeq ($(notdir $(CC)),armclang) -TF_CFLAGS_aarch32 = -target arm-arm-none-eabi -march=armv8-a +TF_CFLAGS_aarch32 = -target arm-arm-none-eabi $(march32-directive) TF_CFLAGS_aarch64 = -target aarch64-arm-none-eabi -march=armv8-a else ifneq ($(findstring clang,$(notdir $(CC))),) -TF_CFLAGS_aarch32 = -target armv8a-none-eabi +TF_CFLAGS_aarch32 = $(target32-directive) TF_CFLAGS_aarch64 = -target aarch64-elf else -TF_CFLAGS_aarch32 = -march=armv8-a +TF_CFLAGS_aarch32 = $(march32-directive) TF_CFLAGS_aarch64 = -march=armv8-a endif TF_CFLAGS_aarch64 += -mgeneral-regs-only -mstrict-align -ASFLAGS_aarch32 = -march=armv8-a +ASFLAGS_aarch32 = $(march32-directive) ASFLAGS_aarch64 = -march=armv8-a CPPFLAGS = ${DEFINES} ${INCLUDES} -nostdinc \ @@ -155,6 +164,8 @@ TF_LDFLAGS += --fatal-warnings -O1 TF_LDFLAGS += --gc-sections TF_LDFLAGS += $(TF_LDFLAGS_$(ARCH)) +DTC_FLAGS += -I dts -O dtb + ################################################################################ # Common sources and include directories ################################################################################ @@ -263,6 +274,10 @@ include ${PLAT_MAKEFILE_FULL} $(eval $(call MAKE_PREREQ_DIR,${BUILD_PLAT})) +ifeq (${ARM_ARCH_MAJOR},7) +include make_helpers/armv7-a-cpus.mk +endif + # Platform compatibility is not supported in AArch32 ifneq (${ARCH},aarch32) # If the platform has not defined ENABLE_PLAT_COMPAT, then enable it by default @@ -371,6 +386,17 @@ ifdef SCP_BL2 NEED_SCP_BL2 := yes endif +# For AArch32, BL31 is not currently supported. +ifneq (${ARCH},aarch32) + ifdef BL31_SOURCES + # When booting an EL3 payload, there is no need to compile the BL31 image nor + # put it in the FIP. + ifndef EL3_PAYLOAD_BASE + NEED_BL31 := yes + endif + endif +endif + # Process TBB related flags ifneq (${GENERATE_COT},0) # Common cert_create options @@ -422,16 +448,14 @@ NEED_BL2U := yes include bl2u/bl2u.mk endif -# For AArch32, BL31 is not currently supported. -ifneq (${ARCH},aarch32) +ifeq (${NEED_BL31},yes) ifdef BL31_SOURCES -# When booting an EL3 payload, there is no need to compile the BL31 image nor -# put it in the FIP. -ifndef EL3_PAYLOAD_BASE -NEED_BL31 := yes include bl31/bl31.mk endif endif + +ifdef FDT_SOURCES +NEED_FDT := yes endif ################################################################################ @@ -444,12 +468,14 @@ $(eval $(call assert_boolean,CTX_INCLUDE_AARCH32_REGS)) $(eval $(call assert_boolean,CTX_INCLUDE_FPREGS)) $(eval $(call assert_boolean,DEBUG)) $(eval $(call assert_boolean,DISABLE_PEDANTIC)) +$(eval $(call assert_boolean,ENABLE_AMU)) $(eval $(call assert_boolean,ENABLE_ASSERTIONS)) $(eval $(call assert_boolean,ENABLE_PLAT_COMPAT)) $(eval $(call assert_boolean,ENABLE_PMF)) $(eval $(call assert_boolean,ENABLE_PSCI_STAT)) $(eval $(call assert_boolean,ENABLE_RUNTIME_INSTRUMENTATION)) $(eval $(call assert_boolean,ENABLE_SPE_FOR_LOWER_ELS)) +$(eval $(call assert_boolean,ENABLE_SVE_FOR_NS)) $(eval $(call assert_boolean,ERROR_DEPRECATED)) $(eval $(call assert_boolean,GENERATE_COT)) $(eval $(call assert_boolean,GICV2_G0_FOR_EL3)) @@ -483,12 +509,14 @@ $(eval $(call add_define,ARM_GIC_ARCH)) $(eval $(call add_define,COLD_BOOT_SINGLE_CPU)) $(eval $(call add_define,CTX_INCLUDE_AARCH32_REGS)) $(eval $(call add_define,CTX_INCLUDE_FPREGS)) +$(eval $(call add_define,ENABLE_AMU)) $(eval $(call add_define,ENABLE_ASSERTIONS)) $(eval $(call add_define,ENABLE_PLAT_COMPAT)) $(eval $(call add_define,ENABLE_PMF)) $(eval $(call add_define,ENABLE_PSCI_STAT)) $(eval $(call add_define,ENABLE_RUNTIME_INSTRUMENTATION)) $(eval $(call add_define,ENABLE_SPE_FOR_LOWER_ELS)) +$(eval $(call add_define,ENABLE_SVE_FOR_NS)) $(eval $(call add_define,ERROR_DEPRECATED)) $(eval $(call add_define,GICV2_G0_FOR_EL3)) $(eval $(call add_define,HW_ASSISTED_COHERENCY)) @@ -530,7 +558,7 @@ endif # Build targets ################################################################################ -.PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip fwu_fip certtool +.PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool fip fwu_fip certtool dtbs .SUFFIXES: all: msg_start @@ -583,6 +611,13 @@ $(if ${BL2U}, ,$(eval $(call MAKE_BL,2u))) $(eval $(call FWU_FIP_ADD_PAYLOAD,${BL2U_PATH},--ap-fwu-cfg)) endif +# Expand build macros for the different images +ifeq (${NEED_FDT},yes) +$(eval $(call MAKE_DTBS,$(BUILD_PLAT)/fdts,$(FDT_SOURCES))) +$(eval $(call MAKE_FDT)) +dtbs: $(DTBS) +endif + locate-checkpatch: ifndef CHECKPATCH $(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/scripts/checkpatch.pl") @@ -710,6 +745,7 @@ help: @echo " distclean Remove all build artifacts for all platforms" @echo " certtool Build the Certificate generation tool" @echo " fiptool Build the Firmware Image Package (FIP) creation tool" + @echo " dtbs Build the Flattened device tree (if required for the platform)" @echo "" @echo "Note: most build targets require PLAT to be set to a specific platform." @echo "" diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S index 2c453bd2..e4c454b3 100644 --- a/bl1/bl1.ld.S +++ b/bl1/bl1.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) OUTPUT_ARCH(PLATFORM_LINKER_ARCH) @@ -18,7 +19,7 @@ MEMORY { SECTIONS { . = BL1_RO_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL1_RO_BASE address is not aligned on a page boundary.") #if SEPARATE_CODE_AND_RODATA @@ -27,7 +28,7 @@ SECTIONS *bl1_entrypoint.o(.text*) *(.text*) *(.vectors) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __TEXT_END__ = .; } >ROM @@ -88,7 +89,7 @@ SECTIONS "cpu_ops not defined for this platform.") . = BL1_RW_BASE; - ASSERT(BL1_RW_BASE == ALIGN(4096), + ASSERT(BL1_RW_BASE == ALIGN(PAGE_SIZE), "BL1_RW_BASE address is not aligned on a page boundary.") /* @@ -141,7 +142,7 @@ SECTIONS * are not mixed with normal data. This is required to set up the correct * memory attributes for the coherent data page tables. */ - coherent_ram (NOLOAD) : ALIGN(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; *(tzfw_coherent_mem) __COHERENT_RAM_END_UNALIGNED__ = .; @@ -150,7 +151,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM #endif diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S index f3ab7061..4fe78f9e 100644 --- a/bl2/bl2.ld.S +++ b/bl2/bl2.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) OUTPUT_ARCH(PLATFORM_LINKER_ARCH) @@ -18,7 +19,7 @@ MEMORY { SECTIONS { . = BL2_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL2_BASE address is not aligned on a page boundary.") #if SEPARATE_CODE_AND_RODATA @@ -27,7 +28,7 @@ SECTIONS *bl2_entrypoint.o(.text*) *(.text*) *(.vectors) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __TEXT_END__ = .; } >RAM @@ -41,7 +42,7 @@ SECTIONS KEEP(*(.img_parser_lib_descs)) __PARSER_LIB_DESCS_END__ = .; - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RODATA_END__ = .; } >RAM #else @@ -64,7 +65,7 @@ SECTIONS * read-only, executable. No RW data from the next section must * creep in. Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RO_END__ = .; } >RAM #endif @@ -120,7 +121,7 @@ SECTIONS * are not mixed with normal data. This is required to set up the correct * memory attributes for the coherent data page tables. */ - coherent_ram (NOLOAD) : ALIGN(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; *(tzfw_coherent_mem) __COHERENT_RAM_END_UNALIGNED__ = .; @@ -129,7 +130,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM #endif diff --git a/bl2u/bl2u.ld.S b/bl2u/bl2u.ld.S index efae293d..da587172 100644 --- a/bl2u/bl2u.ld.S +++ b/bl2u/bl2u.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) OUTPUT_ARCH(PLATFORM_LINKER_ARCH) @@ -18,7 +19,7 @@ MEMORY { SECTIONS { . = BL2U_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL2U_BASE address is not aligned on a page boundary.") #if SEPARATE_CODE_AND_RODATA @@ -27,14 +28,14 @@ SECTIONS *bl2u_entrypoint.o(.text*) *(.text*) *(.vectors) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __TEXT_END__ = .; } >RAM .rodata . : { __RODATA_START__ = .; *(.rodata*) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RODATA_END__ = .; } >RAM #else @@ -51,7 +52,7 @@ SECTIONS * read-only, executable. No RW data from the next section must * creep in. Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RO_END__ = .; } >RAM #endif @@ -107,7 +108,7 @@ SECTIONS * are not mixed with normal data. This is required to set up the correct * memory attributes for the coherent data page tables. */ - coherent_ram (NOLOAD) : ALIGN(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; *(tzfw_coherent_mem) __COHERENT_RAM_END_UNALIGNED__ = .; @@ -116,7 +117,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM #endif diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S index 7f442d00..dd046c43 100644 --- a/bl31/bl31.ld.S +++ b/bl31/bl31.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) OUTPUT_ARCH(PLATFORM_LINKER_ARCH) @@ -22,7 +23,7 @@ MEMORY { SECTIONS { . = BL31_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE address is not aligned on a page boundary.") #if SEPARATE_CODE_AND_RODATA @@ -31,7 +32,7 @@ SECTIONS *bl31_entrypoint.o(.text*) *(.text*) *(.vectors) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __TEXT_END__ = .; } >RAM @@ -66,7 +67,7 @@ SECTIONS . = ALIGN(8); #include <pubsub_events.h> - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RODATA_END__ = .; } >RAM #else @@ -110,7 +111,7 @@ SECTIONS * executable. No RW data from the next section must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RO_END__ = .; } >RAM #endif @@ -127,10 +128,10 @@ SECTIONS * There's no need to include this into the RO section of BL31 because it * doesn't need to be accessed by BL31. */ - spm_shim_exceptions : ALIGN(4096) { + spm_shim_exceptions : ALIGN(PAGE_SIZE) { __SPM_SHIM_EXCEPTIONS_START__ = .; *(.spm_shim_exceptions) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __SPM_SHIM_EXCEPTIONS_END__ = .; } >RAM #endif @@ -223,7 +224,7 @@ SECTIONS __SP_IMAGE_XLAT_TABLES_START__ = .; *secure_partition*.o(xlat_table) /* Make sure that the rest of the page is empty. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __SP_IMAGE_XLAT_TABLES_END__ = .; #endif *(xlat_table) @@ -236,7 +237,7 @@ SECTIONS * are not mixed with normal data. This is required to set up the correct * memory attributes for the coherent data page tables. */ - coherent_ram (NOLOAD) : ALIGN(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; /* * Bakery locks are stored in coherent memory @@ -251,7 +252,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM #endif diff --git a/bl31/bl31.mk b/bl31/bl31.mk index fccdc8a0..fdcc9313 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -50,6 +50,14 @@ ifeq (${ENABLE_SPE_FOR_LOWER_ELS},1) BL31_SOURCES += lib/extensions/spe/spe.c endif +ifeq (${ENABLE_AMU},1) +BL31_SOURCES += lib/extensions/amu/aarch64/amu.c +endif + +ifeq (${ENABLE_SVE_FOR_NS},1) +BL31_SOURCES += lib/extensions/sve/sve.c +endif + BL31_LINKERFILE := bl31/bl31.ld.S # Flag used to indicate if Crash reporting via console should be included diff --git a/bl32/sp_min/aarch32/entrypoint.S b/bl32/sp_min/aarch32/entrypoint.S index cd9fe5cb..b2b7953f 100644 --- a/bl32/sp_min/aarch32/entrypoint.S +++ b/bl32/sp_min/aarch32/entrypoint.S @@ -30,6 +30,16 @@ stcopr \reg, SCR .endm + .macro clrex_on_monitor_entry +#if (ARM_ARCH_MAJOR == 7) + /* + * ARMv7 architectures need to clear the exclusive access when + * entering Monitor mode. + */ + clrex +#endif + .endm + vector_base sp_min_vector_table b sp_min_entrypoint b plat_panic_handler /* Undef */ @@ -147,6 +157,8 @@ func handle_smc smcc_save_gp_mode_regs + clrex_on_monitor_entry + /* * `sp` still points to `smc_ctx_t`. Save it to a register * and restore the C runtime stack pointer to `sp`. @@ -203,11 +215,7 @@ func handle_fiq smcc_save_gp_mode_regs - /* - * AArch32 architectures need to clear the exclusive access when - * entering Monitor mode. - */ - clrex + clrex_on_monitor_entry /* load run-time stack */ mov r2, sp diff --git a/bl32/sp_min/sp_min.ld.S b/bl32/sp_min/sp_min.ld.S index fc44d524..e798a0d3 100644 --- a/bl32/sp_min/sp_min.ld.S +++ b/bl32/sp_min/sp_min.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(elf32-littlearm) OUTPUT_ARCH(arm) @@ -18,7 +19,7 @@ MEMORY { SECTIONS { . = BL32_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL32_BASE address is not aligned on a page boundary.") #if SEPARATE_CODE_AND_RODATA @@ -27,7 +28,7 @@ SECTIONS *entrypoint.o(.text*) *(.text*) *(.vectors) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __TEXT_END__ = .; } >RAM @@ -54,7 +55,7 @@ SECTIONS . = ALIGN(8); #include <pubsub_events.h> - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RODATA_END__ = .; } >RAM #else @@ -91,7 +92,7 @@ SECTIONS * read-only, executable. No RW data from the next section must * creep in. Ensure the rest of the current memory block is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RO_END__ = .; } >RAM #endif @@ -110,6 +111,10 @@ SECTIONS __DATA_END__ = .; } >RAM +#ifdef BL32_PROGBITS_LIMIT + ASSERT(. <= BL32_PROGBITS_LIMIT, "BL32 progbits has exceeded its limit.") +#endif + stacks (NOLOAD) : { __STACKS_START__ = .; *(tzfw_normal_stacks) @@ -186,7 +191,7 @@ SECTIONS * are not mixed with normal data. This is required to set up the correct * memory attributes for the coherent data page tables. */ - coherent_ram (NOLOAD) : ALIGN(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; /* * Bakery locks are stored in coherent memory @@ -201,7 +206,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM diff --git a/bl32/sp_min/sp_min.mk b/bl32/sp_min/sp_min.mk index 39588ce7..56489a3c 100644 --- a/bl32/sp_min/sp_min.mk +++ b/bl32/sp_min/sp_min.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -22,6 +22,10 @@ ifeq (${ENABLE_PMF}, 1) BL32_SOURCES += lib/pmf/pmf_main.c endif +ifeq (${ENABLE_AMU}, 1) +BL32_SOURCES += lib/extensions/amu/aarch32/amu.c +endif + BL32_LINKERFILE := bl32/sp_min/sp_min.ld.S # Include the platform-specific SP_MIN Makefile diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S index 2b672efe..d256b46c 100644 --- a/bl32/tsp/tsp.ld.S +++ b/bl32/tsp/tsp.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) OUTPUT_ARCH(PLATFORM_LINKER_ARCH) @@ -19,7 +20,7 @@ MEMORY { SECTIONS { . = BL32_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL32_BASE address is not aligned on a page boundary.") #if SEPARATE_CODE_AND_RODATA @@ -28,14 +29,14 @@ SECTIONS *tsp_entrypoint.o(.text*) *(.text*) *(.vectors) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __TEXT_END__ = .; } >RAM .rodata . : { __RODATA_START__ = .; *(.rodata*) - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RODATA_END__ = .; } >RAM #else @@ -51,7 +52,7 @@ SECTIONS * read-only, executable. No RW data from the next section must * creep in. Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RO_END__ = .; } >RAM #endif @@ -106,7 +107,7 @@ SECTIONS * are not mixed with normal data. This is required to set up the correct * memory attributes for the coherent data page tables. */ - coherent_ram (NOLOAD) : ALIGN(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; *(tzfw_coherent_mem) __COHERENT_RAM_END_UNALIGNED__ = .; @@ -115,7 +116,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM #endif diff --git a/common/aarch32/debug.S b/common/aarch32/debug.S index 583ee4a5..f5063569 100644 --- a/common/aarch32/debug.S +++ b/common/aarch32/debug.S @@ -71,7 +71,15 @@ endfunc report_exception assert_msg1: .asciz "ASSERT: File " assert_msg2: +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /****************************************************************** + * Virtualization comes with the UDIV/SDIV instructions. If missing + * write file line number in hexadecimal format. + ******************************************************************/ + .asciz " Line 0x" +#else .asciz " Line " +#endif /* --------------------------------------------------------------------------- * Assertion support in assembly. @@ -113,6 +121,13 @@ func asm_assert bne 1f mov r4, r6 +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /****************************************************************** + * Virtualization comes with the UDIV/SDIV instructions. If missing + * write file line number in hexadecimal format. + ******************************************************************/ + bl asm_print_hex +#else /* Print line number in decimal */ mov r6, #10 /* Divide by 10 after every loop iteration */ ldr r5, =MAX_DEC_DIVISOR @@ -124,6 +139,7 @@ dec_print_loop: udiv r5, r5, r6 /* Reduce divisor */ cmp r5, #0 bne dec_print_loop +#endif bl plat_crash_console_flush diff --git a/common/bl_common.c b/common/bl_common.c index e4473ed3..b0d1bfa7 100644 --- a/common/bl_common.c +++ b/common/bl_common.c @@ -200,14 +200,14 @@ size_t image_size(unsigned int image_id) #if LOAD_IMAGE_V2 /******************************************************************************* - * Generic function to load an image at a specific address given + * Internal function to load an image at a specific address given * an image ID and extents of free memory. * * If the load is successful then the image information is updated. * * Returns 0 on success, a negative error code otherwise. ******************************************************************************/ -int load_image(unsigned int image_id, image_info_t *image_data) +static int load_image(unsigned int image_id, image_info_t *image_data) { uintptr_t dev_handle; uintptr_t image_handle; @@ -266,17 +266,6 @@ int load_image(unsigned int image_id, image_info_t *image_data) goto exit; } -#if !TRUSTED_BOARD_BOOT - /* - * File has been successfully loaded. - * Flush the image to main memory so that it can be executed later by - * any CPU, regardless of cache and MMU state. - * When TBB is enabled the image is flushed later, after image - * authentication. - */ - flush_dcache_range(image_base, image_size); -#endif /* TRUSTED_BOARD_BOOT */ - INFO("Image id=%u loaded: %p - %p\n", image_id, (void *) image_base, (void *) (image_base + image_size)); @@ -329,18 +318,19 @@ static int load_auth_image_internal(unsigned int image_id, image_data->image_size); return -EAUTH; } +#endif /* TRUSTED_BOARD_BOOT */ /* - * File has been successfully loaded and authenticated. * Flush the image to main memory so that it can be executed later by - * any CPU, regardless of cache and MMU state. - * Do it only for child images, not for the parents (certificates). + * any CPU, regardless of cache and MMU state. If TBB is enabled, then + * the file has been successfully loaded and authenticated and flush + * only for child images, not for the parents (certificates). */ if (!is_parent_image) { flush_dcache_range(image_data->image_base, image_data->image_size); } -#endif /* TRUSTED_BOARD_BOOT */ + return 0; } diff --git a/docs/firmware-design.rst b/docs/firmware-design.rst index c0ece0ba..405964d2 100644 --- a/docs/firmware-design.rst +++ b/docs/firmware-design.rst @@ -2519,6 +2519,35 @@ This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` == 8 and table entries for a given stage of translation for a particular translation regime. +ARMv7 +~~~~~ + +This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` == 7. + +There are several ARMv7 extensions available. Obviously the TrustZone +extension is mandatory to support the ARM Trusted Firmware bootloader +and runtime services. + +Platform implementing an ARMv7 system can to define from its target +Cortex-A architecture through ``ARM_CORTEX_A<X> = yes`` in their +``plaform.mk`` script. For example ``ARM_CORTEX_A15=yes`` for a +Cortex-A15 target. + +Platform can also set ``ARM_WITH_NEON=yes`` to enable neon support. +Note that using neon at runtime has constraints on non secure wolrd context. +The trusted firmware does not yet provide VFP context management. + +Directive ``ARM_CORTEX_A<x>`` and ``ARM_WITH_NEON`` are used to set +the toolchain target architecture directive. + +Platform may choose to not define straight the toolchain target architecture +directive by defining ``MARCH32_DIRECTIVE``. +I.e: + +:: + + MARCH32_DIRECTIVE := -mach=armv7-a + Code Structure -------------- diff --git a/docs/plat/poplar.rst b/docs/plat/poplar.rst index d7f1fe06..01294783 100644 --- a/docs/plat/poplar.rst +++ b/docs/plat/poplar.rst @@ -11,6 +11,8 @@ of running any commercial set-top solution based on Linux or Android. It supports a premium user experience with up to H.265 HEVC decoding of 4K video at 60 frames per second. +:: + SOC Hisilicon Hi3798CV200 CPU Quad-core ARM Cortex-A53 64 bit DRAM DDR3/3L/4 SDRAM interface, maximum 32-bit data width 2 GB @@ -28,6 +30,8 @@ At the start of the boot sequence, the bootROM executes the so called l-loader binary whose main role is to change the processor state to 64bit mode. This must happen prior invoking the arm trusted firmware: +:: + l-loader --> arm_trusted_firmware --> u-boot How to build @@ -54,10 +58,16 @@ Build Procedure - Prepare the AARCH64 toolchain. - Build u-boot using poplar_defconfig + +.. code:: bash + make CROSS_COMPILE=aarch64-linux-gnu- poplar_defconfig make CROSS_COMPILE=aarch64-linux-gnu- - Build atf providing the previously generated u-boot.bin as the BL33 image + +.. code:: bash + make CROSS_COMPILE=aarch64-linux-gnu- all fip SPD=none PLAT=poplar BL33=u-boot.bin @@ -81,85 +91,86 @@ working firmware to eMMC. Boot trace ========== -Bootrom start -Boot Media: eMMC -Decrypt auxiliary code ...OK - -lsadc voltage min: 000000FE, max: 000000FF, aver: 000000FE, index: 00000000 - -Entry boot auxiliary code - -Auxiliary code - v1.00 -DDR code - V1.1.2 20160205 -Build: Mar 24 2016 - 17:09:44 -Reg Version: v134 -Reg Time: 2016/03/18 09:44:55 -Reg Name: hi3798cv2dmb_hi3798cv200_ddr3_2gbyte_8bitx4_4layers.reg - -Boot auxiliary code success -Bootrom success - -LOADER: Switched to aarch64 mode -LOADER: Entering ARM TRUSTED FIRMWARE -LOADER: CPU0 executes at 0x000ce000 - -INFO: BL1: 0xe1000 - 0xe7000 [size = 24576] -NOTICE: Booting Trusted Firmware -NOTICE: BL1: v1.3(debug):v1.3-372-g1ba9c60 -NOTICE: BL1: Built : 17:51:33, Apr 30 2017 -INFO: BL1: RAM 0xe1000 - 0xe7000 -INFO: BL1: Loading BL2 -INFO: Loading image id=1 at address 0xe9000 -INFO: Image id=1 loaded at address 0xe9000, size = 0x5008 -NOTICE: BL1: Booting BL2 -INFO: Entry point address = 0xe9000 -INFO: SPSR = 0x3c5 -NOTICE: BL2: v1.3(debug):v1.3-372-g1ba9c60 -NOTICE: BL2: Built : 17:51:33, Apr 30 2017 -INFO: BL2: Loading BL31 -INFO: Loading image id=3 at address 0x129000 -INFO: Image id=3 loaded at address 0x129000, size = 0x8038 -INFO: BL2: Loading BL33 -INFO: Loading image id=5 at address 0x37000000 -INFO: Image id=5 loaded at address 0x37000000, size = 0x58f17 -NOTICE: BL1: Booting BL31 -INFO: Entry point address = 0x129000 -INFO: SPSR = 0x3cd -INFO: Boot bl33 from 0x37000000 for 364311 Bytes -NOTICE: BL31: v1.3(debug):v1.3-372-g1ba9c60 -NOTICE: BL31: Built : 17:51:33, Apr 30 2017 -INFO: BL31: Initializing runtime services -INFO: BL31: Preparing for EL3 exit to normal world -INFO: Entry point address = 0x37000000 -INFO: SPSR = 0x3c9 - - -U-Boot 2017.05-rc2-00130-gd2255b0 (Apr 30 2017 - 17:51:28 +0200)poplar - -Model: HiSilicon Poplar Development Board -BOARD: Hisilicon HI3798cv200 Poplar -DRAM: 1 GiB -MMC: Hisilicon DWMMC: 0 -In: serial@f8b00000 -Out: serial@f8b00000 -Err: serial@f8b00000 -Net: Net Initialization Skipped -No ethernet found. - -Hit any key to stop autoboot: 0 -starting USB... -USB0: USB EHCI 1.00 -scanning bus 0 for devices... 1 USB Device(s) found -USB1: USB EHCI 1.00 -scanning bus 1 for devices... 4 USB Device(s) found - scanning usb for storage devices... 1 Storage Device(s) found - scanning usb for ethernet devices... 1 Ethernet Device(s) found - -USB device 0: - Device 0: Vendor: SanDisk Rev: 1.00 Prod: Cruzer Blade - Type: Removable Hard Disk - Capacity: 7632.0 MB = 7.4 GB (15630336 x 512) -... is now current device -Scanning usb 0:1... -=> - +:: + + Bootrom start + Boot Media: eMMC + Decrypt auxiliary code ...OK + + lsadc voltage min: 000000FE, max: 000000FF, aver: 000000FE, index: 00000000 + + Entry boot auxiliary code + + Auxiliary code - v1.00 + DDR code - V1.1.2 20160205 + Build: Mar 24 2016 - 17:09:44 + Reg Version: v134 + Reg Time: 2016/03/18 09:44:55 + Reg Name: hi3798cv2dmb_hi3798cv200_ddr3_2gbyte_8bitx4_4layers.reg + + Boot auxiliary code success + Bootrom success + + LOADER: Switched to aarch64 mode + LOADER: Entering ARM TRUSTED FIRMWARE + LOADER: CPU0 executes at 0x000ce000 + + INFO: BL1: 0xe1000 - 0xe7000 [size = 24576] + NOTICE: Booting Trusted Firmware + NOTICE: BL1: v1.3(debug):v1.3-372-g1ba9c60 + NOTICE: BL1: Built : 17:51:33, Apr 30 2017 + INFO: BL1: RAM 0xe1000 - 0xe7000 + INFO: BL1: Loading BL2 + INFO: Loading image id=1 at address 0xe9000 + INFO: Image id=1 loaded at address 0xe9000, size = 0x5008 + NOTICE: BL1: Booting BL2 + INFO: Entry point address = 0xe9000 + INFO: SPSR = 0x3c5 + NOTICE: BL2: v1.3(debug):v1.3-372-g1ba9c60 + NOTICE: BL2: Built : 17:51:33, Apr 30 2017 + INFO: BL2: Loading BL31 + INFO: Loading image id=3 at address 0x129000 + INFO: Image id=3 loaded at address 0x129000, size = 0x8038 + INFO: BL2: Loading BL33 + INFO: Loading image id=5 at address 0x37000000 + INFO: Image id=5 loaded at address 0x37000000, size = 0x58f17 + NOTICE: BL1: Booting BL31 + INFO: Entry point address = 0x129000 + INFO: SPSR = 0x3cd + INFO: Boot bl33 from 0x37000000 for 364311 Bytes + NOTICE: BL31: v1.3(debug):v1.3-372-g1ba9c60 + NOTICE: BL31: Built : 17:51:33, Apr 30 2017 + INFO: BL31: Initializing runtime services + INFO: BL31: Preparing for EL3 exit to normal world + INFO: Entry point address = 0x37000000 + INFO: SPSR = 0x3c9 + + + U-Boot 2017.05-rc2-00130-gd2255b0 (Apr 30 2017 - 17:51:28 +0200)poplar + + Model: HiSilicon Poplar Development Board + BOARD: Hisilicon HI3798cv200 Poplar + DRAM: 1 GiB + MMC: Hisilicon DWMMC: 0 + In: serial@f8b00000 + Out: serial@f8b00000 + Err: serial@f8b00000 + Net: Net Initialization Skipped + No ethernet found. + + Hit any key to stop autoboot: 0 + starting USB... + USB0: USB EHCI 1.00 + scanning bus 0 for devices... 1 USB Device(s) found + USB1: USB EHCI 1.00 + scanning bus 1 for devices... 4 USB Device(s) found + scanning usb for storage devices... 1 Storage Device(s) found + scanning usb for ethernet devices... 1 Ethernet Device(s) found + + USB device 0: + Device 0: Vendor: SanDisk Rev: 1.00 Prod: Cruzer Blade + Type: Removable Hard Disk + Capacity: 7632.0 MB = 7.4 GB (15630336 x 512) + ... is now current device + Scanning usb 0:1... + => diff --git a/docs/plat/rpi3.rst b/docs/plat/rpi3.rst new file mode 100644 index 00000000..219faaff --- /dev/null +++ b/docs/plat/rpi3.rst @@ -0,0 +1,364 @@ +Arm Trusted Firmware for Raspberry Pi 3 +======================================= + +.. section-numbering:: + :suffix: . + +.. contents:: + +The `Raspberry Pi 3`_ is an inexpensive single-board computer that contains four +Cortex-A53 cores, which makes it possible to have a port of the Arm Trusted +Firmware. + +The following instructions explain how to use this port of the Trusted Firmware +with the default distribution of `Raspbian`_ because that's the distribution +officially supported by the Raspberry Pi Foundation. At the moment of writing +this, the officially supported kernel is a AArch32 kernel. This doesn't mean +that this port of the Trusted Firmware can't boot a AArch64 kernel. The `Linux +tree fork`_ maintained by the Foundation can be compiled for AArch64 by +following the steps in `AArch64 kernel build instructions`_. + +**IMPORTANT NOTE**: This port isn't secure. All of the memory used is DRAM, +which is available from both the Non-secure and Secure worlds. This port +shouldn't be considered more than a prototype to play with and implement +elements like PSCI to support the Linux kernel. + +Design +------ + +The SoC used by the Raspberry Pi 3 is the Broadcom BCM2837. It is a SoC with a +VideoCore IV that acts as primary processor (and loads everything from the SD +card) and is located between all Arm cores and the DRAM. Check the `Raspberry Pi +3 documentation`_ for more information. + +This explains why it is possible to change the execution state (AArch64/AArch32) +depending on a few files on the SD card. We only care about the cases in which +the cores boot in AArch64 mode. + +The rules are simple: + +- If a file called ``kernel8.img`` is located on the ``boot`` partition of the + SD card, it will load it and execute in EL2 in AArch64. Basically, it executes + a `default AArch64 stub`_ at address **0x0** that jumps to the kernel. + +- If there is also a file called ``armstub8.bin``, it will load it at address + **0x0** (instead of the default stub) and execute it in EL3 in AArch64. All + the cores are powered on at the same time and start at address **0x0**. + +This means that we can use the default AArch32 kernel provided in the official +`Raspbian`_ distribution by renaming it to ``kernel8.img``, while the Trusted +Firmware and anything else we need is in ``armstub8.bin``. This way we can +forget about the default bootstrap code. When using a AArch64 kernel, it is only +needed to make sure that the name on the SD card is ``kernel8.img``. + +Ideally, we want to load the kernel and have all cores available, which means +that we need to make the secondary cores work in the way the kernel expects, as +explained in `Secondary cores`_. In practice, a small bootstrap is needed +between the Trusted Firmware and the kernel. + +To get the most out of a AArch32 kernel, we want to boot it in Hypervisor mode +in AArch32. This means that BL33 can't be in EL2 in AArch64 mode. The +architecture specifies that AArch32 Hypervisor mode isn't present when AArch64 +is used for EL2. When using a AArch64 kernel, it should simply start in EL2. + +Placement of images +~~~~~~~~~~~~~~~~~~~ + +The file ``armstub8.bin`` contains BL1 and the FIP. It is needed to add padding +between them so that the addresses they are loaded to match the ones specified +when compiling the Trusted Firmware. + +The device tree block is loaded by the VideoCore loader from an appropriate +file, but we can specify the address it is loaded to in ``config.txt``. + +The file ``kernel8.img`` contains a kernel image that is loaded to the address +specified in ``config.txt``. The `Linux kernel tree`_ has information about how +a AArch32 Linux kernel image is loaded in ``Documentation/arm/Booting``: + +:: + + The zImage may also be placed in system RAM and called there. The + kernel should be placed in the first 128MiB of RAM. It is recommended + that it is loaded above 32MiB in order to avoid the need to relocate + prior to decompression, which will make the boot process slightly + faster. + +There are no similar restrictions for AArch64 kernels, as specified in the file +``Documentation/arm64/booting.txt``. + +This means that we need to avoid the first 128 MiB of RAM when placing the +Trusted Firmware images (and specially the first 32 MiB, as they are directly +used to place the uncompressed AArch32 kernel image. This way, both AArch32 and +AArch64 kernels can be placed at the same address. + +In the end, the images look like the following diagram when placed in memory. +All addresses are Physical Addresses from the point of view of the Arm cores. +Again, note that this is all just part of the same DRAM that goes from +**0x00000000** to **0x3F000000**, it just has different names to simulate a real +secure platform! + +:: + + 0x00000000 +-----------------+ + | ROM | BL1 + 0x00010000 +-----------------+ + | FIP | + 0x00200000 +-----------------+ + | | + | ... | + | | + 0x01000000 +-----------------+ + | Kernel | + +-----------------+ + | | + | ... | + | | + 0x02000000 +-----------------+ + | DTB | + +-----------------+ + | | + | ... | + | | + 0x10000000 +-----------------+ + | Secure SRAM | BL2, BL31 + 0x10100000 +-----------------+ + | Secure DRAM | + 0x10300000 +-----------------+ + | Non-secure DRAM | BL33 + 0x11000000 +-----------------+ + | | + | ... | + | | + 0x3F000000 +-----------------+ + | I/O | + 0x40000000 +-----------------+ + +The area between **0x10000000** and **0x11000000** has to be protected so that +the kernel doesn't use it. That is done by adding ``memmap=256M$16M`` to the +command line passed to the kernel. See the `Setup SD card`_ instructions to see +how to do it. + +The last 16 MiB of DRAM can only be accessed by the VideoCore, that has +different mappings than the Arm cores in which the I/O addresses don't overlap +the DRAM. The memory reserved to be used by the VideoCore is always placed at +the end of the DRAM, so this space isn't wasted. + +Considering the 128 MiB allocated to the GPU and the 16 MiB allocated for the +Trusted Firmware, there are 880 MiB available for Linux. + +Boot sequence +~~~~~~~~~~~~~ + +The boot sequence of the Trusted Firmware is the usual one except when booting +a AArch32 kernel. In that case, BL33 is booted in AArch32 Hypervisor mode so +that it can jump to the kernel in the same mode and let it take over that +privilege level. If BL33 was running in EL2 in AArch64 (as in the default +bootflow of the Trusted Firmware) it could only jump to the kernel in AArch32 in +Supervisor mode. + +The `Linux kernel tree`_ has instructions on how to jump to the Linux kernel +in ``Documentation/arm/Booting`` and ``Documentation/arm64/booting.txt``. The +bootstrap should take care of this. + +Secondary cores +~~~~~~~~~~~~~~~ + +The kernel used by `Raspbian`_ doesn't have support for PSCI, so it is needed to +use mailboxes to trap the secondary cores until they are ready to jump to the +kernel. This mailbox is located at a different address in the AArch32 default +kernel than in the AArch64 kernel. + +Also, this port of the Trusted Firmware has another Trusted Mailbox in Shared BL +RAM. During cold boot, all secondary cores wait in a loop until they are given +given an address to jump to in this Mailbox (``bl31_warm_entrypoint``). + +Once BL31 has finished and the primary core has jumped to the BL33 payload, it +has to call ``PSCI_CPU_ON`` to release the secondary CPUs from the wait loop. +The payload then makes them wait in another waitloop listening from messages +from the kernel. When the primary CPU jumps into the kernel, it will send an +address to the mailbox so that the secondary CPUs jump to it and are recognised +by the kernel. + +Build Instructions +------------------ + +To boot a AArch64 kernel, only the AArch64 toolchain is required. + +To boot a AArch32 kernel, both AArch64 and AArch32 toolchains are required. The +AArch32 toolchain is needed for the AArch32 bootstrap needed to load a 32-bit +kernel. + +First, clone and compile `Raspberry Pi 3 Arm Trusted Firmware bootstrap`_. +Choose the one needed for the architecture of your kernel. + +Then compile the Arm Trusted Firmware. For a AArch32 kernel, use the following +command line: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + RPI3_BL33_IN_AARCH32=1 \ + BL33=../rpi3-arm-tf-bootstrap/aarch32/el2-bootstrap.bin \ + all fip + +For a AArch64 kernel, use this other command line: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + BL33=../rpi3-arm-tf-bootstrap/aarch64/el2-bootstrap.bin \ + all fip + +Then, join BL1 and the FIP with the following instructions (replace ``release`` +by ``debug`` if you set the build option ``DEBUG=1``): + +.. code:: shell + + cp build/rpi3/release/bl1.bin bl1.pad.bin + truncate --size=65536 bl1.pad.bin + cat bl1.pad.bin build/rpi3/release/fip.bin > armstub8.bin + +The resulting file, ``armstub8.bin``, contains BL1 and the FIP in the place they +need to be for the Trusted Firmware to boot correctly. Now, follow the +instructions in `Setup SD card`_. + +The following build options are supported: + +- ``PRELOADED_BL33_BASE``: Specially useful because the file ``kernel8.img`` can + be loaded anywhere by modifying the file ``config.txt``. It doesn't have to + contain a kernel, it could have any arbitrary payload. + +- ``RESET_TO_BL31``: Set to 1 by default. If using a 32-bit kernel like + `Raspbian`_, the space used by BL1 can overwritten by the kernel when it is + being loaded. Even when using a AArch64 kernel the region used by + BL1 isn't protected and the kernel could overwrite it. The space used by BL31 + is reserved by the command line passed to the kernel. + +- ``RPI3_BL33_IN_AARCH32``: This port can load a AArch64 or AArch32 BL33 image. + By default this option is 0, which means that the Trusted Firmware will jump + to BL33 in EL2 in AArch64 mode. If set to 1, it will jump to BL33 in + Hypervisor in AArch32 mode. + +The following is not currently supported: + +- AArch32 for the Trusted Firmware itself. + +- ``EL3_PAYLOAD_BASE``: The reason is that you can already load anything to any + address by changing the file ``armstub8.bin``, so there's no point in using + the Trusted Firmware in this case. + +- ``LOAD_IMAGE_V2=0``: Only version 2 is supported. + +AArch64 kernel build instructions +--------------------------------- + +The following instructions show how to install and run a AArch64 kernel by +using a SD card with the default `Raspbian`_ install as base. Skip them if you +want to use the default 32-bit kernel. + +Note that this system won't be fully 64-bit because all the tools in the +filesystem are 32-bit binaries, but it's a quick way to get it working, and it +allows the user to run 64-bit binaries in addition to 32-bit binaries. + +1. Clone the `Linux tree fork`_ maintained by the Raspberry Pi Foundation. To + speed things up, do a shallow clone of the desired branch. + +.. code:: shell + + git clone --depth=1 -b rpi-4.14.y https://github.com/raspberrypi/linux + cd linux + +2. Configure and compile the kernel. Adapt the number after ``-j`` so that it is + 1.5 times the number of CPUs in your computer. This may take some time to + finish. + +.. code:: shell + + make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcmrpi3_defconfig + make -j 6 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- + +3. Copy the kernel image and the device tree to the SD card. Replace the path + by the corresponding path in your computers to the ``boot`` partition of the + SD card. + +.. code:: shell + + cp arch/arm64/boot/Image /path/to/boot/kernel8.img + cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dtb /path/to/boot/ + +4. Install the kernel modules. Replace the path by the corresponding path to the + filesystem partition of the SD card on your computer. + +.. code:: shell + + make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \ + INSTALL_MOD_PATH=/path/to/filesystem modules_install + +5. Follow the instructions in `Setup SD card`_ except for the step of renaming + the existing ``kernel7.img`` (we have already copied a AArch64 kernel). + +Setup SD card +------------- + +The instructions assume that you have an SD card with a fresh install of +`Raspbian`_ (or that, at least, the ``boot`` partition is untouched, or nearly +untouched). They have been tested with the image available in 2017-09-07. + +1. Insert the SD card and open the ``boot`` partition. + +2. Rename ``kernel7.img`` to ``kernel8.img``. This tricks the VideoCore + bootloader into booting the Arm cores in AArch64 mode, like the Trusted + Firmware needs, even though the kernel is not compiled for AArch64. + +3. Copy ``armstub8.bin`` here. When ``kernel8.img`` is available, The VideoCore + bootloader will look for a file called ``armstub8.bin`` and load it at + address **0x0** instead of a predefined one. + +4. Open ``cmdline.txt`` and add ``memmap=256M$16M`` to prevent the kernel from + using the memory needed by the Trusted Firmware. If you want to enable the + serial port "Mini UART", make sure that this file also contains + ``console=serial0,115200 console=tty1``. + + Note that the 16 MiB reserved this way won't be available for Linux, the same + way as the memory reserved in DRAM for the GPU isn't available. + +5. Open ``config.txt`` and add the following lines at the end (``enable_uart=1`` + is only needed to enable debugging through the Mini UART): + +:: + + enable_uart=1 + kernel_address=0x01000000 + device_tree_address=0x02000000 + +If you connect a serial cable to the Mini UART and your computer, and connect +to it (for example, with ``screen /dev/ttyUSB0 115200``) you should see some +text. In the case of an AArch32 kernel, you should see something like this: + +:: + + NOTICE: Booting Trusted Firmware + NOTICE: BL1: v1.4(release):v1.4-329-g61e94684-dirty + NOTICE: BL1: Built : 00:09:25, Nov 6 2017 + NOTICE: BL1: Booting BL2 + NOTICE: BL2: v1.4(release):v1.4-329-g61e94684-dirty + NOTICE: BL2: Built : 00:09:25, Nov 6 2017 + NOTICE: BL1: Booting BL31 + NOTICE: BL31: v1.4(release):v1.4-329-g61e94684-dirty + NOTICE: BL31: Built : 00:09:25, Nov 6 2017 + [ 0.266484] bcm2835-aux-uart 3f215040.serial: could not get clk: -517 + + Raspbian GNU/Linux 9 raspberrypi ttyS0 + raspberrypi login: + +Just enter your credentials, everything should work as expected. Note that the +HDMI output won't show any text during boot. + +.. _default Arm stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub7.S +.. _default AArch64 stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub8.S +.. _Linux kernel tree: https://github.com/torvalds/linux +.. _Linux tree fork: https://github.com/raspberrypi/linux +.. _Raspberry Pi 3: https://www.raspberrypi.org/products/raspberry-pi-3-model-b/ +.. _Raspberry Pi 3 Arm Trusted Firmware bootstrap: https://github.com/AntonioND/rpi3-arm-tf-bootstrap +.. _Raspberry Pi 3 documentation: https://www.raspberrypi.org/documentation/ +.. _Raspbian: https://www.raspberrypi.org/downloads/raspbian/ diff --git a/docs/user-guide.rst b/docs/user-guide.rst index 542fd80e..13f09641 100644 --- a/docs/user-guide.rst +++ b/docs/user-guide.rst @@ -219,7 +219,8 @@ Common build options - ``ARM_ARCH_MAJOR``: The major version of ARM Architecture to target when compiling ARM Trusted Firmware. Its value must be numeric, and defaults to - 8 . See also, *ARMv8 Architecture Extensions* in `Firmware Design`_. + 8 . See also, *ARMv8 Architecture Extensions* and + *ARMv7 Architecture Extensions* in `Firmware Design`_. - ``ARM_ARCH_MINOR``: The minor version of ARM Architecture to target when compiling ARM Trusted Firmware. Its value must be a numeric, and defaults @@ -320,6 +321,11 @@ Common build options payload. Please refer to the "Booting an EL3 payload" section for more details. +- ``ENABLE_AMU``: Boolean option to enable Activity Monitor Unit extensions. + This is an optional architectural feature available on v8.4 onwards. Some + v8.2 implementations also implement an AMU and this option can be used to + enable this feature on those systems as well. Default is 0. + - ``ENABLE_ASSERTIONS``: This option controls whether or not calls to ``assert()`` are compiled out. For debug builds, this option defaults to 1, and calls to ``assert()`` are left in place. For release builds, this option defaults to 0 @@ -348,6 +354,17 @@ Common build options The default is 1 but is automatically disabled when the target architecture is AArch32. +- ``ENABLE_SVE_FOR_NS``: Boolean option to enable Scalable Vector Extension + (SVE) for the Non-secure world only. SVE is an optional architectural feature + for AArch64. Note that when SVE is enabled for the Non-secure world, access + to SIMD and floating-point functionality from the Secure world is disabled. + This is to avoid corruption of the Non-secure world data in the Z-registers + which are aliased by the SIMD and FP registers. The build option is not + compatible with the ``CTX_INCLUDE_FPREGS`` build option, and will raise an + assert on platforms where SVE is implemented and ``ENABLE_SVE_FOR_NS`` set to + 1. The default is 1 but is automatically disabled when the target + architecture is AArch32. + - ``ENABLE_STACK_PROTECTOR``: String option to enable the stack protection checks in GCC. Allowed values are "all", "strong" and "0" (default). "strong" is the recommended stack protection level if this feature is @@ -1206,7 +1223,7 @@ corrupted binaries. make ARCH=aarch64 PLAT=juno LOAD_IMAGE_V2=1 JUNO_AARCH32_EL3_RUNTIME=1 \ BL33=<path-to-juno32-oe-uboot>/SOFTWARE/bl33-uboot.bin \ - SCP_BL2=<path-to-juno32-oe-uboot>/SOFTWARE/scp_bl2.bin SPD=tspd \ + SCP_BL2=<path-to-juno32-oe-uboot>/SOFTWARE/scp_bl2.bin \ BL32=<path-to-bl32>/bl32.bin all fip The resulting BL1 and FIP images may be found in: diff --git a/drivers/arm/gic/v2/gicv2_main.c b/drivers/arm/gic/v2/gicv2_main.c index 72f15cd7..87986594 100644 --- a/drivers/arm/gic/v2/gicv2_main.c +++ b/drivers/arm/gic/v2/gicv2_main.c @@ -176,7 +176,19 @@ void gicv2_driver_init(const gicv2_driver_data_t *plat_driver_data) gic_version = gicd_read_pidr2(plat_driver_data->gicd_base); gic_version = (gic_version >> PIDR2_ARCH_REV_SHIFT) & PIDR2_ARCH_REV_MASK; - assert(gic_version == ARCH_REV_GICV2); + + /* + * GICv1 with security extension complies with trusted firmware + * GICv2 driver as far as virtualization and few tricky power + * features are not used. GICv2 features that are not supported + * by GICv1 with Security Extensions are: + * - virtual interrupt support. + * - wake up events. + * - writeable GIC state register (for power sequences) + * - interrupt priority drop. + * - interrupt signal bypass. + */ + assert(gic_version == ARCH_REV_GICV2 || gic_version == ARCH_REV_GICV1); driver_data = plat_driver_data; diff --git a/include/common/aarch32/asm_macros.S b/include/common/aarch32/asm_macros.S index f5737449..74322228 100644 --- a/include/common/aarch32/asm_macros.S +++ b/include/common/aarch32/asm_macros.S @@ -79,6 +79,25 @@ ldr r0, =(\_name + \_size) .endm +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /* + * ARMv7 cores without Virtualization extension do not support the + * eret instruction. + */ + .macro eret + movs pc, lr + .endm +#endif + +#if (ARM_ARCH_MAJOR == 7) + /* ARMv7 does not support stl instruction */ + .macro stl _reg, _write_lock + dmb + str \_reg, \_write_lock + dsb + .endm +#endif + /* * Helper macro to generate the best mov/movw/movt combinations * according to the value to be moved. diff --git a/include/common/aarch32/el3_common_macros.S b/include/common/aarch32/el3_common_macros.S index 6fc00dd2..59e99f89 100644 --- a/include/common/aarch32/el3_common_macros.S +++ b/include/common/aarch32/el3_common_macros.S @@ -107,6 +107,7 @@ vmsr FPEXC, r0 isb +#if (ARM_ARCH_MAJOR > 7) /* --------------------------------------------------------------------- * Initialise SDCR, setting all the fields rather than relying on hw. * @@ -116,6 +117,7 @@ */ ldr r0, =(SDCR_RESET_VAL | SDCR_SPD(SDCR_SPD_DISABLE)) stcopr r0, SDCR +#endif .endm diff --git a/include/common/aarch64/el3_common_macros.S b/include/common/aarch64/el3_common_macros.S index ed35df82..63a0fa77 100644 --- a/include/common/aarch64/el3_common_macros.S +++ b/include/common/aarch64/el3_common_macros.S @@ -127,9 +127,9 @@ * CPTR_EL3.TTA: Set to zero so that System register accesses to the * trace registers do not trap to EL3. * - * CPTR_EL3.TFP: Set to zero so that accesses to Advanced SIMD and - * floating-point functionality do not trap to EL3. - * --------------------------------------------------------------------- + * CPTR_EL3.TFP: Set to zero so that accesses to the V- or Z- registers + * by Advanced SIMD, floating-point or SVE instructions (if implemented) + * do not trap to EL3. */ mov_imm x0, (CPTR_EL3_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT)) msr cptr_el3, x0 diff --git a/include/common/bl_common.h b/include/common/bl_common.h index 15ffc578..8915ba06 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -205,7 +205,6 @@ int is_mem_free(uintptr_t free_base, size_t free_size, #if LOAD_IMAGE_V2 -int load_image(unsigned int image_id, image_info_t *image_data); int load_auth_image(unsigned int image_id, image_info_t *image_data); #else diff --git a/include/drivers/arm/gic_common.h b/include/drivers/arm/gic_common.h index efa9703e..001f5736 100644 --- a/include/drivers/arm/gic_common.h +++ b/include/drivers/arm/gic_common.h @@ -72,6 +72,8 @@ #define ARCH_REV_GICV3 0x3 /* GICv2 revision as reported by the PIDR2 register */ #define ARCH_REV_GICV2 0x2 +/* GICv1 revision as reported by the PIDR2 register */ +#define ARCH_REV_GICV1 0x1 #define IGROUPR_SHIFT 5 #define ISENABLER_SHIFT 5 diff --git a/include/lib/aarch32/arch.h b/include/lib/aarch32/arch.h index 3846bec4..4d2a5fc9 100644 --- a/include/lib/aarch32/arch.h +++ b/include/lib/aarch32/arch.h @@ -78,6 +78,11 @@ /* CSSELR definitions */ #define LEVEL_SHIFT 1 +/* ID_PFR0 definitions */ +#define ID_PFR0_AMU_SHIFT U(20) +#define ID_PFR0_AMU_LENGTH U(4) +#define ID_PFR0_AMU_MASK U(0xf) + /* ID_PFR1 definitions */ #define ID_PFR1_VIRTEXT_SHIFT 12 #define ID_PFR1_VIRTEXT_MASK 0xf @@ -87,15 +92,21 @@ #define ID_PFR1_GIC_MASK 0xf /* SCTLR definitions */ -#define SCTLR_RES1 ((1 << 23) | (1 << 22) | (1 << 11) | (1 << 4) | \ - (1 << 3)) +#define SCTLR_RES1_DEF ((1 << 23) | (1 << 22) | (1 << 4) | (1 << 3)) +#if ARM_ARCH_MAJOR == 7 +#define SCTLR_RES1 SCTLR_RES1_DEF +#else +#define SCTLR_RES1 (SCTLR_RES1_DEF | (1 << 11)) +#endif #define SCTLR_M_BIT (1 << 0) #define SCTLR_A_BIT (1 << 1) #define SCTLR_C_BIT (1 << 2) #define SCTLR_CP15BEN_BIT (1 << 5) #define SCTLR_ITD_BIT (1 << 7) +#define SCTLR_Z_BIT (1 << 11) #define SCTLR_I_BIT (1 << 12) #define SCTLR_V_BIT (1 << 13) +#define SCTLR_RR_BIT (1 << 14) #define SCTLR_NTWI_BIT (1 << 16) #define SCTLR_NTWE_BIT (1 << 18) #define SCTLR_WXN_BIT (1 << 19) @@ -181,6 +192,7 @@ /* HCPTR definitions */ #define HCPTR_RES1 ((1 << 13) | (1<<12) | 0x3ff) #define TCPAC_BIT (1 << 31) +#define TAM_BIT (1 << 30) #define TTA_BIT (1 << 20) #define TCP11_BIT (1 << 10) #define TCP10_BIT (1 << 10) @@ -385,6 +397,7 @@ /* System register defines The format is: coproc, opt1, CRn, CRm, opt2 */ #define SCR p15, 0, c1, c1, 0 #define SCTLR p15, 0, c1, c0, 0 +#define ACTLR p15, 0, c1, c0, 1 #define SDCR p15, 0, c1, c3, 1 #define MPIDR p15, 0, c0, c0, 5 #define MIDR p15, 0, c0, c0, 0 @@ -400,6 +413,7 @@ #define DCISW p15, 0, c7, c6, 2 #define CTR p15, 0, c0, c0, 1 #define CNTFRQ p15, 0, c14, c0, 0 +#define ID_PFR0 p15, 0, c0, c1, 0 #define ID_PFR1 p15, 0, c0, c1, 1 #define MAIR0 p15, 0, c10, c2, 0 #define MAIR1 p15, 0, c10, c2, 1 @@ -431,6 +445,11 @@ #define PMCR p15, 0, c9, c12, 0 #define CNTHP_CTL p15, 4, c14, c2, 1 +/* AArch32 coproc registers for 32bit MMU descriptor support */ +#define PRRR p15, 0, c10, c2, 0 +#define NMRR p15, 0, c10, c2, 1 +#define DACR p15, 0, c3, c0, 0 + /* GICv3 CPU Interface system register defines. The format is: coproc, opt1, CRn, CRm, opt2 */ #define ICC_IAR1 p15, 0, c12, c12, 0 #define ICC_IAR0 p15, 0, c12, c8, 0 @@ -513,4 +532,28 @@ #define MAKE_MAIR_NORMAL_MEMORY(inner, outer) ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT)) +/******************************************************************************* + * Definitions for system register interface to AMU for ARMv8.4 onwards + ******************************************************************************/ +#define AMCR p15, 0, c13, c2, 0 +#define AMCFGR p15, 0, c13, c2, 1 +#define AMCGCR p15, 0, c13, c2, 2 +#define AMUSERENR p15, 0, c13, c2, 3 +#define AMCNTENCLR0 p15, 0, c13, c2, 4 +#define AMCNTENSET0 p15, 0, c13, c2, 5 +#define AMCNTENCLR1 p15, 0, c13, c3, 0 +#define AMCNTENSET1 p15, 0, c13, c1, 1 + +/* Activity Monitor Group 0 Event Counter Registers */ +#define AMEVCNTR00 p15, 0, c0 +#define AMEVCNTR01 p15, 1, c0 +#define AMEVCNTR02 p15, 2, c0 +#define AMEVCNTR03 p15, 3, c0 + +/* Activity Monitor Group 0 Event Type Registers */ +#define AMEVTYPER00 p15, 0, c13, c6, 0 +#define AMEVTYPER01 p15, 0, c13, c6, 1 +#define AMEVTYPER02 p15, 0, c13, c6, 2 +#define AMEVTYPER03 p15, 0, c13, c6, 3 + #endif /* __ARCH_H__ */ diff --git a/include/lib/aarch32/arch_helpers.h b/include/lib/aarch32/arch_helpers.h index 469e9b0d..0230195a 100644 --- a/include/lib/aarch32/arch_helpers.h +++ b/include/lib/aarch32/arch_helpers.h @@ -227,6 +227,7 @@ DEFINE_SYSREG_RW_FUNCS(cpsr) ******************************************************************************/ DEFINE_COPROCR_READ_FUNC(mpidr, MPIDR) DEFINE_COPROCR_READ_FUNC(midr, MIDR) +DEFINE_COPROCR_READ_FUNC(id_pfr0, ID_PFR0) DEFINE_COPROCR_READ_FUNC(id_pfr1, ID_PFR1) DEFINE_COPROCR_READ_FUNC(isr, ISR) DEFINE_COPROCR_READ_FUNC(clidr, CLIDR) @@ -235,6 +236,7 @@ DEFINE_COPROCR_READ_FUNC_64(cntpct, CNTPCT_64) DEFINE_COPROCR_RW_FUNCS(scr, SCR) DEFINE_COPROCR_RW_FUNCS(ctr, CTR) DEFINE_COPROCR_RW_FUNCS(sctlr, SCTLR) +DEFINE_COPROCR_RW_FUNCS(actlr, ACTLR) DEFINE_COPROCR_RW_FUNCS(hsctlr, HSCTLR) DEFINE_COPROCR_RW_FUNCS(hcr, HCR) DEFINE_COPROCR_RW_FUNCS(hcptr, HCPTR) @@ -273,6 +275,18 @@ DEFINE_COPROCR_RW_FUNCS(hdcr, HDCR) DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL) DEFINE_COPROCR_READ_FUNC(pmcr, PMCR) +DEFINE_COPROCR_RW_FUNCS(nsacr, NSACR) + +/* AArch32 coproc registers for 32bit MMU descriptor support */ +DEFINE_COPROCR_RW_FUNCS(prrr, PRRR) +DEFINE_COPROCR_RW_FUNCS(nmrr, NMRR) +DEFINE_COPROCR_RW_FUNCS(dacr, DACR) + +DEFINE_COPROCR_RW_FUNCS(amcntenset0, AMCNTENSET0) +DEFINE_COPROCR_RW_FUNCS(amcntenset1, AMCNTENSET1) +DEFINE_COPROCR_RW_FUNCS(amcntenclr0, AMCNTENCLR0) +DEFINE_COPROCR_RW_FUNCS(amcntenclr1, AMCNTENCLR1) + /* * TLBI operation prototypes */ @@ -296,6 +310,7 @@ DEFINE_DCOP_PARAM_FUNC(cvac, DCCMVAC) /* Previously defined accessor functions with incomplete register names */ #define dsb() dsbsy() +#define dmb() dmbsy() #define IS_IN_SECURE() \ (GET_NS_BIT(read_scr()) == 0) diff --git a/include/lib/aarch32/smcc_macros.S b/include/lib/aarch32/smcc_macros.S index cf26175d..93f211f7 100644 --- a/include/lib/aarch32/smcc_macros.S +++ b/include/lib/aarch32/smcc_macros.S @@ -22,6 +22,44 @@ mov r0, sp add r0, r0, #SMC_CTX_SP_USR +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /* Must be in secure state to restore Monitor mode */ + ldcopr r4, SCR + bic r2, r4, #SCR_NS_BIT + stcopr r2, SCR + isb + + cps #MODE32_sys + stm r0!, {sp, lr} + + cps #MODE32_irq + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #MODE32_fiq + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #MODE32_svc + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #MODE32_abt + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #MODE32_und + mrs r2, spsr + stm r0!, {r2, sp, lr} + + /* lr_mon is already saved by caller */ + cps #MODE32_mon + mrs r2, spsr + stm r0!, {r2} + + stcopr r4, SCR + isb +#else /* Save the banked registers including the current SPSR and LR */ mrs r4, sp_usr mrs r5, lr_usr @@ -44,9 +82,10 @@ mrs r11, lr_und mrs r12, spsr stm r0!, {r4-r12} - /* lr_mon is already saved by caller */ + ldcopr r4, SCR +#endif str r4, [sp, #SMC_CTX_SCR] ldcopr r4, PMCR str r4, [sp, #SMC_CTX_PMCR] @@ -82,6 +121,44 @@ /* Restore the banked registers including the current SPSR */ add r1, r0, #SMC_CTX_SP_USR + +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /* Must be in secure state to restore Monitor mode */ + ldcopr r4, SCR + bic r2, r4, #SCR_NS_BIT + stcopr r2, SCR + isb + + cps #MODE32_sys + ldm r1!, {sp, lr} + + cps #MODE32_irq + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_fiq + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_svc + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_abt + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_und + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_mon + ldm r1!, {r2} + msr spsr_fsxc, r2 + + stcopr r4, SCR + isb +#else ldm r1!, {r4-r12} msr sp_usr, r4 msr lr_usr, r5 @@ -109,6 +186,7 @@ * f->[31:24] and c->[7:0] bits of SPSR. */ msr spsr_fsxc, r12 +#endif /* Restore the LR */ ldr lr, [r0, #SMC_CTX_LR_MON] diff --git a/include/lib/aarch64/arch.h b/include/lib/aarch64/arch.h index 777a01a9..96e2d5fe 100644 --- a/include/lib/aarch64/arch.h +++ b/include/lib/aarch64/arch.h @@ -110,7 +110,13 @@ #define ID_AA64PFR0_EL1_SHIFT U(4) #define ID_AA64PFR0_EL2_SHIFT U(8) #define ID_AA64PFR0_EL3_SHIFT U(12) +#define ID_AA64PFR0_AMU_SHIFT U(44) +#define ID_AA64PFR0_AMU_LENGTH U(4) +#define ID_AA64PFR0_AMU_MASK U(0xf) #define ID_AA64PFR0_ELX_MASK U(0xf) +#define ID_AA64PFR0_SVE_SHIFT U(32) +#define ID_AA64PFR0_SVE_MASK U(0xf) +#define ID_AA64PFR0_SVE_LENGTH U(4) /* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */ #define ID_AA64DFR0_PMS_SHIFT U(32) @@ -135,6 +141,7 @@ #define PARANGE_0011 U(42) #define PARANGE_0100 U(44) #define PARANGE_0101 U(48) +#define PARANGE_0110 U(52) #define ID_AA64MMFR0_EL1_TGRAN4_SHIFT U(28) #define ID_AA64MMFR0_EL1_TGRAN4_MASK U(0xf) @@ -294,15 +301,19 @@ /* CPTR_EL3 definitions */ #define TCPAC_BIT (U(1) << 31) +#define TAM_BIT (U(1) << 30) #define TTA_BIT (U(1) << 20) #define TFP_BIT (U(1) << 10) +#define CPTR_EZ_BIT (U(1) << 8) #define CPTR_EL3_RESET_VAL U(0x0) /* CPTR_EL2 definitions */ #define CPTR_EL2_RES1 ((U(1) << 13) | (U(1) << 12) | (U(0x3ff))) #define CPTR_EL2_TCPAC_BIT (U(1) << 31) +#define CPTR_EL2_TAM_BIT (U(1) << 30) #define CPTR_EL2_TTA_BIT (U(1) << 20) #define CPTR_EL2_TFP_BIT (U(1) << 10) +#define CPTR_EL2_TZ_BIT (U(1) << 8) #define CPTR_EL2_RESET_VAL CPTR_EL2_RES1 /* CPSR/SPSR definitions */ @@ -550,6 +561,18 @@ #define PMCR_EL0_D_BIT (U(1) << 3) /******************************************************************************* + * Definitions for system register interface to SVE + ******************************************************************************/ +#define ZCR_EL3 S3_6_C1_C2_0 +#define ZCR_EL2 S3_4_C1_C2_0 + +/* ZCR_EL3 definitions */ +#define ZCR_EL3_LEN_MASK U(0xf) + +/* ZCR_EL2 definitions */ +#define ZCR_EL2_LEN_MASK U(0xf) + +/******************************************************************************* * Definitions of MAIR encodings for device and normal memory ******************************************************************************/ /* @@ -609,4 +632,28 @@ ******************************************************************************/ #define PMBLIMITR_EL1 S3_0_C9_C10_0 +/******************************************************************************* + * Definitions for system register interface to AMU for ARMv8.4 onwards + ******************************************************************************/ +#define AMCR_EL0 S3_3_C13_C2_0 +#define AMCFGR_EL0 S3_3_C13_C2_1 +#define AMCGCR_EL0 S3_3_C13_C2_2 +#define AMUSERENR_EL0 S3_3_C13_C2_3 +#define AMCNTENCLR0_EL0 S3_3_C13_C2_4 +#define AMCNTENSET0_EL0 S3_3_C13_C2_5 +#define AMCNTENCLR1_EL0 S3_3_C13_C3_0 +#define AMCNTENSET1_EL0 S3_3_C13_C3_1 + +/* Activity Monitor Group 0 Event Counter Registers */ +#define AMEVCNTR00_EL0 S3_3_C13_C4_0 +#define AMEVCNTR01_EL0 S3_3_C13_C4_1 +#define AMEVCNTR02_EL0 S3_3_C13_C4_2 +#define AMEVCNTR03_EL0 S3_3_C13_C4_3 + +/* Activity Monitor Group 0 Event Type Registers */ +#define AMEVTYPER00_EL0 S3_3_C13_C6_0 +#define AMEVTYPER01_EL0 S3_3_C13_C6_1 +#define AMEVTYPER02_EL0 S3_3_C13_C6_2 +#define AMEVTYPER03_EL0 S3_3_C13_C6_3 + #endif /* __ARCH_H__ */ diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h index 46d9a1c0..831dfb06 100644 --- a/include/lib/aarch64/arch_helpers.h +++ b/include/lib/aarch64/arch_helpers.h @@ -322,8 +322,16 @@ DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir0_el1, ICC_EOIR0_EL1) DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1) DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_sgi0r_el1, ICC_SGI0R_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr0_el0, AMCNTENCLR0_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset0_el0, AMCNTENSET0_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0) + DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1) +DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el3, ZCR_EL3) +DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el2, ZCR_EL2) + #define IS_IN_EL(x) \ (GET_EL(read_CurrentEl()) == MODE_EL##x) diff --git a/include/lib/cpus/aarch32/cortex_a12.h b/include/lib/cpus/aarch32/cortex_a12.h new file mode 100644 index 00000000..3068a41f --- /dev/null +++ b/include/lib/cpus/aarch32/cortex_a12.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CORTEX_A12_H__ +#define __CORTEX_A12_H__ + +/******************************************************************************* + * Cortex-A12 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A12_MIDR 0x410FC0C0 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A12_ACTLR_SMP_BIT (1 << 6) + +#endif /* __CORTEX_A12_H__ */ diff --git a/include/lib/cpus/aarch32/cortex_a15.h b/include/lib/cpus/aarch32/cortex_a15.h new file mode 100644 index 00000000..905c139d --- /dev/null +++ b/include/lib/cpus/aarch32/cortex_a15.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CORTEX_A15_H__ +#define __CORTEX_A15_H__ + +/******************************************************************************* + * Cortex-A15 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A15_MIDR 0x410FC0F0 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A15_ACTLR_SMP_BIT (1 << 6) + +#endif /* __CORTEX_A15_H__ */ diff --git a/include/lib/cpus/aarch32/cortex_a17.h b/include/lib/cpus/aarch32/cortex_a17.h new file mode 100644 index 00000000..d2ca91c4 --- /dev/null +++ b/include/lib/cpus/aarch32/cortex_a17.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CORTEX_A17_H__ +#define __CORTEX_A17_H__ + +/******************************************************************************* + * Cortex-A17 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A17_MIDR 0x410FC0E0 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A17_ACTLR_SMP_BIT (1 << 6) + +#endif /* __CORTEX_A17_H__ */ diff --git a/include/lib/cpus/aarch32/cortex_a5.h b/include/lib/cpus/aarch32/cortex_a5.h new file mode 100644 index 00000000..0a0b7ffa --- /dev/null +++ b/include/lib/cpus/aarch32/cortex_a5.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CORTEX_A5_H__ +#define __CORTEX_A5_H__ + +/******************************************************************************* + * Cortex-A8 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A5_MIDR 0x410FC050 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A5_ACTLR_SMP_BIT (1 << 6) + +#endif /* __CORTEX_A5_H__ */ diff --git a/include/lib/cpus/aarch32/cortex_a7.h b/include/lib/cpus/aarch32/cortex_a7.h new file mode 100644 index 00000000..61b0d008 --- /dev/null +++ b/include/lib/cpus/aarch32/cortex_a7.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CORTEX_A7_H__ +#define __CORTEX_A7_H__ + +/******************************************************************************* + * Cortex-A7 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A7_MIDR 0x410FC070 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A7_ACTLR_SMP_BIT (1 << 6) + +#endif /* __CORTEX_A7_H__ */ diff --git a/include/lib/cpus/aarch32/cortex_a9.h b/include/lib/cpus/aarch32/cortex_a9.h new file mode 100644 index 00000000..be85f9be --- /dev/null +++ b/include/lib/cpus/aarch32/cortex_a9.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __CORTEX_A9_H__ +#define __CORTEX_A9_H__ + +/******************************************************************************* + * Cortex-A9 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A9_MIDR 0x410FC090 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A9_ACTLR_SMP_BIT (1 << 6) +#define CORTEX_A9_ACTLR_FLZW_BIT (1 << 3) + +/******************************************************************************* + * CPU Power Control Register + ******************************************************************************/ +#define PCR p15, 0, c15, c0, 0 + +#ifndef __ASSEMBLY__ +#include <arch_helpers.h> +DEFINE_COPROCR_RW_FUNCS(pcr, PCR) +#endif + +#endif /* __CORTEX_A9_H__ */ diff --git a/include/lib/cpus/aarch64/cortex_a75.h b/include/lib/cpus/aarch64/cortex_a75.h index 1ffe20bb..d68c9572 100644 --- a/include/lib/cpus/aarch64/cortex_a75.h +++ b/include/lib/cpus/aarch64/cortex_a75.h @@ -19,4 +19,38 @@ /* Definitions of register field mask in CORTEX_A75_CPUPWRCTLR_EL1 */ #define CORTEX_A75_CORE_PWRDN_EN_MASK 0x1 +/******************************************************************************* + * CPU Activity Monitor Unit register specific definitions. + ******************************************************************************/ +#define CPUAMCNTENCLR_EL0 S3_3_C15_C9_7 +#define CPUAMCNTENSET_EL0 S3_3_C15_C9_6 +#define CPUAMCFGR_EL0 S3_3_C15_C10_6 +#define CPUAMUSERENR_EL0 S3_3_C15_C10_7 + +/* Activity Monitor Event Counter Registers */ +#define CPUAMEVCNTR0_EL0 S3_3_C15_C9_0 +#define CPUAMEVCNTR1_EL0 S3_3_C15_C9_1 +#define CPUAMEVCNTR2_EL0 S3_3_C15_C9_2 +#define CPUAMEVCNTR3_EL0 S3_3_C15_C9_3 +#define CPUAMEVCNTR4_EL0 S3_3_C15_C9_4 + +/* Activity Monitor Event Type Registers */ +#define CPUAMEVTYPER0_EL0 S3_3_C15_C10_0 +#define CPUAMEVTYPER1_EL0 S3_3_C15_C10_1 +#define CPUAMEVTYPER2_EL0 S3_3_C15_C10_2 +#define CPUAMEVTYPER3_EL0 S3_3_C15_C10_3 +#define CPUAMEVTYPER4_EL0 S3_3_C15_C10_4 + +#define CORTEX_A75_ACTLR_AMEN_BIT (U(1) << 4) + +/* + * The Cortex-A75 core implements five counters, 0-4. Events 0, 1, 2, are + * fixed and are enabled (Group 0). Events 3 and 4 (Group 1) are + * programmable by programming the appropriate Event count bits in + * CPUAMEVTYPER<n> register and are disabled by default. Platforms may + * enable this with suitable programming. + */ +#define CORTEX_A75_AMU_GROUP0_MASK 0x7 +#define CORTEX_A75_AMU_GROUP1_MASK (0 << 3) + #endif /* __CORTEX_A75_H__ */ diff --git a/include/lib/extensions/amu.h b/include/lib/extensions/amu.h new file mode 100644 index 00000000..bbefe8ff --- /dev/null +++ b/include/lib/extensions/amu.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __AMU_H__ +#define __AMU_H__ + +/* Enable all group 0 counters */ +#define AMU_GROUP0_COUNTERS_MASK 0xf + +void amu_enable(int el2_unused); + +#endif /* __AMU_H__ */ diff --git a/include/lib/extensions/sve.h b/include/lib/extensions/sve.h new file mode 100644 index 00000000..28923e3f --- /dev/null +++ b/include/lib/extensions/sve.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SVE_H__ +#define __SVE_H__ + +void sve_enable(int el2_unused); + +#endif /* __SVE_H__ */ diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h index 73a9c533..ba3e3603 100644 --- a/include/lib/xlat_tables/xlat_tables_v2.h +++ b/include/lib/xlat_tables/xlat_tables_v2.h @@ -168,21 +168,28 @@ typedef struct xlat_ctx xlat_ctx_t; _xlat_tables_count, \ _virt_addr_space_size, \ _phy_addr_space_size, \ - IMAGE_XLAT_DEFAULT_REGIME) + IMAGE_XLAT_DEFAULT_REGIME, \ + "xlat_table") /* - * Same as REGISTER_XLAT_CONTEXT plus the additional parameter _xlat_regime to - * specify the translation regime managed by this xlat_ctx_t instance. The - * values are the one from xlat_regime_t enumeration. + * Same as REGISTER_XLAT_CONTEXT plus the additional parameters: + * + * _xlat_regime: + * Specify the translation regime managed by this xlat_ctx_t instance. The + * values are the one from xlat_regime_t enumeration. + * + * _section_name: + * Specify the name of the section where the translation tables have to be + * placed by the linker. */ #define REGISTER_XLAT_CONTEXT2(_ctx_name, _mmap_count, _xlat_tables_count, \ _virt_addr_space_size, _phy_addr_space_size, \ - _xlat_regime) \ + _xlat_regime, _section_name) \ _REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \ _xlat_tables_count, \ _virt_addr_space_size, \ _phy_addr_space_size, \ - _xlat_regime) + _xlat_regime, _section_name) /****************************************************************************** * Generic translation table APIs. diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h index 96dee1a0..1be99b71 100644 --- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h +++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h @@ -123,7 +123,7 @@ struct xlat_ctx { #define _REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, _xlat_tables_count, \ _virt_addr_space_size, _phy_addr_space_size, \ - _xlat_regime) \ + _xlat_regime, _section_name) \ CASSERT(CHECK_VIRT_ADDR_SPACE_SIZE(_virt_addr_space_size), \ assert_invalid_virtual_addr_space_size_for_##_ctx_name); \ \ @@ -134,7 +134,7 @@ struct xlat_ctx { \ static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count] \ [XLAT_TABLE_ENTRIES] \ - __aligned(XLAT_TABLE_SIZE) __section("xlat_table"); \ + __aligned(XLAT_TABLE_SIZE) __section(_section_name); \ \ static uint64_t _ctx_name##_base_xlat_table \ [GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)] \ diff --git a/include/plat/arm/board/common/board_arm_def.h b/include/plat/arm/board/common/board_arm_def.h index 97a1af4b..69eb727f 100644 --- a/include/plat/arm/board/common/board_arm_def.h +++ b/include/plat/arm/board/common/board_arm_def.h @@ -90,10 +90,14 @@ * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a * little space for growth. */ -#if ENABLE_SPM -#define PLAT_ARM_MAX_BL31_SIZE 0x28000 -#else #define PLAT_ARM_MAX_BL31_SIZE 0x1D000 + +#ifdef AARCH32 +/* + * PLAT_ARM_MAX_BL32_SIZE is calculated for SP_MIN as the AArch32 Secure + * Payload. + */ +# define PLAT_ARM_MAX_BL32_SIZE 0x1D000 #endif #endif /* ARM_BOARD_OPTIMISE_MEM */ diff --git a/include/plat/arm/common/arm_common.ld.S b/include/plat/arm/common/arm_common.ld.S index 478b08c2..6edfa099 100644 --- a/include/plat/arm/common/arm_common.ld.S +++ b/include/plat/arm/common/arm_common.ld.S @@ -6,6 +6,8 @@ #ifndef __ARM_COMMON_LD_S__ #define __ARM_COMMON_LD_S__ +#include <xlat_tables_defs.h> + MEMORY { EL3_SEC_DRAM (rw): ORIGIN = ARM_EL3_TZC_DRAM1_BASE, LENGTH = ARM_EL3_TZC_DRAM1_SIZE } @@ -13,14 +15,14 @@ MEMORY { SECTIONS { . = ARM_EL3_TZC_DRAM1_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "ARM_EL3_TZC_DRAM_BASE address is not aligned on a page boundary.") - el3_tzc_dram (NOLOAD) : ALIGN(4096) { + el3_tzc_dram (NOLOAD) : ALIGN(PAGE_SIZE) { __EL3_SEC_DRAM_START__ = .; *(arm_el3_tzc_dram) __EL3_SEC_DRAM_UNALIGNED_END__ = .; - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __EL3_SEC_DRAM_END__ = .; } >EL3_SEC_DRAM } diff --git a/include/plat/arm/common/arm_def.h b/include/plat/arm/common/arm_def.h index b8955afc..78875259 100644 --- a/include/plat/arm/common/arm_def.h +++ b/include/plat/arm/common/arm_def.h @@ -326,14 +326,21 @@ /******************************************************************************* * BL2 specific defines. ******************************************************************************/ -#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME)) +#if ARM_BL31_IN_DRAM /* - * For AArch32 BL31 is not applicable. * For AArch64 BL31 is loaded in the DRAM. * Put BL2 just below BL1. */ #define BL2_BASE (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE) #define BL2_LIMIT BL1_RW_BASE + +#elif defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME +/* + * Put BL2 just below BL32. + */ +#define BL2_BASE (BL32_BASE - PLAT_ARM_MAX_BL2_SIZE) +#define BL2_LIMIT BL32_BASE + #else /* * Put BL2 just below BL31. @@ -370,76 +377,86 @@ #define BL31_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) #endif +#if defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME /******************************************************************************* - * BL32 specific defines. + * BL32 specific defines for EL3 runtime in AArch32 mode + ******************************************************************************/ +# if RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME +/* SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM to BL32 */ +# define BL32_BASE ARM_BL_RAM_BASE +# define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) +# else +/* Put BL32 at the top of the Trusted SRAM.*/ +# define BL32_BASE (ARM_BL_RAM_BASE + \ + ARM_BL_RAM_SIZE - \ + PLAT_ARM_MAX_BL32_SIZE) +# define BL32_PROGBITS_LIMIT BL1_RW_BASE +# define BL32_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) +# endif /* RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME */ + +#else +/******************************************************************************* + * BL32 specific defines for EL3 runtime in AArch64 mode ******************************************************************************/ /* * On ARM standard platforms, the TSP can execute from Trusted SRAM, * Trusted DRAM (if available) or the DRAM region secured by the TrustZone * controller. */ -#if ENABLE_SPM -# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) -# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000)) -# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) -# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ +# if ENABLE_SPM +# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) +# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000)) +# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ ARM_AP_TZC_DRAM1_SIZE) -#elif ARM_BL31_IN_DRAM -# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + \ +# elif ARM_BL31_IN_DRAM +# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + \ PLAT_ARM_MAX_BL31_SIZE) -# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - \ +# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - \ PLAT_ARM_MAX_BL31_SIZE) -# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + \ +# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + \ PLAT_ARM_MAX_BL31_SIZE) -# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ ARM_AP_TZC_DRAM1_SIZE) -#elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID -# define TSP_SEC_MEM_BASE ARM_BL_RAM_BASE -# define TSP_SEC_MEM_SIZE ARM_BL_RAM_SIZE -# define TSP_PROGBITS_LIMIT BL2_BASE -# define BL32_BASE ARM_BL_RAM_BASE -# define BL32_LIMIT BL31_BASE -#elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID -# define TSP_SEC_MEM_BASE PLAT_ARM_TRUSTED_DRAM_BASE -# define TSP_SEC_MEM_SIZE PLAT_ARM_TRUSTED_DRAM_SIZE -# define BL32_BASE PLAT_ARM_TRUSTED_DRAM_BASE -# define BL32_LIMIT (PLAT_ARM_TRUSTED_DRAM_BASE \ +# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID +# define TSP_SEC_MEM_BASE ARM_BL_RAM_BASE +# define TSP_SEC_MEM_SIZE ARM_BL_RAM_SIZE +# define TSP_PROGBITS_LIMIT BL2_BASE +# define BL32_BASE ARM_BL_RAM_BASE +# define BL32_LIMIT BL31_BASE +# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID +# define TSP_SEC_MEM_BASE PLAT_ARM_TRUSTED_DRAM_BASE +# define TSP_SEC_MEM_SIZE PLAT_ARM_TRUSTED_DRAM_SIZE +# define BL32_BASE PLAT_ARM_TRUSTED_DRAM_BASE +# define BL32_LIMIT (PLAT_ARM_TRUSTED_DRAM_BASE \ + (1 << 21)) -#elif ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID -# define TSP_SEC_MEM_BASE ARM_AP_TZC_DRAM1_BASE -# define TSP_SEC_MEM_SIZE ARM_AP_TZC_DRAM1_SIZE -# define BL32_BASE ARM_AP_TZC_DRAM1_BASE -# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ +# elif ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID +# define TSP_SEC_MEM_BASE ARM_AP_TZC_DRAM1_BASE +# define TSP_SEC_MEM_SIZE ARM_AP_TZC_DRAM1_SIZE +# define BL32_BASE ARM_AP_TZC_DRAM1_BASE +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ ARM_AP_TZC_DRAM1_SIZE) -#else -# error "Unsupported ARM_TSP_RAM_LOCATION_ID value" -#endif +# else +# error "Unsupported ARM_TSP_RAM_LOCATION_ID value" +# endif +#endif /* AARCH32 || JUNO_AARCH32_EL3_RUNTIME */ /* * BL32 is mandatory in AArch32. In AArch64, undefine BL32_BASE if there is no * SPD and no SPM, as they are the only ones that can be used as BL32. */ -#ifndef AARCH32 +#if !(defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME) # if defined(SPD_none) && !ENABLE_SPM # undef BL32_BASE -# endif -#endif +# endif /* defined(SPD_none) && !ENABLE_SPM */ +#endif /* !(defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME) */ /******************************************************************************* * FWU Images: NS_BL1U, BL2U & NS_BL2U defines. ******************************************************************************/ #define BL2U_BASE BL2_BASE -#if ARM_BL31_IN_DRAM || (defined(AARCH32) && !defined(JUNO_AARCH32_EL3_RUNTIME)) -/* - * For AArch32 BL31 is not applicable. - * For AArch64 BL31 is loaded in the DRAM. - * BL2U extends up to BL1. - */ -#define BL2U_LIMIT BL1_RW_BASE -#else -/* BL2U extends up to BL31. */ -#define BL2U_LIMIT BL31_BASE -#endif +#define BL2U_LIMIT BL2_LIMIT + #define NS_BL2U_BASE ARM_NS_DRAM1_BASE #define NS_BL1U_BASE (PLAT_ARM_NVM_BASE + 0x03EB8000) diff --git a/include/plat/arm/common/arm_spm_def.h b/include/plat/arm/common/arm_spm_def.h index 83277a6c..3f5c958d 100644 --- a/include/plat/arm/common/arm_spm_def.h +++ b/include/plat/arm/common/arm_spm_def.h @@ -98,6 +98,12 @@ /* Total number of memory regions with distinct properties */ #define ARM_SP_IMAGE_NUM_MEM_REGIONS 6 +/* + * Name of the section to put the translation tables used by the S-EL1/S-EL0 + * context of a Secure Partition. + */ +#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "arm_el3_tzc_dram" + /* Cookies passed to the Secure Partition at boot. Not used by ARM platforms. */ #define PLAT_SPM_COOKIE_0 ULL(0) #define PLAT_SPM_COOKIE_1 ULL(0) diff --git a/include/services/spm_svc.h b/include/services/spm_svc.h index 2c8c7cd8..738979eb 100644 --- a/include/services/spm_svc.h +++ b/include/services/spm_svc.h @@ -32,24 +32,24 @@ * Manager from the Secure Partition(s). These services enable a partition to * handle delegated events and request privileged operations from the manager. */ -#define SPM_VERSION_AARCH32 U(0x84000060) -#define SP_EVENT_COMPLETE_AARCH64 U(0xC4000061) -#define SP_MEM_ATTRIBUTES_GET_AARCH64 U(0xC4000064) -#define SP_MEM_ATTRIBUTES_SET_AARCH64 U(0xC4000065) +#define SPM_VERSION_AARCH32 U(0x84000060) +#define SP_EVENT_COMPLETE_AARCH64 U(0xC4000061) +#define SP_MEMORY_ATTRIBUTES_GET_AARCH64 U(0xC4000064) +#define SP_MEMORY_ATTRIBUTES_SET_AARCH64 U(0xC4000065) /* - * Macros used by SP_MEM_ATTRIBUTES_SET_AARCH64. + * Macros used by SP_MEMORY_ATTRIBUTES_SET_AARCH64. */ -#define SP_MEM_ATTR_ACCESS_NOACCESS U(0) -#define SP_MEM_ATTR_ACCESS_RW U(1) +#define SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS U(0) +#define SP_MEMORY_ATTRIBUTES_ACCESS_RW U(1) /* Value U(2) is reserved. */ -#define SP_MEM_ATTR_ACCESS_RO U(3) -#define SP_MEM_ATTR_ACCESS_MASK U(3) -#define SP_MEM_ATTR_ACCESS_SHIFT 0 +#define SP_MEMORY_ATTRIBUTES_ACCESS_RO U(3) +#define SP_MEMORY_ATTRIBUTES_ACCESS_MASK U(3) +#define SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT 0 -#define SP_MEM_ATTR_EXEC (U(0) << 2) -#define SP_MEM_ATTR_NON_EXEC (U(1) << 2) +#define SP_MEMORY_ATTRIBUTES_EXEC (U(0) << 2) +#define SP_MEMORY_ATTRIBUTES_NON_EXEC (U(1) << 2) /* * SMC IDs defined in [1] for accessing secure partition services from the @@ -59,8 +59,8 @@ #define SP_VERSION_AARCH64 U(0xC4000040) #define SP_VERSION_AARCH32 U(0x84000040) -#define SP_COMMUNICATE_AARCH64 U(0xC4000041) -#define SP_COMMUNICATE_AARCH32 U(0x84000041) +#define MM_COMMUNICATE_AARCH64 U(0xC4000041) +#define MM_COMMUNICATE_AARCH32 U(0x84000041) /* SPM error codes. */ #define SPM_SUCCESS 0 diff --git a/lib/aarch32/arm32_aeabi_divmod.c b/lib/aarch32/arm32_aeabi_divmod.c new file mode 100644 index 00000000..a8f2e742 --- /dev/null +++ b/lib/aarch32/arm32_aeabi_divmod.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Form ABI specifications: + * int __aeabi_idiv(int numerator, int denominator); + * unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator); + * + * typedef struct { int quot; int rem; } idiv_return; + * typedef struct { unsigned quot; unsigned rem; } uidiv_return; + * + * __value_in_regs idiv_return __aeabi_idivmod(int numerator, + * int *denominator); + * __value_in_regs uidiv_return __aeabi_uidivmod(unsigned *numerator, + * unsigned denominator); + */ + +/* struct qr - stores qutient/remainder to handle divmod EABI interfaces. */ +struct qr { + unsigned int q; /* computed quotient */ + unsigned int r; /* computed remainder */ + unsigned int q_n; /* specficies if quotient shall be negative */ + unsigned int r_n; /* specficies if remainder shall be negative */ +}; + +static void uint_div_qr(unsigned int numerator, unsigned int denominator, + struct qr *qr); + +/* returns in R0 and R1 by tail calling an asm function */ +unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator); + +unsigned int __aeabi_uidiv(unsigned int numerator, unsigned int denominator); +unsigned int __aeabi_uimod(unsigned int numerator, unsigned int denominator); + +/* returns in R0 and R1 by tail calling an asm function */ +signed int __aeabi_idivmod(signed int numerator, signed int denominator); + +signed int __aeabi_idiv(signed int numerator, signed int denominator); +signed int __aeabi_imod(signed int numerator, signed int denominator); + +/* + * __ste_idivmod_ret_t __aeabi_idivmod(signed numerator, signed denominator) + * Numerator and Denominator are received in R0 and R1. + * Where __ste_idivmod_ret_t is returned in R0 and R1. + * + * __ste_uidivmod_ret_t __aeabi_uidivmod(unsigned numerator, + * unsigned denominator) + * Numerator and Denominator are received in R0 and R1. + * Where __ste_uidivmod_ret_t is returned in R0 and R1. + */ +#ifdef __GNUC__ +signed int ret_idivmod_values(signed int quotient, signed int remainder); +unsigned int ret_uidivmod_values(unsigned int quotient, unsigned int remainder); +#else +#error "Compiler not supported" +#endif + +static void division_qr(unsigned int n, unsigned int p, struct qr *qr) +{ + unsigned int i = 1, q = 0; + + if (p == 0) { + qr->r = 0xFFFFFFFF; /* division by 0 */ + return; + } + + while ((p >> 31) == 0) { + i = i << 1; /* count the max division steps */ + p = p << 1; /* increase p until it has maximum size*/ + } + + while (i > 0) { + q = q << 1; /* write bit in q at index (size-1) */ + if (n >= p) { + n -= p; + q++; + } + p = p >> 1; /* decrease p */ + i = i >> 1; /* decrease remaining size in q */ + } + qr->r = n; + qr->q = q; +} + +static void uint_div_qr(unsigned int numerator, unsigned int denominator, + struct qr *qr) +{ + division_qr(numerator, denominator, qr); + + /* negate quotient and/or remainder according to requester */ + if (qr->q_n) + qr->q = -qr->q; + if (qr->r_n) + qr->r = -qr->r; +} + +unsigned int __aeabi_uidiv(unsigned int numerator, unsigned int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + uint_div_qr(numerator, denominator, &qr); + + return qr.q; +} + +unsigned int __aeabi_uimod(unsigned int numerator, unsigned int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + uint_div_qr(numerator, denominator, &qr); + + return qr.r; +} + +unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + uint_div_qr(numerator, denominator, &qr); + + return ret_uidivmod_values(qr.q, qr.r); +} + +signed int __aeabi_idiv(signed int numerator, signed int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + if (((numerator < 0) && (denominator > 0)) || + ((numerator > 0) && (denominator < 0))) + qr.q_n = 1; /* quotient shall be negate */ + + if (numerator < 0) { + numerator = -numerator; + qr.r_n = 1; /* remainder shall be negate */ + } + + if (denominator < 0) + denominator = -denominator; + + uint_div_qr(numerator, denominator, &qr); + + return qr.q; +} + +signed int __aeabi_imod(signed int numerator, signed int denominator) +{ + signed int s; + signed int i; + signed int j; + signed int h; + struct qr qr = { .q_n = 0, .r_n = 0 }; + + /* in case modulo of a power of 2 */ + for (i = 0, j = 0, h = 0, s = denominator; (s != 0) || (h > 1); i++) { + if (s & 1) { + j = i; + h++; + } + s = s >> 1; + } + if (h == 1) + return numerator >> j; + + if (((numerator < 0) && (denominator > 0)) || + ((numerator > 0) && (denominator < 0))) + qr.q_n = 1; /* quotient shall be negate */ + + if (numerator < 0) { + numerator = -numerator; + qr.r_n = 1; /* remainder shall be negate */ + } + + if (denominator < 0) + denominator = -denominator; + + uint_div_qr(numerator, denominator, &qr); + + return qr.r; +} + +signed int __aeabi_idivmod(signed int numerator, signed int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + if (((numerator < 0) && (denominator > 0)) || + ((numerator > 0) && (denominator < 0))) + qr.q_n = 1; /* quotient shall be negate */ + + if (numerator < 0) { + numerator = -numerator; + qr.r_n = 1; /* remainder shall be negate */ + } + + if (denominator < 0) + denominator = -denominator; + + uint_div_qr(numerator, denominator, &qr); + + return ret_idivmod_values(qr.q, qr.r); +} diff --git a/lib/aarch32/arm32_aeabi_divmod_a32.S b/lib/aarch32/arm32_aeabi_divmod_a32.S new file mode 100644 index 00000000..6915dcd8 --- /dev/null +++ b/lib/aarch32/arm32_aeabi_divmod_a32.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <asm_macros.S> + +/* + * EABI wrappers from the udivmod and idivmod functions + */ + + .globl ret_uidivmod_values + .globl ret_idivmod_values + +/* + * signed ret_idivmod_values(signed quot, signed rem); + * return quotient and remaining the EABI way (regs r0,r1) + */ +func ret_idivmod_values + bx lr +endfunc ret_idivmod_values + +/* + * unsigned ret_uidivmod_values(unsigned quot, unsigned rem); + * return quotient and remaining the EABI way (regs r0,r1) + */ +func ret_uidivmod_values + bx lr +endfunc ret_uidivmod_values diff --git a/lib/cpus/aarch32/cortex_a12.S b/lib/cpus/aarch32/cortex_a12.S new file mode 100644 index 00000000..73c97507 --- /dev/null +++ b/lib/cpus/aarch32/cortex_a12.S @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <assert_macros.S> +#include <cortex_a12.h> +#include <cpu_macros.S> + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a12_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A12_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a12_disable_smp + +func cortex_a12_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A12_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a12_enable_smp + +func cortex_a12_reset_func + b cortex_a12_enable_smp +endfunc cortex_a12_reset_func + +func cortex_a12_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a12_disable_smp +endfunc cortex_a12_core_pwr_dwn + +func cortex_a12_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a12_disable_smp +endfunc cortex_a12_cluster_pwr_dwn + +declare_cpu_ops cortex_a12, CORTEX_A12_MIDR, \ + cortex_a12_reset_func, \ + cortex_a12_core_pwr_dwn, \ + cortex_a12_cluster_pwr_dwn diff --git a/lib/cpus/aarch32/cortex_a15.S b/lib/cpus/aarch32/cortex_a15.S new file mode 100644 index 00000000..0d5a1165 --- /dev/null +++ b/lib/cpus/aarch32/cortex_a15.S @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <assert_macros.S> +#include <cortex_a15.h> +#include <cpu_macros.S> + +/* + * Cortex-A15 support LPAE and Virtualization Extensions. + * Don't care if confiugration uses or not LPAE and VE. + * Therefore, where we don't check ARCH_IS_ARMV7_WITH_LPAE/VE + */ + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a15_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A15_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a15_disable_smp + +func cortex_a15_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A15_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a15_enable_smp + +func cortex_a15_reset_func + b cortex_a15_enable_smp +endfunc cortex_a15_reset_func + +func cortex_a15_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a15_disable_smp +endfunc cortex_a15_core_pwr_dwn + +func cortex_a15_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a15_disable_smp +endfunc cortex_a15_cluster_pwr_dwn + +declare_cpu_ops cortex_a15, CORTEX_A15_MIDR, \ + cortex_a15_reset_func, \ + cortex_a15_core_pwr_dwn, \ + cortex_a15_cluster_pwr_dwn diff --git a/lib/cpus/aarch32/cortex_a17.S b/lib/cpus/aarch32/cortex_a17.S new file mode 100644 index 00000000..316d4f05 --- /dev/null +++ b/lib/cpus/aarch32/cortex_a17.S @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <assert_macros.S> +#include <cortex_a17.h> +#include <cpu_macros.S> + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a17_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A17_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a17_disable_smp + +func cortex_a17_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A17_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a17_enable_smp + +func cortex_a17_reset_func + b cortex_a17_enable_smp +endfunc cortex_a17_reset_func + +func cortex_a17_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a17_disable_smp +endfunc cortex_a17_core_pwr_dwn + +func cortex_a17_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a17_disable_smp +endfunc cortex_a17_cluster_pwr_dwn + +declare_cpu_ops cortex_a17, CORTEX_A17_MIDR, \ + cortex_a17_reset_func, \ + cortex_a17_core_pwr_dwn, \ + cortex_a17_cluster_pwr_dwn diff --git a/lib/cpus/aarch32/cortex_a5.S b/lib/cpus/aarch32/cortex_a5.S new file mode 100644 index 00000000..c07c13ea --- /dev/null +++ b/lib/cpus/aarch32/cortex_a5.S @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <assert_macros.S> +#include <cortex_a5.h> +#include <cpu_macros.S> + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a5_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A5_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a5_disable_smp + +func cortex_a5_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A5_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a5_enable_smp + +func cortex_a5_reset_func + b cortex_a5_enable_smp +endfunc cortex_a5_reset_func + +func cortex_a5_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a5_disable_smp +endfunc cortex_a5_core_pwr_dwn + +func cortex_a5_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a5_disable_smp +endfunc cortex_a5_cluster_pwr_dwn + +declare_cpu_ops cortex_a5, CORTEX_A5_MIDR, \ + cortex_a5_reset_func, \ + cortex_a5_core_pwr_dwn, \ + cortex_a5_cluster_pwr_dwn diff --git a/lib/cpus/aarch32/cortex_a53.S b/lib/cpus/aarch32/cortex_a53.S index 74cedc35..1647e169 100644 --- a/lib/cpus/aarch32/cortex_a53.S +++ b/lib/cpus/aarch32/cortex_a53.S @@ -174,7 +174,7 @@ func cortex_a53_core_pwr_dwn push {r12, lr} /* Assert if cache is enabled */ -#if ASM_ASSERTION +#if ENABLE_ASSERTIONS ldcopr r0, SCTLR tst r0, #SCTLR_C_BIT ASM_ASSERT(eq) @@ -204,7 +204,7 @@ func cortex_a53_cluster_pwr_dwn push {r12, lr} /* Assert if cache is enabled */ -#if ASM_ASSERTION +#if ENABLE_ASSERTIONS ldcopr r0, SCTLR tst r0, #SCTLR_C_BIT ASM_ASSERT(eq) diff --git a/lib/cpus/aarch32/cortex_a57.S b/lib/cpus/aarch32/cortex_a57.S index b5189e77..64a6d674 100644 --- a/lib/cpus/aarch32/cortex_a57.S +++ b/lib/cpus/aarch32/cortex_a57.S @@ -406,7 +406,7 @@ func cortex_a57_core_pwr_dwn push {r12, lr} /* Assert if cache is enabled */ -#if ASM_ASSERTION +#if ENABLE_ASSERTIONS ldcopr r0, SCTLR tst r0, #SCTLR_C_BIT ASM_ASSERT(eq) @@ -448,7 +448,7 @@ func cortex_a57_cluster_pwr_dwn push {r12, lr} /* Assert if cache is enabled */ -#if ASM_ASSERTION +#if ENABLE_ASSERTIONS ldcopr r0, SCTLR tst r0, #SCTLR_C_BIT ASM_ASSERT(eq) diff --git a/lib/cpus/aarch32/cortex_a7.S b/lib/cpus/aarch32/cortex_a7.S new file mode 100644 index 00000000..0278d1fd --- /dev/null +++ b/lib/cpus/aarch32/cortex_a7.S @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <assert_macros.S> +#include <cortex_a7.h> +#include <cpu_macros.S> + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a7_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A7_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a7_disable_smp + +func cortex_a7_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A7_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a7_enable_smp + +func cortex_a7_reset_func + b cortex_a7_enable_smp +endfunc cortex_a7_reset_func + +func cortex_a7_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a7_disable_smp +endfunc cortex_a7_core_pwr_dwn + +func cortex_a7_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a7_disable_smp +endfunc cortex_a7_cluster_pwr_dwn + +declare_cpu_ops cortex_a7, CORTEX_A7_MIDR, \ + cortex_a7_reset_func, \ + cortex_a7_core_pwr_dwn, \ + cortex_a7_cluster_pwr_dwn diff --git a/lib/cpus/aarch32/cortex_a72.S b/lib/cpus/aarch32/cortex_a72.S index 69cc2ea5..75505206 100644 --- a/lib/cpus/aarch32/cortex_a72.S +++ b/lib/cpus/aarch32/cortex_a72.S @@ -120,7 +120,7 @@ func cortex_a72_core_pwr_dwn push {r12, lr} /* Assert if cache is enabled */ -#if ASM_ASSERTION +#if ENABLE_ASSERTIONS ldcopr r0, SCTLR tst r0, #SCTLR_C_BIT ASM_ASSERT(eq) @@ -167,7 +167,7 @@ func cortex_a72_cluster_pwr_dwn push {r12, lr} /* Assert if cache is enabled */ -#if ASM_ASSERTION +#if ENABLE_ASSERTIONS ldcopr r0, SCTLR tst r0, #SCTLR_C_BIT ASM_ASSERT(eq) diff --git a/lib/cpus/aarch32/cortex_a9.S b/lib/cpus/aarch32/cortex_a9.S new file mode 100644 index 00000000..4f30f84a --- /dev/null +++ b/lib/cpus/aarch32/cortex_a9.S @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <assert_macros.S> +#include <cortex_a9.h> +#include <cpu_macros.S> + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a9_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A9_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a9_disable_smp + +func cortex_a9_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A9_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a9_enable_smp + +func cortex_a9_reset_func + b cortex_a9_enable_smp +endfunc cortex_a9_reset_func + +func cortex_a9_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a9_disable_smp +endfunc cortex_a9_core_pwr_dwn + +func cortex_a9_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a9_disable_smp +endfunc cortex_a9_cluster_pwr_dwn + +declare_cpu_ops cortex_a9, CORTEX_A9_MIDR, \ + cortex_a9_reset_func, \ + cortex_a9_core_pwr_dwn, \ + cortex_a9_cluster_pwr_dwn diff --git a/lib/cpus/aarch64/cortex_a75.S b/lib/cpus/aarch64/cortex_a75.S index 1f4500cb..4cab9e4f 100644 --- a/lib/cpus/aarch64/cortex_a75.S +++ b/lib/cpus/aarch64/cortex_a75.S @@ -11,6 +11,33 @@ #include <plat_macros.S> #include <cortex_a75.h> +func cortex_a75_reset_func +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, actlr_el3 + orr x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT + msr actlr_el3, x0 + isb + + /* Make sure accesses from EL0/EL1 are not trapped to EL2 */ + mrs x0, actlr_el2 + orr x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT + msr actlr_el2, x0 + isb + + /* Enable group0 counters */ + mov x0, #CORTEX_A75_AMU_GROUP0_MASK + msr CPUAMCNTENSET_EL0, x0 + isb + + /* Enable group1 counters */ + mov x0, #CORTEX_A75_AMU_GROUP1_MASK + msr CPUAMCNTENSET_EL0, x0 + isb +#endif + ret +endfunc cortex_a75_reset_func + /* --------------------------------------------- * HW will do the cache maintenance while powering down * --------------------------------------------- @@ -47,5 +74,5 @@ func cortex_a75_cpu_reg_dump endfunc cortex_a75_cpu_reg_dump declare_cpu_ops cortex_a75, CORTEX_A75_MIDR, \ - CPU_NO_RESET_FUNC, \ + cortex_a75_reset_func, \ cortex_a75_core_pwr_dwn diff --git a/lib/el3_runtime/aarch32/context_mgmt.c b/lib/el3_runtime/aarch32/context_mgmt.c index a8672d6c..76e440e3 100644 --- a/lib/el3_runtime/aarch32/context_mgmt.c +++ b/lib/el3_runtime/aarch32/context_mgmt.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <amu.h> #include <arch.h> #include <arch_helpers.h> #include <assert.h> @@ -132,6 +133,9 @@ static void cm_init_context_common(cpu_context_t *ctx, const entry_point_info_t static void enable_extensions_nonsecure(int el2_unused) { #if IMAGE_BL32 +#if ENABLE_AMU + amu_enable(el2_unused); +#endif #endif } diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index 8f1523f0..c6c2249a 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include <amu.h> #include <arch.h> #include <arch_helpers.h> #include <assert.h> @@ -17,6 +18,7 @@ #include <smcc_helpers.h> #include <spe.h> #include <string.h> +#include <sve.h> #include <utils.h> @@ -220,6 +222,14 @@ static void enable_extensions_nonsecure(int el2_unused) #if ENABLE_SPE_FOR_LOWER_ELS spe_enable(el2_unused); #endif + +#if ENABLE_AMU + amu_enable(el2_unused); +#endif + +#if ENABLE_SVE_FOR_NS + sve_enable(el2_unused); +#endif #endif } diff --git a/lib/extensions/amu/aarch32/amu.c b/lib/extensions/amu/aarch32/amu.c new file mode 100644 index 00000000..d450bd69 --- /dev/null +++ b/lib/extensions/amu/aarch32/amu.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <amu.h> +#include <arch.h> +#include <arch_helpers.h> + +void amu_enable(int el2_unused) +{ + uint64_t features; + + features = read_id_pfr0() >> ID_PFR0_AMU_SHIFT; + if ((features & ID_PFR0_AMU_MASK) == 1) { + if (el2_unused) { + uint64_t v; + + /* + * Non-secure access from EL0 or EL1 to the Activity Monitor + * registers do not trap to EL2. + */ + v = read_hcptr(); + v &= ~TAM_BIT; + write_hcptr(v); + } + + /* Enable group 0 counters */ + write_amcntenset0(AMU_GROUP0_COUNTERS_MASK); + } +} diff --git a/lib/extensions/amu/aarch64/amu.c b/lib/extensions/amu/aarch64/amu.c new file mode 100644 index 00000000..007b3494 --- /dev/null +++ b/lib/extensions/amu/aarch64/amu.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <amu.h> +#include <arch.h> +#include <arch_helpers.h> + +void amu_enable(int el2_unused) +{ + uint64_t features; + + features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT; + if ((features & ID_AA64PFR0_AMU_MASK) == 1) { + uint64_t v; + + if (el2_unused) { + /* + * CPTR_EL2.TAM: Set to zero so any accesses to + * the Activity Monitor registers do not trap to EL2. + */ + v = read_cptr_el2(); + v &= ~CPTR_EL2_TAM_BIT; + write_cptr_el2(v); + } + + /* + * CPTR_EL3.TAM: Set to zero so that any accesses to + * the Activity Monitor registers do not trap to EL3. + */ + v = read_cptr_el3(); + v &= ~TAM_BIT; + write_cptr_el3(v); + + /* Enable group 0 counters */ + write_amcntenset0_el0(AMU_GROUP0_COUNTERS_MASK); + } +} diff --git a/lib/extensions/sve/sve.c b/lib/extensions/sve/sve.c new file mode 100644 index 00000000..14e51bd8 --- /dev/null +++ b/lib/extensions/sve/sve.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <pubsub.h> +#include <sve.h> + +static void *disable_sve_hook(const void *arg) +{ + uint64_t features; + + features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT; + if ((features & ID_AA64PFR0_SVE_MASK) == 1) { + uint64_t cptr; + + /* + * Disable SVE, SIMD and FP access for the Secure world. + * As the SIMD/FP registers are part of the SVE Z-registers, any + * use of SIMD/FP functionality will corrupt the SVE registers. + * Therefore it is necessary to prevent use of SIMD/FP support + * in the Secure world as well as SVE functionality. + */ + cptr = read_cptr_el3(); + cptr = (cptr | TFP_BIT) & ~(CPTR_EZ_BIT); + write_cptr_el3(cptr); + + /* + * No explicit ISB required here as ERET to switch to Secure + * world covers it + */ + } + return 0; +} + +static void *enable_sve_hook(const void *arg) +{ + uint64_t features; + + features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT; + if ((features & ID_AA64PFR0_SVE_MASK) == 1) { + uint64_t cptr; + + /* + * Enable SVE, SIMD and FP access for the Non-secure world. + */ + cptr = read_cptr_el3(); + cptr = (cptr | CPTR_EZ_BIT) & ~(TFP_BIT); + write_cptr_el3(cptr); + + /* + * No explicit ISB required here as ERET to switch to Non-secure + * world covers it + */ + } + return 0; +} + +void sve_enable(int el2_unused) +{ + uint64_t features; + + features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT; + if ((features & ID_AA64PFR0_SVE_MASK) == 1) { + uint64_t cptr; +#if CTX_INCLUDE_FPREGS + /* + * CTX_INCLUDE_FPREGS is not supported on SVE enabled systems. + */ + assert(0); +#endif + /* + * Update CPTR_EL3 to enable access to SVE functionality for the + * Non-secure world. + * NOTE - assumed that CPTR_EL3.TFP is set to allow access to + * the SIMD, floating-point and SVE support. + * + * CPTR_EL3.EZ: Set to 1 to enable access to SVE functionality + * in the Non-secure world. + */ + cptr = read_cptr_el3(); + cptr |= CPTR_EZ_BIT; + write_cptr_el3(cptr); + + /* + * Need explicit ISB here to guarantee that update to ZCR_ELx + * and CPTR_EL2.TZ do not result in trap to EL3. + */ + isb(); + + /* + * Ensure lower ELs have access to full vector length. + */ + write_zcr_el3(ZCR_EL3_LEN_MASK); + + if (el2_unused) { + /* + * Update CPTR_EL2 to enable access to SVE functionality + * for Non-secure world, EL2 and Non-secure EL1 and EL0. + * NOTE - assumed that CPTR_EL2.TFP is set to allow + * access to the SIMD, floating-point and SVE support. + * + * CPTR_EL2.TZ: Set to 0 to enable access to SVE support + * for EL2 and Non-secure EL1 and EL0. + */ + cptr = read_cptr_el2(); + cptr &= ~(CPTR_EL2_TZ_BIT); + write_cptr_el2(cptr); + + /* + * Ensure lower ELs have access to full vector length. + */ + write_zcr_el2(ZCR_EL2_LEN_MASK); + } + /* + * No explicit ISB required here as ERET to switch to + * Non-secure world covers it. + */ + } +} + +SUBSCRIBE_TO_EVENT(cm_exited_normal_world, disable_sve_hook); +SUBSCRIBE_TO_EVENT(cm_entering_normal_world, enable_sve_hook); diff --git a/lib/locks/exclusive/aarch32/spinlock.S b/lib/locks/exclusive/aarch32/spinlock.S index bc77bc9c..9492cc08 100644 --- a/lib/locks/exclusive/aarch32/spinlock.S +++ b/lib/locks/exclusive/aarch32/spinlock.S @@ -9,6 +9,17 @@ .globl spin_lock .globl spin_unlock +#if ARM_ARCH_AT_LEAST(8, 0) +/* + * According to the ARMv8-A Architecture Reference Manual, "when the global + * monitor for a PE changes from Exclusive Access state to Open Access state, + * an event is generated.". This applies to both AArch32 and AArch64 modes of + * ARMv8-A. As a result, no explicit SEV with unlock is required. + */ +#define COND_SEV() +#else +#define COND_SEV() sev +#endif func spin_lock mov r2, #1 @@ -27,5 +38,6 @@ endfunc spin_lock func spin_unlock mov r1, #0 stl r1, [r0] + COND_SEV() bx lr endfunc spin_unlock diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c index 4105e63b..8e41cf02 100644 --- a/lib/psci/psci_main.c +++ b/lib/psci/psci_main.c @@ -220,6 +220,23 @@ int psci_affinity_info(u_register_t target_affinity, if (target_idx == -1) return PSCI_E_INVALID_PARAMS; + /* + * Generic management: + * Perform cache maintanence ahead of reading the target CPU state to + * ensure that the data is not stale. + * There is a theoretical edge case where the cache may contain stale + * data for the target CPU data - this can occur under the following + * conditions: + * - the target CPU is in another cluster from the current + * - the target CPU was the last CPU to shutdown on its cluster + * - the cluster was removed from coherency as part of the CPU shutdown + * + * In this case the cache maintenace that was performed as part of the + * target CPUs shutdown was not seen by the current CPU's cluster. And + * so the cache may contain stale data for the target CPU. + */ + flush_cpu_data_by_index(target_idx, psci_svc_cpu_data.aff_info_state); + return psci_get_aff_info_state_by_idx(target_idx); } diff --git a/lib/psci/psci_setup.c b/lib/psci/psci_setup.c index a841ddab..c00bd94a 100644 --- a/lib/psci/psci_setup.c +++ b/lib/psci/psci_setup.c @@ -266,8 +266,10 @@ int psci_setup(const psci_lib_args_t *lib_args) ******************************************************************************/ void psci_arch_setup(void) { +#if ARM_ARCH_MAJOR > 7 || defined(ARMV7_SUPPORTS_GENERIC_TIMER) /* Program the counter frequency */ write_cntfrq_el0(plat_get_syscnt_freq2()); +#endif /* Initialize the cpu_ops pointer. */ init_cpu_ops(); diff --git a/lib/xlat_tables/aarch32/xlat_tables.c b/lib/xlat_tables/aarch32/xlat_tables.c index c7e34f20..720d4461 100644 --- a/lib/xlat_tables/aarch32/xlat_tables.c +++ b/lib/xlat_tables/aarch32/xlat_tables.c @@ -13,6 +13,10 @@ #include <xlat_tables.h> #include "../xlat_tables_private.h" +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING) +#error ARMv7 target does not support LPAE MMU descriptors +#endif + #define XLAT_TABLE_LEVEL_BASE \ GET_XLAT_TABLE_LEVEL_BASE(PLAT_VIRT_ADDR_SPACE_SIZE) diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c index 28ae1f73..eabc3df9 100644 --- a/lib/xlat_tables/aarch64/xlat_tables.c +++ b/lib/xlat_tables/aarch64/xlat_tables.c @@ -60,7 +60,10 @@ static unsigned long long calc_physical_addr_size_bits( /* Physical Address ranges supported in the AArch64 Memory Model */ static const unsigned int pa_range_bits_arr[] = { PARANGE_0000, PARANGE_0001, PARANGE_0010, PARANGE_0011, PARANGE_0100, - PARANGE_0101 + PARANGE_0101, +#if ARM_ARCH_AT_LEAST(8, 2) + PARANGE_0110, +#endif }; static unsigned long long get_max_supported_pa(void) diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c index 642f799a..fc7ca46a 100644 --- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c +++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c @@ -14,6 +14,10 @@ #include <xlat_tables_v2.h> #include "../xlat_tables_private.h" +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING) +#error ARMv7 target does not support LPAE MMU descriptors +#endif + #if ENABLE_ASSERTIONS unsigned long long xlat_arch_get_max_supported_pa(void) { diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c index 43311079..aa5b9e54 100644 --- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c +++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c @@ -48,7 +48,10 @@ unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr) /* Physical Address ranges supported in the AArch64 Memory Model */ static const unsigned int pa_range_bits_arr[] = { PARANGE_0000, PARANGE_0001, PARANGE_0010, PARANGE_0011, PARANGE_0100, - PARANGE_0101 + PARANGE_0101, +#if ARM_ARCH_AT_LEAST(8, 2) + PARANGE_0110, +#endif }; unsigned long long xlat_arch_get_max_supported_pa(void) diff --git a/maintainers.rst b/maintainers.rst index 388073e4..04ab695e 100644 --- a/maintainers.rst +++ b/maintainers.rst @@ -21,8 +21,8 @@ Jens Wiklander (jens.wiklander@linaro.org, `jenswi-linaro`_) Files: -- docs/spd/optee-dispatcher.md -- docs/plat/qemu.md +- docs/plat/qemu.rst +- docs/spd/optee-dispatcher.rst - services/spd/opteed/\* - plat/qemu/\* @@ -33,8 +33,9 @@ Varun Wadekar (vwadekar@nvidia.com, `vwadekar`_) Files: -- docs/spd/tlk-dispatcher.md -- docs/spd/trusty-dispatcher.md +- docs/plat/nvidia-tegra.rst +- docs/spd/tlk-dispatcher.rst +- docs/spd/trusty-dispatcher.rst - include/bl32/payloads/tlk.h - include/lib/cpus/aarch64/denver.h - lib/cpus/aarch64/denver.S @@ -49,8 +50,9 @@ Haojian Zhuang (haojian.zhuang@linaro.org, `hzhuang1`_) Files: -- docs/plat/hikey.md -- docs/plat/hikey960.md +- docs/plat/hikey.rst +- docs/plat/hikey960.rst +- docs/plat/poplar.rst - drivers/emmc/\* - drivers/partition/\* - drivers/synopsys/emmc/\* @@ -71,32 +73,60 @@ Files: - plat/mediatek/\* +Raspberry Pi 3 platform sub-maintainer +-------------------------------------- + +Antonio Niño DÃaz (antonio.ninodiaz@arm.com, `antonio-nino-diaz-arm`_) + +Files: + +- docs/plat/rpi3.rst +- plat/rpi3/\* + RockChip platform sub-maintainer -------------------------------- Tony Xie (tony.xie@rock-chips.com, `TonyXie06`_ -or `rkchrome`_) +or `rockchip-linux`_) Files: - plat/rockchip/\* +UniPhier platform sub-maintainer +-------------------------------- + +Masahiro Yamada (yamada.masahiro@socionext.com, `masahir0y`_) + +Files: + +- docs/plat/socionext-uniphier.rst +- plat/socionext/\* + Xilinx platform sub-maintainer ------------------------------ -Sören Brinkmann (soren.brinkmann@xilinx.com, `sorenb-xlnx`_) +Siva Durga Prasad Paladugu (siva.durga.paladugu@xilinx.com, `sivadur`_) Files: -- docs/plat/xilinx-zynqmp.md +- docs/plat/xilinx-zynqmp.rst - plat/xilinx/\* +ARMv7 architecture sub-maintainer +--------------------------------- + +Etienne Carriere (etienne.carriere@linaro.org, `etienne-lms`_) + +.. _antonio-nino-diaz-arm: https://github.com/antonio-nino-diaz-arm .. _danh-arm: https://github.com/danh-arm .. _davidcunado-arm: https://github.com/davidcunado-arm .. _jenswi-linaro: https://github.com/jenswi-linaro .. _vwadekar: https://github.com/vwadekar .. _hzhuang1: https://github.com/hzhuang1 +.. _masahir0y: https://github.com/masahir0y .. _mtk09422: https://github.com/mtk09422 .. _TonyXie06: https://github.com/TonyXie06 -.. _rkchrome: https://github.com/rkchrome -.. _sorenb-xlnx: https://github.com/sorenb-xlnx +.. _sivadur: https://github.com/sivadur +.. _rockchip-linux: https://github.com/rockchip-linux +.. _etienne-lms: https://github.com/etienne-lms diff --git a/make_helpers/armv7-a-cpus.mk b/make_helpers/armv7-a-cpus.mk new file mode 100644 index 00000000..20e7ec53 --- /dev/null +++ b/make_helpers/armv7-a-cpus.mk @@ -0,0 +1,50 @@ +# +# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${ARCH},aarch32) +$(error ARM_ARCH_MAJOR=7 mandates ARCH=aarch32) +endif + +# For ARMv7, set march32 from platform directive ARMV7_CORTEX_Ax=yes +# and ARM_WITH_NEON=yes/no. +# +# GCC and Clang require -march=armv7-a for C-A9 and -march=armv7ve for C-A15. +# armClang requires -march=armv7-a for all ARMv7 Cortex-A. To comply with +# all, just drop -march and supply only -mcpu. + +# Platform can override march32-directive through MARCH32_DIRECTIVE +ifdef MARCH32_DIRECTIVE +march32-directive := $(MARCH32_DIRECTIVE) +else +march32-set-${ARM_CORTEX_A5} := -mcpu=cortex-a5 +march32-set-${ARM_CORTEX_A7} := -mcpu=cortex-a7 +march32-set-${ARM_CORTEX_A9} := -mcpu=cortex-a9 +march32-set-${ARM_CORTEX_A12} := -mcpu=cortex-a12 +march32-set-${ARM_CORTEX_A15} := -mcpu=cortex-a15 +march32-set-${ARM_CORTEX_A17} := -mcpu=cortex-a17 +march32-neon-$(ARM_WITH_NEON) := -mfpu=neon + +# default to -march=armv7-a as target directive +march32-set-yes ?= -march=armv7-a +march32-directive := ${march32-set-yes} ${march32-neon-yes} +endif + +# Platform may override these extension support directives: +# +# ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING +# Defined if core supports the Large Page Addressing extension. +# +# ARMV7_SUPPORTS_VIRTUALIZATION +# Defined if ARMv7 core supports the Virtualization extension. +# +# ARMV7_SUPPORTS_GENERIC_TIMER +# Defined if ARMv7 core supports the Generic Timer extension. + +ifeq ($(filter yes,$(ARM_CORTEX_A7) $(ARM_CORTEX_A12) $(ARM_CORTEX_A15) $(ARM_CORTEX_A17)),yes) +$(eval $(call add_define,ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING)) +$(eval $(call add_define,ARMV7_SUPPORTS_VIRTUALIZATION)) +$(eval $(call add_define,ARMV7_SUPPORTS_GENERIC_TIMER)) +endif diff --git a/make_helpers/build_macros.mk b/make_helpers/build_macros.mk index 7531f6d8..e1bfbbe7 100644 --- a/make_helpers/build_macros.mk +++ b/make_helpers/build_macros.mk @@ -336,3 +336,49 @@ $(eval $(call MAKE_TOOL_ARGS,$(1),$(BIN),$(2))) endef +define SOURCES_TO_DTBS + $(notdir $(patsubst %.dts,%.dtb,$(filter %.dts,$(1)))) +endef + +# MAKE_FDT macro defines the targets and options to build each FDT binary +# Arguments: (none) +define MAKE_FDT + $(eval DTB_BUILD_DIR := ${BUILD_PLAT}/fdts) + $(eval DTBS := $(addprefix $(DTB_BUILD_DIR)/,$(call SOURCES_TO_DTBS,$(FDT_SOURCES)))) + $(eval TEMP_DTB_DIRS := $(sort $(dir ${DTBS}))) + # The $(dir ) function leaves a trailing / on the directory names + # Rip off the / to match directory names with make rule targets. + $(eval DTB_DIRS := $(patsubst %/,%,$(TEMP_DTB_DIRS))) + +$(eval $(foreach objd,${DTB_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR}))) + +fdt_dirs: ${DTB_DIRS} + +endef + +# MAKE_DTB generate the Flattened device tree binary (device tree binary) +# $(1) = output directory +# $(2) = input dts +define MAKE_DTB + +$(eval DOBJ := $(1)/$(patsubst %.dts,%.dtb,$(notdir $(2)))) +$(eval DEP := $(patsubst %.dtb,%.d,$(DOBJ))) + +$(DOBJ): $(2) | fdt_dirs + @echo " DTC $$<" + $$(Q)$$(DTC) $$(DTC_FLAGS) -d $(DEP) -o $$@ $$< + +-include $(DEP) + +endef + +# MAKE_DTBS builds flattened device tree sources +# $(1) = output directory +# $(2) = list of flattened device tree source files +define MAKE_DTBS + $(eval DOBJS := $(filter %.dts,$(2))) + $(eval REMAIN := $(filter-out %.dts,$(2))) + $(eval $(foreach obj,$(DOBJS),$(call MAKE_DTB,$(1),$(obj)))) + + $(and $(REMAIN),$(error Unexpected s present: $(REMAIN))) +endef diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index b7ce051b..fa0d17de 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -24,9 +24,6 @@ ARM_ARCH_MINOR := 0 # in EL3. The platform port can change this value if needed. ARM_GIC_ARCH := 2 -# Flag used to indicate if ASM_ASSERTION should be enabled for the build. -ASM_ASSERTION := 0 - # Base commit to perform code check on BASE_COMMIT := origin/master @@ -156,3 +153,14 @@ ENABLE_SPE_FOR_LOWER_ELS := 1 ifeq (${ARCH},aarch32) override ENABLE_SPE_FOR_LOWER_ELS := 0 endif + +ENABLE_AMU := 0 + +# By default, enable Scalable Vector Extension if implemented for Non-secure +# lower ELs +# Note SVE is only supported on AArch64 - therefore do not enable in AArch32 +ifneq (${ARCH},aarch32) + ENABLE_SVE_FOR_NS := 1 +else + override ENABLE_SVE_FOR_NS := 0 +endif diff --git a/make_helpers/tbbr/tbbr_tools.mk b/make_helpers/tbbr/tbbr_tools.mk index b13afe48..6e6e2739 100644 --- a/make_helpers/tbbr/tbbr_tools.mk +++ b/make_helpers/tbbr/tbbr_tools.mk @@ -77,6 +77,7 @@ ifneq (${SCP_BL2},) endif ifeq (${ARCH},aarch64) +ifeq (${NEED_BL31},yes) # Add the BL31 CoT (key cert + img cert + image) $(if ${BL31},$(eval $(call CERT_ADD_CMD_OPT,${BL31},--soc-fw,true)),\ $(eval $(call CERT_ADD_CMD_OPT,$(call IMG_BIN,31),--soc-fw,true))) @@ -86,6 +87,7 @@ $(eval $(call CERT_ADD_CMD_OPT,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert)) $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_content.crt,--soc-fw-cert)) $(eval $(call FIP_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert)) endif +endif # Add the BL32 CoT (key cert + img cert + image) ifeq (${NEED_BL32},yes) diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c index 13bd8f23..72845843 100644 --- a/plat/arm/board/fvp/fvp_pm.c +++ b/plat/arm/board/fvp/fvp_pm.c @@ -402,12 +402,20 @@ plat_psci_ops_t plat_arm_psci_pm_ops = { .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, +#if !ARM_BL31_IN_DRAM + /* + * The TrustZone Controller is set up during the warmboot sequence after + * resuming the CPU from a SYSTEM_SUSPEND. If BL31 is located in SRAM + * this is not a problem but, if it is in TZC-secured DRAM, it tries to + * reconfigure the same memory it is running on, causing an exception. + */ .get_sys_suspend_power_state = fvp_get_sys_suspend_power_state, -/* - * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN, - * as that would require mapping in all of NS DRAM into BL31 or BL32. - */ +#endif #if !RESET_TO_BL31 && !RESET_TO_SP_MIN + /* + * mem_protect is not supported in RESET_TO_BL31 and RESET_TO_SP_MIN, + * as that would require mapping in all of NS DRAM into BL31 or BL32. + */ .mem_protect_chk = arm_psci_mem_protect_chk, .read_mem_protect = arm_psci_read_mem_protect, .write_mem_protect = arm_nor_psci_write_mem_protect, diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h index 310db7b6..7080fc30 100644 --- a/plat/arm/board/fvp/include/platform_def.h +++ b/plat/arm/board/fvp/include/platform_def.h @@ -8,6 +8,7 @@ #define __PLATFORM_DEF_H__ #include <arm_def.h> +#include <arm_spm_def.h> #include <board_arm_def.h> #include <common_def.h> #include <tzc400.h> diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 1b502967..7edbd3df 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -147,6 +147,9 @@ BL31_SOURCES += drivers/arm/smmu/smmu_v3.c \ # Disable the PSCI platform compatibility layer ENABLE_PLAT_COMPAT := 0 +# Enable Activity Monitor Unit extensions by default +ENABLE_AMU := 1 + ifneq (${ENABLE_STACK_PROTECTOR},0) PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_stack_protector.c endif diff --git a/plat/arm/board/juno/include/platform_def.h b/plat/arm/board/juno/include/platform_def.h index ccc7771e..e475ece5 100644 --- a/plat/arm/board/juno/include/platform_def.h +++ b/plat/arm/board/juno/include/platform_def.h @@ -128,6 +128,15 @@ */ #define PLAT_ARM_MAX_BL31_SIZE 0x1E000 +#if JUNO_AARCH32_EL3_RUNTIME +/* + * PLAT_ARM_MAX_BL32_SIZE is calculated for SP_MIN as the AArch32 Secure + * Payload. We also need to take care of SCP_BL2 size as well, as the SCP_BL2 + * is loaded into the space BL32 -> BL1_RW_BASE + */ +# define PLAT_ARM_MAX_BL32_SIZE 0x1E000 +#endif + /* * Since free SRAM space is scant, enable the ASSERTION message size * optimization by fixing the PLAT_LOG_LEVEL_ASSERT to LOG_LEVEL_INFO (40). diff --git a/plat/arm/board/juno/juno_bl2_setup.c b/plat/arm/board/juno/juno_bl2_setup.c index 2771e0f3..cedef66c 100644 --- a/plat/arm/board/juno/juno_bl2_setup.c +++ b/plat/arm/board/juno/juno_bl2_setup.c @@ -29,33 +29,4 @@ int bl2_plat_handle_post_image_load(unsigned int image_id) return err; } - -#if !CSS_USE_SCMI_SDS_DRIVER -/* - * We need to override some of the platform functions when booting SP_MIN - * on Juno AArch32. These needs to be done only for SCPI/BOM SCP systems as - * in case of SDS, the structures remain in memory and doesn't need to be - * overwritten. - */ - -static unsigned int scp_boot_config; - -void bl2_early_platform_setup(meminfo_t *mem_layout) -{ - arm_bl2_early_platform_setup(mem_layout); - - /* Save SCP Boot config before it gets overwritten by SCP_BL2 loading */ - VERBOSE("BL2: Saving SCP Boot config = 0x%x\n", scp_boot_config); - scp_boot_config = mmio_read_32(SCP_BOOT_CFG_ADDR); -} - -void bl2_platform_setup(void) -{ - arm_bl2_platform_setup(); - - mmio_write_32(SCP_BOOT_CFG_ADDR, scp_boot_config); - VERBOSE("BL2: Restored SCP Boot config = 0x%x\n", scp_boot_config); -} -#endif - #endif /* JUNO_AARCH32_EL3_RUNTIME */ diff --git a/plat/arm/board/juno/platform.mk b/plat/arm/board/juno/platform.mk index 5cd125bf..fee4391d 100644 --- a/plat/arm/board/juno/platform.mk +++ b/plat/arm/board/juno/platform.mk @@ -31,6 +31,19 @@ JUNO_AARCH32_EL3_RUNTIME := 0 $(eval $(call assert_boolean,JUNO_AARCH32_EL3_RUNTIME)) $(eval $(call add_define,JUNO_AARCH32_EL3_RUNTIME)) +ifeq (${JUNO_AARCH32_EL3_RUNTIME}, 1) +# Include BL32 in FIP +NEED_BL32 := yes +# BL31 is not required +override BL31_SOURCES = + +# The BL32 needs to be built separately invoking the AARCH32 compiler and +# be specifed via `BL32` build option. + ifneq (${ARCH}, aarch32) + override BL32_SOURCES = + endif +endif + ifeq (${ARCH},aarch64) BL1_SOURCES += lib/cpus/aarch64/cortex_a53.S \ lib/cpus/aarch64/cortex_a57.S \ @@ -86,6 +99,9 @@ ENABLE_PLAT_COMPAT := 0 # Enable memory map related constants optimisation ARM_BOARD_OPTIMISE_MEM := 1 +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + include plat/arm/board/common/board_css.mk include plat/arm/common/arm_common.mk include plat/arm/soc/common/soc_css.mk diff --git a/plat/arm/common/arm_tzc400.c b/plat/arm/common/arm_tzc400.c index 23c03173..cf133268 100644 --- a/plat/arm/common/arm_tzc400.c +++ b/plat/arm/common/arm_tzc400.c @@ -74,8 +74,8 @@ void arm_tzc400_setup(void) #else /* if defined(EL3_PAYLOAD_BASE) */ - /* Allow secure access only to DRAM for EL3 payloads. */ - tzc400_configure_region0(TZC_REGION_S_RDWR, 0); + /* Allow Secure and Non-secure access to DRAM for EL3 payloads */ + tzc400_configure_region0(TZC_REGION_S_RDWR, PLAT_ARM_TZC_NS_DEV_ACCESS); #endif /* EL3_PAYLOAD_BASE */ diff --git a/plat/arm/css/common/css_bl2_setup.c b/plat/arm/css/common/css_bl2_setup.c index 9b4800e3..b4aafd46 100644 --- a/plat/arm/css/common/css_bl2_setup.c +++ b/plat/arm/css/common/css_bl2_setup.c @@ -49,13 +49,13 @@ int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info) } #if !CSS_USE_SCMI_SDS_DRIVER -# ifdef EL3_PAYLOAD_BASE +# if defined(EL3_PAYLOAD_BASE) || JUNO_AARCH32_EL3_RUNTIME /* * We need to override some of the platform functions when booting an EL3 - * payload. These needs to be done only for SCPI/BOM SCP systems as - * in case of SDS, the structures remain in memory and doesn't need to be - * overwritten. + * payload or SP_MIN on Juno AArch32. This needs to be done only for + * SCPI/BOM SCP systems as in case of SDS, the structures remain in memory and + * don't need to be overwritten. */ static unsigned int scp_boot_config; diff --git a/plat/common/aarch32/platform_helpers.S b/plat/common/aarch32/platform_helpers.S index 61d21ab3..0a0e9271 100644 --- a/plat/common/aarch32/platform_helpers.S +++ b/plat/common/aarch32/platform_helpers.S @@ -7,12 +7,15 @@ #include <arch.h> #include <asm_macros.S> + .weak plat_report_exception .weak plat_crash_console_init .weak plat_crash_console_putc .weak plat_crash_console_flush .weak plat_reset_handler .weak plat_disable_acp + .weak bl1_plat_prepare_exit .weak platform_mem_init + .weak plat_error_handler .weak plat_panic_handler .weak bl2_plat_preload_setup .weak plat_try_next_boot_source @@ -22,6 +25,15 @@ * each platform. * ----------------------------------------------------- */ +func plat_report_exception + bx lr +endfunc plat_report_exception + + /* ----------------------------------------------------- + * Placeholder function which should be redefined by + * each platform. + * ----------------------------------------------------- + */ func plat_crash_console_init mov r0, #0 bx lr @@ -74,6 +86,25 @@ func platform_mem_init endfunc platform_mem_init /* ----------------------------------------------------- + * void bl1_plat_prepare_exit(entry_point_info_t *ep_info); + * Called before exiting BL1. Default: do nothing + * ----------------------------------------------------- + */ +func bl1_plat_prepare_exit + bx lr +endfunc bl1_plat_prepare_exit + + /* ----------------------------------------------------- + * void plat_error_handler(int err) __dead2; + * Endless loop by default. + * ----------------------------------------------------- + */ +func plat_error_handler + wfi + b plat_error_handler +endfunc plat_error_handler + + /* ----------------------------------------------------- * void plat_panic_handler(void) __dead2; * Endless loop by default. * ----------------------------------------------------- diff --git a/plat/compat/plat_compat.mk b/plat/compat/plat_compat.mk index af885421..f1867da1 100644 --- a/plat/compat/plat_compat.mk +++ b/plat/compat/plat_compat.mk @@ -18,3 +18,6 @@ PLAT_BL_COMMON_SOURCES += plat/compat/aarch64/plat_helpers_compat.S BL31_SOURCES += plat/common/plat_psci_common.c \ plat/compat/plat_pm_compat.c \ plat/compat/plat_topology_compat.c + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/plat/hisilicon/hikey/platform.mk b/plat/hisilicon/hikey/platform.mk index 26218a40..18b5e15e 100644 --- a/plat/hisilicon/hikey/platform.mk +++ b/plat/hisilicon/hikey/platform.mk @@ -24,6 +24,7 @@ PLAT_PARTITION_MAX_ENTRIES := 12 PLAT_PL061_MAX_GPIOS := 160 COLD_BOOT_SINGLE_CPU := 1 PROGRAMMABLE_RESET_ADDRESS := 1 +ENABLE_SVE_FOR_NS := 0 # Process flags $(eval $(call add_define,HIKEY_TSP_RAM_LOCATION_ID)) diff --git a/plat/hisilicon/hikey960/hikey960_pm.c b/plat/hisilicon/hikey960/hikey960_pm.c index 348cdba5..078f0d81 100644 --- a/plat/hisilicon/hikey960/hikey960_pm.c +++ b/plat/hisilicon/hikey960/hikey960_pm.c @@ -26,6 +26,38 @@ #define SYSTEM_PWR_STATE(state) \ ((state)->pwr_domain_state[PLAT_MAX_PWR_LVL]) +#define PSTATE_WIDTH 4 +#define PSTATE_MASK ((1 << PSTATE_WIDTH) - 1) + +#define MAKE_PWRSTATE(lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl2_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH * 2)) | \ + ((lvl1_state) << (PSTATE_ID_SHIFT + PSTATE_WIDTH)) | \ + ((lvl0_state) << (PSTATE_ID_SHIFT)) | \ + ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) + +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +const unsigned int hikey960_pwr_idle_states[] = { + /* State-id - 0x001 */ + MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE, + PLAT_MAX_STB_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x002 */ + MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE, + PLAT_MAX_RET_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x003 */ + MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_RUN_STATE, + PLAT_MAX_OFF_STATE, MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x033 */ + MAKE_PWRSTATE(PLAT_MAX_RUN_STATE, PLAT_MAX_OFF_STATE, + PLAT_MAX_OFF_STATE, MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN), + 0, +}; + #define DMAC_GLB_REG_SEC 0x694 #define AXI_CONF_BASE 0x820 @@ -36,16 +68,21 @@ static void hikey960_pwr_domain_standby(plat_local_state_t cpu_state) unsigned long scr; unsigned int val = 0; - assert(cpu_state == PLAT_MAX_RET_STATE); + assert(cpu_state == PLAT_MAX_STB_STATE || + cpu_state == PLAT_MAX_RET_STATE); scr = read_scr_el3(); /* Enable Physical IRQ and FIQ to wake the CPU*/ write_scr_el3(scr | SCR_IRQ_BIT | SCR_FIQ_BIT); - set_retention_ticks(val); + if (cpu_state == PLAT_MAX_RET_STATE) + set_retention_ticks(val); + wfi(); - clr_retention_ticks(val); + + if (cpu_state == PLAT_MAX_RET_STATE) + clr_retention_ticks(val); /* * Restore SCR to the original value, synchronisazion of @@ -124,38 +161,34 @@ static void __dead2 hikey960_system_reset(void) int hikey960_validate_power_state(unsigned int power_state, psci_power_state_t *req_state) { - int pstate = psci_get_pstate_type(power_state); - int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + unsigned int state_id; int i; assert(req_state); - if (pwr_lvl > PLAT_MAX_PWR_LVL) - return PSCI_E_INVALID_PARAMS; - - /* Sanity check the requested state */ - if (pstate == PSTATE_TYPE_STANDBY) { - /* - * It's possible to enter standby only on power level 0 - * Ignore any other power level. - */ - if (pwr_lvl != MPIDR_AFFLVL0) - return PSCI_E_INVALID_PARAMS; - - req_state->pwr_domain_state[MPIDR_AFFLVL0] = - PLAT_MAX_RET_STATE; - } else { - for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) - req_state->pwr_domain_state[i] = - PLAT_MAX_OFF_STATE; - } - /* - * We expect the 'state id' to be zero. + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justify the additional complexity. */ - if (psci_get_pstate_id(power_state)) + for (i = 0; !!hikey960_pwr_idle_states[i]; i++) { + if (power_state == hikey960_pwr_idle_states[i]) + break; + } + + /* Return error if entry not found in the idle state array */ + if (!hikey960_pwr_idle_states[i]) return PSCI_E_INVALID_PARAMS; + i = 0; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = state_id & PSTATE_MASK; + state_id >>= PSTATE_WIDTH; + } + return PSCI_E_SUCCESS; } diff --git a/plat/hisilicon/hikey960/include/platform_def.h b/plat/hisilicon/hikey960/include/platform_def.h index cb760907..2ac7f2a7 100644 --- a/plat/hisilicon/hikey960/include/platform_def.h +++ b/plat/hisilicon/hikey960/include/platform_def.h @@ -31,8 +31,10 @@ #define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ PLATFORM_CLUSTER_COUNT + 1) -#define PLAT_MAX_RET_STATE 1 -#define PLAT_MAX_OFF_STATE 2 +#define PLAT_MAX_RUN_STATE 0 +#define PLAT_MAX_STB_STATE 1 +#define PLAT_MAX_RET_STATE 2 +#define PLAT_MAX_OFF_STATE 3 #define MAX_IO_DEVICES 3 #define MAX_IO_HANDLES 4 diff --git a/plat/hisilicon/hikey960/platform.mk b/plat/hisilicon/hikey960/platform.mk index da7bb825..695f0923 100644 --- a/plat/hisilicon/hikey960/platform.mk +++ b/plat/hisilicon/hikey960/platform.mk @@ -20,6 +20,7 @@ endif CRASH_CONSOLE_BASE := PL011_UART6_BASE COLD_BOOT_SINGLE_CPU := 1 PROGRAMMABLE_RESET_ADDRESS := 1 +ENABLE_SVE_FOR_NS := 0 # Process flags $(eval $(call add_define,HIKEY960_TSP_RAM_LOCATION_ID)) diff --git a/plat/hisilicon/poplar/aarch64/platform_common.c b/plat/hisilicon/poplar/aarch64/platform_common.c index a7dac4fb..762bd846 100644 --- a/plat/hisilicon/poplar/aarch64/platform_common.c +++ b/plat/hisilicon/poplar/aarch64/platform_common.c @@ -25,9 +25,14 @@ DEVICE_SIZE, \ MT_DEVICE | MT_RW | MT_SECURE) +#define MAP_TSP_MEM MAP_REGION_FLAT(TSP_SEC_MEM_BASE, \ + TSP_SEC_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + static const mmap_region_t poplar_mmap[] = { MAP_DDR, MAP_DEVICE, + MAP_TSP_MEM, {0} }; diff --git a/plat/hisilicon/poplar/bl2_plat_setup.c b/plat/hisilicon/poplar/bl2_plat_setup.c index 1741475b..db507c32 100644 --- a/plat/hisilicon/poplar/bl2_plat_setup.c +++ b/plat/hisilicon/poplar/bl2_plat_setup.c @@ -29,8 +29,10 @@ typedef struct bl2_to_bl31_params_mem { bl31_params_t bl31_params; image_info_t bl31_image_info; + image_info_t bl32_image_info; image_info_t bl33_image_info; entry_point_info_t bl33_ep_info; + entry_point_info_t bl32_ep_info; entry_point_info_t bl31_ep_info; } bl2_to_bl31_params_mem_t; @@ -61,6 +63,16 @@ bl31_params_t *bl2_plat_get_bl31_params(void) SET_PARAM_HEAD(bl2_to_bl31_params->bl31_image_info, PARAM_IMAGE_BINARY, VERSION_1, 0); + /* Fill BL3-2 related information if it exists */ +#ifdef BL32_BASE + bl2_to_bl31_params->bl32_ep_info = &bl31_params_mem.bl32_ep_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_ep_info, PARAM_EP, + VERSION_1, 0); + bl2_to_bl31_params->bl32_image_info = &bl31_params_mem.bl32_image_info; + SET_PARAM_HEAD(bl2_to_bl31_params->bl32_image_info, PARAM_IMAGE_BINARY, + VERSION_1, 0); +#endif + /* Fill BL3-3 related information */ bl2_to_bl31_params->bl33_ep_info = &bl31_params_mem.bl33_ep_info; SET_PARAM_HEAD(bl2_to_bl31_params->bl33_ep_info, @@ -89,6 +101,41 @@ void bl2_plat_set_bl31_ep_info(image_info_t *image, DISABLE_ALL_EXCEPTIONS); } +/******************************************************************************* + * Before calling this function BL32 is loaded in memory and its entrypoint + * is set by load_image. This is a placeholder for the platform to change + * the entrypoint of BL32 and set SPSR and security state. + * On Poplar we only set the security state of the entrypoint + ******************************************************************************/ +#ifdef BL32_BASE +void bl2_plat_set_bl32_ep_info(image_info_t *bl32_image_info, + entry_point_info_t *bl32_ep_info) +{ + SET_SECURITY_STATE(bl32_ep_info->h.attr, SECURE); + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + bl32_ep_info->spsr = 0; +} + +/******************************************************************************* + * Populate the extents of memory available for loading BL32 + ******************************************************************************/ +void bl2_plat_get_bl32_meminfo(meminfo_t *bl32_meminfo) +{ + /* + * Populate the extents of memory available for loading BL32. + */ + bl32_meminfo->total_base = BL32_BASE; + bl32_meminfo->free_base = BL32_BASE; + bl32_meminfo->total_size = + (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE; + bl32_meminfo->free_size = + (TSP_SEC_MEM_BASE + TSP_SEC_MEM_SIZE) - BL32_BASE; +} +#endif /* BL32_BASE */ + static uint32_t hisi_get_spsr_for_bl33_entry(void) { unsigned long el_status; @@ -159,5 +206,5 @@ void bl2_platform_setup(void) unsigned long plat_get_ns_image_entrypoint(void) { - return PLAT_ARM_NS_IMAGE_OFFSET; + return PLAT_POPLAR_NS_IMAGE_OFFSET; } diff --git a/plat/hisilicon/poplar/bl31_plat_setup.c b/plat/hisilicon/poplar/bl31_plat_setup.c index b9a0e18e..e3a5c50f 100644 --- a/plat/hisilicon/poplar/bl31_plat_setup.c +++ b/plat/hisilicon/poplar/bl31_plat_setup.c @@ -32,11 +32,31 @@ #define BL31_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) #define BL31_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) +#define TZPC_SEC_ATTR_CTRL_VALUE (0x9DB98D45) + +static entry_point_info_t bl32_image_ep_info; static entry_point_info_t bl33_image_ep_info; +static void hisi_tzpc_sec_init(void) +{ + mmio_write_32(HISI_TZPC_SEC_ATTR_CTRL, TZPC_SEC_ATTR_CTRL_VALUE); +} + entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) { - return &bl33_image_ep_info; + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type)); + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; + /* + * None of the images on the ARM development platforms can have 0x0 + * as the entrypoint + */ + if (next_image_info->pc) + return next_image_info; + else + return NULL; } void bl31_early_platform_setup(bl31_params_t *from_bl2, @@ -47,6 +67,13 @@ void bl31_early_platform_setup(bl31_params_t *from_bl2, /* Init console for crash report */ plat_crash_console_init(); + + /* + * Copy BL32 (if populated by BL2) and BL33 entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + if (from_bl2->bl32_ep_info) + bl32_image_ep_info = *from_bl2->bl32_ep_info; bl33_image_ep_info = *from_bl2->bl33_ep_info; } @@ -58,6 +85,9 @@ void bl31_platform_setup(void) /* Init GIC distributor and CPU interface */ plat_arm_gic_driver_init(); plat_arm_gic_init(); + + /* Init security properties of IP blocks */ + hisi_tzpc_sec_init(); } void bl31_plat_runtime_setup(void) diff --git a/plat/hisilicon/poplar/include/hi3798cv200.h b/plat/hisilicon/poplar/include/hi3798cv200.h index 6318b9c6..540d0aa1 100644 --- a/plat/hisilicon/poplar/include/hi3798cv200.h +++ b/plat/hisilicon/poplar/include/hi3798cv200.h @@ -30,7 +30,7 @@ #define TIMER20_BGLOAD (SEC_TIMER2_BASE + 0x018) /* GPIO */ -#define GPIO_MAX (12) +#define GPIO_MAX (13) #define GPIO_BASE(x) (x != 5 ? \ 0xf820000 + x * 0x1000 : 0xf8004000) @@ -97,4 +97,7 @@ /* Watchdog */ #define HISI_WDG0_BASE (0xF8A2C000) +#define HISI_TZPC_BASE (0xF8A80000) +#define HISI_TZPC_SEC_ATTR_CTRL (HISI_TZPC_BASE + 0x10) + #endif /* __HI3798cv200_H__ */ diff --git a/plat/hisilicon/poplar/include/platform_def.h b/plat/hisilicon/poplar/include/platform_def.h index b7afe820..3d1ad9b9 100644 --- a/plat/hisilicon/poplar/include/platform_def.h +++ b/plat/hisilicon/poplar/include/platform_def.h @@ -48,11 +48,55 @@ #define TEE_SEC_MEM_BASE (0x70000000) #define TEE_SEC_MEM_SIZE (0x10000000) +/* Memory location options for TSP */ +#define POPLAR_SRAM_ID 0 +#define POPLAR_DRAM_ID 1 + +/* + * DDR for OP-TEE (28MB from 0x02200000 -0x04000000) is divided in several + * regions: + * - Secure DDR (default is the top 16MB) used by OP-TEE + * - Non-secure DDR (4MB) reserved for OP-TEE's future use + * - Secure DDR (4MB aligned on 4MB) for OP-TEE's "Secure Data Path" feature + * - Non-secure DDR used by OP-TEE (shared memory and padding) (4MB) + * - Non-secure DDR (2MB) reserved for OP-TEE's future use + */ +#define DDR_SEC_SIZE 0x01000000 +#define DDR_SEC_BASE 0x03000000 + #define BL_MEM_BASE (BL1_RO_BASE) #define BL_MEM_LIMIT (BL31_LIMIT) #define BL_MEM_SIZE (BL_MEM_LIMIT - BL_MEM_BASE) -#define PLAT_ARM_NS_IMAGE_OFFSET 0x37000000 +/* + * BL3-2 specific defines. + */ + +/* + * The TSP currently executes from TZC secured area of DRAM. + */ +#define BL32_DRAM_BASE 0x03000000 +#define BL32_DRAM_LIMIT 0x04000000 + +#if (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_DRAM_ID) +#define TSP_SEC_MEM_BASE BL32_DRAM_BASE +#define TSP_SEC_MEM_SIZE (BL32_DRAM_LIMIT - BL32_DRAM_BASE) +#define BL32_BASE BL32_DRAM_BASE +#define BL32_LIMIT BL32_DRAM_LIMIT +#elif (POPLAR_TSP_RAM_LOCATION_ID == POPLAR_SRAM_ID) +#error "SRAM storage of TSP payload is currently unsupported" +#else +#error "Currently unsupported POPLAR_TSP_LOCATION_ID value" +#endif + +/* BL32 is mandatory in AArch32 */ +#ifndef AARCH32 +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ +#endif + +#define PLAT_POPLAR_NS_IMAGE_OFFSET 0x37000000 /* Page table and MMU setup constants */ #define ADDR_SPACE_SIZE (1ull << 32) diff --git a/plat/hisilicon/poplar/include/poplar_layout.h b/plat/hisilicon/poplar/include/poplar_layout.h index 192bcb9c..e0b5618e 100644 --- a/plat/hisilicon/poplar/include/poplar_layout.h +++ b/plat/hisilicon/poplar/include/poplar_layout.h @@ -74,16 +74,16 @@ * "OFFSET" is an offset to the start of a region relative to the * base of the "l-loader" TEXT section (also a multiple of page size). */ -#define LLOADER_TEXT_BASE 0x00001000 /* page aligned */ +#define LLOADER_TEXT_BASE 0x02001000 /* page aligned */ #define BL1_OFFSET 0x0000D000 /* page multiple */ -#define FIP_BASE 0x00040000 +#define FIP_BASE 0x02040000 #define BL1_RO_SIZE 0x00008000 /* page multiple */ #define BL1_RW_SIZE 0x00008000 /* page multiple */ #define BL1_SIZE (BL1_RO_SIZE + BL1_RW_SIZE) #define BL2_SIZE 0x0000c000 /* page multiple */ #define BL31_SIZE 0x00014000 -#define FIP_SIZE 0x00068000 +#define FIP_SIZE 0x000c0000 /* absolute max */ /* BL1_OFFSET */ /* (Defined above) */ #define BL1_BASE (LLOADER_TEXT_BASE + BL1_OFFSET) diff --git a/plat/hisilicon/poplar/plat_storage.c b/plat/hisilicon/poplar/plat_storage.c index 623a61b7..ab94cba3 100644 --- a/plat/hisilicon/poplar/plat_storage.c +++ b/plat/hisilicon/poplar/plat_storage.c @@ -43,6 +43,10 @@ static const io_uuid_spec_t bl31_uuid_spec = { .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, }; +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + static const io_uuid_spec_t bl33_uuid_spec = { .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, }; @@ -69,6 +73,11 @@ static const struct plat_io_policy policies[] = { (uintptr_t)&bl31_uuid_spec, open_fip }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, [BL33_IMAGE_ID] = { &fip_dev_handle, (uintptr_t)&bl33_uuid_spec, diff --git a/plat/hisilicon/poplar/platform.mk b/plat/hisilicon/poplar/platform.mk index fc75ff35..818e3115 100644 --- a/plat/hisilicon/poplar/platform.mk +++ b/plat/hisilicon/poplar/platform.mk @@ -4,6 +4,17 @@ # SPDX-License-Identifier: BSD-3-Clause # +# On Poplar, the TSP can execute from TZC secure area in DRAM. +POPLAR_TSP_RAM_LOCATION := dram +ifeq (${POPLAR_TSP_RAM_LOCATION}, dram) + POPLAR_TSP_RAM_LOCATION_ID = POPLAR_DRAM_ID +else ifeq (${HIKEY960_TSP_RAM_LOCATION}, sram) + POPLAR_TSP_RAM_LOCATION_ID := POPLAR_SRAM_ID +else + $(error "Currently unsupported POPLAR_TSP_RAM_LOCATION value") +endif +$(eval $(call add_define,POPLAR_TSP_RAM_LOCATION_ID)) + NEED_BL33 := yes COLD_BOOT_SINGLE_CPU := 1 @@ -13,6 +24,7 @@ ENABLE_PLAT_COMPAT := 0 ERRATA_A53_855873 := 1 ERRATA_A53_835769 := 1 ERRATA_A53_843419 := 1 +ENABLE_SVE_FOR_NS := 0 ARM_GIC_ARCH := 2 $(eval $(call add_define,ARM_GIC_ARCH)) @@ -69,4 +81,3 @@ BL31_SOURCES += \ plat/hisilicon/poplar/bl31_plat_setup.c \ plat/hisilicon/poplar/plat_topology.c \ plat/hisilicon/poplar/plat_pm.c - diff --git a/plat/mediatek/mt6795/bl31.ld.S b/plat/mediatek/mt6795/bl31.ld.S index 0f60a0c6..eacb1b27 100644 --- a/plat/mediatek/mt6795/bl31.ld.S +++ b/plat/mediatek/mt6795/bl31.ld.S @@ -5,6 +5,7 @@ */ #include <platform_def.h> +#include <xlat_tables_defs.h> OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) OUTPUT_ARCH(PLATFORM_LINKER_ARCH) @@ -29,7 +30,7 @@ SECTIONS *(.vectors) } >RAM - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "BL31_BASE address is not aligned on a page boundary.") ro . : { @@ -58,7 +59,7 @@ SECTIONS * executable. No RW data from the next section must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __RO_END__ = .; } >RAM @@ -144,7 +145,7 @@ SECTIONS * are not mixed with normal data. This is required to set up the correct * memory attributes for the coherent data page tables. */ - coherent_ram (NOLOAD) : ALIGN(4096) { + coherent_ram (NOLOAD) : ALIGN(PAGE_SIZE) { __COHERENT_RAM_START__ = .; /* * Bakery locks are stored in coherent memory @@ -159,7 +160,7 @@ SECTIONS * as device memory. No other unexpected data must creep in. * Ensure the rest of the current memory page is unused. */ - . = NEXT(4096); + . = NEXT(PAGE_SIZE); __COHERENT_RAM_END__ = .; } >RAM2 #endif diff --git a/plat/mediatek/mt6795/platform.mk b/plat/mediatek/mt6795/platform.mk index 4ebc78e5..82300674 100644 --- a/plat/mediatek/mt6795/platform.mk +++ b/plat/mediatek/mt6795/platform.mk @@ -66,3 +66,5 @@ PROGRAMMABLE_RESET_ADDRESS := 1 $(eval $(call add_define,MTK_SIP_KERNEL_BOOT_ENABLE)) +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/plat/mediatek/mt8173/platform.mk b/plat/mediatek/mt8173/platform.mk index cd016451..2eef81bb 100644 --- a/plat/mediatek/mt8173/platform.mk +++ b/plat/mediatek/mt8173/platform.mk @@ -70,3 +70,6 @@ ERRATA_A53_855873 := 1 PROGRAMMABLE_RESET_ADDRESS := 1 $(eval $(call add_define,MTK_SIP_SET_AUTHORIZED_SECURE_REG_ENABLE)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk index 9a9e79e2..ad60620a 100644 --- a/plat/nvidia/tegra/platform.mk +++ b/plat/nvidia/tegra/platform.mk @@ -29,6 +29,9 @@ SEPARATE_CODE_AND_RODATA := 1 # do not use coherent memory USE_COHERENT_MEM := 0 +# do not enable SVE +ENABLE_SVE_FOR_NS := 0 + include plat/nvidia/tegra/common/tegra_common.mk include ${SOC_DIR}/platform_${TARGET_SOC}.mk diff --git a/plat/qemu/platform.mk b/plat/qemu/platform.mk index 2a7415f5..43ab846b 100644 --- a/plat/qemu/platform.mk +++ b/plat/qemu/platform.mk @@ -153,3 +153,6 @@ endif # Process flags $(eval $(call add_define,BL32_RAM_LOCATION_ID)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/plat/rockchip/rk3328/platform.mk b/plat/rockchip/rk3328/platform.mk index 8863fb4f..5de4680e 100644 --- a/plat/rockchip/rk3328/platform.mk +++ b/plat/rockchip/rk3328/platform.mk @@ -48,7 +48,10 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \ ${RK_PLAT_SOC}/drivers/pmu/pmu.c \ ${RK_PLAT_SOC}/drivers/soc/soc.c -ENABLE_PLAT_COMPAT := 0 +ENABLE_PLAT_COMPAT := 0 $(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) $(eval $(call add_define,PLAT_SKIP_OPTEE_S_EL1_INT_REGISTER)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/plat/rockchip/rk3368/platform.mk b/plat/rockchip/rk3368/platform.mk index f6960cf4..d3c6eeff 100644 --- a/plat/rockchip/rk3368/platform.mk +++ b/plat/rockchip/rk3368/platform.mk @@ -48,6 +48,9 @@ BL31_SOURCES += ${RK_GIC_SOURCES} \ ${RK_PLAT_SOC}/drivers/soc/soc.c \ ${RK_PLAT_SOC}/drivers/ddr/ddr_rk3368.c \ -ENABLE_PLAT_COMPAT := 0 +ENABLE_PLAT_COMPAT := 0 $(eval $(call add_define,PLAT_EXTRA_LD_SCRIPT)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/plat/rockchip/rk3399/include/plat.ld.S b/plat/rockchip/rk3399/include/plat.ld.S index c42d9a9a..85f4dc33 100644 --- a/plat/rockchip/rk3399/include/plat.ld.S +++ b/plat/rockchip/rk3399/include/plat.ld.S @@ -6,6 +6,8 @@ #ifndef __ROCKCHIP_PLAT_LD_S__ #define __ROCKCHIP_PLAT_LD_S__ +#include <xlat_tables_defs.h> + MEMORY { SRAM (rwx): ORIGIN = SRAM_BASE, LENGTH = SRAM_SIZE PMUSRAM (rwx): ORIGIN = PMUSRAM_BASE, LENGTH = PMUSRAM_RSIZE @@ -14,7 +16,7 @@ MEMORY { SECTIONS { . = SRAM_BASE; - ASSERT(. == ALIGN(4096), + ASSERT(. == ALIGN(PAGE_SIZE), "SRAM_BASE address is not aligned on a page boundary.") /* @@ -27,40 +29,40 @@ SECTIONS * | sram data * ---------------- */ - .incbin_sram : ALIGN(4096) { + .incbin_sram : ALIGN(PAGE_SIZE) { __sram_incbin_start = .; *(.sram.incbin) __sram_incbin_real_end = .; - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __sram_incbin_end = .; } >SRAM ASSERT((__sram_incbin_real_end - __sram_incbin_start) <= SRAM_BIN_LIMIT, ".incbin_sram has exceeded its limit") - .text_sram : ALIGN(4096) { + .text_sram : ALIGN(PAGE_SIZE) { __bl31_sram_text_start = .; *(.sram.text) *(.sram.rodata) __bl31_sram_text_real_end = .; - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __bl31_sram_text_end = .; } >SRAM ASSERT((__bl31_sram_text_real_end - __bl31_sram_text_start) <= SRAM_TEXT_LIMIT, ".text_sram has exceeded its limit") - .data_sram : ALIGN(4096) { + .data_sram : ALIGN(PAGE_SIZE) { __bl31_sram_data_start = .; *(.sram.data) __bl31_sram_data_real_end = .; - . = ALIGN(4096); + . = ALIGN(PAGE_SIZE); __bl31_sram_data_end = .; } >SRAM ASSERT((__bl31_sram_data_real_end - __bl31_sram_data_start) <= SRAM_DATA_LIMIT, ".data_sram has exceeded its limit") - .stack_sram : ALIGN(4096) { + .stack_sram : ALIGN(PAGE_SIZE) { __bl31_sram_stack_start = .; - . += 4096; + . += PAGE_SIZE; __bl31_sram_stack_end = .; } >SRAM diff --git a/plat/rockchip/rk3399/plat_sip_calls.c b/plat/rockchip/rk3399/plat_sip_calls.c index 074dc193..2fbda673 100644 --- a/plat/rockchip/rk3399/plat_sip_calls.c +++ b/plat/rockchip/rk3399/plat_sip_calls.c @@ -11,6 +11,7 @@ #include <plat_sip_calls.h> #include <rockchip_sip_svc.h> #include <runtime_svc.h> +#include <stdint.h> #define RK_SIP_DDR_CFG 0x82000008 #define DRAM_INIT 0x00 diff --git a/plat/rockchip/rk3399/platform.mk b/plat/rockchip/rk3399/platform.mk index 6cd5b242..33b9723d 100644 --- a/plat/rockchip/rk3399/platform.mk +++ b/plat/rockchip/rk3399/platform.mk @@ -92,3 +92,6 @@ $(eval $(call MAKE_PREREQ_DIR,${BUILD_M0},${BUILD_PLAT})) .PHONY: $(RK3399M0FW) $(RK3399M0FW): | ${BUILD_M0} $(MAKE) -C ${RK_PLAT_SOC}/drivers/m0 BUILD=$(abspath ${BUILD_PLAT}/m0) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/plat/rpi3/aarch64/plat_helpers.S b/plat/rpi3/aarch64/plat_helpers.S new file mode 100644 index 00000000..76a542f5 --- /dev/null +++ b/plat/rpi3/aarch64/plat_helpers.S @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <asm_macros.S> +#include <assert_macros.S> +#include <platform_def.h> + +#include "../rpi3_hw.h" + + .globl plat_crash_console_flush + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl platform_mem_init + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + .globl plat_my_core_pos + .globl plat_reset_handler + .globl plat_rpi3_calc_core_pos + .globl plat_secondary_cold_boot_setup + + /* ----------------------------------------------------- + * unsigned int plat_my_core_pos(void) + * + * This function uses the plat_rpi3_calc_core_pos() + * definition to get the index of the calling CPU. + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_rpi3_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr); + * + * CorePos = (ClusterId * 4) + CoreId + * ----------------------------------------------------- + */ +func plat_rpi3_calc_core_pos + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret +endfunc plat_rpi3_calc_core_pos + + /* ----------------------------------------------------- + * 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 + and x0, x0, #(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + cmp x0, #RPI3_PRIMARY_CPU + cset w0, eq + ret +endfunc plat_is_my_cpu_primary + + /* ----------------------------------------------------- + * void plat_secondary_cold_boot_setup (void); + * + * This function performs any platform specific actions + * needed for a secondary cpu after a cold reset e.g + * mark the cpu's presence, mechanism to place it in a + * holding pen etc. + * ----------------------------------------------------- + */ +func plat_secondary_cold_boot_setup + /* Calculate address of our hold entry */ + bl plat_my_core_pos + lsl x0, x0, #3 + mov_imm x2, PLAT_RPI3_TM_HOLD_BASE + add x0, x0, x2 + + /* + * This code runs way before requesting the warmboot of this core, + * so it is possible to clear the mailbox before getting a request + * to boot. + */ + mov x1, PLAT_RPI3_TM_HOLD_STATE_WAIT + str x1,[x0] + + /* Wait until we have a go */ +poll_mailbox: + wfe + ldr x1, [x0] + cmp x1, PLAT_RPI3_TM_HOLD_STATE_GO + bne poll_mailbox + + /* Jump to the provided entrypoint */ + mov_imm x0, PLAT_RPI3_TM_ENTRYPOINT + ldr x1, [x0] + br x1 +endfunc plat_secondary_cold_boot_setup + + /* --------------------------------------------------------------------- + * uintptr_t plat_get_my_entrypoint (void); + * + * Main job of this routine is to distinguish between a cold and a warm + * boot. + * + * This functions returns: + * - 0 for a cold boot. + * - Any other value for a warm boot. + * --------------------------------------------------------------------- + */ +func plat_get_my_entrypoint + /* TODO: support warm boot */ + mov x0, #0 + ret +endfunc plat_get_my_entrypoint + + /* --------------------------------------------- + * void platform_mem_init (void); + * + * No need to carry out any memory initialization. + * --------------------------------------------- + */ +func platform_mem_init + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize the crash console + * without a C Runtime to print crash report. + * Clobber list : x0 - x3 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm x0, PLAT_RPI3_UART_BASE + mov_imm x1, PLAT_RPI3_UART_CLK_IN_HZ + mov_imm x2, PLAT_RPI3_UART_BAUDRATE + b console_core_init +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to print a character on the crash + * console without a C Runtime. + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, PLAT_RPI3_UART_BASE + b console_core_putc +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * int plat_crash_console_flush() + * Function to force a write of all buffered + * data that hasn't been output. + * Out : return -1 on error else return 0. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func plat_crash_console_flush + mov_imm x1, PLAT_RPI3_UART_BASE + b console_core_flush +endfunc plat_crash_console_flush + + /* --------------------------------------------- + * void plat_reset_handler(void); + * --------------------------------------------- + */ +func plat_reset_handler + /* use the 19.2 MHz clock for the architected timer */ + mov x0, #RPI3_INTC_BASE_ADDRESS + mov w1, #0x80000000 + str wzr, [x0, #RPI3_INTC_CONTROL_OFFSET] + str w1, [x0, #RPI3_INTC_PRESCALER_OFFSET] + + /* wire mailbox 3 to the FIQ line */ + mov w1, RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ + str w1, [x0, #RPI3_INTC_MBOX_CONTROL_OFFSET] + ret +endfunc plat_reset_handler diff --git a/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c new file mode 100644 index 00000000..e3acfe9f --- /dev/null +++ b/plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <bl_common.h> +#include <desc_image_load.h> +#include <platform.h> +#include <platform_def.h> + +/******************************************************************************* + * Following descriptor provides BL image/ep information that gets used + * by BL2 to load the images and also subset of this information is + * passed to next BL image. The image loading sequence is managed by + * populating the images in required loading order. The image execution + * sequence is managed by populating the `next_handoff_image_id` with + * the next executable image id. + ******************************************************************************/ +static bl_mem_params_node_t bl2_mem_params_descs[] = { + + /* Fill BL31 related information */ + { + .image_id = BL31_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE | EP_FIRST_EXE), + .ep_info.pc = BL31_BASE, + .ep_info.spsr = SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS), +#if DEBUG + .ep_info.args.arg1 = RPI3_BL31_PLAT_PARAM_VAL, +#endif + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_PLAT_SETUP), + .image_info.image_base = BL31_BASE, + .image_info.image_max_size = BL31_LIMIT - BL31_BASE, + +# ifdef BL32_BASE + .next_handoff_image_id = BL32_IMAGE_ID, +# else + .next_handoff_image_id = BL33_IMAGE_ID, +# endif + }, + +# ifdef BL32_BASE + /* Fill BL32 related information */ + { + .image_id = BL32_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | EXECUTABLE), + .ep_info.pc = BL32_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + + /* + * Fill BL32 external 1 related information. + * A typical use for extra1 image is with OP-TEE where it is the pager + * image. + */ + { + .image_id = BL32_EXTRA1_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + .image_info.image_base = BL32_BASE, + .image_info.image_max_size = BL32_LIMIT - BL32_BASE, + + .next_handoff_image_id = INVALID_IMAGE_ID, + }, + + /* + * Fill BL32 external 2 related information. + * A typical use for extra2 image is with OP-TEE where it is the paged + * image. + */ + { + .image_id = BL32_EXTRA2_IMAGE_ID, + + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + SECURE | NON_EXECUTABLE), + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), + .next_handoff_image_id = INVALID_IMAGE_ID, + }, +# endif /* BL32_BASE */ + + /* Fill BL33 related information */ + { + .image_id = BL33_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_2, entry_point_info_t, + NON_SECURE | EXECUTABLE), +# ifdef PRELOADED_BL33_BASE + .ep_info.pc = PRELOADED_BL33_BASE, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, + IMAGE_ATTRIB_SKIP_LOADING), +# else + .ep_info.pc = PLAT_RPI3_NS_IMAGE_OFFSET, + + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_2, image_info_t, 0), + .image_info.image_base = PLAT_RPI3_NS_IMAGE_OFFSET, + .image_info.image_max_size = PLAT_RPI3_NS_IMAGE_MAX_SIZE, +# endif /* PRELOADED_BL33_BASE */ + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/plat/rpi3/include/plat_macros.S b/plat/rpi3/include/plat_macros.S new file mode 100644 index 00000000..f5e057ed --- /dev/null +++ b/plat/rpi3/include/plat_macros.S @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef __PLAT_MACROS_S__ +#define __PLAT_MACROS_S__ + +#include <arm_macros.S> +#include <platform_def.h> + + /* --------------------------------------------- + * The below required platform porting macro + * prints out relevant platform registers + * whenever an unhandled exception is taken in + * BL31. + * Clobbers: x0 - x10, x16, x17, sp + * --------------------------------------------- + */ + .macro plat_crash_print_regs + .endm + +#endif /* __PLAT_MACROS_S__ */ diff --git a/plat/rpi3/include/platform_def.h b/plat/rpi3/include/platform_def.h new file mode 100644 index 00000000..5e2f1da5 --- /dev/null +++ b/plat/rpi3/include/platform_def.h @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2015-2017, 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 <common_def.h> +#include <tbbr_img_def.h> +#include <utils_def.h> + +#include "../rpi3_hw.h" + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define RPI3_BL31_PLAT_PARAM_VAL ULL(0x0F1E2D3C4B5A6978) + +#define PLATFORM_STACK_SIZE ULL(0x1000) + +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(4) +#define PLATFORM_CLUSTER_COUNT U(1) +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CORE_COUNT PLATFORM_CLUSTER0_CORE_COUNT + +#define RPI3_PRIMARY_CPU U(0) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL1 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +/* Local power state for power domains in Run state. */ +#define PLAT_LOCAL_STATE_RUN U(0) +/* Local power state for retention. Valid only for CPU power domains */ +#define PLAT_LOCAL_STATE_RET U(1) +/* + * Local power state for OFF/power-down. Valid for CPU and cluster power + * domains. + */ +#define PLAT_LOCAL_STATE_OFF U(2) + +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define PLAT_LOCAL_PSTATE_WIDTH U(4) +#define PLAT_LOCAL_PSTATE_MASK ((U(1) << PLAT_LOCAL_PSTATE_WIDTH) - 1) + +/* + * Some data must be aligned on the biggest cache line size in the platform. + * This is known only to the platform as it might have a combination of + * integrated and external caches. + */ +#define CACHE_WRITEBACK_SHIFT U(6) +#define CACHE_WRITEBACK_GRANULE (U(1) << CACHE_WRITEBACK_SHIFT) + +/* + * Partition memory into secure ROM, non-secure DRAM, secure "SRAM", and + * secure DRAM. Note that this is all actually DRAM with different names, + * there is no Secure RAM in the Raspberry Pi 3. + */ +#define SEC_ROM_BASE ULL(0x00000000) +#define SEC_ROM_SIZE ULL(0x00010000) + +/* FIP placed after ROM to append it to BL1 with very little padding. */ +#define PLAT_RPI3_FIP_BASE ULL(0x00010000) +#define PLAT_RPI3_FIP_MAX_SIZE ULL(0x001F0000) + +/* We have 16M of memory reserved at at 256M */ +#define SEC_SRAM_BASE ULL(0x10000000) +#define SEC_SRAM_SIZE ULL(0x00100000) + +#define SEC_DRAM0_BASE ULL(0x10100000) +#define SEC_DRAM0_SIZE ULL(0x00200000) + +#define NS_DRAM0_BASE ULL(0x10300000) +#define NS_DRAM0_SIZE ULL(0x00D00000) +/* End of reserved memory */ + +/* + * BL33 entrypoint. + */ +#define PLAT_RPI3_NS_IMAGE_OFFSET NS_DRAM0_BASE +#define PLAT_RPI3_NS_IMAGE_MAX_SIZE NS_DRAM0_SIZE + +/* + * I/O registers. + */ +#define DEVICE0_BASE RPI3_IO_BASE +#define DEVICE0_SIZE RPI3_IO_SIZE + +/* + * Arm TF lives in SRAM, partition it here + */ +#define SHARED_RAM_BASE SEC_SRAM_BASE +#define SHARED_RAM_SIZE ULL(0x00001000) + +#define BL_RAM_BASE (SHARED_RAM_BASE + SHARED_RAM_SIZE) +#define BL_RAM_SIZE (SEC_SRAM_SIZE - SHARED_RAM_SIZE) + +/* + * Mailbox to control the secondary cores.All secondary cores are held in a wait + * loop in cold boot. To release them perform the following steps (plus any + * additional barriers that may be needed): + * + * uint64_t *entrypoint = (uint64_t *)PLAT_RPI3_TM_ENTRYPOINT; + * *entrypoint = ADDRESS_TO_JUMP_TO; + * + * uint64_t *mbox_entry = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE; + * mbox_entry[cpu_id] = PLAT_RPI3_TM_HOLD_STATE_GO; + * + * sev(); + */ +#define PLAT_RPI3_TRUSTED_MAILBOX_BASE SHARED_RAM_BASE + +#define PLAT_RPI3_TM_ENTRYPOINT PLAT_RPI3_TRUSTED_MAILBOX_BASE +#define PLAT_RPI3_TM_ENTRYPOINT_SIZE ULL(8) + +#define PLAT_RPI3_TM_HOLD_BASE (PLAT_RPI3_TM_ENTRYPOINT + \ + PLAT_RPI3_TM_ENTRYPOINT_SIZE) +#define PLAT_RPI3_TM_HOLD_ENTRY_SIZE ULL(8) +#define PLAT_RPI3_TM_HOLD_SIZE (PLAT_RPI3_TM_HOLD_ENTRY_SIZE * \ + PLATFORM_CORE_COUNT) + +#define PLAT_RPI3_TRUSTED_MAILBOX_SIZE (PLAT_RPI3_TM_ENTRYPOINT_SIZE + \ + PLAT_RPI3_TM_HOLD_SIZE) + +#define PLAT_RPI3_TM_HOLD_STATE_WAIT ULL(0) +#define PLAT_RPI3_TM_HOLD_STATE_GO ULL(1) + +/* + * BL1 specific defines. + * + * BL1 RW data is relocated from ROM to RAM at runtime so we need 2 sets of + * addresses. + * + * Put BL1 RW at the top of the Secure SRAM. BL1_RW_BASE is calculated using + * the current BL1 RW debug size plus a little space for growth. + */ +#define PLAT_MAX_BL1_RW_SIZE ULL(0x12000) + +#define BL1_RO_BASE SEC_ROM_BASE +#define BL1_RO_LIMIT (SEC_ROM_BASE + SEC_ROM_SIZE) +#define BL1_RW_BASE (BL1_RW_LIMIT - PLAT_MAX_BL1_RW_SIZE) +#define BL1_RW_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) + +/* + * BL2 specific defines. + * + * Put BL2 just below BL31. BL2_BASE is calculated using the current BL2 debug + * size plus a little space for growth. + */ +#define PLAT_MAX_BL2_SIZE ULL(0x2C000) + +#define BL2_BASE (BL2_LIMIT - PLAT_MAX_BL2_SIZE) +#define BL2_LIMIT BL31_BASE + +/* + * BL31 specific defines. + * + * Put BL31 at the top of the Trusted SRAM. BL31_BASE is calculated using the + * current BL31 debug size plus a little space for growth. + */ +#define PLAT_MAX_BL31_SIZE ULL(0x20000) + +#define BL31_BASE (BL31_LIMIT - PLAT_MAX_BL31_SIZE) +#define BL31_LIMIT (BL_RAM_BASE + BL_RAM_SIZE) +#define BL31_PROGBITS_LIMIT BL1_RW_BASE + +/* + * BL32 specific defines. + * + * BL32 can execute from Secure SRAM or Secure DRAM. + */ +#define BL32_SRAM_BASE BL_RAM_BASE +#define BL32_SRAM_LIMIT BL31_BASE +#define BL32_DRAM_BASE SEC_DRAM0_BASE +#define BL32_DRAM_LIMIT (SEC_DRAM0_BASE + SEC_DRAM0_SIZE) + +#define SEC_SRAM_ID 0 +#define SEC_DRAM_ID 1 + +#if RPI3_BL32_RAM_LOCATION_ID == SEC_SRAM_ID +# define BL32_MEM_BASE BL_RAM_BASE +# define BL32_MEM_SIZE BL_RAM_SIZE +# define BL32_BASE BL32_SRAM_BASE +# define BL32_LIMIT BL32_SRAM_LIMIT +#elif RPI3_BL32_RAM_LOCATION_ID == SEC_DRAM_ID +# define BL32_MEM_BASE SEC_DRAM0_BASE +# define BL32_MEM_SIZE SEC_DRAM0_SIZE +# define BL32_BASE BL32_DRAM_BASE +# define BL32_LIMIT BL32_DRAM_LIMIT +#else +# error "Unsupported RPI3_BL32_RAM_LOCATION_ID value" +#endif +#define BL32_SIZE (BL32_LIMIT - BL32_BASE) + +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ + +/* + * Other memory-related defines. + */ +#define ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_MMAP_REGIONS U(8) +#define MAX_XLAT_TABLES U(4) + +#define MAX_IO_DEVICES U(3) +#define MAX_IO_HANDLES U(4) + +/* + * Serial-related constants. + */ +#define PLAT_RPI3_UART_BASE RPI3_MINI_UART_BASE +#define PLAT_RPI3_UART_CLK_IN_HZ RPI3_MINI_UART_CLK_IN_HZ +#define PLAT_RPI3_UART_BAUDRATE ULL(115200) + +/* + * System counter + */ +#define SYS_COUNTER_FREQ_IN_TICKS ULL(19200000) + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/rpi3/platform.mk b/plat/rpi3/platform.mk new file mode 100644 index 00000000..821f8015 --- /dev/null +++ b/plat/rpi3/platform.mk @@ -0,0 +1,113 @@ +# +# Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_INCLUDES := -Iinclude/common/tbbr \ + -Iinclude/plat/arm/common/ \ + -Iinclude/plat/arm/common/aarch64/ \ + -Iplat/rpi3/include + +PLAT_BL_COMMON_SOURCES := drivers/console/aarch64/console.S \ + drivers/ti/uart/aarch64/16550_console.S \ + plat/rpi3/rpi3_common.c + +BL1_SOURCES += drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + lib/cpus/aarch64/cortex_a53.S \ + plat/common/aarch64/platform_mp_stack.S \ + plat/rpi3/aarch64/plat_helpers.S \ + plat/rpi3/rpi3_bl1_setup.c \ + plat/rpi3/rpi3_io_storage.c + +BL2_SOURCES += common/desc_image_load.c \ + drivers/io/io_fip.c \ + drivers/io/io_memmap.c \ + drivers/io/io_storage.c \ + plat/common/aarch64/platform_mp_stack.S \ + plat/rpi3/aarch64/plat_helpers.S \ + plat/rpi3/aarch64/rpi3_bl2_mem_params_desc.c \ + plat/rpi3/rpi3_bl2_setup.c \ + plat/rpi3/rpi3_image_load.c \ + plat/rpi3/rpi3_io_storage.c + +BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \ + plat/common/aarch64/plat_psci_common.c \ + plat/rpi3/aarch64/plat_helpers.S \ + plat/rpi3/rpi3_bl31_setup.c \ + plat/rpi3/rpi3_pm.c \ + plat/rpi3/rpi3_topology.c + +# Translation tables library +include lib/xlat_tables_v2/xlat_tables.mk + +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} + +# Tune compiler for Cortex-A53 +ifeq ($(notdir $(CC)),armclang) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else ifneq ($(findstring clang,$(notdir $(CC))),) + TF_CFLAGS_aarch64 += -mcpu=cortex-a53 +else + TF_CFLAGS_aarch64 += -mtune=cortex-a53 +endif + +# Build config flags +# ------------------ + +# Enable all errata workarounds for Cortex-A53 +ERRATA_A53_826319 := 1 +ERRATA_A53_835769 := 1 +ERRATA_A53_836870 := 1 +ERRATA_A53_843419 := 1 +ERRATA_A53_855873 := 1 + +# Disable the PSCI platform compatibility layer by default +ENABLE_PLAT_COMPAT := 0 + +# Enable reset to BL31 by default +RESET_TO_BL31 := 1 + +# Have different sections for code and rodata +SEPARATE_CODE_AND_RODATA := 1 + +# Use Coherent memory +USE_COHERENT_MEM := 1 + +# Enable new version of image loading +LOAD_IMAGE_V2 := 1 + +# Platform build flags +# -------------------- + +# BL33 images are in AArch64 by default +RPI3_BL33_IN_AARCH32 := 0 + +# BL32 location +RPI3_BL32_RAM_LOCATION := tdram +ifeq (${RPI3_BL32_RAM_LOCATION}, tsram) + RPI3_BL32_RAM_LOCATION_ID = SEC_SRAM_ID +else ifeq (${RPI3_BL32_RAM_LOCATION}, tdram) + RPI3_BL32_RAM_LOCATION_ID = SEC_DRAM_ID +else + $(error "Unsupported RPI3_BL32_RAM_LOCATION value") +endif + +# Process platform flags +# ---------------------- + +$(eval $(call add_define,RPI3_BL32_RAM_LOCATION_ID)) +$(eval $(call add_define,RPI3_BL33_IN_AARCH32)) + +# Verify build config +# ------------------- + +ifneq (${LOAD_IMAGE_V2}, 1) + $(error Error: rpi3 needs LOAD_IMAGE_V2=1) +endif + +ifeq (${ARCH},aarch32) + $(error Error: AArch32 not supported on rpi3) +endif diff --git a/plat/rpi3/rpi3_bl1_setup.c b/plat/rpi3/rpi3_bl1_setup.c new file mode 100644 index 00000000..11c0f4af --- /dev/null +++ b/plat/rpi3/rpi3_bl1_setup.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <arch_helpers.h> +#include <bl_common.h> +#include <console.h> +#include <platform_def.h> +#include <xlat_mmu_helpers.h> +#include <xlat_tables_defs.h> + +#include "../../bl1/bl1_private.h" +#include "rpi3_private.h" + +/* Data structure which holds the extents of the trusted SRAM for BL1 */ +static meminfo_t bl1_tzram_layout; + +meminfo_t *bl1_plat_sec_mem_layout(void) +{ + return &bl1_tzram_layout; +} + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ +void bl1_early_platform_setup(void) +{ + /* Initialize the console to provide early debug support */ + console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ, + PLAT_RPI3_UART_BAUDRATE); + + /* Allow BL1 to see the whole Trusted RAM */ + bl1_tzram_layout.total_base = BL_RAM_BASE; + bl1_tzram_layout.total_size = BL_RAM_SIZE; +} + +/****************************************************************************** + * Perform the very early platform specific architecture setup. This only + * does basic initialization. Later architectural setup (bl1_arch_setup()) + * does not do anything platform specific. + *****************************************************************************/ +void bl1_plat_arch_setup(void) +{ + rpi3_setup_page_tables(bl1_tzram_layout.total_base, + bl1_tzram_layout.total_size, + BL_CODE_BASE, BL1_CODE_END, + BL1_RO_DATA_BASE, BL1_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END +#endif + ); + + enable_mmu_el3(0); +} + +void bl1_platform_setup(void) +{ + /* Initialise the IO layer and register platform IO devices */ + plat_rpi3_io_setup(); +} diff --git a/plat/rpi3/rpi3_bl2_setup.c b/plat/rpi3/rpi3_bl2_setup.c new file mode 100644 index 00000000..1fd822e9 --- /dev/null +++ b/plat/rpi3/rpi3_bl2_setup.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <bl_common.h> +#include <console.h> +#include <debug.h> +#include <desc_image_load.h> +#include <platform_def.h> +#include <xlat_mmu_helpers.h> +#include <xlat_tables_defs.h> + +#include "rpi3_private.h" + +/* Data structure which holds the extents of the trusted SRAM for BL2 */ +static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE); + +/******************************************************************************* + * BL1 has passed the extents of the trusted SRAM that should be visible to BL2 + * in x0. This memory layout is sitting at the base of the free trusted SRAM. + * Copy it to a safe location before its reclaimed by later BL2 functionality. + ******************************************************************************/ +void bl2_early_platform_setup(meminfo_t *mem_layout) +{ + /* Initialize the console to provide early debug support */ + console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ, + PLAT_RPI3_UART_BAUDRATE); + + /* Setup the BL2 memory layout */ + bl2_tzram_layout = *mem_layout; + + plat_rpi3_io_setup(); +} + +void bl2_platform_setup(void) +{ + /* + * This is where a TrustZone address space controller and other + * security related peripherals, would be configured. + */ +} + +/******************************************************************************* + * Perform the very early platform specific architectural setup here. + ******************************************************************************/ +void bl2_plat_arch_setup(void) +{ + rpi3_setup_page_tables(bl2_tzram_layout.total_base, + bl2_tzram_layout.total_size, + BL_CODE_BASE, BL_CODE_END, + BL_RO_DATA_BASE, BL_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END +#endif + ); + + enable_mmu_el1(0); +} + +/******************************************************************************* + * This function can be used by the platforms to update/use image + * information for given `image_id`. + ******************************************************************************/ +int bl2_plat_handle_post_image_load(unsigned int image_id) +{ + int err = 0; + bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); + + assert(bl_mem_params != NULL); + + switch (image_id) { + case BL32_IMAGE_ID: + bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl32_entry(); + break; + + case BL33_IMAGE_ID: + /* BL33 expects to receive the primary CPU MPID (through r0) */ + bl_mem_params->ep_info.args.arg0 = 0xffff & read_mpidr(); + bl_mem_params->ep_info.spsr = rpi3_get_spsr_for_bl33_entry(); + break; + + } + + return err; +} diff --git a/plat/rpi3/rpi3_bl31_setup.c b/plat/rpi3/rpi3_bl31_setup.c new file mode 100644 index 00000000..39133564 --- /dev/null +++ b/plat/rpi3/rpi3_bl31_setup.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <bl_common.h> +#include <console.h> +#include <platform.h> +#include <platform_def.h> +#include <xlat_mmu_helpers.h> +#include <xlat_tables_defs.h> + +#include "rpi3_private.h" + +#define BL31_END (uintptr_t)(&__BL31_END__) + +/* + * Placeholder variables for copying the arguments that have been passed to + * BL31 from BL2. + */ +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +/******************************************************************************* + * Return a pointer to the 'entry_point_info' structure of the next image for + * the security state specified. BL33 corresponds to the non-secure image type + * while BL32 corresponds to the secure image type. A NULL pointer is returned + * if the image does not exist. + ******************************************************************************/ +entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + entry_point_info_t *next_image_info; + + assert(sec_state_is_valid(type) != 0); + + next_image_info = (type == NON_SECURE) + ? &bl33_image_ep_info : &bl32_image_ep_info; + + /* None of the images can have 0x0 as the entrypoint. */ + if (next_image_info->pc) { + return next_image_info; + } else { + return NULL; + } +} + +/******************************************************************************* + * Perform any BL31 early platform setup. Here is an opportunity to copy + * parameters passed by the calling EL (S-EL1 in BL2 & S-EL3 in BL1) before + * they are lost (potentially). This needs to be done before the MMU is + * initialized so that the memory layout can be used while creating page + * tables. BL2 has flushed this information to memory, so we are guaranteed + * to pick up good data. + ******************************************************************************/ +void bl31_early_platform_setup(void *from_bl2, + void *plat_params_from_bl2) +{ + /* Initialize the console to provide early debug support */ + console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ, + PLAT_RPI3_UART_BAUDRATE); + +#if RESET_TO_BL31 + + /* There are no parameters from BL2 if BL31 is a reset vector */ + assert(from_bl2 == NULL); + assert(plat_params_from_bl2 == NULL); + +#ifdef BL32_BASE + /* Populate entry point information for BL32 */ + SET_PARAM_HEAD(&bl32_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + SET_SECURITY_STATE(bl32_image_ep_info.h.attr, SECURE); + bl32_image_ep_info.pc = BL32_BASE; + bl32_image_ep_info.spsr = rpi3_get_spsr_for_bl32_entry(); +#endif /* BL32_BASE */ + + /* Populate entry point information for BL33 */ + SET_PARAM_HEAD(&bl33_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + /* + * Tell BL31 where the non-trusted software image + * is located and the entry state information + */ + bl33_image_ep_info.pc = plat_get_ns_image_entrypoint(); + + bl33_image_ep_info.spsr = rpi3_get_spsr_for_bl33_entry(); + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); + +#else /* RESET_TO_BL31 */ + + /* + * In debug builds, we pass a special value in 'plat_params_from_bl2' + * to verify platform parameters from BL2 to BL31. + * In release builds, it's not used. + */ + assert(((uintptr_t)plat_params_from_bl2) == RPI3_BL31_PLAT_PARAM_VAL); + + /* + * Check params passed from BL2 should not be NULL, + */ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + + assert(params_from_bl2 != NULL); + assert(params_from_bl2->h.type == PARAM_BL_PARAMS); + assert(params_from_bl2->h.version >= VERSION_2); + + bl_params_node_t *bl_params = params_from_bl2->head; + + /* + * Copy BL33 and BL32 (if present), entry point information. + * They are stored in Secure RAM, in BL2's address space. + */ + while (bl_params) { + if (bl_params->image_id == BL32_IMAGE_ID) { + bl32_image_ep_info = *bl_params->ep_info; + } + + if (bl_params->image_id == BL33_IMAGE_ID) { + bl33_image_ep_info = *bl_params->ep_info; + } + + bl_params = bl_params->next_params_info; + } + + if (bl33_image_ep_info.pc == 0) { + panic(); + } + +#endif /* RESET_TO_BL31 */ +} + +void bl31_plat_arch_setup(void) +{ + rpi3_setup_page_tables(BL31_BASE, BL31_END - BL31_BASE, + BL_CODE_BASE, BL_CODE_END, + BL_RO_DATA_BASE, BL_RO_DATA_END +#if USE_COHERENT_MEM + , BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END +#endif + ); + + enable_mmu_el3(0); +} + +void bl31_platform_setup(void) +{ +#if RESET_TO_BL31 + /* + * Do initial security configuration to allow DRAM/device access + * (if earlier BL has not already done so). + */ +#endif /* RESET_TO_BL31 */ + + return; +} + +void bl31_plat_runtime_setup(void) +{ + /* Initialize the runtime console */ + console_init(PLAT_RPI3_UART_BASE, PLAT_RPI3_UART_CLK_IN_HZ, + PLAT_RPI3_UART_BAUDRATE); +} diff --git a/plat/rpi3/rpi3_common.c b/plat/rpi3/rpi3_common.c new file mode 100644 index 00000000..97dce091 --- /dev/null +++ b/plat/rpi3/rpi3_common.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <bl_common.h> +#include <debug.h> +#include <interrupt_mgmt.h> +#include <platform_def.h> +#include <xlat_tables_v2.h> + +#include "rpi3_hw.h" +#include "rpi3_private.h" + +#define MAP_DEVICE0 MAP_REGION_FLAT(DEVICE0_BASE, \ + DEVICE0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_SHARED_RAM MAP_REGION_FLAT(SHARED_RAM_BASE, \ + SHARED_RAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define MAP_NS_DRAM0 MAP_REGION_FLAT(NS_DRAM0_BASE, NS_DRAM0_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#define MAP_FIP MAP_REGION_FLAT(PLAT_RPI3_FIP_BASE, \ + PLAT_RPI3_FIP_MAX_SIZE, \ + MT_MEMORY | MT_RO | MT_NS) + +#define MAP_BL32_MEM MAP_REGION_FLAT(BL32_MEM_BASE, BL32_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * Table of regions for various BL stages to map using the MMU. + */ +#ifdef IMAGE_BL1 +static const mmap_region_t plat_rpi3_mmap[] = { + MAP_SHARED_RAM, + MAP_DEVICE0, + MAP_FIP, + {0} +}; +#endif + +#ifdef IMAGE_BL2 +static const mmap_region_t plat_rpi3_mmap[] = { + MAP_SHARED_RAM, + MAP_DEVICE0, + MAP_FIP, + MAP_NS_DRAM0, +#ifdef BL32_BASE + MAP_BL32_MEM, +#endif + {0} +}; +#endif + +#ifdef IMAGE_BL31 +static const mmap_region_t plat_rpi3_mmap[] = { + MAP_SHARED_RAM, + MAP_DEVICE0, +#ifdef BL32_BASE + MAP_BL32_MEM, +#endif + {0} +}; +#endif + +/******************************************************************************* + * Function that sets up the translation tables. + ******************************************************************************/ +void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size, + uintptr_t code_start, uintptr_t code_limit, + uintptr_t rodata_start, uintptr_t rodata_limit +#if USE_COHERENT_MEM + , uintptr_t coh_start, uintptr_t coh_limit +#endif + ) +{ + /* + * Map the Trusted SRAM with appropriate memory attributes. + * Subsequent mappings will adjust the attributes for specific regions. + */ + VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n", + (void *) total_base, (void *) (total_base + total_size)); + mmap_add_region(total_base, total_base, + total_size, + MT_MEMORY | MT_RW | MT_SECURE); + + /* Re-map the code section */ + VERBOSE("Code region: %p - %p\n", + (void *) code_start, (void *) code_limit); + mmap_add_region(code_start, code_start, + code_limit - code_start, + MT_CODE | MT_SECURE); + + /* Re-map the read-only data section */ + VERBOSE("Read-only data region: %p - %p\n", + (void *) rodata_start, (void *) rodata_limit); + mmap_add_region(rodata_start, rodata_start, + rodata_limit - rodata_start, + MT_RO_DATA | MT_SECURE); + +#if USE_COHERENT_MEM + /* Re-map the coherent memory region */ + VERBOSE("Coherent region: %p - %p\n", + (void *) coh_start, (void *) coh_limit); + mmap_add_region(coh_start, coh_start, + coh_limit - coh_start, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + + mmap_add(plat_rpi3_mmap); + + init_xlat_tables(); +} + +/******************************************************************************* + * Return entrypoint of BL33. + ******************************************************************************/ +uintptr_t plat_get_ns_image_entrypoint(void) +{ +#ifdef PRELOADED_BL33_BASE + return PRELOADED_BL33_BASE; +#else + return PLAT_RPI3_NS_IMAGE_OFFSET; +#endif +} + +/******************************************************************************* + * Gets SPSR for BL32 entry + ******************************************************************************/ +uint32_t rpi3_get_spsr_for_bl32_entry(void) +{ + /* + * The Secure Payload Dispatcher service is responsible for + * setting the SPSR prior to entry into the BL32 image. + */ + return 0; +} + +/******************************************************************************* + * Gets SPSR for BL33 entry + ******************************************************************************/ +uint32_t rpi3_get_spsr_for_bl33_entry(void) +{ +#if RPI3_BL33_IN_AARCH32 + INFO("BL33 will boot in Non-secure AArch32 Hypervisor mode\n"); + return SPSR_MODE32(MODE32_hyp, SPSR_T_ARM, SPSR_E_LITTLE, + DISABLE_ALL_EXCEPTIONS); +#else + return SPSR_64(MODE_EL2, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); +#endif +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} + +uint32_t plat_ic_get_pending_interrupt_type(void) +{ + return INTR_TYPE_INVAL; +} diff --git a/plat/rpi3/rpi3_hw.h b/plat/rpi3/rpi3_hw.h new file mode 100644 index 00000000..70272e00 --- /dev/null +++ b/plat/rpi3/rpi3_hw.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __RPI3_HW__ +#define __RPI3_HW__ + +#include <utils_def.h> + +/* + * Peripherals + */ + +#define RPI3_IO_BASE ULL(0x3F000000) +#define RPI3_IO_SIZE ULL(0x01000000) + +/* + * Serial port (called 'Mini UART' in the BCM docucmentation). + */ +#define RPI3_IO_MINI_UART_OFFSET ULL(0x00215040) +#define RPI3_MINI_UART_BASE (RPI3_IO_BASE + RPI3_IO_MINI_UART_OFFSET) +#define RPI3_MINI_UART_CLK_IN_HZ ULL(500000000) + +/* + * Power management, reset controller, watchdog. + */ +#define RPI3_IO_PM_OFFSET ULL(0x00100000) +#define RPI3_PM_BASE (RPI3_IO_BASE + RPI3_IO_PM_OFFSET) +/* Registers on top of RPI3_PM_BASE. */ +#define RPI3_PM_RSTC_OFFSET ULL(0x0000001C) +#define RPI3_PM_WDOG_OFFSET ULL(0x00000024) +/* Watchdog constants */ +#define RPI3_PM_PASSWORD ULL(0x5A000000) +#define RPI3_PM_RSTC_WRCFG_MASK ULL(0x00000030) +#define RPI3_PM_RSTC_WRCFG_FULL_RESET ULL(0x00000020) + +/* + * Local interrupt controller + */ +#define RPI3_INTC_BASE_ADDRESS ULL(0x40000000) +/* Registers on top of RPI3_INTC_BASE_ADDRESS */ +#define RPI3_INTC_CONTROL_OFFSET ULL(0x00000000) +#define RPI3_INTC_PRESCALER_OFFSET ULL(0x00000008) +#define RPI3_INTC_MBOX_CONTROL_OFFSET ULL(0x00000050) +#define RPI3_INTC_MBOX_CONTROL_SLOT3_FIQ ULL(0x00000080) +#define RPI3_INTC_PENDING_FIQ_OFFSET ULL(0x00000070) +#define RPI3_INTC_PENDING_FIQ_MBOX3 ULL(0x00000080) + +#endif /* __RPI3_HW__ */ diff --git a/plat/rpi3/rpi3_image_load.c b/plat/rpi3/rpi3_image_load.c new file mode 100644 index 00000000..fad9e4f3 --- /dev/null +++ b/plat/rpi3/rpi3_image_load.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <bl_common.h> +#include <desc_image_load.h> +#include <platform.h> +#include <platform_def.h> + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void plat_flush_next_bl_params(void) +{ + flush_bl_params_desc(); +} + +/******************************************************************************* + * This function returns the list of loadable images. + ******************************************************************************/ +bl_load_info_t *plat_get_bl_image_load_info(void) +{ + return get_bl_load_info_from_mem_params_desc(); +} + +/******************************************************************************* + * This function returns the list of executable images. + ******************************************************************************/ +bl_params_t *plat_get_next_bl_params(void) +{ + return get_next_bl_params_from_mem_params_desc(); +} diff --git a/plat/rpi3/rpi3_io_storage.c b/plat/rpi3/rpi3_io_storage.c new file mode 100644 index 00000000..7ac45ef6 --- /dev/null +++ b/plat/rpi3/rpi3_io_storage.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <assert.h> +#include <bl_common.h> +#include <debug.h> +#include <firmware_image_package.h> +#include <io_driver.h> +#include <io_fip.h> +#include <io_memmap.h> +#include <platform_def.h> +#include <string.h> + +/* Semihosting filenames */ +#define BL2_IMAGE_NAME "bl2.bin" +#define BL31_IMAGE_NAME "bl31.bin" +#define BL32_IMAGE_NAME "bl32.bin" +#define BL33_IMAGE_NAME "bl33.bin" + +#if TRUSTED_BOARD_BOOT +#define BL2_CERT_NAME "bl2.crt" +#define TRUSTED_KEY_CERT_NAME "trusted_key.crt" +#define BL31_KEY_CERT_NAME "bl31_key.crt" +#define BL32_KEY_CERT_NAME "bl32_key.crt" +#define BL33_KEY_CERT_NAME "bl33_key.crt" +#define BL31_CERT_NAME "bl31.crt" +#define BL32_CERT_NAME "bl32.crt" +#define BL33_CERT_NAME "bl33.crt" +#endif /* TRUSTED_BOARD_BOOT */ + +/* IO devices */ +static const io_dev_connector_t *fip_dev_con; +static uintptr_t fip_dev_handle; +static const io_dev_connector_t *memmap_dev_con; +static uintptr_t memmap_dev_handle; + +static const io_block_spec_t fip_block_spec = { + .offset = PLAT_RPI3_FIP_BASE, + .length = PLAT_RPI3_FIP_MAX_SIZE +}; + +static const io_uuid_spec_t bl2_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, +}; + +static const io_uuid_spec_t bl31_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, +}; + +static const io_uuid_spec_t bl32_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32, +}; + +static const io_uuid_spec_t bl33_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, +}; + +#if TRUSTED_BOARD_BOOT +static const io_uuid_spec_t bl2_cert_uuid_spec = { + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2_CERT, +}; + +static const io_uuid_spec_t trusted_key_cert_uuid_spec = { + .uuid = UUID_TRUSTED_KEY_CERT, +}; + +static const io_uuid_spec_t bl31_key_cert_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_KEY_CERT, +}; + +static const io_uuid_spec_t bl32_key_cert_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_KEY_CERT, +}; + +static const io_uuid_spec_t bl33_key_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_KEY_CERT, +}; + +static const io_uuid_spec_t bl31_cert_uuid_spec = { + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31_CERT, +}; + +static const io_uuid_spec_t bl32_cert_uuid_spec = { + .uuid = UUID_SECURE_PAYLOAD_BL32_CERT, +}; + +static const io_uuid_spec_t bl33_cert_uuid_spec = { + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33_CERT, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static int open_fip(const uintptr_t spec); +static int open_memmap(const uintptr_t spec); + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +/* By default, load images from the FIP */ +static const struct plat_io_policy policies[] = { + [FIP_IMAGE_ID] = { + &memmap_dev_handle, + (uintptr_t)&fip_block_spec, + open_memmap + }, + [BL2_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_uuid_spec, + open_fip + }, + [BL31_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_uuid_spec, + open_fip + }, + [BL32_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_uuid_spec, + open_fip + }, + [BL33_IMAGE_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_uuid_spec, + open_fip + }, +#if TRUSTED_BOARD_BOOT + [BL2_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl2_cert_uuid_spec, + open_fip + }, + [TRUSTED_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&trusted_key_cert_uuid_spec, + open_fip + }, + [BL31_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_key_cert_uuid_spec, + open_fip + }, + [BL32_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_key_cert_uuid_spec, + open_fip + }, + [BL33_KEY_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_key_cert_uuid_spec, + open_fip + }, + [BL31_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl31_cert_uuid_spec, + open_fip + }, + [BL32_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl32_cert_uuid_spec, + open_fip + }, + [BL33_CERT_ID] = { + &fip_dev_handle, + (uintptr_t)&bl33_cert_uuid_spec, + open_fip + }, +#endif /* TRUSTED_BOARD_BOOT */ +}; + +static int open_fip(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + /* See if a Firmware Image Package is available */ + result = io_dev_init(fip_dev_handle, (uintptr_t)FIP_IMAGE_ID); + if (result == 0) { + result = io_open(fip_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using FIP\n"); + io_close(local_image_handle); + } + } + return result; +} + +static int open_memmap(const uintptr_t spec) +{ + int result; + uintptr_t local_image_handle; + + result = io_dev_init(memmap_dev_handle, (uintptr_t)NULL); + if (result == 0) { + result = io_open(memmap_dev_handle, spec, &local_image_handle); + if (result == 0) { + VERBOSE("Using Memmap\n"); + io_close(local_image_handle); + } + } + return result; +} + +void plat_rpi3_io_setup(void) +{ + int io_result; + + io_result = register_io_dev_fip(&fip_dev_con); + assert(io_result == 0); + + io_result = register_io_dev_memmap(&memmap_dev_con); + assert(io_result == 0); + + /* Open connections to devices and cache the handles */ + io_result = io_dev_open(fip_dev_con, (uintptr_t)NULL, + &fip_dev_handle); + assert(io_result == 0); + + io_result = io_dev_open(memmap_dev_con, (uintptr_t)NULL, + &memmap_dev_handle); + assert(io_result == 0); + + /* Ignore improbable errors in release builds */ + (void)io_result; +} + +/* + * Return an IO device handle and specification which can be used to access + * an image. Use this to enforce platform load policy + */ +int plat_get_image_source(unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec) +{ + int result; + const struct plat_io_policy *policy; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + result = policy->check(policy->image_spec); + if (result == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } + + return result; +} diff --git a/plat/rpi3/rpi3_pm.c b/plat/rpi3/rpi3_pm.c new file mode 100644 index 00000000..1d067fb1 --- /dev/null +++ b/plat/rpi3/rpi3_pm.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch_helpers.h> +#include <assert.h> +#include <console.h> +#include <debug.h> +#include <mmio.h> +#include <platform_def.h> +#include <platform.h> +#include <psci.h> + +#include "rpi3_hw.h" + +/* + * The secure entry point to be used on warm reset. + */ +static uintptr_t secure_entrypoint; + +/* Make composite power state parameter till power level 0 */ +#if PSCI_EXTENDED_STATE_ID + +#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) + +#else + +#define rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | \ + ((pwr_lvl) << PSTATE_PWR_LVL_SHIFT) | \ + ((type) << PSTATE_TYPE_SHIFT)) + +#endif /* PSCI_EXTENDED_STATE_ID */ + +#define rpi3_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl1_state) << PLAT_LOCAL_PSTATE_WIDTH) | \ + rpi3_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) + +/* + * The table storing the valid idle power states. Ensure that the + * array entries are populated in ascending order of state-id to + * enable us to use binary search during power state validation. + * The table must be terminated by a NULL entry. + */ +static const unsigned int rpi3_pm_idle_states[] = { + /* State-id - 0x01 */ + rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_RET, + MPIDR_AFFLVL0, PSTATE_TYPE_STANDBY), + /* State-id - 0x02 */ + rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_RUN, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL0, PSTATE_TYPE_POWERDOWN), + /* State-id - 0x22 */ + rpi3_make_pwrstate_lvl1(PLAT_LOCAL_STATE_OFF, PLAT_LOCAL_STATE_OFF, + MPIDR_AFFLVL1, PSTATE_TYPE_POWERDOWN), + 0, +}; + +/******************************************************************************* + * Platform handler called to check the validity of the power state + * parameter. The power state parameter has to be a composite power state. + ******************************************************************************/ +static int rpi3_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + unsigned int state_id; + int i; + + assert(req_state != 0); + + /* + * Currently we are using a linear search for finding the matching + * entry in the idle power state array. This can be made a binary + * search if the number of entries justify the additional complexity. + */ + for (i = 0; rpi3_pm_idle_states[i] != 0; i++) { + if (power_state == rpi3_pm_idle_states[i]) { + break; + } + } + + /* Return error if entry not found in the idle state array */ + if (!rpi3_pm_idle_states[i]) { + return PSCI_E_INVALID_PARAMS; + } + + i = 0; + state_id = psci_get_pstate_id(power_state); + + /* Parse the State ID and populate the state info parameter */ + while (state_id) { + req_state->pwr_domain_state[i++] = state_id & + PLAT_LOCAL_PSTATE_MASK; + state_id >>= PLAT_LOCAL_PSTATE_WIDTH; + } + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Platform handler called when a CPU is about to enter standby. + ******************************************************************************/ +static void rpi3_cpu_standby(plat_local_state_t cpu_state) +{ + assert(cpu_state == PLAT_LOCAL_STATE_RET); + + /* + * Enter standby state. + * dsb is good practice before using wfi to enter low power states + */ + dsb(); + wfi(); +} + +/******************************************************************************* + * Platform handler called when a power domain is about to be turned on. The + * mpidr determines the CPU to be turned on. + ******************************************************************************/ +static int rpi3_pwr_domain_on(u_register_t mpidr) +{ + int rc = PSCI_E_SUCCESS; + unsigned int pos = plat_core_pos_by_mpidr(mpidr); + uint64_t *hold_base = (uint64_t *)PLAT_RPI3_TM_HOLD_BASE; + + assert(pos < PLATFORM_CORE_COUNT); + + hold_base[pos] = PLAT_RPI3_TM_HOLD_STATE_GO; + + /* Make sure that the write has completed */ + dsb(); + isb(); + + sev(); + + return rc; +} + +/******************************************************************************* + * Platform handler called when a power domain has just been powered on after + * being turned off earlier. The target_state encodes the low power state that + * each level has woken up from. + ******************************************************************************/ +void rpi3_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + assert(target_state->pwr_domain_state[MPIDR_AFFLVL0] == + PLAT_LOCAL_STATE_OFF); +} + +/******************************************************************************* + * Platform handler to reboot the system + ******************************************************************************/ +#define RESET_TIMEOUT 10 + +static void __dead2 rpi3_system_reset(void) +{ + /* Setup watchdog for reset */ + + static const uintptr_t base = RPI3_PM_BASE; + uint32_t rstc; + + INFO("rpi3: PSCI System Reset: invoking watchdog reset\n"); + + console_flush(); + + rstc = mmio_read_32(base + RPI3_PM_RSTC_OFFSET); + rstc &= ~RPI3_PM_RSTC_WRCFG_MASK; + rstc |= RPI3_PM_RSTC_WRCFG_FULL_RESET; + + dmbst(); + + /* + * Watchdog timer = Timer clock / 16 + * Password (31:16) | Value (11:0) + */ + mmio_write_32(base + RPI3_PM_WDOG_OFFSET, + RPI3_PM_PASSWORD | RESET_TIMEOUT); + mmio_write_32(base + RPI3_PM_RSTC_OFFSET, + RPI3_PM_PASSWORD | rstc); + + for (;;) { + wfi(); + } +} + +/******************************************************************************* + * Platform handlers and setup function. + ******************************************************************************/ +static const plat_psci_ops_t plat_rpi3_psci_pm_ops = { + .cpu_standby = rpi3_cpu_standby, + .pwr_domain_on = rpi3_pwr_domain_on, + .pwr_domain_on_finish = rpi3_pwr_domain_on_finish, + .system_reset = rpi3_system_reset, + .validate_power_state = rpi3_validate_power_state, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const plat_psci_ops_t **psci_ops) +{ + uintptr_t *mailbox = (void *)PLAT_RPI3_TRUSTED_MAILBOX_BASE; + + *mailbox = sec_entrypoint; + secure_entrypoint = (uintptr_t)sec_entrypoint; + *psci_ops = &plat_rpi3_psci_pm_ops; + + return 0; +} diff --git a/plat/rpi3/rpi3_private.h b/plat/rpi3/rpi3_private.h new file mode 100644 index 00000000..01c4055f --- /dev/null +++ b/plat/rpi3/rpi3_private.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __RPI3_PRIVATE_H__ +#define __RPI3_PRIVATE_H__ + +#include <sys/types.h> + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ + +/* Utility functions */ +void rpi3_setup_page_tables(uintptr_t total_base, size_t total_size, + uintptr_t code_start, uintptr_t code_limit, + uintptr_t rodata_start, uintptr_t rodata_limit +#if USE_COHERENT_MEM + , uintptr_t coh_start, uintptr_t coh_limit +#endif + ); + +/* Optional functions required in the Raspberry Pi 3 port */ +unsigned int plat_rpi3_calc_core_pos(u_register_t mpidr); + +/* BL2 utility functions */ +uint32_t rpi3_get_spsr_for_bl32_entry(void); +uint32_t rpi3_get_spsr_for_bl33_entry(void); + +/* IO storage utility functions */ +void plat_rpi3_io_setup(void); + +#endif /*__RPI3_PRIVATE_H__ */ diff --git a/plat/rpi3/rpi3_topology.c b/plat/rpi3/rpi3_topology.c new file mode 100644 index 00000000..0e03ec32 --- /dev/null +++ b/plat/rpi3/rpi3_topology.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include <arch.h> +#include <platform_def.h> +#include <sys/types.h> + +#include "rpi3_private.h" + +/* The power domain tree descriptor */ +static unsigned char power_domain_tree_desc[] = { + /* Number of root nodes */ + PLATFORM_CLUSTER_COUNT, + /* Number of children for the first node */ + PLATFORM_CLUSTER0_CORE_COUNT, +}; + +/******************************************************************************* + * This function returns the ARM default topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return power_domain_tree_desc; +} + +/******************************************************************************* + * This function implements a part of the critical interface between the psci + * generic layer and the platform that allows the former to query the platform + * to convert an MPIDR to a unique linear index. An error code (-1) is returned + * in case the MPIDR is invalid. + ******************************************************************************/ +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + unsigned int cluster_id, cpu_id; + + mpidr &= MPIDR_AFFINITY_MASK; + if (mpidr & ~(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK)) { + return -1; + } + + cluster_id = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cpu_id = (mpidr >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK; + + if (cluster_id >= PLATFORM_CLUSTER_COUNT) { + return -1; + } + + if (cpu_id >= PLATFORM_MAX_CPUS_PER_CLUSTER) { + return -1; + } + + return plat_rpi3_calc_core_pos(mpidr); +} diff --git a/plat/socionext/uniphier/platform.mk b/plat/socionext/uniphier/platform.mk index c91abb6b..3c78054b 100644 --- a/plat/socionext/uniphier/platform.mk +++ b/plat/socionext/uniphier/platform.mk @@ -10,6 +10,7 @@ override ERROR_DEPRECATED := 1 override LOAD_IMAGE_V2 := 1 override USE_COHERENT_MEM := 1 override USE_TBBR_DEFS := 1 +override ENABLE_SVE_FOR_NS := 0 # Cortex-A53 revision r0p4-51rel0 # needed for LD20, unneeded for LD11, PXs3 (no ACE) diff --git a/plat/xilinx/zynqmp/platform.mk b/plat/xilinx/zynqmp/platform.mk index ca87cc8f..cb3b4421 100644 --- a/plat/xilinx/zynqmp/platform.mk +++ b/plat/xilinx/zynqmp/platform.mk @@ -11,6 +11,9 @@ A53_DISABLE_NON_TEMPORAL_HINT := 0 SEPARATE_CODE_AND_RODATA := 1 override RESET_TO_BL31 := 1 +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + ifdef ZYNQMP_ATF_MEM_BASE $(eval $(call add_define,ZYNQMP_ATF_MEM_BASE)) diff --git a/services/std_svc/sdei/sdei_main.c b/services/std_svc/sdei/sdei_main.c index 2f08c8ba..1969307f 100644 --- a/services/std_svc/sdei/sdei_main.c +++ b/services/std_svc/sdei/sdei_main.c @@ -795,7 +795,7 @@ static int sdei_private_reset(void) */ ret = sdei_event_unregister(map->ev_num); if ((ret == SDEI_EPEND) && (final_ret == 0)) - final_ret = ret; + final_ret = SDEI_EDENY; } return final_ret; @@ -817,7 +817,7 @@ static int sdei_shared_reset(void) */ ret = sdei_event_unregister(map->ev_num); if ((ret == SDEI_EPEND) && (final_ret == 0)) - final_ret = ret; + final_ret = SDEI_EDENY; } if (final_ret != 0) diff --git a/services/std_svc/spm/secure_partition_setup.c b/services/std_svc/spm/secure_partition_setup.c index 67301608..c1f0edf6 100644 --- a/services/std_svc/spm/secure_partition_setup.c +++ b/services/std_svc/spm/secure_partition_setup.c @@ -6,7 +6,6 @@ #include <arch.h> #include <arch_helpers.h> -#include <arm_spm_def.h> #include <assert.h> #include <common_def.h> #include <context.h> @@ -22,12 +21,17 @@ #include "spm_private.h" #include "spm_shim_private.h" +/* Place translation tables by default along with the ones used by BL31. */ +#ifndef PLAT_SP_IMAGE_XLAT_SECTION_NAME +#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "xlat_table" +#endif + /* Allocate and initialise the translation context for the secure partition. */ REGISTER_XLAT_CONTEXT2(secure_partition, PLAT_SP_IMAGE_MMAP_REGIONS, PLAT_SP_IMAGE_MAX_XLAT_TABLES, PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE, - EL1_EL0_REGIME); + EL1_EL0_REGIME, PLAT_SP_IMAGE_XLAT_SECTION_NAME); /* Export a handle on the secure partition translation context */ xlat_ctx_t *secure_partition_xlat_ctx_handle = &secure_partition_xlat_ctx; @@ -92,20 +96,20 @@ void secure_partition_setup(void) /* Get max granularity supported by the platform. */ - u_register_t id_aa64prf0_el1 = read_id_aa64pfr0_el1(); + u_register_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1(); int tgran64_supported = - ((id_aa64prf0_el1 >> ID_AA64MMFR0_EL1_TGRAN64_SHIFT) & + ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN64_SHIFT) & ID_AA64MMFR0_EL1_TGRAN64_MASK) == ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED; int tgran16_supported = - ((id_aa64prf0_el1 >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT) & + ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT) & ID_AA64MMFR0_EL1_TGRAN16_MASK) == ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED; int tgran4_supported = - ((id_aa64prf0_el1 >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT) & + ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT) & ID_AA64MMFR0_EL1_TGRAN4_MASK) == ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED; @@ -121,7 +125,7 @@ void secure_partition_setup(void) } VERBOSE("Max translation granule supported: %lu KiB\n", - max_granule_size); + max_granule_size / 1024); uintptr_t max_granule_size_mask = max_granule_size - 1; diff --git a/services/std_svc/spm/spm_main.c b/services/std_svc/spm/spm_main.c index 1b40d81d..ae71c1df 100644 --- a/services/std_svc/spm/spm_main.c +++ b/services/std_svc/spm/spm_main.c @@ -48,7 +48,7 @@ void spm_setup_next_eret_into_sel0(cpu_context_t *secure_context) * 2. Saves the current C runtime state (callee-saved registers) on the stack * frame and saves a reference to this state. * 3. Calls el3_exit() so that the EL3 system and general purpose registers - * from the sp_ctx->cpu_ctx are used to enter the secure payload image. + * from the sp_ctx->cpu_ctx are used to enter the secure partition image. ******************************************************************************/ static uint64_t spm_synchronous_sp_entry(secure_partition_context_t *sp_ctx_ptr) { @@ -75,7 +75,7 @@ static uint64_t spm_synchronous_sp_entry(secure_partition_context_t *sp_ctx_ptr) /******************************************************************************* * This function takes a Secure partition context pointer and: - * 1. Saves the S-EL1 system register context tp sp_ctx->cpu_ctx. + * 1. Saves the S-EL1 system register context to sp_ctx->cpu_ctx. * 2. Restores the current C runtime state (callee saved registers) from the * stack frame using the reference to this state saved in * spm_secure_partition_enter(). @@ -101,7 +101,7 @@ static void __dead2 spm_synchronous_sp_exit( * This function passes control to the Secure Partition image (BL32) for the * first time on the primary cpu after a cold boot. It assumes that a valid * secure context has already been created by spm_setup() which can be directly - * used. This function performs a synchronous entry into the Secure payload. + * used. This function performs a synchronous entry into the Secure partition. * The SP passes control back to this routine through a SMC. ******************************************************************************/ int32_t spm_init(void) @@ -126,21 +126,21 @@ int32_t spm_init(void) secure_partition_setup(); /* - * Arrange for an entry into the secure payload. + * Arrange for an entry into the secure partition. */ sp_init_in_progress = 1; rc = spm_synchronous_sp_entry(&sp_ctx); assert(rc == 0); sp_init_in_progress = 0; - VERBOSE("SP_MEM_ATTRIBUTES_SET_AARCH64 availability has been revoked\n"); + VERBOSE("SP_MEMORY_ATTRIBUTES_SET_AARCH64 availability has been revoked\n"); return rc; } /******************************************************************************* - * Given a secure payload entrypoint info pointer, entry point PC & pointer to + * Given a secure partition entrypoint info pointer, entry point PC & pointer to * a context data structure, this function will initialize the SPM context and - * entry point info for the secure payload + * entry point info for the secure partition. ******************************************************************************/ void spm_init_sp_ep_state(struct entry_point_info *sp_ep_info, uint64_t pc, @@ -161,7 +161,7 @@ void spm_init_sp_ep_state(struct entry_point_info *sp_ep_info, SET_PARAM_HEAD(sp_ep_info, PARAM_EP, VERSION_1, ep_attr); sp_ep_info->pc = pc; - /* The SPM payload runs in S-EL0 */ + /* The secure partition runs in S-EL0. */ sp_ep_info->spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS); @@ -228,21 +228,21 @@ static mmap_attr_t smc_attr_to_mmap_attr(unsigned int attributes) { mmap_attr_t tf_attr = 0; - unsigned int access = (attributes & SP_MEM_ATTR_ACCESS_MASK) - >> SP_MEM_ATTR_ACCESS_SHIFT; + unsigned int access = (attributes & SP_MEMORY_ATTRIBUTES_ACCESS_MASK) + >> SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; - if (access == SP_MEM_ATTR_ACCESS_RW) { + if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RW) { tf_attr |= MT_RW | MT_USER; - } else if (access == SP_MEM_ATTR_ACCESS_RO) { + } else if (access == SP_MEMORY_ATTRIBUTES_ACCESS_RO) { tf_attr |= MT_RO | MT_USER; } else { /* Other values are reserved. */ - assert(access == SP_MEM_ATTR_ACCESS_NOACCESS); + assert(access == SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS); /* The only requirement is that there's no access from EL0 */ tf_attr |= MT_RO | MT_PRIVILEGED; } - if ((attributes & SP_MEM_ATTR_NON_EXEC) == 0) { + if ((attributes & SP_MEMORY_ATTRIBUTES_NON_EXEC) == 0) { tf_attr |= MT_EXECUTE; } else { tf_attr |= MT_EXECUTE_NEVER; @@ -263,20 +263,21 @@ static int smc_mmap_to_smc_attr(mmap_attr_t attr) if ((attr & MT_USER) == 0) { /* No access from EL0. */ - data_access = SP_MEM_ATTR_ACCESS_NOACCESS; + data_access = SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS; } else { if ((attr & MT_RW) != 0) { assert(MT_TYPE(attr) != MT_DEVICE); - data_access = SP_MEM_ATTR_ACCESS_RW; + data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RW; } else { - data_access = SP_MEM_ATTR_ACCESS_RO; + data_access = SP_MEMORY_ATTRIBUTES_ACCESS_RO; } } - smc_attr |= (data_access & SP_MEM_ATTR_ACCESS_MASK) << SP_MEM_ATTR_ACCESS_SHIFT; + smc_attr |= (data_access & SP_MEMORY_ATTRIBUTES_ACCESS_MASK) + << SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; if (attr & MT_EXECUTE_NEVER) { - smc_attr |= SP_MEM_ATTR_NON_EXEC; + smc_attr |= SP_MEMORY_ATTRIBUTES_NON_EXEC; } return smc_attr; @@ -349,7 +350,7 @@ uint64_t spm_smc_handler(uint32_t smc_fid, switch (smc_fid) { - case SPM_VERSION_AARCH32: + case SPM_VERSION_AARCH32: SMC_RET1(handle, SPM_VERSION_COMPILED); case SP_EVENT_COMPLETE_AARCH64: @@ -387,20 +388,20 @@ uint64_t spm_smc_handler(uint32_t smc_fid, /* Return to normal world */ SMC_RET1(ns_cpu_context, x1); - case SP_MEM_ATTRIBUTES_GET_AARCH64: - INFO("Received SP_MEM_ATTRIBUTES_GET_AARCH64 SMC\n"); + case SP_MEMORY_ATTRIBUTES_GET_AARCH64: + INFO("Received SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n"); if (!sp_init_in_progress) { - WARN("SP_MEM_ATTRIBUTES_GET_AARCH64 is available at boot time only\n"); + WARN("SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n"); SMC_RET1(handle, SPM_NOT_SUPPORTED); } SMC_RET1(handle, spm_memory_attributes_get_smc_handler(x1)); - case SP_MEM_ATTRIBUTES_SET_AARCH64: - INFO("Received SP_MEM_ATTRIBUTES_SET_AARCH64 SMC\n"); + case SP_MEMORY_ATTRIBUTES_SET_AARCH64: + INFO("Received SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n"); if (!sp_init_in_progress) { - WARN("SP_MEM_ATTRIBUTES_SET_AARCH64 is available at boot time only\n"); + WARN("SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n"); SMC_RET1(handle, SPM_NOT_SUPPORTED); } SMC_RET1(handle, spm_memory_attributes_set_smc_handler(x1, x2, x3)); @@ -413,12 +414,31 @@ uint64_t spm_smc_handler(uint32_t smc_fid, switch (smc_fid) { - case SP_VERSION_AARCH64: - case SP_VERSION_AARCH32: + case SP_VERSION_AARCH64: + case SP_VERSION_AARCH32: SMC_RET1(handle, SP_VERSION_COMPILED); - case SP_COMMUNICATE_AARCH32: - case SP_COMMUNICATE_AARCH64: + case MM_COMMUNICATE_AARCH32: + case MM_COMMUNICATE_AARCH64: + { + uint64_t mm_cookie = x1; + uint64_t comm_buffer_address = x2; + uint64_t comm_size_address = x3; + + /* Cookie. Reserved for future use. It must be zero. */ + if (mm_cookie != 0) { + ERROR("MM_COMMUNICATE: cookie is not zero\n"); + SMC_RET1(handle, SPM_INVALID_PARAMETER); + } + + if (comm_buffer_address == 0) { + ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n"); + SMC_RET1(handle, SPM_INVALID_PARAMETER); + } + + if (comm_size_address != 0) { + VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n"); + } /* Save the Normal world context */ cm_el1_sysregs_context_save(NON_SECURE); @@ -431,15 +451,12 @@ uint64_t spm_smc_handler(uint32_t smc_fid, cm_el1_sysregs_context_restore(SECURE); cm_set_next_eret_context(SECURE); - if (x2 != 0) { - VERBOSE("SP_COMMUNICATE_AARCH32/64: X2 is not 0 as recommended."); - } - - SMC_RET4(&sp_ctx.cpu_ctx, - smc_fid, x2, x3, plat_my_core_pos()); + SMC_RET4(&sp_ctx.cpu_ctx, smc_fid, comm_buffer_address, + comm_size_address, plat_my_core_pos()); + } - case SP_MEM_ATTRIBUTES_GET_AARCH64: - case SP_MEM_ATTRIBUTES_SET_AARCH64: + case SP_MEMORY_ATTRIBUTES_GET_AARCH64: + case SP_MEMORY_ATTRIBUTES_SET_AARCH64: /* SMC interfaces reserved for secure callers. */ SMC_RET1(handle, SPM_NOT_SUPPORTED); |