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/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/shim/aarch64/spm_shim_exceptions.S b/spm/ivy/shim/aarch64/spm_shim_exceptions.S
new file mode 100644
index 0000000..07527e6
--- /dev/null
+++ b/spm/ivy/shim/aarch64/spm_shim_exceptions.S
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+
+/* -----------------------------------------------------------------------------
+ * Very simple stackless exception handlers used by the spm shim layer.
+ * -----------------------------------------------------------------------------
+ */
+	.globl	spm_shim_exceptions_ptr
+
+vector_base spm_shim_exceptions_ptr
+
+	/* -----------------------------------------------------
+	 * Current EL with SP0 : 0x0 - 0x200
+	 * -----------------------------------------------------
+	 */
+vector_entry_spin sync_exception_sp_el0
+
+vector_entry_spin irq_sp_el0
+
+vector_entry_spin fiq_ep_el0
+
+vector_entry_spin serror_ep_el0
+
+	/* -----------------------------------------------------
+	 * Current EL with SPx: 0x200 - 0x400
+	 * -----------------------------------------------------
+	 */
+vector_entry_spin sync_exception_sp_elx
+
+vector_entry_spin irq_sp_elx
+
+vector_entry_spin fiq_sp_elx
+
+vector_entry_spin serror_sp_elx
+
+	/* -----------------------------------------------------
+	 * Lower EL using AArch64 : 0x400 - 0x600. No exceptions
+	 * are handled since secure_partition does not implement
+	 * a lower EL
+	 * -----------------------------------------------------
+	 */
+vector_entry sync_exception_aarch64
+	msr	tpidr_el1, x30
+	mrs	x30, esr_el1
+	ubfx	x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH
+
+	cmp	x30, #EC_AARCH64_SVC
+	b.eq 	do_smc
+
+	cmp	x30, #EC_AARCH32_SVC
+	b.eq	do_smc
+
+	cmp	x30, #EC_AARCH64_SYS
+	b.eq	handle_sys_trap
+
+	/* Fail in all the other cases */
+	b	panic
+
+	/* ---------------------------------------------
+	 * Tell SPM that we are done initialising
+	 * ---------------------------------------------
+	 */
+do_smc:
+	mrs	x30, tpidr_el1
+	smc	#0
+	eret
+
+	/* AArch64 system instructions trap are handled as a panic for now */
+handle_sys_trap:
+panic:
+	b	panic
+end_vector_entry sync_exception_aarch64
+
+vector_entry_spin irq_aarch64
+
+vector_entry_spin fiq_aarch64
+
+vector_entry_spin serror_aarch64
+
+	/* -----------------------------------------------------
+	 * Lower EL using AArch32 : 0x600 - 0x800
+	 * -----------------------------------------------------
+	 */
+vector_entry_spin sync_exception_aarch32
+
+vector_entry_spin irq_aarch32
+
+vector_entry_spin fiq_aarch32
+
+vector_entry_spin serror_aarch32
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;
+}