[coreboot-gerrit] Patch set updated for coreboot: 2798945 arm64: Add support for secure monitor

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Fri Mar 27 12:44:34 CET 2015


Patrick Georgi (pgeorgi at google.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/9080

-gerrit

commit 2798945237a194d771132569f9485117a1556062
Author: Furquan Shaikh <furquan at google.com>
Date:   Tue Aug 26 15:39:51 2014 -0700

    arm64: Add support for secure monitor
    
    Secure monitor runs at EL3 and is responsible for jumping to the payload at
    specified EL and also to manage features like PSCI.
    Adding basic implementation of secure monitor as a rmodule. Currently, it just
    jumps to the the payload at current EL. Support for switching el and PSCI will
    be added as separate patches.
    
    CQ-DEPEND=CL:218300
    BUG=chrome-os-partner:30785
    BRANCH=None
    TEST=Compiles succesfully and secure monitor loads and runs payload on ryu
    
    Change-Id: If0f22299a9bad4e93311154e5546f5bae3f3395c
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: 5e40a21115aeac1cc3c73922bdc3e42d4cdb7d34
    Original-Change-Id: I86d5e93583afac141ff61475bd05c8c82d17d926
    Original-Signed-off-by: Furquan Shaikh <furquan at google.com>
    Original-Reviewed-on: https://chromium-review.googlesource.com/214371
    Original-Tested-by: Furquan Shaikh <furquan at chromium.org>
    Original-Reviewed-by: Aaron Durbin <adurbin at chromium.org>
    Original-Commit-Queue: Furquan Shaikh <furquan at chromium.org>
---
 Makefile.inc                               |   2 +-
 src/arch/arm64/Kconfig                     |   5 ++
 src/arch/arm64/Makefile.inc                |   6 ++
 src/arch/arm64/armv8/Makefile.inc          |   4 ++
 src/arch/arm64/armv8/lib/Makefile.inc      |   5 ++
 src/arch/arm64/armv8/secmon/Makefile.inc   |  50 +++++++++++++
 src/arch/arm64/armv8/secmon/secmon_init.c  |  83 +++++++++++++++++++++
 src/arch/arm64/armv8/secmon_loader.c       | 111 +++++++++++++++++++++++++++++
 src/arch/arm64/boot.c                      |   8 ++-
 src/arch/arm64/include/armv8/arch/secmon.h |  43 +++++++++++
 src/console/Makefile.inc                   |   4 ++
 src/include/console/console.h              |   1 +
 src/include/rules.h                        |  13 +++-
 src/lib/Makefile.inc                       |   1 +
 14 files changed, 332 insertions(+), 4 deletions(-)

diff --git a/Makefile.inc b/Makefile.inc
index 2877a62..838a680 100644
--- a/Makefile.inc
+++ b/Makefile.inc
@@ -63,7 +63,7 @@ subdirs-y += site-local
 
 #######################################################################
 # Add source classes and their build options
-classes-y := ramstage romstage bootblock smm smmstub cpu_microcode verstage
+classes-y := ramstage romstage bootblock smm smmstub cpu_microcode verstage secmon
 
 # Add dynamic classes for rmodules
 $(foreach supported_arch,$(ARCH_SUPPORTED), \
diff --git a/src/arch/arm64/Kconfig b/src/arch/arm64/Kconfig
index 186dd44..a070b90 100644
--- a/src/arch/arm64/Kconfig
+++ b/src/arch/arm64/Kconfig
@@ -15,4 +15,9 @@ config ARCH_RAMSTAGE_ARM64
 	bool
 	default n
 
+config ARCH_USE_SECURE_MONITOR
+	bool
+	default n
+	select RELOCATABLE_MODULES
+
 source src/arch/arm64/armv8/Kconfig
diff --git a/src/arch/arm64/Makefile.inc b/src/arch/arm64/Makefile.inc
index 12f936e..1dfaa96 100644
--- a/src/arch/arm64/Makefile.inc
+++ b/src/arch/arm64/Makefile.inc
@@ -129,6 +129,12 @@ rmodules_arm64-y += ../../lib/memset.c
 rmodules_arm64-y += ../../lib/memcpy.c
 rmodules_arm64-y += ../../lib/memmove.c
 rmodules_arm64-y += eabi_compat.c
+
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += stage_entry.S
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/memset.c
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/memcmp.c
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += ../../lib/memcpy.c
+
 ramstage-$(CONFIG_COLLECT_TIMESTAMPS) += timestamp.c
 
 ramstage-srcs += $(wildcard src/mainboard/$(MAINBOARDDIR)/mainboard.c)
diff --git a/src/arch/arm64/armv8/Makefile.inc b/src/arch/arm64/armv8/Makefile.inc
index 52663b8..955ca67 100644
--- a/src/arch/arm64/armv8/Makefile.inc
+++ b/src/arch/arm64/armv8/Makefile.inc
@@ -21,6 +21,8 @@
 
 subdirs-y += lib/
 
+subdirs-$(CONFIG_ARCH_USE_SECURE_MONITOR) += secmon/
+
 armv8_flags = -march=armv8-a -I$(src)/arch/arm64/include/armv8/ -D__COREBOOT_ARM_ARCH__=8
 
 armv8_asm_flags = $(armv8_flags)
@@ -71,6 +73,8 @@ ramstage-y += cpu.S
 ramstage-y += exception.c
 ramstage-y += mmu.c
 
+ramstage-$(CONFIG_ARCH_USE_SECURE_MONITOR) += secmon_loader.c
+
 ramstage-c-ccopts += $(armv8_flags)
 ramstage-S-ccopts += $(armv8_asm_flags)
 
diff --git a/src/arch/arm64/armv8/lib/Makefile.inc b/src/arch/arm64/armv8/lib/Makefile.inc
index fe08662..0622593 100644
--- a/src/arch/arm64/armv8/lib/Makefile.inc
+++ b/src/arch/arm64/armv8/lib/Makefile.inc
@@ -32,4 +32,9 @@ endif
 
 ifeq ($(CONFIG_ARCH_RAMSTAGE_ARMV8_64),y)
 ramstage-y += $(lib_access)
+
+ifeq ($(CONFIG_ARCH_USE_SECURE_MONITOR),y)
+secmon-y += $(lib_access)
+endif
+
 endif
diff --git a/src/arch/arm64/armv8/secmon/Makefile.inc b/src/arch/arm64/armv8/secmon/Makefile.inc
new file mode 100644
index 0000000..8ff4968
--- /dev/null
+++ b/src/arch/arm64/armv8/secmon/Makefile.inc
@@ -0,0 +1,50 @@
+################################################################################
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2014 Google Inc.
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; version 2 of the License.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+################################################################################
+
+$(eval $(call create_class_compiler,secmon,arm64))
+CPPFLAGS_secmon += -D__SECMON__
+
+SECMON_DIR=$(obj)/arch/arm64/armv8/secmon
+SECMON_SRC=$(SECMON_DIR)/secmon
+SECMON_OBJ=$(SECMON_DIR)/secmon.o
+SECMON_ELF=$(SECMON_DIR)/secmon.elf
+SECMON_RMOD=$(SECMON_DIR)/secmon.elf.rmod
+SECMON_RAMSTAGE=$(SECMON_DIR)/secmon.ramstage.o
+
+secmon-c-ccopts += -I$(src)/arch/arm64/include/armv8/ -include $(src)/include/kconfig.h -D__SECMON__
+secmon-S-ccopts += -I$(src)/arch/arm64/include/armv8/ -include $(src)/include/kconfig.h -D__SECMON__
+
+secmon-y += secmon_init.c
+secmon-y += ../../transition_asm.S ../../transition.c
+
+ramstage-srcs += $(SECMON_SRC)
+
+$(SECMON_OBJ):  $$(secmon-objs)
+		$(CC_secmon) $(LDFLAGS) -nostdlib -r -o $@ $^
+
+$(eval $(call rmodule_link,$(SECMON_ELF), $(SECMON_OBJ), 0,arm64))
+
+$(SECMON_SRC): $(SECMON_RMOD)
+	       $(OBJCOPY_secmon) -O binary $< $@
+
+$(SECMON_RAMSTAGE): $(SECMON_SRC)
+		    @printf "    OBJCOPY $(subst $(obj)/,,$(@))\n"
+		    cd $(dir $@); $(OBJCOPY_secmon) -I binary $(notdir $<) -O elf64-littleaarch64 -B aarch64 $(notdir $@)
\ No newline at end of file
diff --git a/src/arch/arm64/armv8/secmon/secmon_init.c b/src/arch/arm64/armv8/secmon/secmon_init.c
new file mode 100644
index 0000000..e8bdd82
--- /dev/null
+++ b/src/arch/arm64/armv8/secmon/secmon_init.c
@@ -0,0 +1,83 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ */
+
+#include <arch/barrier.h>
+#include <arch/io.h>
+#include <arch/lib_helpers.h>
+#include <arch/secmon.h>
+#include <arch/transition.h>
+#include <console/console.h>
+#include <rmodule.h>
+#include <stddef.h>
+
+static void secmon_wait(void)
+{
+	/*
+	 * TODO(furquan): This should be a point of no-return. Once we have PSCI
+	 * support we need to respond to kernel calls
+	 */
+	while (1)
+		wfe();
+}
+
+static void secmon_el3_init(void)
+{
+	uint32_t scr;
+
+	scr = raw_read_scr_el3();
+
+	/* Enable SMC */
+	scr &= ~(SCR_SMC_MASK);
+	scr |= SCR_SMC_ENABLE;
+
+	raw_write_scr_el3(scr);
+	isb();
+}
+
+static void secmon_init(void *arg)
+{
+	struct exc_state exc_state;
+	struct secmon_params *params = arg;
+
+	printk(BIOS_DEBUG, "ARM64: secmon in %s\n", __func__);
+
+	secmon_el3_init();
+
+	/*
+	 * Check if the arg is non-NULL
+	 * 1) If yes, we make an EL2 transition to that entry point
+	 * 2) If no, we just wait
+	 */
+	if (params == NULL) {
+		secmon_wait();
+	}
+
+	memset(&exc_state, 0, sizeof(exc_state));
+	exc_state.elx.spsr = get_eret_el(params->elx_el, params->elx_mode);
+
+	transition_with_entry(params->entry, params->arg, &exc_state);
+}
+
+/*
+ * This variable holds entry point for secmon init code. Once the stacks are
+ * setup by the stage_entry.S, it jumps to c_entry.
+ */
+void (*c_entry)(void*) = &secmon_init;
diff --git a/src/arch/arm64/armv8/secmon_loader.c b/src/arch/arm64/armv8/secmon_loader.c
new file mode 100644
index 0000000..066f1c1
--- /dev/null
+++ b/src/arch/arm64/armv8/secmon_loader.c
@@ -0,0 +1,111 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2014 Google Inc
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; version 2 of
+ * the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
+ * MA 02110-1301 USA
+ *
+ * secmon_loader.c: Responsible for loading the rmodule, providing entry point
+ * and parameter location for the rmodule.
+ */
+
+#include <arch/lib_helpers.h>
+#include <arch/secmon.h>
+#include <console/console.h>
+#include <rmodule.h>
+#include <string.h>
+
+/* SECMON entry point encoded as an rmodule */
+extern unsigned char _binary_secmon_start[];
+
+typedef void (*secmon_entry_t)(struct secmon_params *);
+
+void __attribute__((weak)) soc_get_secmon_base_size(uint64_t *secmon_base, size_t *secmon_size)
+{
+	/* Default weak implementation initializes to 0 */
+	*secmon_base = 0;
+	*secmon_size = 0;
+}
+
+static secmon_entry_t secmon_load_rmodule(void)
+{
+	struct rmodule secmon_mod;
+	uint64_t secmon_base;
+	size_t secmon_size;
+
+	/* Get base address and size of the area available for secure monitor
+	 * rmodule.
+	 */
+	soc_get_secmon_base_size(&secmon_base, &secmon_size);
+
+	if ((secmon_base == 0) || (secmon_size == 0)) {
+		printk(BIOS_ERR, "ARM64: secmon_base / secmon_size invalid\n");
+		return NULL;
+	}
+
+	printk(BIOS_DEBUG,"secmon_base:%lx,secmon_size:%lx\n",
+	       (unsigned long)secmon_base, (unsigned long)secmon_size);
+
+	/* Fail if can't parse secmon module */
+	if (rmodule_parse(&_binary_secmon_start, &secmon_mod)) {
+		printk(BIOS_ERR, "ARM64: secmon_mod not found\n");
+		return NULL;
+	}
+
+	/* Load rmodule at secmon_base */
+	if (rmodule_load((void *)secmon_base, &secmon_mod)) {
+		printk(BIOS_ERR, "ARM64:secmon_mod cannot load\n");
+		return NULL;
+	}
+
+	/* Identify the entry point for secure monitor */
+	return rmodule_entry(&secmon_mod);
+}
+
+void secmon_run(void (*entry)(void *), void *cb_tables)
+{
+	struct secmon_params params;
+	uint32_t scr;
+
+	printk(BIOS_SPEW, "payload jump @ %p\n", entry);
+
+	if (get_current_el() != EL3) {
+		printk(BIOS_DEBUG, "Secmon Error: Can only be loaded in EL3\n");
+		return;
+	}
+
+	secmon_entry_t doit = secmon_load_rmodule();
+
+	if (doit == NULL)
+		die("ARM64 Error: secmon load error");
+
+	printk(BIOS_DEBUG, "ARM64: Loaded the el3 monitor...jumping to %p\n",
+	       doit);
+
+	params.entry = entry;
+	params.arg = cb_tables;
+	params.elx_el = EL2;
+	params.elx_mode = SPSR_USE_L;
+
+	/* We want to enforce the following policies:
+	 * NS bit is set for lower EL
+	 */
+	scr = raw_read_scr_el3();
+	scr |= SCR_NS;
+	raw_write_scr_el3(scr);
+
+	doit(&params);
+}
diff --git a/src/arch/arm64/boot.c b/src/arch/arm64/boot.c
index 91980fb..6307e60 100644
--- a/src/arch/arm64/boot.c
+++ b/src/arch/arm64/boot.c
@@ -19,6 +19,7 @@
 
 #include <arch/cache.h>
 #include <arch/lib_helpers.h>
+#include <arch/secmon.h>
 #include <arch/stages.h>
 #include <arch/transition.h>
 #include <cbmem.h>
@@ -28,17 +29,20 @@
 
 void arch_payload_run(const struct payload *payload)
 {
-	void (*doit)(void *) = payload->entry;
+	void (*payload_entry)(void *) = payload->entry;
+
 	void *cb_tables = cbmem_find(CBMEM_ID_CBTABLE);
 	uint8_t current_el = get_current_el();
 
 	printk(BIOS_SPEW, "entry    = %p\n", payload->entry);
 
+	secmon_run(payload_entry, cb_tables);
+
 	/* If current EL is not EL3, jump to payload at same EL. */
 	if (current_el != EL3) {
 		cache_sync_instructions();
 		/* Point of no-return */
-		doit(cb_tables);
+		payload_entry(cb_tables);
 	}
 
 	/* If current EL is EL3, we transition to payload in EL2. */
diff --git a/src/arch/arm64/include/armv8/arch/secmon.h b/src/arch/arm64/include/armv8/arch/secmon.h
new file mode 100644
index 0000000..5245e31
--- /dev/null
+++ b/src/arch/arm64/include/armv8/arch/secmon.h
@@ -0,0 +1,43 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright 2014 Google Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __ARCH_ARM64_ARMV8_SECMON__
+#define __ARCH_ARM64_ARMV8_SECMON__
+
+#include <arch/cpu.h>
+
+#if IS_ENABLED(CONFIG_ARCH_USE_SECURE_MONITOR)
+
+struct secmon_params {
+	void (*entry)(void *);
+	void *arg;
+	uint8_t elx_el;
+	uint8_t elx_mode;
+};
+
+void secmon_run(void (*entry)(void *), void *arg);
+void soc_get_secmon_base_size(uint64_t *secmon_base, size_t *secmon_size);
+
+#else
+
+static inline void secmon_run(void (*entry)(void *), void *arg) {}
+
+#endif /* IS_ENABLED(CONFIG_ARCH_USE_SECURE_MONITOR) */
+
+#endif /*__ARCH_ARM64_ARMV8_SECMON__ */
diff --git a/src/console/Makefile.inc b/src/console/Makefile.inc
index 64d980b..75a75eb 100644
--- a/src/console/Makefile.inc
+++ b/src/console/Makefile.inc
@@ -18,3 +18,7 @@ romstage-y += die.c
 bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += vtxprintf.c printk.c
 bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += init.c console.c
 bootblock-$(CONFIG_BOOTBLOCK_CONSOLE) += die.c
+
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += vtxprintf.c printk.c
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += init.c console.c
+secmon-$(CONFIG_ARCH_USE_SECURE_MONITOR) += die.c
diff --git a/src/include/console/console.h b/src/include/console/console.h
index 38e05b3..b5de7d7 100644
--- a/src/include/console/console.h
+++ b/src/include/console/console.h
@@ -43,6 +43,7 @@ void __attribute__ ((noreturn)) die(const char *msg);
 
 #define __CONSOLE_ENABLE__ \
 	((ENV_BOOTBLOCK && CONFIG_BOOTBLOCK_CONSOLE) || \
+	ENV_SECMON || \
 	ENV_ROMSTAGE || ENV_RAMSTAGE || (ENV_SMM && CONFIG_DEBUG_SMI))
 
 #if __CONSOLE_ENABLE__
diff --git a/src/include/rules.h b/src/include/rules.h
index 22111e8..5740b77 100644
--- a/src/include/rules.h
+++ b/src/include/rules.h
@@ -28,24 +28,35 @@
 #define ENV_ROMSTAGE 0
 #define ENV_RAMSTAGE 0
 #define ENV_SMM 0
+#define ENV_SECMON 0
 
 #elif defined(__PRE_RAM__)
 #define ENV_BOOTBLOCK 0
 #define ENV_ROMSTAGE 1
 #define ENV_RAMSTAGE 0
 #define ENV_SMM 0
+#define ENV_SECMON 0
 
 #elif defined(__SMM__)
 #define ENV_BOOTBLOCK 0
 #define ENV_ROMSTAGE 0
 #define ENV_RAMSTAGE 0
 #define ENV_SMM 1
-#else
+#define ENV_SECMON 0
 
+#elif defined(__SECMON__)
+#define ENV_BOOTBLOCK 0
+#define ENV_ROMSTAGE 0
+#define ENV_RAMSTAGE 0
+#define ENV_SMM 0
+#define ENV_SECMON 1
+
+#else
 #define ENV_BOOTBLOCK 0
 #define ENV_ROMSTAGE 0
 #define ENV_RAMSTAGE 1
 #define ENV_SMM 0
+#define ENV_SECMON 0
 #endif
 
 /* For romstage and ramstage always build with simple device model, ie.
diff --git a/src/lib/Makefile.inc b/src/lib/Makefile.inc
index beb3abe..1e8c7d9 100644
--- a/src/lib/Makefile.inc
+++ b/src/lib/Makefile.inc
@@ -116,6 +116,7 @@ bootblock-y += halt.c
 romstage-y += halt.c
 ramstage-y += halt.c
 smm-y += halt.c
+secmon-y += halt.c
 
 ifeq ($(CONFIG_RELOCATABLE_MODULES),y)
 ramstage-y += rmodule.c



More information about the coreboot-gerrit mailing list