diff --git a/bl1/aarch32/bl1_exceptions.S b/bl1/aarch32/bl1_exceptions.S index f73db40..a1e32f0 100644 --- a/bl1/aarch32/bl1_exceptions.S +++ b/bl1/aarch32/bl1_exceptions.S @@ -73,6 +73,11 @@ ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)] msr spsr, r1 + /* Some BL32 stages expect lr_svc to provide the BL33 entry address */ + cps #MODE32_svc + ldr lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET] + cps #MODE32_mon + add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET ldm r8, {r0, r1, r2, r3} eret diff --git a/bl2/bl2_image_load_v2.c b/bl2/bl2_image_load_v2.c index ebbad45..f51dea8 100644 --- a/bl2/bl2_image_load_v2.c +++ b/bl2/bl2_image_load_v2.c @@ -93,8 +93,10 @@ assert(bl2_to_next_bl_params->h.version >= VERSION_2); assert(bl2_to_next_bl_params->head->ep_info); - /* Populate arg0 for the next BL image */ - bl2_to_next_bl_params->head->ep_info->args.arg0 = (u_register_t)bl2_to_next_bl_params; + /* Populate arg0 for the next BL image if not already provided */ + if (bl2_to_next_bl_params->head->ep_info->args.arg0 == (u_register_t)0) + bl2_to_next_bl_params->head->ep_info->args.arg0 = + (u_register_t)bl2_to_next_bl_params; /* Flush the parameters to be passed to next image */ plat_flush_next_bl_params(); diff --git a/bl32/optee/optee.mk b/bl32/optee/optee.mk new file mode 100644 index 0000000..462020f --- /dev/null +++ b/bl32/optee/optee.mk @@ -0,0 +1,15 @@ +# +# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# This makefile only aims at complying with ARM Trusted Firmware build process so +# that "optee" is a valid ARM Trusted Firmware AArch32 Secure Playload identifier. + +ifneq ($(ARCH),aarch32) +$(error This directory targets AArch32 support) +endif + +$(eval $(call add_define,AARCH32_SP_OPTEE)) + +$(info ARM Trusted Firmware built for OP-TEE payload support) diff --git a/include/common/ep_info.h b/include/common/ep_info.h index 3f6213f..3c2fe44 100644 --- a/include/common/ep_info.h +++ b/include/common/ep_info.h @@ -20,7 +20,8 @@ ******************************************************************************/ #define ENTRY_POINT_INFO_PC_OFFSET U(0x08) #ifdef AARCH32 -#define ENTRY_POINT_INFO_ARGS_OFFSET U(0x10) +#define ENTRY_POINT_INFO_LR_SVC_OFFSET U(0x10) +#define ENTRY_POINT_INFO_ARGS_OFFSET U(0x14) #else #define ENTRY_POINT_INFO_ARGS_OFFSET U(0x18) #endif @@ -93,6 +94,7 @@ uintptr_t pc; uint32_t spsr; #ifdef AARCH32 + uintptr_t lr_svc; aapcs32_params_t args; #else aapcs64_params_t args; @@ -108,6 +110,12 @@ __builtin_offsetof(entry_point_info_t, pc), \ assert_BL31_pc_offset_mismatch); +#ifdef AARCH32 +CASSERT(ENTRY_POINT_INFO_LR_SVC_OFFSET == + __builtin_offsetof(entry_point_info_t, lr_svc), + assert_entrypoint_lr_offset_error); +#endif + CASSERT(ENTRY_POINT_INFO_ARGS_OFFSET == \ __builtin_offsetof(entry_point_info_t, args), \ assert_BL31_args_offset_mismatch); diff --git a/lib/optee/optee_utils.c b/lib/optee/optee_utils.c index deb948c..87e52bd 100644 --- a/lib/optee/optee_utils.c +++ b/lib/optee/optee_utils.c @@ -158,9 +158,12 @@ * and BL32_EXTRA2_IMAGE_ID to load pager and paged bin. */ if (!tee_validate_header(optee_header)) { - INFO("Invalid OPTEE header, legacy mode.\n"); - /* Set legacy OPTEE runtime arch - aarch64 */ + INFO("Invalid OPTEE header, set legacy mode.\n"); +#ifdef AARCH64 header_ep->args.arg0 = MODE_RW_64; +#else + header_ep->args.arg0 = MODE_RW_32; +#endif return 0; } @@ -208,10 +211,16 @@ header_ep->args.arg2 = paged_image_info->image_size; /* Set OPTEE runtime arch - aarch32/aarch64 */ - if (optee_header->arch == 0) + if (optee_header->arch == 0) { header_ep->args.arg0 = MODE_RW_32; - else + } else { +#ifdef AARCH64 header_ep->args.arg0 = MODE_RW_64; +#else + ERROR("Cannot boot an AArch64 OP-TEE\n"); + return -1; +#endif + } return 0; } diff --git a/plat/qemu/aarch32/plat_helpers.S b/plat/qemu/aarch32/plat_helpers.S new file mode 100644 index 0000000..a9b1d8f --- /dev/null +++ b/plat/qemu/aarch32/plat_helpers.S @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl plat_my_core_pos + .globl plat_get_my_entrypoint + .globl platform_mem_init + .globl plat_qemu_calc_core_pos + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_secondary_cold_boot_setup + .globl plat_get_my_entrypoint + .globl plat_is_my_cpu_primary + + +func plat_my_core_pos + ldcopr r0, MPIDR + b plat_qemu_calc_core_pos +endfunc plat_my_core_pos + +/* + * unsigned int plat_qemu_calc_core_pos(u_register_t mpidr); + * With this function: CorePos = (ClusterId * 4) + CoreId + */ +func plat_qemu_calc_core_pos + and r1, r0, #MPIDR_CPU_MASK + and r0, r0, #MPIDR_CLUSTER_MASK + add r0, r1, r0, LSR #6 + bx lr +endfunc plat_qemu_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 + ldcopr r0, MPIDR + ldr r1, =(MPIDR_CLUSTER_MASK | MPIDR_CPU_MASK) + and r0, r1 + cmp r0, #QEMU_PRIMARY_CPU + moveq r0, #1 + movne r0, #0 + bx lr +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 r0, r0, #PLAT_QEMU_HOLD_ENTRY_SHIFT + mov_imm r2, PLAT_QEMU_HOLD_BASE + + /* Wait until we have a go */ +poll_mailbox: + ldr r1, [r2, r0] + cmp r1, #0 + beq 1f + mov_imm r0, PLAT_QEMU_TRUSTED_MAILBOX_BASE + ldr r1, [r0] + bx r1 +1: + wfe + b poll_mailbox +endfunc plat_secondary_cold_boot_setup + +func plat_get_my_entrypoint + /* TODO support warm boot */ + mov r0, #0 + bx lr +endfunc plat_get_my_entrypoint + +func platform_mem_init + bx lr +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, x1, x2 + * --------------------------------------------- + */ +func plat_crash_console_init + mov_imm r0, PLAT_QEMU_CRASH_UART_BASE + mov_imm r1, PLAT_QEMU_CRASH_UART_CLK_IN_HZ + mov_imm r2, PLAT_QEMU_CONSOLE_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 r1, PLAT_QEMU_CRASH_UART_BASE + b console_core_putc +endfunc plat_crash_console_putc + diff --git a/plat/qemu/include/platform_def.h b/plat/qemu/include/platform_def.h index 0ae28ea..3eafb43 100644 --- a/plat/qemu/include/platform_def.h +++ b/plat/qemu/include/platform_def.h @@ -16,10 +16,17 @@ #define PLATFORM_STACK_SIZE 0x1000 +#if ARM_ARCH_MAJOR == 7 +#define PLATFORM_MAX_CPUS_PER_CLUSTER 4 +#define PLATFORM_CLUSTER_COUNT 1 +#define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#define PLATFORM_CLUSTER1_CORE_COUNT 0 +#else #define PLATFORM_MAX_CPUS_PER_CLUSTER 4 #define PLATFORM_CLUSTER_COUNT 2 #define PLATFORM_CLUSTER0_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER #define PLATFORM_CLUSTER1_CORE_COUNT PLATFORM_MAX_CPUS_PER_CLUSTER +#endif #define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER0_CORE_COUNT + \ PLATFORM_CLUSTER1_CORE_COUNT) diff --git a/plat/qemu/platform.mk b/plat/qemu/platform.mk index 3d15a74..334fbe4 100644 --- a/plat/qemu/platform.mk +++ b/plat/qemu/platform.mk @@ -4,6 +4,25 @@ # SPDX-License-Identifier: BSD-3-Clause # +ifeq (${ARM_ARCH_MAJOR},7) +# ARMv7 Qemu support in trusted firmware expects the Cortex-A15 model. +# Qemu Cortex-A15 model does not implement the virtualization extension. +# For this reason, we cannot set ARM_CORTEX_A15=yes and must define all +# the ARMv7 build directives. +MARCH32_DIRECTIVE := -mcpu=cortex-a15 +$(eval $(call add_define,ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING)) +$(eval $(call add_define,ARMV7_SUPPORTS_GENERIC_TIMER)) +# Qemu expects a BL32 boot stage. +NEED_BL32 := yes +endif # ARMv7 + +ifeq (${SPD},opteed) +add-lib-optee := yes +endif +ifeq ($(AARCH32_SP),optee) +add-lib-optee := yes +endif + include lib/libfdt/libfdt.mk # Enable new version of image loading on QEMU platforms @@ -15,10 +34,13 @@ PLAT_PATH := plat/qemu/ PLAT_INCLUDES := -Iinclude/plat/arm/common/ \ - -Iinclude/plat/arm/common/aarch64/ \ -Iplat/qemu/include \ -Iinclude/common/tbbr +ifeq (${ARM_ARCH_MAJOR},8) +PLAT_INCLUDES += -Iinclude/plat/arm/common/${ARCH} +endif + # Use translation tables library v2 by default ARM_XLAT_TABLES_LIB_V1 := 0 $(eval $(call assert_boolean,ARM_XLAT_TABLES_LIB_V1)) @@ -26,11 +48,11 @@ PLAT_BL_COMMON_SOURCES := plat/qemu/qemu_common.c \ - drivers/arm/pl011/aarch64/pl011_console.S + drivers/arm/pl011/${ARCH}/pl011_console.S ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) PLAT_BL_COMMON_SOURCES += lib/xlat_tables/xlat_tables_common.c \ - lib/xlat_tables/aarch64/xlat_tables.c + lib/xlat_tables/${ARCH}/xlat_tables.c else include lib/xlat_tables_v2/xlat_tables.mk @@ -87,22 +109,27 @@ drivers/io/io_fip.c \ drivers/io/io_memmap.c \ lib/semihosting/semihosting.c \ - lib/semihosting/aarch64/semihosting_call.S \ + lib/semihosting/${ARCH}/semihosting_call.S \ plat/qemu/qemu_io_storage.c \ - lib/cpus/aarch64/aem_generic.S \ - lib/cpus/aarch64/cortex_a53.S \ - lib/cpus/aarch64/cortex_a57.S \ - plat/qemu/aarch64/plat_helpers.S \ + plat/qemu/${ARCH}/plat_helpers.S \ plat/qemu/qemu_bl1_setup.c +ifeq (${ARM_ARCH_MAJOR},8) +BL1_SOURCES += lib/cpus/aarch64/aem_generic.S \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a57.S +else +BL1_SOURCES += lib/cpus/${ARCH}/cortex_a15.S +endif + BL2_SOURCES += drivers/io/io_semihosting.c \ drivers/io/io_storage.c \ drivers/io/io_fip.c \ drivers/io/io_memmap.c \ lib/semihosting/semihosting.c \ - lib/semihosting/aarch64/semihosting_call.S\ + lib/semihosting/${ARCH}/semihosting_call.S\ plat/qemu/qemu_io_storage.c \ - plat/qemu/aarch64/plat_helpers.S \ + plat/qemu/${ARCH}/plat_helpers.S \ plat/qemu/qemu_bl2_setup.c \ plat/qemu/dt.c \ $(LIBFDT_SRCS) @@ -111,11 +138,12 @@ plat/qemu/qemu_image_load.c \ common/desc_image_load.c endif -ifeq (${SPD},opteed) +ifeq ($(add-lib-optee),yes) BL2_SOURCES += lib/optee/optee_utils.c endif +ifeq (${ARM_ARCH_MAJOR},8) BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \ lib/cpus/aarch64/cortex_a53.S \ lib/cpus/aarch64/cortex_a57.S \ @@ -128,7 +156,7 @@ plat/qemu/aarch64/plat_helpers.S \ plat/qemu/qemu_bl31_setup.c \ plat/qemu/qemu_gic.c - +endif # Add the build options to pack Trusted OS Extra1 and Trusted OS Extra2 images # in the FIP if the platform requires. diff --git a/plat/qemu/qemu_bl1_setup.c b/plat/qemu/qemu_bl1_setup.c index 5a70558..7c820fd 100644 --- a/plat/qemu/qemu_bl1_setup.c +++ b/plat/qemu/qemu_bl1_setup.c @@ -57,9 +57,15 @@ * does basic initialization. Later architectural setup (bl1_arch_setup()) * does not do anything platform specific. *****************************************************************************/ +#ifdef AARCH32 +#define QEMU_CONFIGURE_BL1_MMU(...) qemu_configure_mmu_secure(__VA_ARGS__) +#else +#define QEMU_CONFIGURE_BL1_MMU(...) qemu_configure_mmu_el3(__VA_ARGS__) +#endif + void bl1_plat_arch_setup(void) { - qemu_configure_mmu_el3(bl1_tzram_layout.total_base, + QEMU_CONFIGURE_BL1_MMU(bl1_tzram_layout.total_base, bl1_tzram_layout.total_size, BL1_RO_BASE, BL1_RO_LIMIT, BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END); diff --git a/plat/qemu/qemu_bl2_mem_params_desc.c b/plat/qemu/qemu_bl2_mem_params_desc.c index 47f88ac..9965cfd 100644 --- a/plat/qemu/qemu_bl2_mem_params_desc.c +++ b/plat/qemu/qemu_bl2_mem_params_desc.c @@ -34,6 +34,7 @@ .next_handoff_image_id = INVALID_IMAGE_ID, }, #else /* EL3_PAYLOAD_BASE */ +#ifdef AARCH64 /* Fill BL31 related information */ { .image_id = BL31_IMAGE_ID, @@ -57,16 +58,27 @@ .next_handoff_image_id = BL33_IMAGE_ID, # endif }, +#endif /* AARCH64 */ # ifdef QEMU_LOAD_BL32 + +#ifdef AARCH64 +#define BL32_EP_ATTRIBS (SECURE | EXECUTABLE) +#define BL32_IMG_ATTRIBS 0 +#else +#define BL32_EP_ATTRIBS (SECURE | EXECUTABLE | EP_FIRST_EXE) +#define BL32_IMG_ATTRIBS IMAGE_ATTRIB_PLAT_SETUP +#endif + /* 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), + entry_point_info_t, BL32_EP_ATTRIBS), .ep_info.pc = BL32_BASE, - SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, - 0), + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, + image_info_t, BL32_IMG_ATTRIBS), + .image_info.image_base = BL32_BASE, .image_info.image_max_size = BL32_LIMIT - BL32_BASE, @@ -103,7 +115,7 @@ SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, VERSION_2, image_info_t, IMAGE_ATTRIB_SKIP_LOADING), -#ifdef SPD_opteed +#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) .image_info.image_base = QEMU_OPTEE_PAGEABLE_LOAD_BASE, .image_info.image_max_size = QEMU_OPTEE_PAGEABLE_LOAD_SIZE, #endif diff --git a/plat/qemu/qemu_bl2_setup.c b/plat/qemu/qemu_bl2_setup.c index 60d9623..9e4a4a0 100644 --- a/plat/qemu/qemu_bl2_setup.c +++ b/plat/qemu/qemu_bl2_setup.c @@ -9,10 +9,9 @@ #include #include #include -#ifdef SPD_opteed #include -#endif #include +#include #include #include #include @@ -183,9 +182,15 @@ /* TODO Initialize timer */ } +#ifdef AARCH32 +#define QEMU_CONFIGURE_BL2_MMU(...) qemu_configure_mmu_secure(__VA_ARGS__) +#else +#define QEMU_CONFIGURE_BL2_MMU(...) qemu_configure_mmu_el1(__VA_ARGS__) +#endif + void bl2_plat_arch_setup(void) { - qemu_configure_mmu_el1(bl2_tzram_layout.total_base, + QEMU_CONFIGURE_BL2_MMU(bl2_tzram_layout.total_base, bl2_tzram_layout.total_size, BL2_RO_BASE, BL2_RO_LIMIT, BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END); @@ -196,11 +201,16 @@ ******************************************************************************/ static uint32_t qemu_get_spsr_for_bl32_entry(void) { +#ifdef AARCH64 /* * The Secure Payload Dispatcher service is responsible for * setting the SPSR prior to entry into the BL3-2 image. */ return 0; +#else + return SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE, + DISABLE_ALL_EXCEPTIONS); +#endif } /******************************************************************************* @@ -208,8 +218,9 @@ ******************************************************************************/ static uint32_t qemu_get_spsr_for_bl33_entry(void) { - unsigned int mode; uint32_t spsr; +#ifdef AARCH64 + unsigned int mode; /* Figure out what mode we enter the non-secure world in */ mode = EL_IMPLEMENTED(2) ? MODE_EL2 : MODE_EL1; @@ -220,6 +231,11 @@ * well. */ spsr = SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); +#else + spsr = SPSR_MODE32(MODE32_svc, + plat_get_ns_image_entrypoint() & 0x1, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); +#endif return spsr; } @@ -228,7 +244,7 @@ { int err = 0; bl_mem_params_node_t *bl_mem_params = get_bl_mem_params_node(image_id); -#ifdef SPD_opteed +#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) bl_mem_params_node_t *pager_mem_params = NULL; bl_mem_params_node_t *paged_mem_params = NULL; #endif @@ -236,9 +252,8 @@ assert(bl_mem_params); switch (image_id) { -# ifdef AARCH64 case BL32_IMAGE_ID: -#ifdef SPD_opteed +#if defined(SPD_opteed) || defined(AARCH32_SP_OPTEE) pager_mem_params = get_bl_mem_params_node(BL32_EXTRA1_IMAGE_ID); assert(pager_mem_params); @@ -252,16 +267,31 @@ WARN("OPTEE header parse error.\n"); } +#if defined(SPD_opteed) /* * OP-TEE expect to receive DTB address in x2. * This will be copied into x2 by dispatcher. */ bl_mem_params->ep_info.args.arg3 = PLAT_QEMU_DT_BASE; +#else /* case AARCH32_SP_OPTEE */ + bl_mem_params->ep_info.args.arg0 = + bl_mem_params->ep_info.args.arg1; + bl_mem_params->ep_info.args.arg1 = 0; + bl_mem_params->ep_info.args.arg2 = PLAT_QEMU_DT_BASE; + bl_mem_params->ep_info.args.arg3 = 0; +#endif #endif bl_mem_params->ep_info.spsr = qemu_get_spsr_for_bl32_entry(); break; -# endif + case BL33_IMAGE_ID: +#ifdef AARCH32_SP_OPTEE + /* AArch32 only core: OP-TEE expects NSec EP in register LR */ + pager_mem_params = get_bl_mem_params_node(BL32_IMAGE_ID); + assert(pager_mem_params); + pager_mem_params->ep_info.lr_svc = bl_mem_params->ep_info.pc; +#endif + /* 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 = qemu_get_spsr_for_bl33_entry(); @@ -349,7 +379,7 @@ } #endif /* !LOAD_IMAGE_V2 */ -unsigned long plat_get_ns_image_entrypoint(void) +uintptr_t plat_get_ns_image_entrypoint(void) { return NS_IMAGE_OFFSET; } diff --git a/plat/qemu/qemu_common.c b/plat/qemu/qemu_common.c index e34b16f..6f9fcc6 100644 --- a/plat/qemu/qemu_common.c +++ b/plat/qemu/qemu_common.c @@ -85,6 +85,16 @@ {0} }; #endif +#ifdef IMAGE_BL32 +static const mmap_region_t plat_qemu_mmap[] = { + MAP_SHARED_RAM, + MAP_DEVICE0, +#ifdef MAP_DEVICE1 + MAP_DEVICE1, +#endif + {0} +}; +#endif /******************************************************************************* * Macro generating the code for the function setting up the pagetables as per @@ -92,7 +102,7 @@ ******************************************************************************/ #define DEFINE_CONFIGURE_MMU_EL(_el) \ - void qemu_configure_mmu_el##_el(unsigned long total_base, \ + void qemu_configure_mmu_##_el(unsigned long total_base, \ unsigned long total_size, \ unsigned long ro_start, \ unsigned long ro_limit, \ @@ -111,11 +121,15 @@ mmap_add(plat_qemu_mmap); \ init_xlat_tables(); \ \ - enable_mmu_el##_el(0); \ + enable_mmu_##_el(0); \ } /* Define EL1 and EL3 variants of the function initialising the MMU */ -DEFINE_CONFIGURE_MMU_EL(1) -DEFINE_CONFIGURE_MMU_EL(3) +#ifdef AARCH32 +DEFINE_CONFIGURE_MMU_EL(secure) +#else +DEFINE_CONFIGURE_MMU_EL(el1) +DEFINE_CONFIGURE_MMU_EL(el3) +#endif diff --git a/plat/qemu/qemu_private.h b/plat/qemu/qemu_private.h index 1671ec7..202d604 100644 --- a/plat/qemu/qemu_private.h +++ b/plat/qemu/qemu_private.h @@ -9,6 +9,11 @@ #include +void qemu_configure_mmu_secure(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, unsigned long ro_limit, + unsigned long coh_start, unsigned long coh_limit); + void qemu_configure_mmu_el1(unsigned long total_base, unsigned long total_size, unsigned long ro_start, unsigned long ro_limit, unsigned long coh_start, unsigned long coh_limit); diff --git a/plat/qemu/sp_min/sp_min-qemu.mk b/plat/qemu/sp_min/sp_min-qemu.mk new file mode 100644 index 0000000..5e8875b --- /dev/null +++ b/plat/qemu/sp_min/sp_min-qemu.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_SOURCES += plat/qemu/sp_min/sp_min_setup.c \ + plat/qemu/aarch32/plat_helpers.S \ + plat/qemu/qemu_gic.c \ + plat/qemu/qemu_pm.c \ + plat/qemu/topology.c + +BL32_SOURCES += lib/cpus/aarch32/aem_generic.S \ + lib/cpus/aarch32/cortex_a15.S + +BL32_SOURCES += plat/common/aarch32/platform_mp_stack.S \ + plat/common/plat_psci_common.c + + +BL32_SOURCES += drivers/arm/gic/v2/gicv2_helpers.c \ + drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/common/gic_common.c diff --git a/plat/qemu/sp_min/sp_min_setup.c b/plat/qemu/sp_min/sp_min_setup.c new file mode 100644 index 0000000..fd8fa1c --- /dev/null +++ b/plat/qemu/sp_min/sp_min_setup.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../qemu_private.h" + +#if RESET_TO_SP_MIN +#error qemu does not support RESET_TO_SP_MIN +#endif + +static entry_point_info_t bl33_image_ep_info; + +/* + * The next 3 constants identify the extents of the code, RO data region and the + * limit of the BL3-1 image. These addresses are used by the MMU setup code and + * therefore they must be page-aligned. It is the responsibility of the linker + * script to ensure that __RO_START__, __RO_END__ & __BL31_END__ linker symbols + * refer to page-aligned addresses. + */ +#define BL32_RO_BASE (unsigned long)(&__RO_START__) +#define BL32_RO_LIMIT (unsigned long)(&__RO_END__) +#define BL32_END (unsigned long)(&__BL32_END__) + +#if USE_COHERENT_MEM +/* + * The next 2 constants identify the extents of the coherent memory region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols + * refer to page-aligned addresses. + */ +#define BL32_COHERENT_RAM_BASE (unsigned long)(&__COHERENT_RAM_START__) +#define BL32_COHERENT_RAM_LIMIT (unsigned long)(&__COHERENT_RAM_END__) +#endif + +/****************************************************************************** + * On a GICv2 system, the Group 1 secure interrupts are treated as Group 0 + * interrupts. + *****************************************************************************/ +#define PLATFORM_G1S_PROPS(grp) \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(QEMU_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, \ + grp, GIC_INTR_CFG_LEVEL) + +#define PLATFORM_G0_PROPS(grp) + +static const interrupt_prop_t stih410_interrupt_props[] = { + PLATFORM_G1S_PROPS(GICV2_INTR_GROUP0), + PLATFORM_G0_PROPS(GICV2_INTR_GROUP0) +}; + +static unsigned int target_mask_array[PLATFORM_CORE_COUNT]; + +static const struct gicv2_driver_data plat_gicv2_driver_data = { + .gicd_base = GICD_BASE, + .gicc_base = GICC_BASE, + .interrupt_props = stih410_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(stih410_interrupt_props), + .target_masks = target_mask_array, + .target_masks_num = ARRAY_SIZE(target_mask_array), +}; + +/******************************************************************************* + * 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 *sp_min_plat_get_bl33_ep_info(void) +{ + entry_point_info_t *next_image_info = &bl33_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 sp_min_early_platform_setup(void *from_bl2, void *plat_params_from_bl2) +{ + bl_params_t *params_from_bl2 = (bl_params_t *)from_bl2; + + /* Initialize the console to provide early debug support */ + console_init(PLAT_QEMU_BOOT_UART_BASE, PLAT_QEMU_BOOT_UART_CLK_IN_HZ, + PLAT_QEMU_CONSOLE_BAUDRATE); + + ERROR("qemu sp_min, console init\n"); + /* + * Check params passed from BL2 + */ + assert(params_from_bl2); + 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 entry point information from BL2's address space. + */ + while (bl_params) { + 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) + panic(); +} + +void sp_min_plat_arch_setup(void) +{ + qemu_configure_mmu_secure(BL32_RO_BASE, BL32_END - BL32_RO_BASE, + BL32_RO_BASE, BL32_RO_LIMIT, + BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_END); + +} + +void sp_min_platform_setup(void) +{ + /* Initialize the gic cpu and distributor interfaces */ + gicv2_driver_init(&plat_gicv2_driver_data); + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return SYS_COUNTER_FREQ_IN_TICKS; +} + +void sp_min_plat_fiq_handler(uint32_t id) +{ + VERBOSE("[sp_min] interrupt #%d\n", id); +}