mirror of
https://github.com/ARM-software/arm-trusted-firmware.git
synced 2025-04-27 07:15:20 +00:00
Merge pull request #1173 from etienne-lms/armv7-qemu
support to boot OP-TEE on AArch32/Armv7+example with Cortex-A15/Qemu
This commit is contained in:
commit
5b75b4a725
15 changed files with 487 additions and 37 deletions
|
@ -73,6 +73,11 @@ debug_loop:
|
|||
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
|
||||
|
|
|
@ -93,8 +93,10 @@ entry_point_info_t *bl2_load_images(void)
|
|||
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();
|
||||
|
|
15
bl32/optee/optee.mk
Normal file
15
bl32/optee/optee.mk
Normal file
|
@ -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)
|
|
@ -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 @@ typedef struct entry_point_info {
|
|||
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 @@ CASSERT(ENTRY_POINT_INFO_PC_OFFSET ==
|
|||
__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);
|
||||
|
|
|
@ -158,9 +158,12 @@ int parse_optee_header(entry_point_info_t *header_ep,
|
|||
* 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 @@ int parse_optee_header(entry_point_info_t *header_ep,
|
|||
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;
|
||||
}
|
||||
|
|
119
plat/qemu/aarch32/plat_helpers.S
Normal file
119
plat/qemu/aarch32/plat_helpers.S
Normal file
|
@ -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
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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 @@ endif
|
|||
|
||||
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 @@ $(eval $(call add_define,ARM_XLAT_TABLES_LIB_V1))
|
|||
|
||||
|
||||
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 @@ BL1_SOURCES += drivers/io/io_semihosting.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 \
|
||||
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 @@ BL2_SOURCES += plat/qemu/qemu_bl2_mem_params_desc.c \
|
|||
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 @@ BL31_SOURCES += lib/cpus/aarch64/aem_generic.S \
|
|||
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.
|
||||
|
|
|
@ -57,9 +57,15 @@ void bl1_early_platform_setup(void)
|
|||
* 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);
|
||||
|
|
|
@ -34,6 +34,7 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = {
|
|||
.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 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = {
|
|||
.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 @@ static bl_mem_params_node_t bl2_mem_params_descs[] = {
|
|||
|
||||
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
|
||||
|
|
|
@ -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 @@ void bl2_platform_setup(void)
|
|||
/* 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 @@ void bl2_plat_arch_setup(void)
|
|||
******************************************************************************/
|
||||
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_bl32_entry(void)
|
|||
******************************************************************************/
|
||||
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 @@ static uint32_t qemu_get_spsr_for_bl33_entry(void)
|
|||
* 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 @@ static int qemu_bl2_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);
|
||||
#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 @@ static int qemu_bl2_handle_post_image_load(unsigned int image_id)
|
|||
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 @@ static int qemu_bl2_handle_post_image_load(unsigned int image_id)
|
|||
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 @@ void bl2_plat_get_bl33_meminfo(meminfo_t *bl33_meminfo)
|
|||
}
|
||||
#endif /* !LOAD_IMAGE_V2 */
|
||||
|
||||
unsigned long plat_get_ns_image_entrypoint(void)
|
||||
uintptr_t plat_get_ns_image_entrypoint(void)
|
||||
{
|
||||
return NS_IMAGE_OFFSET;
|
||||
}
|
||||
|
|
|
@ -85,6 +85,16 @@ static const mmap_region_t plat_qemu_mmap[] = {
|
|||
{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 @@ static const mmap_region_t plat_qemu_mmap[] = {
|
|||
******************************************************************************/
|
||||
|
||||
#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 @@ static const mmap_region_t plat_qemu_mmap[] = {
|
|||
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
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
22
plat/qemu/sp_min/sp_min-qemu.mk
Normal file
22
plat/qemu/sp_min/sp_min-qemu.mk
Normal file
|
@ -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
|
168
plat/qemu/sp_min/sp_min_setup.c
Normal file
168
plat/qemu/sp_min/sp_min_setup.c
Normal file
|
@ -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);
|
||||
}
|
Loading…
Add table
Reference in a new issue