SPM: Split S-EL1 shim from S-EL0 application
The shim prepares the S-EL1/0 environment (stack, VBAR, MMU, I-cache,
BSS clear, PIE fixup) for usage by the S-EL0 application. Split ivy
and shim parition code into separate folders.
Signed-off-by: Ruari Phipps <ruari.phipps@arm.com>
Signed-off-by: Olivier Deprez <olivier.deprez@arm.com>
Signed-off-by: Daniel Boulby <daniel.boulby@arm.com>
Change-Id: I203bbc0d379b12bd5cf1991b95e4f3a7d78d63d4
diff --git a/spm/ivy/aarch64/ivy_entrypoint.S b/spm/ivy/app/aarch64/ivy_entrypoint.S
similarity index 61%
rename from spm/ivy/aarch64/ivy_entrypoint.S
rename to spm/ivy/app/aarch64/ivy_entrypoint.S
index f79a577..d981d6a 100644
--- a/spm/ivy/aarch64/ivy_entrypoint.S
+++ b/spm/ivy/app/aarch64/ivy_entrypoint.S
@@ -20,23 +20,6 @@
/* Setup the stack pointer. */
adr x0, stacks_end
mov sp, x0
- adr x0, spm_shim_exceptions_ptr
- msr vbar_el1, x0
-
- /* Enable I-Cache */
- mrs x0, sctlr_el1
- orr x0, x0, #SCTLR_I_BIT
- msr sctlr_el1, x0
- isb
-
- /* Relocate symbols */
-pie_fixup:
- ldr x0, =pie_fixup
- and x0, x0, #~(0x1000 - 1)
- mov x1, #IVY_IMAGE_SIZE
- add x1, x1, x0
- bl fixup_gdt_reloc
-
/* And jump to the C entrypoint. */
b ivy_main
diff --git a/spm/ivy/ivy.dts b/spm/ivy/app/ivy.dts
similarity index 94%
rename from spm/ivy/ivy.dts
rename to spm/ivy/app/ivy.dts
index aa2324b..49a84bd 100644
--- a/spm/ivy/ivy.dts
+++ b/spm/ivy/app/ivy.dts
@@ -25,7 +25,7 @@
xlat-granule = <0>; /* 4KiB */
boot-order = <0>;
messaging-method = <0>; /* Direct messaging only */
- run-time-model = <0>; /* Run to completion */
+ run-time-model = <1>; /* SP pre-emptible */
/* Boot protocol */
gp-register-num = <0x0>;
diff --git a/spm/ivy/app/ivy.h b/spm/ivy/app/ivy.h
new file mode 100644
index 0000000..a40f7e1
--- /dev/null
+++ b/spm/ivy/app/ivy.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IVY_H
+#define IVY_H
+
+#include <stdint.h>
+
+/* Linker symbols used to figure out the memory layout of the S-EL1 shim. */
+extern uintptr_t __SHIM_TEXT_START__, __SHIM_TEXT_END__;
+#define SHIM_TEXT_START ((uintptr_t)&__SHIM_TEXT_START__)
+#define SHIM_TEXT_END ((uintptr_t)&__SHIM_TEXT_END__)
+
+extern uintptr_t __SHIM_RODATA_START__, __SHIM_RODATA_END__;
+#define SHIM_RODATA_START ((uintptr_t)&__SHIM_RODATA_START__)
+#define SHIM_RODATA_END ((uintptr_t)&__SHIM_RODATA_END__)
+
+extern uintptr_t __SHIM_DATA_START__, __SHIM_DATA_END__;
+#define SHIM_DATA_START ((uintptr_t)&__SHIM_DATA_START__)
+#define SHIM_DATA_END ((uintptr_t)&__SHIM_DATA_END__)
+
+extern uintptr_t __SHIM_BSS_START__, __SHIM_BSS_END__;
+#define SHIM_BSS_START ((uintptr_t)&__SHIM_BSS_START__)
+#define SHIM_BSS_END ((uintptr_t)&__SHIM_BSS_END__)
+
+/* Linker symbols used to figure out the memory layout of Ivy (S-EL0). */
+extern uintptr_t __TEXT_START__, __TEXT_END__;
+#define IVY_TEXT_START ((uintptr_t)&__TEXT_START__)
+#define IVY_TEXT_END ((uintptr_t)&__TEXT_END__)
+
+extern uintptr_t __RODATA_START__, __RODATA_END__;
+#define IVY_RODATA_START ((uintptr_t)&__RODATA_START__)
+#define IVY_RODATA_END ((uintptr_t)&__RODATA_END__)
+
+extern uintptr_t __DATA_START__, __DATA_END__;
+#define IVY_DATA_START ((uintptr_t)&__DATA_START__)
+#define IVY_DATA_END ((uintptr_t)&__DATA_END__)
+
+extern uintptr_t __BSS_START__, __BSS_END__;
+#define IVY_BSS_START ((uintptr_t)&__BSS_START__)
+#define IVY_BSS_END ((uintptr_t)&__BSS_END__)
+
+#endif /* __IVY_H__ */
diff --git a/spm/ivy/ivy_def.h b/spm/ivy/app/ivy_def.h
similarity index 100%
rename from spm/ivy/ivy_def.h
rename to spm/ivy/app/ivy_def.h
diff --git a/spm/ivy/app/ivy_main.c b/spm/ivy/app/ivy_main.c
new file mode 100644
index 0000000..f51fcb5
--- /dev/null
+++ b/spm/ivy/app/ivy_main.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <ffa_helpers.h>
+#include <ivy_def.h>
+#include <platform_def.h>
+#include <sp_helpers.h>
+
+#include "ivy.h"
+
+/* Host machine information injected by the build system in the ELF file. */
+extern const char build_message[];
+extern const char version_string[];
+
+void __dead2 ivy_main(void)
+{
+ u_register_t ret;
+ svc_args args;
+
+ NOTICE("Entering S-EL0 Secure Partition\n");
+ NOTICE("%s\n", build_message);
+ NOTICE("%s\n", version_string);
+
+init:
+ args = (svc_args){.fid = FFA_MSG_WAIT};
+ ret = sp_svc(&args);
+ while (1) {
+ if (ret != FFA_MSG_SEND_DIRECT_REQ_SMC32) {
+ ERROR("unknown FF-A request %lx\n", ret);
+ goto init;
+ }
+ VERBOSE("Received request: %lx\n", args.arg3);
+ args.fid = FFA_MSG_SEND_DIRECT_RESP_SMC32;
+ args.arg1 = 0x80020000;
+ args.arg2 = 0;
+ args.arg3 = 0;
+ ret = sp_svc(&args);
+ }
+}
diff --git a/spm/ivy/ivy.h b/spm/ivy/ivy.h
deleted file mode 100644
index c5cac2e..0000000
--- a/spm/ivy/ivy.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * Copyright (c) 2018, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#ifndef IVY_H
-#define IVY_H
-
-#include <stdint.h>
-
-/* Linker symbols used to figure out the memory layout of Ivy. */
-extern uintptr_t __TEXT_START__, __TEXT_END__;
-#define IVY_TEXT_START ((uintptr_t)&__TEXT_START__)
-#define IVY_TEXT_END ((uintptr_t)&__TEXT_END__)
-
-extern uintptr_t __RODATA_START__, __RODATA_END__;
-#define IVY_RODATA_START ((uintptr_t)&__RODATA_START__)
-#define IVY_RODATA_END ((uintptr_t)&__RODATA_END__)
-
-extern uintptr_t __DATA_START__, __DATA_END__;
-#define IVY_DATA_START ((uintptr_t)&__DATA_START__)
-#define IVY_DATA_END ((uintptr_t)&__DATA_END__)
-
-extern uintptr_t __BSS_START__, __BSS_END__;
-#define IVY_BSS_START ((uintptr_t)&__BSS_START__)
-#define IVY_BSS_END ((uintptr_t)&__BSS_END__)
-
-#endif /* __IVY_H__ */
diff --git a/spm/ivy/ivy.ld.S b/spm/ivy/ivy.ld.S
index a247ee4..0e47c21 100644
--- a/spm/ivy/ivy.ld.S
+++ b/spm/ivy/ivy.ld.S
@@ -10,7 +10,7 @@
OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
-ENTRY(ivy_entrypoint)
+ENTRY(shim_entrypoint)
SECTIONS
{
@@ -19,6 +19,48 @@
ASSERT(. == ALIGN(PAGE_SIZE),
"TEXT_START address is not aligned to PAGE_SIZE.")
+ /*----------------- START S-EL1 SHIM ----------------*/
+
+ .shim_text : {
+ __SHIM_TEXT_START__ = .;
+ *spm_shim_entrypoint.o(.text*)
+ *(.vectors)
+ . = NEXT(PAGE_SIZE);
+ __SHIM_TEXT_END__ = .;
+ }
+
+ .shim_rodata : {
+ . = ALIGN(PAGE_SIZE);
+ __SHIM_RODATA_START__ = .;
+
+ . = NEXT(PAGE_SIZE);
+ __SHIM_RODATA_END__ = .;
+ }
+
+ .shim_data : {
+ . = ALIGN(PAGE_SIZE);
+ __SHIM_DATA_START__ = .;
+
+ . = NEXT(PAGE_SIZE);
+ __SHIM_DATA_END__ = .;
+ }
+
+ .shim_bss (NOLOAD) : {
+ . = ALIGN(PAGE_SIZE);
+ __SHIM_BSS_START__ = .;
+
+ *(.bss.shim_stacks)
+ *(.bss.tf_base_xlat_table)
+ *(.bss.tf_mmap)
+ *xlat_tables_context.o(COMMON)
+ *xlat_tables_context.o(xlat_table)
+
+ . = NEXT(PAGE_SIZE);
+ __SHIM_BSS_END__ = .;
+ }
+
+ /*----------------- END S-EL1 SHIM ----------------*/
+
.text : {
__TEXT_START__ = .;
*ivy_entrypoint.o(.text*)
@@ -32,6 +74,7 @@
. = ALIGN(PAGE_SIZE);
__RODATA_START__ = .;
*(.rodata*)
+
/*
* Keep the .got section in the RO section as it is patched
* prior to enabling the MMU, so having it in RO is better for
diff --git a/spm/ivy/ivy.mk b/spm/ivy/ivy.mk
index e762f99..7230a45 100644
--- a/spm/ivy/ivy.mk
+++ b/spm/ivy/ivy.mk
@@ -20,15 +20,20 @@
-Iinclude/lib/xlat_tables \
-Iinclude/runtime_services \
-Iinclude/runtime_services/secure_el0_payloads \
- -Ispm/ivy \
+ -Ispm/ivy/app \
+ -Ispm/ivy/shim \
-Ispm/common
IVY_SOURCES := \
- $(addprefix spm/ivy/, \
+ $(addprefix spm/ivy/app/, \
aarch64/ivy_entrypoint.S \
- aarch64/spm_shim_exceptions.S \
ivy_main.c \
) \
+ $(addprefix spm/ivy/shim/, \
+ aarch64/spm_shim_entrypoint.S \
+ aarch64/spm_shim_exceptions.S \
+ shim_main.c \
+ ) \
$(addprefix spm/common/, \
aarch64/sp_arch_helpers.S \
sp_debug.c \
@@ -69,10 +74,10 @@
$(eval $(call add_define,IVY_DEFINES,PLAT_${PLAT}))
$(IVY_DTB) : $(BUILD_PLAT)/ivy $(BUILD_PLAT)/ivy/ivy.elf
-$(IVY_DTB) : spm/ivy/ivy.dts
- @echo " DTBGEN spm/ivy/ivy.dts"
+$(IVY_DTB) : spm/ivy/app/ivy.dts
+ @echo " DTBGEN spm/ivy/app/ivy.dts"
${Q}tools/generate_dtb/generate_dtb.sh \
- ivy spm/ivy/ivy.dts $(BUILD_PLAT)
+ ivy spm/ivy/app/ivy.dts $(BUILD_PLAT)
@echo
@echo "Built $@ successfully"
@echo
diff --git a/spm/ivy/ivy_main.c b/spm/ivy/ivy_main.c
deleted file mode 100644
index 02f8be2..0000000
--- a/spm/ivy/ivy_main.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <assert.h>
-#include <debug.h>
-#include <drivers/console.h>
-#include <drivers/arm/pl011.h>
-#include <errno.h>
-#include <ivy_def.h>
-#include <plat_arm.h>
-#include <platform_def.h>
-#include <sp_helpers.h>
-
-#include "ivy.h"
-#include "ivy_def.h"
-
-/* Host machine information injected by the build system in the ELF file. */
-extern const char build_message[];
-extern const char version_string[];
-
-static void ivy_print_memory_layout(void)
-{
- NOTICE("Secure Partition memory layout:\n");
-
- NOTICE(" Image regions\n");
- NOTICE(" Text region : %p - %p\n",
- (void *)IVY_TEXT_START, (void *)IVY_TEXT_END);
- NOTICE(" Read-only data region : %p - %p\n",
- (void *)IVY_RODATA_START, (void *)IVY_RODATA_END);
- NOTICE(" Data region : %p - %p\n",
- (void *)IVY_DATA_START, (void *)IVY_DATA_END);
- NOTICE(" BSS region : %p - %p\n",
- (void *)IVY_BSS_START, (void *)IVY_BSS_END);
- NOTICE(" Total image memory : %p - %p\n",
- (void *)IVY_IMAGE_BASE,
- (void *)(IVY_IMAGE_BASE + IVY_IMAGE_SIZE));
- NOTICE(" SPM regions\n");
- NOTICE(" SPM <-> SP buffer : %p - %p\n",
- (void *)IVY_SPM_BUF_BASE,
- (void *)(IVY_SPM_BUF_BASE + IVY_SPM_BUF_SIZE));
- NOTICE(" NS <-> SP buffer : %p - %p\n",
- (void *)IVY_NS_BUF_BASE,
- (void *)(IVY_NS_BUF_BASE + IVY_NS_BUF_SIZE));
-}
-
-void __dead2 ivy_main(void)
-{
- u_register_t ret;
- svc_args args;
-
- console_init(PL011_UART3_BASE,
- PL011_UART3_CLK_IN_HZ,
- PL011_BAUDRATE);
-
- NOTICE("Booting test Secure Partition Ivy\n");
- NOTICE("%s\n", build_message);
- NOTICE("%s\n", version_string);
- NOTICE("Running at S-EL0\n");
-
- ivy_print_memory_layout();
-
-init:
- args = (svc_args){.fid = FFA_MSG_WAIT};
- ret = sp_svc(&args);
- while (1) {
- if (ret != FFA_MSG_SEND_DIRECT_REQ_SMC32) {
- ERROR("unknown FF-A request %lx\n", ret);
- goto init;
- }
- VERBOSE("Received request: %lx\n", args.arg3);
- args.fid = FFA_MSG_SEND_DIRECT_RESP_SMC32;
- args.arg1 = 0x80020000;
- args.arg2 = 0;
- args.arg3 = 0;
- ret = sp_svc(&args);
- }
-}
diff --git a/spm/ivy/shim/aarch64/spm_shim_entrypoint.S b/spm/ivy/shim/aarch64/spm_shim_entrypoint.S
new file mode 100644
index 0000000..55d8dd8
--- /dev/null
+++ b/spm/ivy/shim/aarch64/spm_shim_entrypoint.S
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <ivy_def.h>
+#include <platform_def.h>
+
+ .globl shim_entrypoint
+
+.section .bss.shim_stacks
+ .balign CACHE_WRITEBACK_GRANULE
+ .fill IVY_STACKS_SIZE
+shim_stacks_end:
+
+func shim_entrypoint
+
+ /* Setup the stack pointer. */
+ adr x0, shim_stacks_end
+ mov sp, x0
+
+ /* Setup vector base address */
+ adr x0, spm_shim_exceptions_ptr
+ msr vbar_el1, x0
+ isb
+
+ /*
+ * Invalidate the data cache for the shim and whole partition.
+ * This prevents re-use of stale data cache entries from prior
+ * bootloader stages.
+ */
+ adrp x0, __SHIM_TEXT_START__
+ adrp x1, __BSS_END__
+ sub x1, x1, x0
+ bl inv_dcache_range
+
+ /* Enable I-Cache */
+ mrs x0, sctlr_el1
+ orr x0, x0, #SCTLR_I_BIT
+ msr sctlr_el1, x0
+ isb
+
+ /* Relocate symbols */
+shim_pie_fixup:
+ ldr x0, =shim_pie_fixup
+ and x0, x0, #~(0x1000 - 1)
+ mov x1, #IVY_IMAGE_SIZE
+ add x1, x1, x0
+ bl fixup_gdt_reloc
+
+ /* Clear S-EL1 shim BSS */
+ adrp x0, __SHIM_BSS_START__
+ adrp x2, __SHIM_BSS_END__
+ sub x2, x2, x0
+ mov x1, xzr
+ bl memset
+
+ /* Clear S-EL0 partition BSS */
+ adrp x0, __BSS_START__
+ adrp x2, __BSS_END__
+ sub x2, x2, x0
+ mov x1, xzr
+ bl memset
+
+ /* And jump to the C entrypoint. */
+ bl shim_main
+
+ /* Exception return to S-EL0 Ivy application code */
+ adrp x0, ivy_entrypoint
+ msr elr_el1, x0
+
+ /* AArch64 EL0t */
+ mov x0, #((DAIF_FIQ_BIT | DAIF_IRQ_BIT) << SPSR_DAIF_SHIFT)
+ msr spsr_el1, x0
+
+ /* TODO: clear GP/SIMD registers */
+ /* TODO: tune EL0 system registers */
+
+ eret
+
+endfunc shim_entrypoint
diff --git a/spm/ivy/aarch64/spm_shim_exceptions.S b/spm/ivy/shim/aarch64/spm_shim_exceptions.S
similarity index 100%
rename from spm/ivy/aarch64/spm_shim_exceptions.S
rename to spm/ivy/shim/aarch64/spm_shim_exceptions.S
diff --git a/spm/ivy/shim/shim_main.c b/spm/ivy/shim/shim_main.c
new file mode 100644
index 0000000..97df1cc
--- /dev/null
+++ b/spm/ivy/shim/shim_main.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <drivers/arm/pl011.h>
+#include <drivers/console.h>
+#include <errno.h>
+#include <ffa_helpers.h>
+#include <lib/aarch64/arch_helpers.h>
+#include <lib/xlat_tables/xlat_mmu_helpers.h>
+#include <lib/xlat_tables/xlat_tables_v2.h>
+#include <plat_arm.h>
+#include <plat/common/platform.h>
+#include <platform_def.h>
+#include <sp_debug.h>
+#include <sp_helpers.h>
+#include <std_svc.h>
+
+#include "ivy.h"
+#include "ivy_def.h"
+
+static void shim_print_memory_layout(void)
+{
+ NOTICE("Secure Partition memory layout:\n");
+
+ NOTICE(" Image regions\n");
+ NOTICE(" Text region : %p - %p\n",
+ (void *)IVY_TEXT_START, (void *)IVY_TEXT_END);
+ NOTICE(" Read-only data region : %p - %p\n",
+ (void *)IVY_RODATA_START, (void *)IVY_RODATA_END);
+ NOTICE(" Data region : %p - %p\n",
+ (void *)IVY_DATA_START, (void *)IVY_DATA_END);
+ NOTICE(" BSS region : %p - %p\n",
+ (void *)IVY_BSS_START, (void *)IVY_BSS_END);
+ NOTICE(" Total image memory : %p - %p\n",
+ (void *)IVY_IMAGE_BASE,
+ (void *)(IVY_IMAGE_BASE + IVY_IMAGE_SIZE));
+ NOTICE(" SPM regions\n");
+ NOTICE(" SPM <-> SP buffer : %p - %p\n",
+ (void *)IVY_SPM_BUF_BASE,
+ (void *)(IVY_SPM_BUF_BASE + IVY_SPM_BUF_SIZE));
+ NOTICE(" NS <-> SP buffer : %p - %p\n",
+ (void *)IVY_NS_BUF_BASE,
+ (void *)(IVY_NS_BUF_BASE + IVY_NS_BUF_SIZE));
+}
+
+static void shim_plat_configure_mmu(void)
+{
+ mmap_add_region(SHIM_TEXT_START,
+ SHIM_TEXT_START,
+ SHIM_TEXT_END - SHIM_TEXT_START,
+ MT_CODE | MT_PRIVILEGED);
+ mmap_add_region(SHIM_RODATA_START,
+ SHIM_RODATA_START,
+ SHIM_RODATA_END - SHIM_RODATA_START,
+ MT_RO_DATA | MT_PRIVILEGED);
+ mmap_add_region(SHIM_DATA_START,
+ SHIM_DATA_START,
+ SHIM_DATA_END - SHIM_DATA_START,
+ MT_RW_DATA | MT_PRIVILEGED);
+ mmap_add_region(SHIM_BSS_START,
+ SHIM_BSS_START,
+ SHIM_BSS_END - SHIM_BSS_START,
+ MT_RW_DATA | MT_PRIVILEGED);
+ mmap_add_region(IVY_TEXT_START,
+ IVY_TEXT_START,
+ IVY_TEXT_END - IVY_TEXT_START,
+ MT_CODE | MT_USER);
+ mmap_add_region(IVY_RODATA_START,
+ IVY_RODATA_START,
+ IVY_RODATA_END - IVY_RODATA_START,
+ MT_RO_DATA | MT_USER);
+ mmap_add_region(IVY_DATA_START,
+ IVY_DATA_START,
+ IVY_DATA_END - IVY_DATA_START,
+ MT_RW_DATA | MT_USER);
+ mmap_add_region(IVY_BSS_START,
+ IVY_BSS_START,
+ IVY_BSS_END - IVY_BSS_START,
+ MT_RW_DATA | MT_USER);
+
+ init_xlat_tables();
+}
+
+int shim_main(void)
+{
+ assert(IS_IN_EL1() != 0);
+
+ /* Initialise console */
+ set_putc_impl(HVC_CALL_AS_STDOUT);
+
+ NOTICE("Booting S-EL1 Shim\n");
+
+ /* Configure and enable Stage-1 MMU, enable D-Cache */
+ shim_plat_configure_mmu();
+ enable_mmu_el1(0);
+
+ shim_print_memory_layout();
+
+ return 0;
+}