Trusted Firmware-A Tests, version 2.0

This is the first public version of the tests for the Trusted
Firmware-A project. Please see the documentation provided in the
source tree for more details.

Change-Id: I6f3452046a1351ac94a71b3525c30a4ca8db7867
Signed-off-by: Sandrine Bailleux <sandrine.bailleux@arm.com>
Co-authored-by: amobal01 <amol.balasokamble@arm.com>
Co-authored-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
Co-authored-by: Asha R <asha.r@arm.com>
Co-authored-by: Chandni Cherukuri <chandni.cherukuri@arm.com>
Co-authored-by: David Cunado <david.cunado@arm.com>
Co-authored-by: Dimitris Papastamos <dimitris.papastamos@arm.com>
Co-authored-by: Douglas Raillard <douglas.raillard@arm.com>
Co-authored-by: dp-arm <dimitris.papastamos@arm.com>
Co-authored-by: Jeenu Viswambharan <jeenu.viswambharan@arm.com>
Co-authored-by: Jonathan Wright <jonathan.wright@arm.com>
Co-authored-by: Kévin Petit <kevin.petit@arm.com>
Co-authored-by: Roberto Vargas <roberto.vargas@arm.com>
Co-authored-by: Sathees Balya <sathees.balya@arm.com>
Co-authored-by: Shawon Roy <Shawon.Roy@arm.com>
Co-authored-by: Soby Mathew <soby.mathew@arm.com>
Co-authored-by: Thomas Abraham <thomas.abraham@arm.com>
Co-authored-by: Vikram Kanigiri <vikram.kanigiri@arm.com>
Co-authored-by: Yatharth Kochar <yatharth.kochar@arm.com>
diff --git a/el3_payload/.gitignore b/el3_payload/.gitignore
new file mode 100644
index 0000000..381e354
--- /dev/null
+++ b/el3_payload/.gitignore
@@ -0,0 +1,6 @@
+*.o
+*~
+*.elf
+*.bin
+*.ld
+*.dump
diff --git a/el3_payload/Makefile b/el3_payload/Makefile
new file mode 100644
index 0000000..f6e809f
--- /dev/null
+++ b/el3_payload/Makefile
@@ -0,0 +1,91 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+CROSS_COMPILE	:=	aarch64-linux-gnu-
+CC		:=	${CROSS_COMPILE}gcc
+AS		:=	${CROSS_COMPILE}as
+LD		:=	${CROSS_COMPILE}ld
+OC		:=	${CROSS_COMPILE}objcopy
+OD		:=	${CROSS_COMPILE}objdump
+
+PLAT		?=	fvp
+
+ASFLAGS		:=	-nostdinc -ffreestanding -Wa,--fatal-warnings -Werror
+ASFLAGS		+=	-Iplat/${PLAT}/ -I.
+
+PLAT_BUILD_DIR	:=	build/${PLAT}
+SOURCES		:=	entrypoint.S spin.S uart.S plat/${PLAT}/platform.S
+OBJS		:=	$(patsubst %,$(PLAT_BUILD_DIR)/%,$(notdir $(SOURCES:.S=.o)))
+
+PROGRAM		:=	el3_payload
+LINKER_SCRIPT	:=	${PLAT_BUILD_DIR}/${PROGRAM}.ld
+ELF		:=	${PLAT_BUILD_DIR}/${PROGRAM}.elf
+BIN		:=	${PLAT_BUILD_DIR}/${PROGRAM}.bin
+DUMP		:=	${PLAT_BUILD_DIR}/${PROGRAM}.dump
+
+include plat/${PLAT}/platform.mk
+
+all: ${BIN}
+
+${PLAT_BUILD_DIR}:
+	mkdir -p $@
+
+${PLAT_BUILD_DIR}/%.o: %.S ${PLAT_BUILD_DIR}
+	@echo "  CC      $<"
+	${CC} ${ASFLAGS} -c $< -o $@
+
+# Specific rule for this '.o' file to avoid worrying about
+# plat/${PLAT}/platform.S being in a sub-directory...
+# TODO: Fix this workaround.
+${PLAT_BUILD_DIR}/platform.o: plat/${PLAT}/platform.S ${PLAT_BUILD_DIR}
+	@echo "  CC      $<"
+	${CC} ${ASFLAGS} -c $< -o $@
+
+${PLAT_BUILD_DIR}/%.ld: %.ld.S ${PLAT_BUILD_DIR}
+	@echo "  PP      $<"
+	${CC} -DDRAM_BASE=${DRAM_BASE} -DDRAM_SIZE=${DRAM_SIZE} -E -P -o $@ $<
+
+${ELF}: ${LINKER_SCRIPT} ${OBJS}
+	@echo "  LD      $<"
+	${LD} ${LDFLAGS} ${OBJS} --script ${LINKER_SCRIPT} -o $@
+
+${BIN}: ${ELF}
+	@echo "  BIN     $@"
+	${OC} -O binary $< $@
+
+${DUMP}: $(ELF)
+	@echo "  OD      $$@"
+	${OD} -dx $< > $@
+
+dump: ${DUMP}
+
+clean:
+	rm -rf ${PLAT_BUILD_DIR}
+
+distclean: clean
+	rm -rf build/
+
+run: run_${PLAT}
+
+run_juno: ${ELF} scripts/juno/run_ds5_script.sh scripts/juno/load_el3_payload.ds
+	scripts/juno/run_ds5_script.sh scripts/juno/load_el3_payload.ds
+
+run_fvp: scripts/fvp/run_fvp.sh
+	scripts/fvp/run_fvp.sh
+
+help:
+	@echo "EL3 test payload"
+	@echo
+	@echo "To build:"
+	@echo "make [PLAT=fvp|juno] [TARGETS]"
+	@echo ""
+	@echo "The default platform is fvp."
+	@echo
+	@echo "TARGETS:"
+	@echo "  all		Build the payload  [default target]"
+	@echo "  dump		Generate a dump file of the program"
+	@echo "  run		Run the payload on the given platform."
+	@echo "         	/!\ For Juno, requires a connection to a Juno board via DSTREAM"
diff --git a/el3_payload/README b/el3_payload/README
new file mode 100644
index 0000000..fcb3ae1
--- /dev/null
+++ b/el3_payload/README
@@ -0,0 +1,141 @@
+EL3 test payload
+================
+
+This program is a very simple EL3 baremetal application. It has been developed
+to test the ability of the Trusted Firmware-A to load an EL3 payload. All it
+does is making sure that all CPUs enter this image and if so, reports it through
+the UART.
+
+
+Building
+--------
+
+$ make PLAT=juno
+or
+$ make PLAT=fvp
+
+
+Preparing Juno board configuration files
+----------------------------------------
+
+You should have the following line in your 'SITE1/HBI0262X/board.txt' Juno
+configuration file on the SD card (where X depends on the revision of your Juno
+board):
+
+  SCC: 0x0F4 0x000003F8
+
+This:
+ - ensures all CPUs are powered on at reset;
+ - designates the Cortex-A53 #0 as the primary CPU.
+
+See the 'Assumptions' section below' for more details.
+
+
+Running on Juno
+---------------
+
+The Trusted Firmware-A must be compiled with SPIN_ON_BL1_EXIT=1. This will
+introduce an infinite loop in BL1 that gives you some time to load and run the
+EL3 payload over JTAG.
+
+Boot the board and wait until you see the following messages on the UART.
+(Note that the "INFO" messages appear only in a debug build of the Trusted
+Firmware but you should see the "NOTICE" messages in any case.)
+
+  NOTICE:  BL1: Booting BL31
+  INFO:    BL1: BL31 address = 0x80000000
+  INFO:    BL1: BL31 spsr = 0x3cd
+  INFO:    BL1: BL31 params address = 0x0
+  INFO:    BL1: BL31 plat params address = 0xf1e2d3c4b5a6978
+  INFO:    BL1: BL31 address = 0x80000000
+  INFO:    BL1: BL31 spsr = 0x3cd
+  INFO:    BL1: BL31 params address = 0x0
+  INFO:    BL1: BL31 plat params address = 0xf1e2d3c4b5a6978
+  NOTICE:  BL1: Debug loop, spinning forever
+  NOTICE:  BL1: Please connect the debugger to jump over it
+
+TODO: Update the above messages.
+
+At this point, type the following command in a shell from the EL3 test payload
+top directory:
+
+$ make PLAT=juno run
+
+You should see something like this in your shell (it takes a few seconds):
+
+  Trying to detect your DSTREAM unit...
+  Available connections:
+    USB:000765
+  Connecting to USB:000765...
+  Connected to running target Cortex-A53_0
+  Execution stopped in EL3h mode at EL3:0x000000000BEC2548
+  EL3:0x000000000BEC2548   B        {pc} ; 0xbec2548
+  Loaded section ro: EL3:0x0000000080000000 ~ EL3:0x0000000080000123 (size 0x124)
+  Loaded section .data: EL3:0x0000000080000128 ~ EL3:0x0000000080000197 (size 0x70)
+  Entry point EL3:0x0000000080000000
+  Disconnected from running target Cortex-A53_0
+
+And on the Juno UART, this should print the following messages:
+
+  Booting the EL3 test payload
+  All CPUs booted!
+
+
+Running on FVP (AEMv8A)
+-----------------------
+
+First, copy the "bl1.bin" and "fip.bin" files into the current directory.
+Alternatively, symbolic links might be created.
+
+Then run:
+
+$ make PLAT=fvp run
+
+Note: The EL3 payload does not work on the Foundation FVP.
+(This is because it expects 8 CPUs and the Foundation FVP has maximum 4.)
+
+
+How does it work?
+-----------------
+
+There is a per-cpu array. Each entry is initialised to a "dead" value.  On entry
+into the payload, each CPU writes its MPID to its entry, which allows it to
+signal its presence.
+
+Secondary CPUs then spin forever.
+
+The primary CPU carries on.
+  1) It prints a "welcome" string.
+  2) It waits for each entry in the CPUs array to be updated.
+  3) Once all CPUs have been detected in that way, it prints a success message.
+  4) Finally, it spins forever.
+
+
+Assumptions
+-----------
+
+- All CPUs enter the EL3 test payload at some point.
+  The order doesn't matter, though.
+  If some CPU doesn't boot then the EL3 payload will wait forever.
+
+- On FVP, the number of cores is hard-coded to 8.
+  If the FVP model is configured to disable some CPUs then the EL3 payload will
+  hang, waiting forever for absent CPUs.
+  For the same reason, the EL3 payload hangs on the Foundation FVP (which has
+  4 CPUs only).
+
+- The UART is already configured.
+
+- On Juno, the primary CPU is hard-coded to the Cortex-A53 #0.
+  Any CPU could be the primary CPU, though. However, the DS-5 scripts launched
+  by 'make run' assumes the Cortex-A53 #0 is the primary CPU.
+
+  On FVP, the primary CPU is hard-coded to the CPU with MPID 0x0.
+
+  Designating a CPU as the primary one simplifies the code, More particularly,
+  only the primary CPU accesses the UART, which removes the need for
+  synchronisation locks to avoid interleaved messages.
+
+- The EL3 test pyaload runs from RAM.
+  It can't execute from flash, as we would need to relocate the .data section
+  in RAM at run-time and this is not implemented for now.
diff --git a/el3_payload/arch.h b/el3_payload/arch.h
new file mode 100644
index 0000000..a6a480c
--- /dev/null
+++ b/el3_payload/arch.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __ARCH_H__
+#define __ARCH_H__
+
+#define MPIDR_MT_MASK		(1 << 24)
+#define MPIDR_AFFLVL_MASK	0xff
+#define MPIDR_AFFINITY_BITS	8
+#define MPIDR_CPU_MASK		MPIDR_AFFLVL_MASK
+#define MPIDR_CLUSTER_MASK	(MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS)
+#define MPIDR_AFF0_SHIFT	0
+#define MPIDR_AFF1_SHIFT	8
+#define MPIDR_AFF2_SHIFT	16
+#define MPIDR_AFFINITY_MASK	0xff00ffffff
+
+#endif /* __ARCH_H__ */
diff --git a/el3_payload/asm_macros.S b/el3_payload/asm_macros.S
new file mode 100644
index 0000000..d02afba
--- /dev/null
+++ b/el3_payload/asm_macros.S
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+	/*
+	 * This macro is used to create a function label.
+	 */
+	.macro func _name
+	.type \_name, %function
+	.func \_name
+	\_name:
+	.endm
+
+	/*
+	 * This macro is used to mark the end of a function.
+	 */
+	.macro endfunc _name
+	.endfunc
+	.size \_name, . - \_name
+	.endm
diff --git a/el3_payload/el3_payload.ld.S b/el3_payload/el3_payload.ld.S
new file mode 100644
index 0000000..b1c28dc
--- /dev/null
+++ b/el3_payload/el3_payload.ld.S
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+OUTPUT_FORMAT("elf64-littleaarch64")
+OUTPUT_ARCH("aarch64")
+ENTRY(entrypoint)
+
+MEMORY {
+    RAM (rwx): ORIGIN = DRAM_BASE, LENGTH = (DRAM_BASE + DRAM_SIZE)
+}
+
+SECTIONS
+{
+    . = DRAM_BASE;
+
+    ro . : {
+        */entrypoint.o(.text)
+        *(.text*)
+        *(.rodata*)
+    } >RAM
+
+    .data : {
+        *(.data*)
+    } >RAM
+}
diff --git a/el3_payload/entrypoint.S b/el3_payload/entrypoint.S
new file mode 100644
index 0000000..2da4936
--- /dev/null
+++ b/el3_payload/entrypoint.S
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "arch.h"
+#include "asm_macros.S"
+#include "platform.h"
+
+#define EOT_ASCII_CODE		4
+
+	.data
+welcome_str:
+	.asciz "Booting the EL3 test payload\r\n"
+all_cpus_booted_str:
+	.asciz "All CPUs booted!\r\n"
+
+	.text
+	.global entrypoint
+
+func entrypoint
+	bl	mark_cpu_presence
+
+	/* Distinguish primary from secondary CPUs */
+	mrs	x0, mpidr_el1
+	ldr	x1, =MPIDR_AFFINITY_MASK
+	and	x0, x0, x1
+
+	ldr	x1, =PRIMARY_CPU_MPID
+	cmp	x0, x1
+	b.ne	spin_forever
+
+	/*
+	 * Only the primary CPU executes the code below
+	 */
+
+	adr	x0, welcome_str
+	bl	print_string
+
+	/* Wait to see each CPU */
+	mov	x3, xzr
+1:
+	mov	x0, x3
+	bl	is_cpu_present
+	cbz	x0, 1b
+
+	/* Next CPU, if any */
+	add	x3, x3, #1
+	mov	x0, #CPUS_COUNT
+	cmp	x3, x0
+	b.lt	1b
+
+	/* All CPUs have been detected, announce the good news! */
+	adr	x0, all_cpus_booted_str
+	bl	print_string
+
+	/* Send EOT (End of Transmission character) character over the UART */
+	mov	x0, #EOT_ASCII_CODE
+	bl	print_char
+
+spin_forever:
+	wfe
+	b	spin_forever
+endfunc entrypoint
diff --git a/el3_payload/plat/fvp/platform.S b/el3_payload/plat/fvp/platform.S
new file mode 100644
index 0000000..5855ca7
--- /dev/null
+++ b/el3_payload/plat/fvp/platform.S
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "arch.h"
+#include "asm_macros.S"
+#include "platform.h"
+
+	.text
+	.global platform_get_core_pos
+
+/*----------------------------------------------------------------------
+ * unsigned int platform_get_core_pos(unsigned long mpid)
+ *
+ * Function to calculate the core position on FVP.
+ *
+ * (ClusterId * FVP_MAX_CPUS_PER_CLUSTER * FVP_MAX_PE_PER_CPU) +
+ * (CPUId * FVP_MAX_PE_PER_CPU) +
+ * ThreadId
+ *
+ * which can be simplified as:
+ *
+ * ((ClusterId * FVP_MAX_CPUS_PER_CLUSTER + CPUId) * FVP_MAX_PE_PER_CPU)
+ * + ThreadId
+ *
+ * clobbers: x0, x1, x3, x4
+ * ---------------------------------------------------------------------
+ */
+func platform_get_core_pos
+	/*
+	 * Check for MT bit in MPIDR. If not set, shift MPIDR to left to make it
+	 * look as if in a multi-threaded implementation.
+	 */
+	tst	x0, #MPIDR_MT_MASK
+	lsl	x3, x0, #MPIDR_AFFINITY_BITS
+	csel	x3, x3, x0, eq
+
+	/* Extract individual affinity fields from MPIDR */
+	ubfx	x0, x3, #MPIDR_AFF0_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x1, x3, #MPIDR_AFF1_SHIFT, #MPIDR_AFFINITY_BITS
+	ubfx	x4, x3, #MPIDR_AFF2_SHIFT, #MPIDR_AFFINITY_BITS
+
+	/* Compute linear position */
+	mov	x3, #FVP_MAX_CPUS_PER_CLUSTER
+	madd	x1, x4, x3, x1
+	mov	x3, #FVP_MAX_PE_PER_CPU
+	madd	x0, x1, x3, x0
+	ret
+endfunc platform_get_core_pos
diff --git a/el3_payload/plat/fvp/platform.h b/el3_payload/plat/fvp/platform.h
new file mode 100644
index 0000000..809ae7e
--- /dev/null
+++ b/el3_payload/plat/fvp/platform.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_H__
+#define __PLATFORM_H__
+
+#define PRIMARY_CPU_MPID	0x0
+
+/* Always expect 8 cores, although this is configurable on FVP */
+#define CPUS_COUNT		8
+
+#define UART_BASE		0x1c090000
+
+#define FVP_MAX_CPUS_PER_CLUSTER        4
+/* Currently multi-threaded CPUs only have a single thread */
+#define FVP_MAX_PE_PER_CPU              1
+
+#endif /* __PLATFORM_H__ */
diff --git a/el3_payload/plat/fvp/platform.mk b/el3_payload/plat/fvp/platform.mk
new file mode 100644
index 0000000..b4cda9b
--- /dev/null
+++ b/el3_payload/plat/fvp/platform.mk
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+DRAM_BASE	:=	0x80000000
+DRAM_SIZE	:=	0x80000000
diff --git a/el3_payload/plat/juno/platform.S b/el3_payload/plat/juno/platform.S
new file mode 100644
index 0000000..6c8773b
--- /dev/null
+++ b/el3_payload/plat/juno/platform.S
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "arch.h"
+#include "asm_macros.S"
+
+	.text
+	.global platform_get_core_pos
+
+	/* --------------------------------------------------------------------
+	 * unsigned int get_core_pos(uint64_t mpidr);
+	 *
+	 * Helper function to calculate the core position from its MPID.
+	 * Core positions must be consecutive, there must be no holes.
+	 *
+	 * MPID  -> core position:
+	 * 0x100 -> 0
+	 * 0x101 -> 1
+	 * 0x102 -> 2
+	 * 0x103 -> 3
+	 *   0x0 -> 4
+	 *   0x1 -> 5
+	 * --------------------------------------------------------------------
+	 */
+func platform_get_core_pos
+	and	x1, x0, #MPIDR_CPU_MASK
+	and	x0, x0, #MPIDR_CLUSTER_MASK
+	eor	x0, x0, #(1 << MPIDR_AFFINITY_BITS)  /* swap cluster order */
+	add	x0, x1, x0, LSR #6
+	ret
+endfunc platform_get_core_pos
diff --git a/el3_payload/plat/juno/platform.h b/el3_payload/plat/juno/platform.h
new file mode 100644
index 0000000..7fdcb3e
--- /dev/null
+++ b/el3_payload/plat/juno/platform.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PLATFORM_H__
+#define __PLATFORM_H__
+
+/* Designate the Cortex-A53 #0 as the primary CPU */
+#define PRIMARY_CPU_MPID	0x100
+
+#define CPUS_COUNT		6
+
+#define UART_BASE		0x7ff80000
+
+#endif /* __PLATFORM_H__ */
diff --git a/el3_payload/plat/juno/platform.mk b/el3_payload/plat/juno/platform.mk
new file mode 100644
index 0000000..b4cda9b
--- /dev/null
+++ b/el3_payload/plat/juno/platform.mk
@@ -0,0 +1,8 @@
+#
+# Copyright (c) 2018, Arm Limited. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+DRAM_BASE	:=	0x80000000
+DRAM_SIZE	:=	0x80000000
diff --git a/el3_payload/scripts/fvp/run_foundation.sh b/el3_payload/scripts/fvp/run_foundation.sh
new file mode 100755
index 0000000..f8ec343
--- /dev/null
+++ b/el3_payload/scripts/fvp/run_foundation.sh
@@ -0,0 +1,51 @@
+#! /bin/bash
+
+#
+# Script to run the EL3 payload on the Foundation FVP.
+#
+# /!\ The EL3 payload is not supported on the Foundation FVP without tweaking
+# the code. You need to modify the number of expected cores in
+# plat/fvp/platform.h:
+#  -#define CPUS_COUNT             8
+#  +#define CPUS_COUNT             4
+#
+
+set -e
+
+# usage: check_file_is_present <filename>
+# Check that <filename> exists in the current directory.
+# If not, print an error message and exit.
+function check_file_is_present
+{
+	BIN_FILE=$1
+	if [ ! -e "$BIN_FILE" ]; then
+		echo "ERROR: Can't find \"$BIN_FILE\" file"
+		echo "Please copy $BIN_FILE into the current working directory."
+		echo "Alternatively, a symbolic link might be created."
+		echo
+		exit 1
+	fi
+}
+
+check_file_is_present "bl1.bin"
+check_file_is_present "fip.bin"
+
+# Create an 8-byte file containing all zero bytes.
+# It will be loaded at the beginning of the Trusted SRAM to zero the mailbox.
+MAILBOX_FILE=mailbox.dat
+rm -f $MAILBOX_FILE
+dd if=/dev/zero of=$MAILBOX_FILE bs=1 count=8
+
+# The path to the Foundation model must be provided by the user.
+MODEL_EXEC="${MODEL_EXEC:?}"
+MODEL_PARAMETERS="				\
+	--cores=4				\
+	--visualization				\
+	--data=bl1.bin@0x0			\
+	--data=fip.bin@0x08000000		\
+	--data=$MAILBOX_FILE@0x04000000		\
+        --data=build/fvp/el3_payload.bin@0x80000000 \
+"
+
+echo $MODEL_EXEC $MODEL_PARAMETERS
+$MODEL_EXEC $MODEL_PARAMETERS
diff --git a/el3_payload/scripts/fvp/run_fvp.sh b/el3_payload/scripts/fvp/run_fvp.sh
new file mode 100755
index 0000000..788c90c
--- /dev/null
+++ b/el3_payload/scripts/fvp/run_fvp.sh
@@ -0,0 +1,56 @@
+#! /bin/bash
+
+set -e
+
+UART_OUTPUT_FILE=uart0.log
+
+# usage: check_file_is_present <filename>
+# Check that <filename> exists in the current directory.
+# If not, print an error message and exit.
+function check_file_is_present
+{
+	BIN_FILE=$1
+	if [ ! -e "$BIN_FILE" ]; then
+		echo "ERROR: Can't find \"$BIN_FILE\" file"
+		echo "Please copy $BIN_FILE into the current working directory."
+		echo "Alternatively, a symbolic link might be created."
+		echo
+		exit 1
+	fi
+}
+
+check_file_is_present "bl1.bin"
+check_file_is_present "fip.bin"
+
+# The path to the Foundation model must be provided by the user.
+MODEL_EXEC="${MODEL_EXEC:?}"
+MODEL_PARAMETERS="
+	-C pctl.startup=0.0.*.*,0.1.*.*					\
+	-C bp.secureflashloader.fname=bl1.bin				\
+	-C bp.flashloader0.fname=fip.bin				\
+	--data cluster0.cpu0=build/fvp/el3_payload.bin@0x80000000	\
+	-C bp.secureSRAM.fill1=0x00000000				\
+	-C bp.secureSRAM.fill2=0x00000000				\
+	-C bp.pl011_uart0.out_file=$UART_OUTPUT_FILE			\
+	-C bp.pl011_uart0.shutdown_on_eot=1				\
+"
+
+echo $MODEL_EXEC $MODEL_PARAMETERS
+$MODEL_EXEC $MODEL_PARAMETERS
+
+# Print results
+green='\033[1;32;40m'
+no_color='\033[0m'
+echo
+echo -e "$green"
+echo "============"
+echo " COMPLETE!"
+echo "============"
+echo -e "$no_color"
+echo "UART output:"
+echo "--------------------------------8<------------------------------"
+cat $UART_OUTPUT_FILE
+echo "--------------------------------8<------------------------------"
+echo
+echo "Output saved in $UART_OUTPUT_FILE file."
+echo
diff --git a/el3_payload/scripts/juno/load_el3_payload.ds b/el3_payload/scripts/juno/load_el3_payload.ds
new file mode 100644
index 0000000..23db44d
--- /dev/null
+++ b/el3_payload/scripts/juno/load_el3_payload.ds
@@ -0,0 +1,11 @@
+# Stop target
+interrupt
+
+# Load EL3 payload
+load build/juno/el3_payload.elf
+
+# Jump over BL1 infinite loop
+set var $pc = $pc + 4
+
+# Resume execution
+continue
diff --git a/el3_payload/scripts/juno/run_ds5_script.sh b/el3_payload/scripts/juno/run_ds5_script.sh
new file mode 100755
index 0000000..67d0736
--- /dev/null
+++ b/el3_payload/scripts/juno/run_ds5_script.sh
@@ -0,0 +1,49 @@
+#! /bin/sh
+
+set -e
+
+# Expect the script to run in argument
+if [ $# != 1 ]; then
+	echo "ERROR: No script provided"
+	echo "usage: $(basename $0) <ds5_script_to_run>"
+	exit 1
+fi
+
+# Is DS-5 command-line debugger found?
+if [ ! $(which debugger) ]; then
+	echo 'ERROR: Failed to find DS-5 command-line debugger.'
+	echo 'Please add the path to the command-line debugger in your PATH.'
+	echo 'E.g.: export PATH=<DS-5 install dir>/bin:$PATH'
+	exit 1
+fi
+
+# DS-5 configuration database entry for Juno r0
+juno_cdb_entry='ARM Development Boards::Juno ARM Development Platform (r0)::Bare Metal Debug::Bare Metal Debug::Debug Cortex-A53_0::DSTREAM'
+
+# Browse for available DSTREAM connections and lists targets that match the
+# connection type specified in the configuration database entry
+echo "Trying to detect your DSTREAM unit..."
+connections_list=available_connections
+debugger --cdb-entry "$juno_cdb_entry" --browse \
+  | tee $connections_list
+
+# Remove first line in the file (i.e. "Available connections:")
+tail -n +2 $connections_list > ${connections_list}_stripped
+mv ${connections_list}_stripped ${connections_list}
+
+# Use first available connection
+read connection < $connections_list || true
+rm $connections_list
+
+if [ -z "$connection" ] ; then
+  echo "ERROR: Found no connection"
+  exit 1
+fi
+
+# Run DS-5 script
+echo "Connecting to $connection..."
+debugger \
+	--cdb-entry "$juno_cdb_entry" \
+	--cdb-entry-param "Connection=$connection" \
+	--stop_on_connect=false \
+	--script=$1
diff --git a/el3_payload/spin.S b/el3_payload/spin.S
new file mode 100644
index 0000000..8cf067f
--- /dev/null
+++ b/el3_payload/spin.S
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "arch.h"
+#include "asm_macros.S"
+#include "platform.h"
+
+/* Initial value of each entry in the cpus_table[] array */
+#define NO_CPU	0xDEADDEADDEADDEAD
+
+/*
+ * Declare a per-CPU array to mark the CPUs presence.
+ *
+ * If cpus_table[i] == NO_CPU then CPU 'i' hasn't successfully booted to the
+ * to the EL3 test payload yet.
+ *
+ * Otherwise, it successfully booted (and cpus_table[i] should contain the
+ * CPU MPID).
+ */
+	.data
+	.align 3
+cpus_table:
+	.rept CPUS_COUNT
+	.quad NO_CPU
+	.endr
+
+
+	.text
+	.global mark_cpu_presence
+	.global is_cpu_present
+
+	/*
+	 * void mark_cpu_presence();
+	 * Mark the calling CPU present in the CPUs array.
+	 * clobbers: x0, x1, x2, x9
+	 */
+func mark_cpu_presence
+	/* Store masked MPID in x2 */
+	mrs	x0, mpidr_el1
+	ldr	x1, =MPIDR_AFFINITY_MASK
+	and	x2, x0, x1
+
+	/* Store core position in x0 */
+	mov	x9, x30
+	bl	platform_get_core_pos
+	mov	x30, x9
+
+	/* Write masked CPU MPID in the CPU entry */
+	adr	x1, cpus_table
+	add	x1, x1, x0, lsl #3
+	str	x2, [x1]
+
+	ret
+endfunc mark_cpu_presence
+
+	/*
+	 * unsigned int is_cpu_present(unsigned int core_pos);
+	 * Return 0 if CPU is absent, 1 if it is present.
+	 * clobbers: x0, x1
+	 */
+func is_cpu_present
+	adr	x1, cpus_table
+	add	x1, x1, x0, lsl #3
+	ldr	x0, [x1]
+
+	ldr	x1, =NO_CPU
+	cmp	x0, x1
+	b.eq	1f
+	mov	x0, #1
+	ret
+1:
+	mov	x0, #0
+	ret
+endfunc is_cpu_present
diff --git a/el3_payload/uart.S b/el3_payload/uart.S
new file mode 100644
index 0000000..b7c5e94
--- /dev/null
+++ b/el3_payload/uart.S
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include "asm_macros.S"
+#include "platform.h"
+
+/*
+ * PL011 UART registers
+ */
+/* UART Flag Register */
+#define UARTFR			0x018
+/* Transmit FIFO full bit in UARTFR register */
+#define PL011_UARTFR_TXFF_BIT	5
+/* UART Data Register */
+#define UARTDR			0x000
+
+	.text
+	.global print_string
+	.global print_char
+
+	/*
+	 * void print_char(unsigned int c);
+	 * clobbers: x3, x4
+	 */
+func print_char
+	ldr	x3, =UART_BASE
+1:
+	/* Check if the transmit FIFO is full */
+	ldr	w4, [x3, #UARTFR]
+	tbnz	w4, #PL011_UARTFR_TXFF_BIT, 1b
+	str	w0, [x3, #UARTDR]
+	ret
+endfunc print_char
+
+	/*
+	 * void print_string(const char *str);
+	 * clobbers: x0, x1, x2, x9
+	 */
+func print_string
+	ldr	x1, =UART_BASE
+	mov	x2, x0
+1:
+	ldrb	w0, [x2], #1
+	cmp	wzr, w0
+	b.eq	2f
+
+	mov	x9, x30
+	bl	print_char
+	mov	x30, x9
+	b	1b
+2:
+	ret
+endfunc print_string