summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile19
-rw-r--r--cactus/aarch64/cactus_arch_helpers.S14
-rw-r--r--cactus/aarch64/cactus_entrypoint.S119
-rw-r--r--cactus/cactus.h28
-rw-r--r--cactus/cactus.ld.S52
-rw-r--r--cactus/cactus.mk32
-rw-r--r--cactus/cactus_helpers.c55
-rw-r--r--cactus/cactus_helpers.h40
-rw-r--r--cactus/cactus_main.c73
-rw-r--r--cactus/cactus_tests.h46
-rw-r--r--cactus/cactus_tests_memory_attributes.c238
-rw-r--r--cactus/cactus_tests_misc.c38
-rw-r--r--cactus/cactus_tests_system_setup.c77
-rw-r--r--include/common/debug.h36
-rw-r--r--include/common/param_header.h55
-rw-r--r--include/lib/aarch64/arch_helpers.h1
-rw-r--r--include/lib/utils_def.h95
-rw-r--r--include/runtime_services/secure_el0_payloads/secure_partition.h81
-rw-r--r--include/runtime_services/secure_el0_payloads/spm_svc.h72
19 files changed, 1144 insertions, 27 deletions
diff --git a/Makefile b/Makefile
index d7d06ab..4a3ce5f 100644
--- a/Makefile
+++ b/Makefile
@@ -164,6 +164,7 @@ INCLUDES := -Iinclude \
-Iinclude/lib/utils \
-Iinclude/plat/common \
-Iinclude/runtime_services \
+ -Iinclude/runtime_services/secure_el0_payloads \
-Iinclude/runtime_services/secure_el1_payloads \
-Iinclude/stdlib \
-Iinclude/stdlib/sys \
@@ -223,6 +224,10 @@ ifeq (${FIRMWARE_UPDATE},1)
NS_BL2U_SOURCES += ${PLAT_SOURCES}
endif
+ifneq (${ARCH},aarch32)
+ include cactus/cactus.mk
+endif
+
# Check that the file pointed by $TESTS_FILE exists
ifeq (,$(wildcard ${TESTS_FILE}))
$(error "The file TESTS_FILE points to cannot be found")
@@ -316,6 +321,13 @@ ns_bl1u ns_bl2u:
on this platform."
@exit 1
endif
+ifneq (${ARCH},aarch32)
+ BUILD_TARGETS += cactus
+else
+cactus:
+ @echo "ERROR: Can't build $@ for AArch32."
+ @exit 1
+endif
# Does the list of goals specified on the command line include a build target?
ifneq ($(call match_goals,${BUILD_TARGETS}),)
@@ -466,13 +478,17 @@ ifeq ($(FIRMWARE_UPDATE), 1)
$(eval $(call MAKE_IMG,ns_bl2u))
endif
+ifneq (${ARCH},aarch32)
+ $(eval $(call MAKE_IMG,cactus))
+endif
+
cscope:
@echo " CSCOPE"
${Q}find ${CURDIR} -name "*.[chsS]" > cscope.files
${Q}cscope -b -q -k
help:
- @echo "usage: ${MAKE} PLAT=<${PLATFORMS}> <all|tftf|ns_bl1u|ns_bl2u|distclean|clean|checkcodebase|checkpatch>"
+ @echo "usage: ${MAKE} PLAT=<${PLATFORMS}> <all|tftf|ns_bl1u|ns_bl2u|cactus|distclean|clean|checkcodebase|checkpatch>"
@echo ""
@echo "PLAT is used to specify which platform you wish to build."
@echo "If no platform is specified, PLAT defaults to: ${DEFAULT_PLAT}"
@@ -483,6 +499,7 @@ help:
@echo " tftf Build the TFTF image"
@echo " ns_bl1u Build the NS_BL1U image"
@echo " ns_bl2u Build the NS_BL2U image"
+ @echo " cactus Build the Cactus image (Test S-EL0 payload)."
@echo " checkcodebase Check the coding style of the entire source tree"
@echo " checkpatch Check the coding style on changes in the current"
@echo " branch against BASE_COMMIT (default origin/master)"
diff --git a/cactus/aarch64/cactus_arch_helpers.S b/cactus/aarch64/cactus_arch_helpers.S
new file mode 100644
index 0000000..2b69883
--- /dev/null
+++ b/cactus/aarch64/cactus_arch_helpers.S
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+
+ .globl cactus_svc
+
+func cactus_svc
+ svc #0
+ ret
+endfunc cactus_svc
diff --git a/cactus/aarch64/cactus_entrypoint.S b/cactus/aarch64/cactus_entrypoint.S
new file mode 100644
index 0000000..a9f1920
--- /dev/null
+++ b/cactus/aarch64/cactus_entrypoint.S
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <secure_partition.h>
+#include <spm_svc.h>
+#include <xlat_tables.h>
+
+ .globl cactus_entrypoint
+
+func cactus_entrypoint
+
+ /*
+ * All the information needed to remap the memory of the Secure
+ * Partition is in the buffer whose pointer is passed on X0 and size on
+ * X1. If the size is 0, return with an error.
+ */
+ cmp x1, #0
+ beq .return_error
+
+ /* Save the base address and size of the buffer. */
+ mov x20, x0
+ mov x21, x1
+ /* Size of the Secure Partition image. */
+ ldr x22, [x20, SP_BOOT_INFO_IMAGE_SIZE_OFFSET]
+
+ /*
+ * Remap all sections of the image before doing anything else.
+ *
+ * Not even the console can be initialized before because it needs to
+ * initialize variables (that can only be modified after remapping that
+ * region as RW).
+ *
+ * If any of the calls fails, loop, as there is no console to print an
+ * error message to.
+ */
+ .macro set_sp_mem_attributes
+ cmp x2, #0 /* If size is 0, skip the call. */
+ beq 1f
+ mov_imm x0, SP_MEM_ATTRIBUTES_SET_AARCH64
+ svc #0
+ cmp x0, #0
+ bne .return_error
+1:
+ .endm
+
+ adr x1, __TEXT_START__
+ adr x2, __TEXT_END__
+ sub x2, x2, x1 /* __TEXT_SIZE__ */
+ lsr x2, x2, PAGE_SIZE_SHIFT /* __TEXT_SIZE__ in pages */
+ mov x3, SP_MEM_ATTR_ACCESS_RO | SP_MEM_ATTR_EXEC
+ set_sp_mem_attributes
+
+ adr x1, __RODATA_START__
+ adr x2, __RODATA_END__
+ sub x2, x2, x1 /* __RODATA_SIZE__ */
+ lsr x2, x2, PAGE_SIZE_SHIFT /* __RODATA_SIZE__ in pages */
+ mov x3, SP_MEM_ATTR_ACCESS_RO | SP_MEM_ATTR_NON_EXEC
+ set_sp_mem_attributes
+
+ adr x1, __RWDATA_START__
+ adr x2, __RWDATA_END__
+ sub x2, x2, x1 /* __RWDATA_SIZE__ */
+ lsr x2, x2, PAGE_SIZE_SHIFT /* __RWDATA_SIZE__ in pages */
+ mov x3, SP_MEM_ATTR_ACCESS_RW | SP_MEM_ATTR_NON_EXEC
+ set_sp_mem_attributes
+
+ /*
+ * To avoid accessing it by mistake, prevent EL0 from accessing the rest
+ * of the memory reserved for the Secure Partition.
+ *
+ * Unused size = Total size - Used size
+ * = Total size - (__RWDATA_END__ - __TEXT_START__)
+ */
+ adr x1, __RWDATA_END__
+ adr x2, __TEXT_START__
+ sub x2, x1, x2 /* x2 = Used size, x22 = Total size */
+ sub x2, x22, x2 /* x2 = Unused size */
+ lsr x2, x2, PAGE_SIZE_SHIFT /* Unused size in pages */
+ mov x3, SP_MEM_ATTR_ACCESS_NOACCESS | SP_MEM_ATTR_NON_EXEC
+ set_sp_mem_attributes
+
+ adr x0, __BSS_START__
+ adr x1, __BSS_END__
+ sub x1, x1, x0
+ bl zeromem16
+
+ /* Setup the stack pointer. */
+ ldr x0, [x20, SP_BOOT_INFO_STACK_BASE_OFFSET]
+ ldr x1, [x20, SP_BOOT_INFO_PCPU_STACK_SIZE_OFFSET]
+ add x0, x0, x1
+ mov sp, x0
+
+ /* And do the rest in C code */
+ mov x0, x20
+ mov x1, x21
+ bl cactus_main
+
+ /* Tell SPM that we are done initialising */
+ mov_imm x0, SP_EVENT_COMPLETE_AARCH64
+ mov x1, #0
+ svc #0
+
+ /* Loop forever */
+ b .
+
+.return_error:
+ /* Tell SPM that the initialization failed. */
+ mov_imm x0, SP_EVENT_COMPLETE_AARCH64
+ mov x1, #1
+ svc #0
+
+ /* Loop forever */
+ b .
+
+endfunc cactus_entrypoint
diff --git a/cactus/cactus.h b/cactus/cactus.h
new file mode 100644
index 0000000..976fe62
--- /dev/null
+++ b/cactus/cactus.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CACTUS_H__
+#define __CACTUS_H__
+
+#include <types.h>
+
+extern uintptr_t __TEXT_START__, __TEXT_END__;
+#define CACTUS_TEXT_START ((uintptr_t)&__TEXT_START__)
+#define CACTUS_TEXT_END ((uintptr_t)&__TEXT_END__)
+
+extern uintptr_t __RODATA_START__, __RODATA_END__;
+#define CACTUS_RODATA_START ((uintptr_t)&__RODATA_START__)
+#define CACTUS_RODATA_END ((uintptr_t)&__RODATA_END__)
+
+extern uintptr_t __RWDATA_START__, __RWDATA_END__;
+#define CACTUS_RWDATA_START ((uintptr_t)&__RWDATA_START__)
+#define CACTUS_RWDATA_END ((uintptr_t)&__RWDATA_END__)
+
+extern uintptr_t __BSS_START__, __BSS_END__;
+#define CACTUS_BSS_START ((uintptr_t)&__BSS_START__)
+#define CACTUS_BSS_END ((uintptr_t)&__BSS_END__)
+
+#endif /* __CACTUS_H__ */
diff --git a/cactus/cactus.ld.S b/cactus/cactus.ld.S
new file mode 100644
index 0000000..3ff11e8
--- /dev/null
+++ b/cactus/cactus.ld.S
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+#include <xlat_tables.h>
+
+OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT)
+OUTPUT_ARCH(PLATFORM_LINKER_ARCH)
+ENTRY(cactus_entrypoint)
+
+SECTIONS
+{
+ ASSERT(. == ALIGN(PAGE_SIZE),
+ "TEXT_START address is not aligned to PAGE_SIZE.")
+
+ .text : {
+ __TEXT_START__ = .;
+ *cactus_entrypoint.o(.text*)
+ *(.text*)
+ *(.vectors)
+ . = NEXT(PAGE_SIZE);
+ __TEXT_END__ = .;
+ }
+
+ .rodata : {
+ . = ALIGN(PAGE_SIZE);
+ __RODATA_START__ = .;
+ *(.rodata*)
+ . = NEXT(PAGE_SIZE);
+ __RODATA_END__ = .;
+ }
+
+
+ .data : {
+ . = ALIGN(PAGE_SIZE);
+ __RWDATA_START__ = .;
+ *(.data*)
+ }
+
+ .bss : {
+ . = ALIGN(16);
+ __BSS_START__ = .;
+ *(SORT_BY_ALIGNMENT(.bss*))
+ *(COMMON)
+ . = NEXT(PAGE_SIZE);
+ __BSS_END__ = .;
+ __RWDATA_END__ = .;
+ }
+}
diff --git a/cactus/cactus.mk b/cactus/cactus.mk
new file mode 100644
index 0000000..5c37276
--- /dev/null
+++ b/cactus/cactus.mk
@@ -0,0 +1,32 @@
+#
+# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+INCLUDES += -I cactus
+
+CACTUS_SOURCES := cactus/aarch64/cactus_entrypoint.S \
+ cactus/aarch64/cactus_arch_helpers.S \
+ cactus/cactus_helpers.c \
+ cactus/cactus_main.c \
+ cactus/cactus_tests_memory_attributes.c \
+ cactus/cactus_tests_misc.c \
+ cactus/cactus_tests_system_setup.c \
+ drivers/arm/pl011/${ARCH}/pl011_console.S \
+ framework/${ARCH}/asm_debug.S \
+ lib/${ARCH}/cache_helpers.S \
+ lib/${ARCH}/misc_helpers.S \
+ lib/stdlib/assert.c \
+ lib/stdlib/putchar.c \
+ lib/stdlib/printf.c \
+ lib/stdlib/rand.c \
+ lib/stdlib/strlen.c \
+ lib/stdlib/subr_prf.c \
+ plat/common/${ARCH}/platform_helpers.S
+
+CACTUS_LINKERFILE := cactus/cactus.ld.S
+
+# Position-independent code
+ASFLAGS_aarch64 += -fpie
+TFTF_CFLAGS_aarch64 += -fpie
diff --git a/cactus/cactus_helpers.c b/cactus/cactus_helpers.c
new file mode 100644
index 0000000..7b646bc
--- /dev/null
+++ b/cactus/cactus_helpers.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+uintptr_t bound_rand(uintptr_t min, uintptr_t max)
+{
+ /*
+ * This is not ideal as some numbers will never be generated because of
+ * the integer arithmetic rounding.
+ */
+ return ((rand() * (UINT64_MAX/RAND_MAX)) % (max - min)) + min;
+}
+
+/*******************************************************************************
+ * Test framework helpers
+ ******************************************************************************/
+
+void expect(int expr, int expected)
+{
+ if (expr != expected) {
+ ERROR("Expected value %i, got %i\n", expected, expr);
+ while (1)
+ continue;
+ }
+}
+
+void announce_test_section_start(const char *test_sect_desc)
+{
+ INFO("========================================\n");
+ INFO("Starting %s tests\n", test_sect_desc);
+ INFO("========================================\n");
+}
+void announce_test_section_end(const char *test_sect_desc)
+{
+ INFO("========================================\n");
+ INFO("End of %s tests\n", test_sect_desc);
+ INFO("========================================\n");
+}
+
+void announce_test_start(const char *test_desc)
+{
+ INFO("[+] %s\n", test_desc);
+}
+
+void announce_test_end(const char *test_desc)
+{
+ INFO("Test \"%s\" passed.\n", test_desc);
+}
+
diff --git a/cactus/cactus_helpers.h b/cactus/cactus_helpers.h
new file mode 100644
index 0000000..f4c766c
--- /dev/null
+++ b/cactus/cactus_helpers.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CACTUS_HELPERS_H__
+#define __CACTUS_HELPERS_H__
+
+#include <stdint.h>
+
+/*
+ * Helper functions
+ */
+uint64_t cactus_svc(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3,
+ uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7);
+
+/*
+ * Choose a pseudo-random number within the [min,max] range (both limits are
+ * inclusive).
+ */
+uintptr_t bound_rand(uintptr_t min, uintptr_t max);
+
+/*
+ * Check that expr == expected.
+ * If not, loop forever.
+ */
+void expect(int expr, int expected);
+
+/*
+ * Test framework functions
+ */
+
+void announce_test_section_start(const char *test_sect_desc);
+void announce_test_section_end(const char *test_sect_desc);
+
+void announce_test_start(const char *test_desc);
+void announce_test_end(const char *test_desc);
+
+#endif /* __CACTUS_HELPERS_H__ */
diff --git a/cactus/cactus_main.c b/cactus/cactus_main.c
new file mode 100644
index 0000000..a67d1fe
--- /dev/null
+++ b/cactus/cactus_main.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <console.h>
+#include <debug.h>
+#include <pl011.h>
+#include <plat_arm.h>
+#include <platform_def.h>
+#include <secure_partition.h>
+#include <std_svc.h>
+
+#include "cactus.h"
+#include "cactus_tests.h"
+
+extern const char build_message[];
+extern const char version_string[];
+
+static void cactus_print_memory_layout(secure_partition_boot_info_t *boot_info)
+{
+ NOTICE("Secure Partition memory layout:\n");
+ NOTICE(" Secure Partition image : %p - %p\n",
+ (void *) boot_info->sp_image_base,
+ (void *)(boot_info->sp_image_base + boot_info->sp_image_size));
+ NOTICE(" Text region : %p - %p\n",
+ (void *) CACTUS_TEXT_START, (void *) CACTUS_TEXT_END);
+ NOTICE(" Read-only data region : %p - %p\n",
+ (void *) CACTUS_RODATA_START, (void *) CACTUS_RODATA_END);
+ NOTICE(" Read-write data region : %p - %p\n",
+ (void *) CACTUS_RWDATA_START, (void *) CACTUS_RWDATA_END);
+ NOTICE(" BSS region : %p - %p\n",
+ (void *) CACTUS_BSS_START, (void *) CACTUS_BSS_END);
+ NOTICE(" Unused SP image space : %p - %p\n",
+ (void *) CACTUS_BSS_END,
+ (void *)(boot_info->sp_image_base + boot_info->sp_image_size));
+ NOTICE(" EL3-EL0 shared buffer : %p - %p\n",
+ (void *) boot_info->sp_shared_buf_base,
+ (void *)(boot_info->sp_shared_buf_base + boot_info->sp_shared_buf_size));
+ NOTICE(" S-NS shared buffer : %p - %p\n",
+ (void *) boot_info->sp_ns_comm_buf_base,
+ (void *)(boot_info->sp_ns_comm_buf_base + boot_info->sp_ns_comm_buf_size));
+ NOTICE(" Stack region : %p - %p\n",
+ (void *) boot_info->sp_stack_base,
+ (void *)(boot_info->sp_stack_base +
+ (boot_info->sp_pcpu_stack_size * boot_info->num_cpus)));
+ NOTICE(" Heap region : %p - %p\n",
+ (void *) boot_info->sp_heap_base,
+ (void *)(boot_info->sp_heap_base + boot_info->sp_heap_size));
+ NOTICE("Total memory : %p - %p\n",
+ (void *) boot_info->sp_mem_base, (void *) boot_info->sp_mem_limit);
+}
+
+int cactus_main(void *el3_el0_buffer, size_t el3_el0_buffer_size)
+{
+ console_init(PLAT_ARM_UART_BASE,
+ PLAT_ARM_UART_CLK_IN_HZ,
+ PL011_BAUDRATE);
+
+ NOTICE("Booting test Secure Partition Cactus\n");
+ NOTICE("%s\n", build_message);
+ NOTICE("%s\n", version_string);
+ NOTICE("Running at S-EL0\n");
+
+ cactus_print_memory_layout(el3_el0_buffer);
+
+ misc_tests();
+ system_setup_tests();
+ mem_attr_changes_tests((secure_partition_boot_info_t *)el3_el0_buffer);
+
+ return 0;
+}
diff --git a/cactus/cactus_tests.h b/cactus/cactus_tests.h
new file mode 100644
index 0000000..85261a9
--- /dev/null
+++ b/cactus/cactus_tests.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __CACTUS_TESTS_H__
+#define __CACTUS_TESTS_H__
+
+#include <secure_partition.h>
+
+/*
+ * Test functions
+ */
+
+/*
+ * Test other things like the version number returned by SPM.
+ */
+void misc_tests(void);
+
+/*
+ * The Arm TF is responsible for setting up system registers on behalf of the
+ * Secure Partition. For example, TF is supposed to allow Secure Partitions to
+ * perform cache maintenance operations (by setting the SCTLR_EL1.UCI bit).
+ *
+ * This function attempts to verify that we indeed have access to these system
+ * features from S-EL0. These tests report their results on the UART. They do
+ * not recover from a failure : when an error is encountered they will most
+ * likely trigger an exception into S-EL1.
+ */
+void system_setup_tests(void);
+
+/*
+ * Exercise the SP_MEM_ATTRIBUTES_SET_AARCH64 SMC interface. A variety of valid
+ * and invalid requests to change memory attributes are tested.
+ *
+ * These tests report their results on the UART. They do not recover from a
+ * failure : when an error is encountered they endlessly loop.
+ *
+ * The argument is a pointer to a secure_partition_boot_info_t struct that has
+ * been filled by EL3 with the information about the memory map of this Secure
+ * Partition.
+ */
+void mem_attr_changes_tests(const secure_partition_boot_info_t *boot_info);
+
+#endif /* __CACTUS_TESTS_H__ */
diff --git a/cactus/cactus_tests_memory_attributes.c b/cactus/cactus_tests_memory_attributes.c
new file mode 100644
index 0000000..ac15f7e
--- /dev/null
+++ b/cactus/cactus_tests_memory_attributes.c
@@ -0,0 +1,238 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <secure_partition.h>
+#include <spm_svc.h>
+#include <stdio.h>
+#include <types.h>
+#include <xlat_tables.h>
+
+#include "cactus.h"
+#include "cactus_helpers.h"
+#include "cactus_tests.h"
+
+/* This is filled at runtime. */
+static uintptr_t cactus_tests_start;
+static uintptr_t cactus_tests_end;
+static uintptr_t cactus_tests_size;
+
+/*
+ * Given the required instruction and data access permissions,
+ * create a memory access controls value that is formatted as expected
+ * by the SP_MEM_ATTRIBUTES_SET_AARCH64 SMC.
+ */
+static inline uint32_t mem_access_perm(int instr_access_perm,
+ int data_access_perm)
+{
+ return instr_access_perm |
+ ((data_access_perm & SP_MEM_ATTR_ACCESS_MASK)
+ << SP_MEM_ATTR_ACCESS_SHIFT);
+}
+
+/*
+ * Send an SP_MEM_ATTRIBUTES_SET_AARCH64 SVC with the given arguments.
+ * Return the return value of the SVC.
+ */
+static int32_t request_mem_attr_changes(uintptr_t base_address,
+ int pages_count,
+ uint32_t memory_access_controls)
+{
+ INFO("Requesting memory attributes change\n");
+ INFO(" Start address : %p\n", (void *) base_address);
+ INFO(" Number of pages: %i\n", pages_count);
+ INFO(" Attributes : 0x%x\n", memory_access_controls);
+
+ uint64_t ret = cactus_svc(SP_MEM_ATTRIBUTES_SET_AARCH64,
+ base_address,
+ pages_count,
+ memory_access_controls,
+ 0, 0, 0, 0);
+
+ return (int32_t) ret;
+}
+
+/*
+ * Send an SP_MEM_ATTRIBUTES_GET_AARCH64 SVC with the given arguments.
+ * Return the return value of the SVC.
+ */
+static int32_t request_get_mem_attr(uintptr_t base_address)
+{
+ INFO("Requesting memory attributes\n");
+ INFO(" Base address : %p\n", (void *) base_address);
+
+ uint64_t ret = cactus_svc(SP_MEM_ATTRIBUTES_GET_AARCH64,
+ base_address,
+ 0, 0, 0, 0, 0, 0);
+
+ return (int32_t) ret;
+}
+
+/*
+ * This function expects a base address and number of pages identifying the
+ * extents of some memory region mapped as non-executable, read-only.
+ *
+ * 1) It changes its data access permissions to read-write.
+ * 2) It checks this memory can now be written to.
+ * 3) It restores the original data access permissions.
+ *
+ * If any check fails, it loops forever. It could also trigger a permission
+ * fault while trying to write to the memory.
+ */
+static void mem_attr_changes_unittest(uintptr_t addr, int pages_count)
+{
+ int32_t ret;
+ uintptr_t end_addr = addr + pages_count * PAGE_SIZE;
+ uint32_t old_attr, new_attr;
+
+ char test_desc[50];
+
+ snprintf(test_desc, sizeof(test_desc),
+ "RO -> RW (%i page(s) from address 0x%lx)", pages_count, addr);
+ announce_test_start(test_desc);
+
+ /*
+ * Ensure we don't change the attributes of some random memory
+ * location
+ */
+ assert(addr >= cactus_tests_start);
+ assert(end_addr < (cactus_tests_start + cactus_tests_size));
+
+ old_attr = mem_access_perm(SP_MEM_ATTR_NON_EXEC, SP_MEM_ATTR_ACCESS_RO);
+ /* Memory was read-only, let's try changing that to RW */
+ new_attr = mem_access_perm(SP_MEM_ATTR_NON_EXEC, SP_MEM_ATTR_ACCESS_RW);
+
+ ret = request_mem_attr_changes(addr, pages_count, new_attr);
+ expect(ret, SPM_SUCCESS);
+ printf("Successfully changed memory attributes\n");
+
+ /* The attributes should be the ones we have just written. */
+ ret = request_get_mem_attr(addr);
+ expect(ret, new_attr);
+
+ /* If it worked, we should be able to write to this memory now! */
+ for (unsigned char *data = (unsigned char *) addr;
+ (uintptr_t) data != end_addr;
+ ++data) {
+ *data = 42;
+ }
+ printf("Successfully wrote to the memory\n");
+
+ /* Let's revert back to the original attributes for the next test */
+ ret = request_mem_attr_changes(addr, pages_count, old_attr);
+ expect(ret, SPM_SUCCESS);
+ printf("Successfully restored the old attributes\n");
+
+ /* The attributes should be the original ones again. */
+ ret = request_get_mem_attr(addr);
+ expect(ret, old_attr);
+
+ announce_test_end(test_desc);
+}
+
+/*
+ * Exercise the ability of the Trusted Firmware to change the data access
+ * permissions and instruction execution permissions of some memory region.
+ */
+void mem_attr_changes_tests(const secure_partition_boot_info_t *boot_info)
+{
+ uint32_t attributes;
+ int32_t ret;
+ uintptr_t addr;
+
+ cactus_tests_start = CACTUS_BSS_END;
+ cactus_tests_end = boot_info->sp_image_base + boot_info->sp_image_size;
+ cactus_tests_size = cactus_tests_end - cactus_tests_start;
+
+ const char *test_sect_desc = "memory attributes changes";
+
+ announce_test_section_start(test_sect_desc);
+ /*
+ * Start with error cases, i.e. requests that are expected to be denied
+ */
+ const char *test_desc1 = "Read-write, executable";
+
+ announce_test_start(test_desc1);
+ attributes = mem_access_perm(SP_MEM_ATTR_EXEC, SP_MEM_ATTR_ACCESS_RW);
+ ret = request_mem_attr_changes(CACTUS_RWDATA_START, 1, attributes);
+ expect(ret, SPM_INVALID_PARAMETER);
+ announce_test_end(test_desc1);
+
+ const char *test_desc2 = "Size == 0";
+
+ announce_test_start(test_desc2);
+ attributes = mem_access_perm(SP_MEM_ATTR_NON_EXEC, SP_MEM_ATTR_ACCESS_RW);
+ ret = request_mem_attr_changes(CACTUS_RWDATA_START, 0, attributes);
+ expect(ret, SPM_INVALID_PARAMETER);
+ announce_test_end(test_desc2);
+
+ const char *test_desc3 = "Unaligned address";
+
+ announce_test_start(test_desc3);
+ attributes = mem_access_perm(SP_MEM_ATTR_NON_EXEC, SP_MEM_ATTR_ACCESS_RW);
+ /* Choose an address not aligned to a page boundary. */
+ addr = cactus_tests_start + 5;
+ ret = request_mem_attr_changes(addr, 1, attributes);
+ expect(ret, SPM_INVALID_PARAMETER);
+ announce_test_end(test_desc3);
+
+ const char *test_desc4 = "Unmapped memory region";
+
+ announce_test_start(test_desc4);
+ addr = boot_info->sp_mem_limit + 2 * PAGE_SIZE;
+ attributes = mem_access_perm(SP_MEM_ATTR_NON_EXEC, SP_MEM_ATTR_ACCESS_RW);
+ ret = request_mem_attr_changes(addr, 3, attributes);
+ expect(ret, SPM_INVALID_PARAMETER);
+ announce_test_end(test_desc4);
+
+ const char *test_desc5 = "Partially unmapped memory region";
+
+ announce_test_start(test_desc5);
+ addr = boot_info->sp_mem_base - 2 * PAGE_SIZE;
+ attributes = mem_access_perm(SP_MEM_ATTR_NON_EXEC, SP_MEM_ATTR_ACCESS_RW);
+ ret = request_mem_attr_changes(addr, 6, attributes);
+ expect(ret, SPM_INVALID_PARAMETER);
+ announce_test_end(test_desc5);
+
+ const char *test_desc6 = "Memory region mapped with the wrong granularity";
+
+ announce_test_start(test_desc6);
+ /*
+ * The Secure Partition is placed in DRAM, so there is a lot of
+ * remaining space that doesn't have any restrictions when it is mapped.
+ * It has most likely been mapped with a granularity of 2MB.
+ */
+ addr = boot_info->sp_mem_limit - 2 * PAGE_SIZE;
+ attributes = mem_access_perm(SP_MEM_ATTR_NON_EXEC, SP_MEM_ATTR_ACCESS_RW);
+ ret = request_mem_attr_changes(addr, 1, attributes);
+ expect(ret, SPM_INVALID_PARAMETER);
+ announce_test_end(test_desc6);
+
+ const char *test_desc7 = "Try some valid memory change requests";
+
+ announce_test_start(test_desc7);
+ for (unsigned int i = 0; i < 20; ++i) {
+ /*
+ * Choose some random address in the pool of memory reserved
+ * for these tests.
+ */
+ const int pages_max = cactus_tests_size / PAGE_SIZE;
+ int pages_count = bound_rand(1, pages_max);
+
+ addr = bound_rand(
+ cactus_tests_start,
+ cactus_tests_end - (pages_count * PAGE_SIZE));
+ /* Align to PAGE_SIZE. */
+ addr &= ~(PAGE_SIZE - 1);
+
+ mem_attr_changes_unittest(addr, pages_count);
+ }
+ announce_test_end(test_desc7);
+
+ announce_test_section_end(test_sect_desc);
+}
diff --git a/cactus/cactus_tests_misc.c b/cactus/cactus_tests_misc.c
new file mode 100644
index 0000000..785c157
--- /dev/null
+++ b/cactus/cactus_tests_misc.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <spm_svc.h>
+#include <types.h>
+
+#include "cactus.h"
+#include "cactus_helpers.h"
+#include "cactus_tests.h"
+
+/*
+ * Miscellaneous SPM tests.
+ */
+void misc_tests(void)
+{
+ int32_t ret;
+
+ const char *test_sect_desc = "miscellaneous";
+
+ announce_test_section_start(test_sect_desc);
+
+ const char *test_version = "SPM version check";
+
+ announce_test_start(test_version);
+ ret = cactus_svc(SPM_VERSION_AARCH32, 0, 0, 0, 0, 0, 0, 0);
+ INFO("Version = 0x%x (%u.%u)\n", ret,
+ (ret >> 16) & 0x7FFF, ret & 0xFFFF);
+ expect(ret, SPM_VERSION_COMPILED);
+ announce_test_end(test_version);
+
+ announce_test_section_end(test_sect_desc);
+}
diff --git a/cactus/cactus_tests_system_setup.c b/cactus/cactus_tests_system_setup.c
new file mode 100644
index 0000000..e761540
--- /dev/null
+++ b/cactus/cactus_tests_system_setup.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <debug.h>
+#include <types.h>
+
+#include "cactus.h"
+#include "cactus_helpers.h"
+
+extern uintptr_t __TEXT_START__;
+
+void system_setup_tests(void)
+{
+ const char *test_sect_desc = "system setup";
+
+ announce_test_section_start(test_sect_desc);
+
+ /*
+ * Try accessing CTR_EL0 register. This should work if SCTLR_EL1.UCT bit
+ * has been correctly setup by TF.
+ */
+ const char *test_desc1 = "Read CTR_EL0 register";
+
+ announce_test_start(test_desc1);
+
+ uint32_t ctr __unused = read_ctr_el0();
+
+ INFO("CTR_EL0 = 0x%x\n", ctr);
+ announce_test_end(test_desc1);
+
+ /*
+ * Try to execute a cache maintenance instruction. This should work if
+ * SCTLR_EL1.UCI bit has been correctly setup by TF.
+ */
+ const char *test_desc2 = "Access to cache maintenance operations";
+
+ announce_test_start(test_desc2);
+ flush_dcache_range((uintptr_t)&__TEXT_START__, 1);
+ announce_test_end(test_desc2);
+
+#if 0
+ /*
+ * Try accessing a floating point register. This is supposed to trap to
+ * S-EL1, so the test is not enabled by default.
+ *
+ * Expected ESR_EL1 value: 0x1FE00000
+ * i.e. error code = b000111 ("Access to SVE, Advanced SIMD, or
+ * floating-point functionality trapped by CPACR_EL1.FPEN").
+ */
+ const char *test_desc3 = "Access to FP regs";
+
+ announce_test_start(test_desc3);
+ /*
+ * Can't use the 'double' type here because Cactus (like the rest of
+ * the TF code) is compiled with GCC's -mgeneral-regs-only compiler flag
+ * that disables floating point support in GCC.
+ */
+ uint64_t fp_reg;
+
+ __asm__ volatile("fmov %0, d0" : "=r" (fp_reg) :: "d0");
+ INFO("D0 = 0x%lx\n", fp_reg);
+ __asm__ volatile(
+ "fmov d0, #1.0 \n\t"
+ "fmov %0, d0 \n\t"
+ : "=r" (fp_reg)
+ :
+ : "d0");
+ INFO("D0 = 0x%lx\n", fp_reg);
+ announce_test_end(test_desc3);
+#endif
+
+ announce_test_section_end(test_sect_desc);
+}
diff --git a/include/common/debug.h b/include/common/debug.h
index 3b568c5..3c0ee42 100644
--- a/include/common/debug.h
+++ b/include/common/debug.h
@@ -1,31 +1,7 @@
/*
- * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved.
*
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- *
- * Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * Neither the name of ARM nor the names of its contributors may be used
- * to endorse or promote products derived from this software without specific
- * prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
- * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
+ * SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __DEBUG_H__
@@ -33,6 +9,13 @@
#include <stdio.h>
+#ifdef IMAGE_CACTUS
+/*
+ * The register MPIDR_EL1 can't be read from EL0, which means that mp_printf()
+ * can't be used.
+ */
+#define mp_printf printf
+#else
/*
* Print a formatted string on the UART.
*
@@ -51,6 +34,7 @@
*/
__attribute__((format(printf, 1, 2)))
void mp_printf(const char *fmt, ...);
+#endif
/*
* The log output macros print output to the console. These macros produce
diff --git a/include/common/param_header.h b/include/common/param_header.h
new file mode 100644
index 0000000..c982fc9
--- /dev/null
+++ b/include/common/param_header.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __PARAM_HEADER_H__
+#define __PARAM_HEADER_H__
+
+/* Param header types */
+#define PARAM_EP 0x01
+#define PARAM_IMAGE_BINARY 0x02
+#define PARAM_BL31 0x03
+#define PARAM_BL_LOAD_INFO 0x04
+#define PARAM_BL_PARAMS 0x05
+#define PARAM_PSCI_LIB_ARGS 0x06
+#define PARAM_SP_IMAGE_BOOT_INFO 0x07
+
+/* Param header version */
+#define VERSION_1 0x01
+#define VERSION_2 0x02
+
+#define SET_PARAM_HEAD(_p, _type, _ver, _attr) do { \
+ (_p)->h.type = (uint8_t)(_type); \
+ (_p)->h.version = (uint8_t)(_ver); \
+ (_p)->h.size = (uint16_t)sizeof(*_p); \
+ (_p)->h.attr = (uint32_t)(_attr) ; \
+ } while (0)
+
+/* Following is used for populating structure members statically. */
+#define SET_STATIC_PARAM_HEAD(_p, _type, _ver, _p_type, _attr) \
+ ._p.h.type = (uint8_t)(_type), \
+ ._p.h.version = (uint8_t)(_ver), \
+ ._p.h.size = (uint16_t)sizeof(_p_type), \
+ ._p.h.attr = (uint32_t)(_attr)
+
+#ifndef __ASSEMBLY__
+
+#include <types.h>
+
+/***************************************************************************
+ * This structure provides version information and the size of the
+ * structure, attributes for the structure it represents
+ ***************************************************************************/
+typedef struct param_header {
+ uint8_t type; /* type of the structure */
+ uint8_t version; /* version of this structure */
+ uint16_t size; /* size of this structure in bytes */
+ uint32_t attr; /* attributes: unused bits SBZ */
+} param_header_t;
+
+#endif /*__ASSEMBLY__*/
+
+#endif /* __PARAM_HEADER_H__ */
+
diff --git a/include/lib/aarch64/arch_helpers.h b/include/lib/aarch64/arch_helpers.h
index 23e4bd9..3612b9d 100644
--- a/include/lib/aarch64/arch_helpers.h
+++ b/include/lib/aarch64/arch_helpers.h
@@ -204,6 +204,7 @@ static inline void disable_debug_exceptions(void)
DEFINE_SYSREG_READ_FUNC(id_pfr1_el1)
DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1)
DEFINE_SYSREG_READ_FUNC(CurrentEl)
+DEFINE_SYSREG_READ_FUNC(ctr_el0)
DEFINE_SYSREG_RW_FUNCS(daif)
DEFINE_SYSREG_RW_FUNCS(spsr_el1)
DEFINE_SYSREG_RW_FUNCS(spsr_el2)
diff --git a/include/lib/utils_def.h b/include/lib/utils_def.h
new file mode 100644
index 0000000..185a1c1
--- /dev/null
+++ b/include/lib/utils_def.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __UTILS_DEF_H__
+#define __UTILS_DEF_H__
+
+/* Compute the number of elements in the given array */
+#define ARRAY_SIZE(a) \
+ (sizeof(a) / sizeof((a)[0]))
+
+#define IS_POWER_OF_TWO(x) \
+ (((x) & ((x) - 1)) == 0)
+
+#define SIZE_FROM_LOG2_WORDS(n) (4 << (n))
+
+#define BIT(nr) (1ULL << (nr))
+
+/*
+ * This variant of div_round_up can be used in macro definition but should not
+ * be used in C code as the `div` parameter is evaluated twice.
+ */
+#define DIV_ROUND_UP_2EVAL(n, d) (((n) + (d) - 1) / (d))
+
+#define MIN(x, y) __extension__ ({ \
+ __typeof__(x) _x = (x); \
+ __typeof__(y) _y = (y); \
+ (void)(&_x == &_y); \
+ _x < _y ? _x : _y; \
+})
+
+#define MAX(x, y) __extension__ ({ \
+ __typeof__(x) _x = (x); \
+ __typeof__(y) _y = (y); \
+ (void)(&_x == &_y); \
+ _x > _y ? _x : _y; \
+})
+
+/*
+ * The round_up() macro rounds up a value to the given boundary in a
+ * type-agnostic yet type-safe manner. The boundary must be a power of two.
+ * In other words, it computes the smallest multiple of boundary which is
+ * greater than or equal to value.
+ *
+ * round_down() is similar but rounds the value down instead.
+ */
+#define round_boundary(value, boundary) \
+ ((__typeof__(value))((boundary) - 1))
+
+#define round_up(value, boundary) \
+ ((((value) - 1) | round_boundary(value, boundary)) + 1)
+
+#define round_down(value, boundary) \
+ ((value) & ~round_boundary(value, boundary))
+
+#define div_round_up(val, div) __extension__ ({ \
+ __typeof__(div) _div = (div); \
+ round_up((val), _div)/_div; \
+})
+
+/*
+ * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise.
+ * Both arguments must be unsigned pointer values (i.e. uintptr_t).
+ */
+#define check_uptr_overflow(ptr, inc) \
+ (((ptr) > UINTPTR_MAX - (inc)) ? 1 : 0)
+
+/*
+ * For those constants to be shared between C and other sources, apply a 'u'
+ * or 'ull' suffix to the argument only in C, to avoid undefined or unintended
+ * behaviour.
+ *
+ * The GNU assembler and linker do not support the 'u' and 'ull' suffix (it
+ * causes the build process to fail) therefore the suffix is omitted when used
+ * in linker scripts and assembler files.
+*/
+#if defined(__LINKER__) || defined(__ASSEMBLY__)
+# define U(_x) (_x)
+# define ULL(_x) (_x)
+#else
+# define U(_x) (_x##u)
+# define ULL(_x) (_x##ull)
+#endif
+
+/*
+ * Test for the current architecture version to be at least the version
+ * expected.
+ */
+#define ARM_ARCH_AT_LEAST(_maj, _min) \
+ ((ARM_ARCH_MAJOR > _maj) || \
+ ((ARM_ARCH_MAJOR == _maj) && (ARM_ARCH_MINOR >= _min)))
+
+#endif /* __UTILS_DEF_H__ */
diff --git a/include/runtime_services/secure_el0_payloads/secure_partition.h b/include/runtime_services/secure_el0_payloads/secure_partition.h
new file mode 100644
index 0000000..906fa2b
--- /dev/null
+++ b/include/runtime_services/secure_el0_payloads/secure_partition.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SECURE_PARTITION_H__
+#define __SECURE_PARTITION_H__
+
+#include <utils_def.h>
+
+/*
+ * Definitions used to access the members of secure_partition_boot_info from
+ * assembly code.
+ */
+#define SP_BOOT_INFO_STACK_BASE_OFFSET U(32)
+#define SP_BOOT_INFO_IMAGE_SIZE_OFFSET U(64)
+#define SP_BOOT_INFO_PCPU_STACK_SIZE_OFFSET U(72)
+
+#ifndef __ASSEMBLY__
+
+#include <cassert.h>
+#include <param_header.h>
+#include <types.h>
+
+/*
+ * Flags used by the secure_partition_mp_info structure to describe the
+ * characteristics of a cpu. Only a single flag is defined at the moment to
+ * indicate the primary cpu.
+ */
+#define MP_INFO_FLAG_PRIMARY_CPU U(0x00000001)
+
+/*
+ * This structure is used to provide information required to initialise a S-EL0
+ * partition.
+ */
+typedef struct secure_partition_mp_info {
+ u_register_t mpidr;
+ unsigned int linear_id;
+ unsigned int flags;
+} secure_partition_mp_info_t;
+
+typedef struct secure_partition_boot_info {
+ param_header_t h;
+ uintptr_t sp_mem_base;
+ uintptr_t sp_mem_limit;
+ uintptr_t sp_image_base;
+ uintptr_t sp_stack_base;
+ uintptr_t sp_heap_base;
+ uintptr_t sp_ns_comm_buf_base;
+ uintptr_t sp_shared_buf_base;
+ size_t sp_image_size;
+ size_t sp_pcpu_stack_size;
+ size_t sp_heap_size;
+ size_t sp_ns_comm_buf_size;
+ size_t sp_shared_buf_size;
+ unsigned int num_sp_mem_regions;
+ unsigned int num_cpus;
+ secure_partition_mp_info_t *mp_info;
+} secure_partition_boot_info_t;
+
+/*
+ * Compile time assertions related to the 'secure_partition_boot_info' structure
+ * to ensure that the assembler and the compiler view of the offsets of the
+ * structure members is the same.
+ */
+CASSERT(SP_BOOT_INFO_STACK_BASE_OFFSET ==
+ __builtin_offsetof(secure_partition_boot_info_t, sp_stack_base), \
+ assert_secure_partition_boot_info_sp_stack_base_offset_mismatch);
+
+CASSERT(SP_BOOT_INFO_IMAGE_SIZE_OFFSET ==
+ __builtin_offsetof(secure_partition_boot_info_t, sp_image_size), \
+ assert_secure_partition_boot_info_sp_image_size_offset_mismatch);
+
+CASSERT(SP_BOOT_INFO_PCPU_STACK_SIZE_OFFSET ==
+ __builtin_offsetof(secure_partition_boot_info_t, sp_pcpu_stack_size), \
+ assert_secure_partition_boot_info_sp_pcpu_stack_size_offset_mismatch);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __SECURE_PARTITION_H__ */
diff --git a/include/runtime_services/secure_el0_payloads/spm_svc.h b/include/runtime_services/secure_el0_payloads/spm_svc.h
new file mode 100644
index 0000000..48132fd
--- /dev/null
+++ b/include/runtime_services/secure_el0_payloads/spm_svc.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __SPM_SVC_H__
+#define __SPM_SVC_H__
+
+#include <utils_def.h>
+
+#define SPM_VERSION_MAJOR U(0)
+#define SPM_VERSION_MINOR U(1)
+#define SPM_VERSION_FORM(major, minor) ((major << 16) | (minor))
+#define SPM_VERSION_COMPILED SPM_VERSION_FORM(SPM_VERSION_MAJOR, SPM_VERSION_MINOR)
+
+#define SP_VERSION_MAJOR U(1)
+#define SP_VERSION_MINOR U(0)
+#define SP_VERSION_FORM(major, minor) ((major << 16) | (minor))
+#define SP_VERSION_COMPILED SP_VERSION_FORM(SP_VERSION_MAJOR, SP_VERSION_MINOR)
+
+/* The macros below are used to identify SPM calls from the SMC function ID */
+#define SPM_FID_MASK U(0xffff)
+#define SPM_FID_MIN_VALUE U(0x40)
+#define SPM_FID_MAX_VALUE U(0x7f)
+#define is_spm_fid(_fid) \
+ ((((_fid) & SPM_FID_MASK) >= SPM_FID_MIN_VALUE) && \
+ (((_fid) & SPM_FID_MASK) <= SPM_FID_MAX_VALUE))
+
+/*
+ * SVC IDs defined for accessing services implemented by the Secure Partition
+ * Manager from the Secure Partition(s). These services enable a partition to
+ * handle delegated events and request privileged operations from the manager.
+ */
+#define SPM_VERSION_AARCH32 U(0x84000060)
+#define SP_EVENT_COMPLETE_AARCH64 U(0xC4000061)
+#define SP_MEM_ATTRIBUTES_GET_AARCH64 U(0xC4000064)
+#define SP_MEM_ATTRIBUTES_SET_AARCH64 U(0xC4000065)
+
+/*
+ * Macros used by SP_MEM_ATTRIBUTES_SET_AARCH64.
+ */
+
+#define SP_MEM_ATTR_ACCESS_NOACCESS U(0)
+#define SP_MEM_ATTR_ACCESS_RW U(1)
+/* Value U(2) is reserved. */
+#define SP_MEM_ATTR_ACCESS_RO U(3)
+#define SP_MEM_ATTR_ACCESS_MASK U(3)
+#define SP_MEM_ATTR_ACCESS_SHIFT 0
+
+#define SP_MEM_ATTR_EXEC (U(0) << 2)
+#define SP_MEM_ATTR_NON_EXEC (U(1) << 2)
+
+/*
+ * SMC IDs defined in [1] for accessing secure partition services from the
+ * Non-secure world. These FIDs occupy the range 0x40 - 0x5f
+ * [1] DEN0060A_ARM_MM_Interface_Specification.pdf
+ */
+#define SP_VERSION_AARCH64 U(0xC4000040)
+#define SP_VERSION_AARCH32 U(0x84000040)
+
+#define SP_COMMUNICATE_AARCH64 U(0xC4000041)
+#define SP_COMMUNICATE_AARCH32 U(0x84000041)
+
+/* SPM error codes. */
+#define SPM_SUCCESS 0
+#define SPM_NOT_SUPPORTED -1
+#define SPM_INVALID_PARAMETER -2
+#define SPM_DENIED -3
+#define SPM_NO_MEMORY -5
+
+#endif /* __SPM_SVC_H__ */