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:
davidcunado-arm 2018-02-07 11:57:19 +08:00 committed by GitHub
commit 5b75b4a725
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 487 additions and 37 deletions

View File

@ -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

View File

@ -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
View 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)

View File

@ -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);

View File

@ -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;
}

View 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

View File

@ -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)

View File

@ -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.

View File

@ -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);

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View 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

View 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);
}