Merge pull request #1173 from etienne-lms/armv7-qemu
support to boot OP-TEE on AArch32/Armv7+example with Cortex-A15/Qemu
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 <arch.h>
+#include <asm_macros.S>
+#include <assert_macros.S>
+#include <platform_def.h>
+
+ .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 <console.h>
#include <debug.h>
#include <desc_image_load.h>
-#ifdef SPD_opteed
#include <optee_utils.h>
-#endif
#include <libfdt.h>
+#include <platform.h>
#include <platform_def.h>
#include <string.h>
#include <utils.h>
@@ -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 <sys/types.h>
+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 <arch_helpers.h>
+#include <arm_gic.h>
+#include <assert.h>
+#include <bl_common.h>
+#include <console.h>
+#include <debug.h>
+#include <gic_common.h>
+#include <gicv2.h>
+#include <mmio.h>
+#include <platform.h>
+#include <platform_def.h>
+#include <string.h>
+#include <xlat_tables.h>
+#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);
+}