[coreboot-gerrit] Patch set updated for coreboot: 3bf7a68 arm64: add spin table support

Patrick Georgi (pgeorgi@google.com) gerrit at coreboot.org
Fri Mar 27 14:27:24 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/9084

-gerrit

commit 3bf7a68eb0bd3d63b5814000389a49146b3aeeef
Author: Aaron Durbin <adurbin at chromium.org>
Date:   Wed Sep 17 11:43:20 2014 -0500

    arm64: add spin table support
    
    There was a hacky and one-off spin table support in tegra132.
    Make this support generic for all arm64 chips.
    
    BUG=chrome-os-partner:32082
    BRANCH=None
    TEST=Ran with and without secure monitor booting smp into the kernel.
    
    Change-Id: I3425ab0c30983d4c74d0aa465dda38bb2c91c83b
    Signed-off-by: Patrick Georgi <pgeorgi at chromium.org>
    Original-Commit-Id: 024dc3f3e5262433a56ed14934db837b5feb1748
    Original-Change-Id: If12083a9afc3b2be663d36cfeed10f9b74bae3c8
    Original-Signed-off-by: Aaron Durbin <adurbin at chromium.org>
    Original-Reviewed-on: https://chromium-review.googlesource.com/218654
    Original-Reviewed-by: Furquan Shaikh <furquan at chromium.org>
---
 src/arch/arm64/Kconfig                  |   5 ++
 src/arch/arm64/Makefile.inc             |   1 +
 src/arch/arm64/armv8/secmon_loader.c    |  69 +++++++++++++++++-----
 src/arch/arm64/boot.c                   |   4 ++
 src/arch/arm64/include/arch/spintable.h |  50 ++++++++++++++++
 src/arch/arm64/spintable.c              | 100 ++++++++++++++++++++++++++++++++
 src/arch/arm64/spintable_asm.S          |  38 ++++++++++++
 src/include/cbmem.h                     |   4 +-
 8 files changed, 254 insertions(+), 17 deletions(-)

diff --git a/src/arch/arm64/Kconfig b/src/arch/arm64/Kconfig
index a070b90..2465bb1 100644
--- a/src/arch/arm64/Kconfig
+++ b/src/arch/arm64/Kconfig
@@ -20,4 +20,9 @@ config ARCH_USE_SECURE_MONITOR
 	default n
 	select RELOCATABLE_MODULES
 
+config ARCH_SPINTABLE
+	bool
+	default n
+	depends on ARCH_RAMSTAGE_ARM64
+
 source src/arch/arm64/armv8/Kconfig
diff --git a/src/arch/arm64/Makefile.inc b/src/arch/arm64/Makefile.inc
index 1dfaa96..c2caf64 100644
--- a/src/arch/arm64/Makefile.inc
+++ b/src/arch/arm64/Makefile.inc
@@ -123,6 +123,7 @@ ramstage-y += ../../lib/memset.c
 ramstage-y += ../../lib/memcpy.c
 ramstage-y += ../../lib/memmove.c
 ramstage-y += stage_entry.S
+ramstage-$(CONFIG_ARCH_SPINTABLE) += spintable.c spintable_asm.S
 ramstage-y += transition.c transition_asm.S
 
 rmodules_arm64-y += ../../lib/memset.c
diff --git a/src/arch/arm64/armv8/secmon_loader.c b/src/arch/arm64/armv8/secmon_loader.c
index 066f1c1..4d83764 100644
--- a/src/arch/arm64/armv8/secmon_loader.c
+++ b/src/arch/arm64/armv8/secmon_loader.c
@@ -24,6 +24,7 @@
 
 #include <arch/lib_helpers.h>
 #include <arch/secmon.h>
+#include <arch/spintable.h>
 #include <console/console.h>
 #include <rmodule.h>
 #include <string.h>
@@ -75,10 +76,43 @@ static secmon_entry_t secmon_load_rmodule(void)
 	return rmodule_entry(&secmon_mod);
 }
 
-void secmon_run(void (*entry)(void *), void *cb_tables)
+struct secmon_runit {
+	secmon_entry_t entry;
+	struct secmon_params bsp_params;
+	struct secmon_params secondary_params;
+};
+
+static void secmon_start(void *arg)
 {
-	struct secmon_params params;
 	uint32_t scr;
+	struct secmon_params *p = NULL;
+	struct secmon_runit *r = arg;
+
+	if (cpu_is_bsp())
+		p = &r->bsp_params;
+	else if (r->secondary_params.entry != NULL)
+		p = &r->secondary_params;
+
+	printk(BIOS_DEBUG, "CPU%x entering secure monitor.\n", cpu_info()->id);
+
+	/* 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);
+
+	r->entry(p);
+}
+
+void secmon_run(void (*entry)(void *), void *cb_tables)
+{
+	const struct spintable_attributes *spin_attrs;
+	static struct secmon_runit runit;
+	struct cpu_action action = {
+		.run = secmon_start,
+		.arg = &runit,
+	};
 
 	printk(BIOS_SPEW, "payload jump @ %p\n", entry);
 
@@ -87,25 +121,28 @@ void secmon_run(void (*entry)(void *), void *cb_tables)
 		return;
 	}
 
-	secmon_entry_t doit = secmon_load_rmodule();
+	runit.entry = secmon_load_rmodule();
 
-	if (doit == NULL)
+	if (runit.entry == NULL)
 		die("ARM64 Error: secmon load error");
 
 	printk(BIOS_DEBUG, "ARM64: Loaded the el3 monitor...jumping to %p\n",
-	       doit);
+	       runit.entry);
 
-	params.entry = entry;
-	params.arg = cb_tables;
-	params.elx_el = EL2;
-	params.elx_mode = SPSR_USE_L;
+	runit.bsp_params.entry = entry;
+	runit.bsp_params.arg = cb_tables;
+	runit.bsp_params.elx_el = EL2;
+	runit.bsp_params.elx_mode = SPSR_USE_L;
+	runit.secondary_params.elx_el = EL2;
+	runit.secondary_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);
+	spin_attrs = spintable_get_attributes();
+
+	if (spin_attrs != NULL) {
+		runit.secondary_params.entry = spin_attrs->entry;
+		runit.secondary_params.arg = spin_attrs->addr;
+	}
 
-	doit(&params);
+	arch_run_on_all_cpus_but_self_async(&action);
+	secmon_start(&runit);
 }
diff --git a/src/arch/arm64/boot.c b/src/arch/arm64/boot.c
index 6307e60..01630f3 100644
--- a/src/arch/arm64/boot.c
+++ b/src/arch/arm64/boot.c
@@ -21,6 +21,7 @@
 #include <arch/lib_helpers.h>
 #include <arch/secmon.h>
 #include <arch/stages.h>
+#include <arch/spintable.h>
 #include <arch/transition.h>
 #include <cbmem.h>
 #include <console/console.h>
@@ -38,6 +39,9 @@ void arch_payload_run(const struct payload *payload)
 
 	secmon_run(payload_entry, cb_tables);
 
+	/* Start the other CPUs spinning. */
+	spintable_start();
+
 	/* If current EL is not EL3, jump to payload at same EL. */
 	if (current_el != EL3) {
 		cache_sync_instructions();
diff --git a/src/arch/arm64/include/arch/spintable.h b/src/arch/arm64/include/arch/spintable.h
new file mode 100644
index 0000000..b583ddb
--- /dev/null
+++ b/src/arch/arm64/include/arch/spintable.h
@@ -0,0 +1,50 @@
+/*
+ * 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_SPINTABLE_H__
+#define __ARCH_SPINTABLE_H__
+
+struct spintable_attributes {
+	void (*entry)(void *);
+	void *addr;
+};
+
+#if IS_ENABLED(CONFIG_ARCH_SPINTABLE)
+
+/* Initialize spintable with provided monitor address. */
+void spintable_init(void *monitor_address);
+
+/* Start spinning on the non-boot CPUS. */
+void spintable_start(void);
+
+/* Return NULL on failure, otherwise the spintable info. */
+const struct spintable_attributes *spintable_get_attributes(void);
+
+#else /* IS_ENABLED(CONFIG_SPINTABLE) */
+
+static inline void spintable_init(void *monitor_address) {}
+static inline void spintable_start(void) {}
+static inline const struct spintable_attributes *spintable_get_attributes(void)
+{
+	return NULL;
+}
+
+#endif /* IS_ENABLED(CONFIG_SPINTABLE) */
+
+#endif /* __ARCH_SPINTABLE_H__ */
diff --git a/src/arch/arm64/spintable.c b/src/arch/arm64/spintable.c
new file mode 100644
index 0000000..7a1ab7f
--- /dev/null
+++ b/src/arch/arm64/spintable.c
@@ -0,0 +1,100 @@
+/*
+ * 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
+ */
+
+#include <arch/cache.h>
+#include <arch/spintable.h>
+#include <arch/transition.h>
+#include <console/console.h>
+#include <cpu/cpu.h>
+#include <cbmem.h>
+#include <string.h>
+
+static struct spintable_attributes spin_attrs;
+
+void spintable_init(void *monitor_address)
+{
+	extern void __wait_for_spin_table_request(void);
+	const size_t code_size = 4096;
+
+	if (monitor_address == NULL) {
+		printk(BIOS_ERR, "spintable: NULL address to monitor.\n");
+		return;
+	}
+
+	spin_attrs.entry = cbmem_add(CBMEM_ID_SPINTABLE, code_size);
+
+	if (spin_attrs.entry == NULL)
+		return;
+
+	spin_attrs.addr = monitor_address;
+
+	printk(BIOS_INFO, "spintable @ %p will monitor %p\n",
+		spin_attrs.entry, spin_attrs.addr);
+
+	/* Ensure the memory location is zero'd out. */
+	*(uint64_t *)monitor_address = 0;
+
+	memcpy(spin_attrs.entry, __wait_for_spin_table_request, code_size);
+
+	dcache_clean_invalidate_by_mva(monitor_address, sizeof(uint64_t));
+	dcache_clean_invalidate_by_mva(spin_attrs.entry, code_size);
+}
+
+static void spintable_enter(void *unused)
+{
+	struct exc_state state;
+	const struct spintable_attributes *attrs;
+	int current_el;
+
+	attrs = spintable_get_attributes();
+
+	current_el = get_current_el();
+
+	if (current_el != EL3)
+		attrs->entry(attrs->addr);
+
+	memset(&state, 0, sizeof(state));
+	state.elx.spsr = get_eret_el(EL2, SPSR_USE_L);
+
+	transition_with_entry(attrs->entry, attrs->addr, &state);
+}
+
+const struct spintable_attributes *spintable_get_attributes(void)
+{
+	if (spin_attrs.entry == NULL) {
+		printk(BIOS_ERR, "spintable: monitor code not present.\n");
+		return NULL;
+	}
+
+	return &spin_attrs;
+}
+
+void spintable_start(void)
+{
+	struct cpu_action action = {
+		.run = spintable_enter,
+	};
+
+	if (spintable_get_attributes() == NULL)
+		return;
+
+	printk(BIOS_INFO, "All non-boot CPUs to enter spintable.\n");
+
+	arch_run_on_all_cpus_but_self_async(&action);
+}
diff --git a/src/arch/arm64/spintable_asm.S b/src/arch/arm64/spintable_asm.S
new file mode 100644
index 0000000..3066b7e
--- /dev/null
+++ b/src/arch/arm64/spintable_asm.S
@@ -0,0 +1,38 @@
+/*
+ * 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
+ */
+
+#include <arch/asm.h>
+
+ENTRY(__wait_for_spin_table_request)
+	/* Entry here is in EL2 with the magic address in x0. */
+	mov	x28, x0
+1:
+	ldr	x27, [x28]
+	cmp	x27, xzr
+	b.ne	2f
+	wfe
+	b	1b
+2:
+	/* Entry into the kernel. */
+	mov	x0, xzr
+	mov	x1, xzr
+	mov	x2, xzr
+	mov	x3, xzr
+	br	x27
+ENDPROC(__wait_for_spin_table_request)
diff --git a/src/include/cbmem.h b/src/include/cbmem.h
index 49eaf48..f605191 100644
--- a/src/include/cbmem.h
+++ b/src/include/cbmem.h
@@ -73,6 +73,7 @@
 #define CBMEM_ID_SMM_SAVE_SPACE	0x07e9acee
 #define CBMEM_ID_RAM_OOPS	0x05430095
 #define CBMEM_ID_MEMINFO	0x494D454D
+#define CBMEM_ID_SPINTABLE	0x59175917
 #define CBMEM_ID_NONE		0x00000000
 #define CBMEM_ID_AGESA_RUNTIME	0x41474553
 #define CBMEM_ID_HOB_POINTER	0x484f4221
@@ -117,7 +118,8 @@ struct cbmem_id_to_name {
 	{ CBMEM_ID_REFCODE_CACHE,	"REFCODE $  " }, \
 	{ CBMEM_ID_POWER_STATE,		"POWER STATE" }, \
 	{ CBMEM_ID_RAM_OOPS,		"RAMOOPS    " }, \
-	{ CBMEM_ID_MEMINFO,		"MEM INFO   " },
+	{ CBMEM_ID_MEMINFO,		"MEM INFO   " }, \
+	{ CBMEM_ID_SPINTABLE,		"SPIN TABLE " },
 
 struct cbmem_entry;
 



More information about the coreboot-gerrit mailing list