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@chromium.org>
Original-Commit-Id: 5e40a21115aeac1cc3c73922bdc3e42d4cdb7d34
Original-Change-Id: I86d5e93583afac141ff61475bd05c8c82d17d926
Original-Signed-off-by: Furquan Shaikh <furquan@google.com>
Original-Reviewed-on: https://chromium-review.googlesource.com/214371
Original-Tested-by: Furquan Shaikh <furquan@chromium.org>
Original-Reviewed-by: Aaron Durbin <adurbin@chromium.org>
Original-Commit-Queue: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9080
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
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);
+}