summaryrefslogtreecommitdiff
path: root/src/arch/arm64/armv8
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/arm64/armv8')
-rw-r--r--src/arch/arm64/armv8/Makefile.inc4
-rw-r--r--src/arch/arm64/armv8/lib/Makefile.inc4
-rw-r--r--src/arch/arm64/armv8/secmon/Makefile.inc53
-rw-r--r--src/arch/arm64/armv8/secmon/psci.c705
-rw-r--r--src/arch/arm64/armv8/secmon/secmon.h29
-rw-r--r--src/arch/arm64/armv8/secmon/secmon_init.c132
-rw-r--r--src/arch/arm64/armv8/secmon/smc.c163
-rw-r--r--src/arch/arm64/armv8/secmon/trampoline.S47
-rw-r--r--src/arch/arm64/armv8/secmon_loader.c157
9 files changed, 0 insertions, 1294 deletions
diff --git a/src/arch/arm64/armv8/Makefile.inc b/src/arch/arm64/armv8/Makefile.inc
index 48358adb97..357159d6a7 100644
--- a/src/arch/arm64/armv8/Makefile.inc
+++ b/src/arch/arm64/armv8/Makefile.inc
@@ -17,8 +17,6 @@
subdirs-y += lib/
-subdirs-$(CONFIG_ARM64_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)
@@ -88,8 +86,6 @@ ramstage-y += cpu.S
ramstage-y += exception.c
ramstage-y += mmu.c
-ramstage-$(CONFIG_ARM64_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 c3de597c54..2bf1a37c7a 100644
--- a/src/arch/arm64/armv8/lib/Makefile.inc
+++ b/src/arch/arm64/armv8/lib/Makefile.inc
@@ -32,8 +32,4 @@ endif
ifeq ($(CONFIG_ARCH_RAMSTAGE_ARMV8_64),y)
ramstage-y += $(lib_access)
-ifeq ($(CONFIG_ARM64_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
deleted file mode 100644
index 7d66adfcc1..0000000000
--- a/src/arch/arm64/armv8/secmon/Makefile.inc
+++ /dev/null
@@ -1,53 +0,0 @@
-################################################################################
-##
-## 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.
-##
-################################################################################
-
-$(eval $(call create_class_compiler,secmon,arm64))
-
-SECMON_DIR=$(obj)/arch/arm64/armv8/secmon
-SECMON_BIN=$(SECMON_DIR)/secmon
-SECMON_OBJ=$(SECMON_BIN).o
-SECMON_ELF=$(SECMON_BIN).elf
-SECMON_RMOD=$(SECMON_ELF).rmod
-SECMON_RAMSTAGE=$(SECMON_DIR)/secmon.manual
-
-secmon-generic-ccopts += -I$(src)/arch/arm64/include/armv8/ -include $(src)/include/kconfig.h -D__SECMON__
-
-secmon-y += secmon_init.c
-secmon-y += psci.c
-secmon-y += smc.c
-secmon-y += trampoline.S
-secmon-y += ../cache.c
-secmon-y += ../cache_helpers.S
-secmon-y += ../cpu.S
-secmon-y += ../exception.c
-secmon-y += ../../cpu.c
-secmon-y += ../../transition_asm.S ../../transition.c
-secmon-y += ../../../../drivers/gic/gic.c
-
-ramstage-srcs += $(SECMON_RAMSTAGE)
-
-$(SECMON_OBJ): $$(secmon-objs)
- $(CC_secmon) $(LDFLAGS) -nostdlib -r -o $@ $^
-
-$(eval $(call rmodule_link,$(SECMON_ELF), $(SECMON_OBJ), 8192,arm64))
-
-$(SECMON_BIN): $(SECMON_RMOD)
- $(OBJCOPY_secmon) -O binary $< $@
-
-$(SECMON_BIN).ramstage.manual: $(SECMON_BIN)
- @printf " OBJCOPY $(subst $(obj)/,,$(@))\n"
- cd $(dir $@); $(OBJCOPY_secmon) -I binary $(notdir $<) -O elf64-littleaarch64 -B aarch64 $(notdir $@)
diff --git a/src/arch/arm64/armv8/secmon/psci.c b/src/arch/arm64/armv8/secmon/psci.c
deleted file mode 100644
index 9ae8cc5c7f..0000000000
--- a/src/arch/arm64/armv8/secmon/psci.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * 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.
- */
-
-#include <gic.h>
-#include <string.h>
-#include <stdlib.h>
-#include <smp/spinlock.h>
-#include <arch/cpu.h>
-#include <arch/psci.h>
-#include <arch/smc.h>
-#include <arch/transition.h>
-#include <arch/lib_helpers.h>
-#include <console/console.h>
-#include "secmon.h"
-
-DECLARE_SPIN_LOCK(psci_spinlock);
-
-/* Root of PSCI node tree. */
-static struct psci_node psci_root;
-
-/* Array of all the psci_nodes in system. */
-static size_t psci_num_nodes;
-static struct psci_node **psci_nodes;
-
-static inline void psci_lock(void)
-{
- spin_lock(&psci_spinlock);
-}
-
-static inline void psci_unlock(void)
-{
- spin_unlock(&psci_spinlock);
-}
-
-static inline int psci_state_locked(const struct psci_node *e)
-{
- return e->state;
-}
-
-static inline void psci_set_state_locked(struct psci_node *e, int s)
-{
- e->state = s;
-}
-
-static struct psci_node *psci_node_lookup(uint64_t mpidr, int level)
-{
- size_t i;
-
- /* The array of node pointers are in depth-first order of the tree. */
- for (i = 0; i < psci_num_nodes; i++) {
- struct psci_node *current = psci_nodes[i];
-
- if (current->mpidr > mpidr)
- break;
- if (current->mpidr < mpidr)
- continue;
- if (current->level == level)
- return current;
- }
- return NULL;
-}
-
-static inline struct psci_node *node_self(void)
-{
- return psci_node_lookup(cpu_info()->mpidr, PSCI_AFFINITY_LEVEL_0);
-}
-
-/* Find the ancestor of node affected by a state transition limited by level. */
-static struct psci_node *psci_find_ancestor(struct psci_node *e, int level,
- int state)
-{
- struct psci_node *p;
-
- /* If all siblings of the node are already off then parent can be
- * set to off as well. */
- if (state == PSCI_STATE_OFF) {
- while (1) {
- size_t i;
- struct psci_node *s;
-
- if (psci_root_node(e))
- return e;
-
- p = psci_node_parent(e);
-
- if (p->level > level)
- return e;
-
- for (i = 0; i < p->children.num; i++) {
- s = &p->children.nodes[i];
- /* Don't check target. */
- if (s == e)
- continue;
- if (psci_state_locked(s) != PSCI_STATE_OFF)
- return e;
- }
-
- e = p;
- }
- }
-
- /* All ancestors in state OFF are affected. */
- if (state == PSCI_STATE_ON_PENDING) {
- while (1) {
- /* At the root. Return last affected node. */
- if (psci_root_node(e))
- return e;
-
- p = psci_node_parent(e);
-
- if (p->level > level)
- return e;
-
- /* This parent is already ON. */
- if (psci_state_locked(p) != PSCI_STATE_OFF)
- return e;
-
- e = p;
- }
- }
-
- /* Default to returning node passed in. */
- return e;
-}
-
-static void psci_set_hierarchy_state(struct psci_node *from,
- struct psci_node *to,
- int state)
-{
- struct psci_node *end;
-
- end = psci_node_parent(to);
-
- while (from != end) {
- /* Raced with another CPU as state is already set. */
- if (psci_state_locked(from) == state)
- break;
- psci_set_state_locked(from, state);
- from = psci_node_parent(from);
- }
-}
-
-static void psci_cpu_on_callback(void *arg)
-{
- struct exc_state state;
- int target_el;
- struct psci_node *e = arg;
-
- psci_lock();
- psci_set_hierarchy_state(e, e->cpu_state.ancestor, PSCI_STATE_ON);
- psci_unlock();
-
- /* Target EL is determined if HVC is enabled or not. */
- target_el = (raw_read_scr_el3() & SCR_HVC_ENABLE) ? EL2 : EL1;
-
- memset(&state, 0, sizeof(state));
- state.elx.spsr = get_eret_el(target_el, SPSR_USE_H);
- transition_with_entry(e->cpu_state.startup.run,
- e->cpu_state.startup.arg, &state);
-}
-
-static void psci_cpu_on_prepare(struct psci_cmd *cmd,
- const struct cpu_action *a)
-{
- struct psci_node *ancestor;
- struct psci_node *e;
- int state = PSCI_STATE_ON_PENDING;
-
- e = cmd->target;
- e->cpu_state.startup = *a;
- ancestor = psci_find_ancestor(e, PSCI_AFFINITY_LEVEL_HIGHEST, state);
- e->cpu_state.ancestor = ancestor;
- cmd->ancestor = ancestor;
-}
-
-static int psci_schedule_cpu_on(struct psci_node *e)
-{
- struct cpu_info *ci;
- struct cpu_action action = {
- .run = &psci_cpu_on_callback,
- .arg = e,
- };
-
- ci = e->cpu_state.ci;
- if (ci == NULL || arch_run_on_cpu_async(ci->id, &action)) {
- psci_set_hierarchy_state(e, e->cpu_state.ancestor,
- PSCI_STATE_OFF);
- return PSCI_RET_INTERNAL_FAILURE;
- }
-
- return PSCI_RET_SUCCESS;
-}
-
-static void psci_cpu_resume_prepare(struct psci_cmd *cmd,
- const struct cpu_action *a)
-{
- struct psci_node *ancestor;
- struct psci_node *e;
- int state = PSCI_STATE_ON_PENDING;
-
- e = cmd->target;
- e->cpu_state.resume = *a;
- ancestor = psci_find_ancestor(e, PSCI_AFFINITY_LEVEL_HIGHEST, state);
- e->cpu_state.ancestor = ancestor;
- cmd->ancestor = ancestor;
-}
-
-static void psci_schedule_cpu_resume(struct psci_node *e)
-{
- struct cpu_info *ci;
- struct cpu_action *action;
-
- if (e->cpu_state.resume.run == NULL)
- return;
-
- ci = e->cpu_state.ci;
- action = &e->cpu_state.resume;
-
- arch_run_on_cpu(ci->id, action);
-}
-
-void psci_turn_on_self(const struct cpu_action *action)
-{
- struct psci_node *e = node_self();
- struct psci_cmd cmd = {
- .type = PSCI_CMD_ON,
- };
-
- if (e == NULL) {
- printk(BIOS_ERR, "Couldn't turn on self: mpidr %llx\n",
- cpu_info()->mpidr);
- return;
- }
-
- cmd.target = e;
-
- psci_lock();
- psci_cpu_on_prepare(&cmd, action);
- psci_set_hierarchy_state(e, cmd.ancestor, PSCI_STATE_ON_PENDING);
- psci_unlock();
-
- psci_schedule_cpu_on(e);
-}
-
-void psci_cpu_entry(void)
-{
- gic_enable();
-
- /*
- * Just wait for an action to be performed.
- */
- psci_schedule_cpu_resume(node_self());
- secmon_wait_for_action();
-}
-
-static void psci_cpu_resume(void *arg)
-{
- uint64_t power_state = (uint64_t)arg;
- struct psci_node *e;
- struct psci_power_state state;
- struct psci_cmd cmd = {
- .type = PSCI_CMD_RESUME,
- };
-
- psci_power_state_unpack(power_state, &state);
-
- psci_lock();
-
- e = node_self();
- /* clear the resume action after resume */
- e->cpu_state.resume.run = NULL;
- e->cpu_state.resume.arg = NULL;
-
- cmd.target = e;
- cmd.state = &state;
- soc_psci_ops.cmd_prepare(&cmd);
-
- psci_unlock();
-
- soc_psci_ops.cmd_commit(&cmd);
-
- psci_lock();
- psci_set_hierarchy_state(e, e->cpu_state.ancestor, PSCI_STATE_ON);
- psci_unlock();
-
- psci_schedule_cpu_on(node_self());
-}
-
-static void psci_cpu_suspend(struct psci_func *pf)
-{
- uint64_t power_state;
- uint64_t entry;
- uint64_t context_id;
- struct psci_node *e;
- struct psci_power_state state;
- struct cpu_action action;
- struct cpu_action resume_action;
- struct psci_cmd cmd = {
- .type = PSCI_CMD_SUSPEND,
- };
- int ret;
-
- power_state = psci64_arg(pf, PSCI_PARAM_0);
- entry = psci64_arg(pf, PSCI_PARAM_1);
- context_id = psci64_arg(pf, PSCI_PARAM_2);
- psci_power_state_unpack(power_state, &state);
-
- psci_lock();
-
- e = node_self();
- cmd.target = e;
- cmd.state = &state;
- action.run = (void *)entry;
- action.arg = (void *)context_id;
- resume_action.run = &psci_cpu_resume;
- resume_action.arg = (void*)power_state;
-
- psci_cpu_on_prepare(&cmd, &action);
- psci_cpu_resume_prepare(&cmd, &resume_action);
-
- ret = soc_psci_ops.cmd_prepare(&cmd);
-
- if (ret == PSCI_RET_SUCCESS)
- psci_set_hierarchy_state(e, cmd.ancestor, PSCI_STATE_OFF);
-
- psci_unlock();
-
- if (ret != PSCI_RET_SUCCESS)
- return psci32_return(pf, ret);
-
- gic_disable();
-
- ret = soc_psci_ops.cmd_commit(&cmd);
-
- /* PSCI_POWER_STATE_TYPE_STANDBY mode only */
-
- psci_lock();
- resume_action.run = NULL;
- resume_action.arg = NULL;
- psci_cpu_resume_prepare(&cmd, &resume_action);
- psci_unlock();
-
- if (ret != PSCI_RET_SUCCESS)
- return psci32_return(pf, ret);
-
- psci_lock();
- psci_set_hierarchy_state(e, e->cpu_state.ancestor, PSCI_STATE_ON);
- psci_unlock();
-
- psci32_return(pf, PSCI_RET_SUCCESS);
-}
-
-static void psci_cpu_on(struct psci_func *pf)
-{
- uint64_t entry;
- uint64_t target_mpidr;
- uint64_t context_id;
- int cpu_state;
- int ret;
- struct psci_node *e;
- struct cpu_action action;
- struct psci_cmd cmd = {
- .type = PSCI_CMD_ON,
- };
-
- target_mpidr = psci64_arg(pf, PSCI_PARAM_0);
- entry = psci64_arg(pf, PSCI_PARAM_1);
- context_id = psci64_arg(pf, PSCI_PARAM_2);
-
- e = psci_node_lookup(target_mpidr, PSCI_AFFINITY_LEVEL_0);
-
- if (e == NULL) {
- psci32_return(pf, PSCI_RET_INVALID_PARAMETERS);
- return;
- }
-
- psci_lock();
- cpu_state = psci_state_locked(e);
-
- if (cpu_state == PSCI_STATE_ON_PENDING) {
- psci32_return(pf, PSCI_RET_ON_PENDING);
- psci_unlock();
- return;
- } else if (cpu_state == PSCI_STATE_ON) {
- psci32_return(pf, PSCI_RET_ALREADY_ON);
- psci_unlock();
- return;
- }
-
- cmd.target = e;
- action.run = (void *)entry;
- action.arg = (void *)context_id;
- psci_cpu_on_prepare(&cmd, &action);
-
- ret = soc_psci_ops.cmd_prepare(&cmd);
-
- if (ret == PSCI_RET_SUCCESS)
- psci_set_hierarchy_state(e, cmd.ancestor,
- PSCI_STATE_ON_PENDING);
-
- psci_unlock();
-
- if (ret != PSCI_RET_SUCCESS)
- return psci32_return(pf, ret);
-
- ret = soc_psci_ops.cmd_commit(&cmd);
-
- if (ret != PSCI_RET_SUCCESS) {
- psci_lock();
- psci_set_hierarchy_state(e, cmd.ancestor, PSCI_STATE_OFF);
- psci_unlock();
- return psci32_return(pf, ret);
- }
-
- psci32_return(pf, psci_schedule_cpu_on(e));
-}
-
-static int psci_turn_off_node(struct psci_node *e, int level,
- int state_id)
-{
- int ret;
- struct psci_cmd cmd = {
- .type = PSCI_CMD_OFF,
- .state_id = state_id,
- .target = e,
- };
-
- psci_lock();
-
- cmd.ancestor = psci_find_ancestor(e, level, PSCI_STATE_OFF);
-
- ret = soc_psci_ops.cmd_prepare(&cmd);
-
- if (ret == PSCI_RET_SUCCESS)
- psci_set_hierarchy_state(e, cmd.ancestor, PSCI_STATE_OFF);
-
- psci_unlock();
-
- if (ret != PSCI_RET_SUCCESS)
- return ret;
-
- gic_disable();
-
- /* Should never return. */
- ret = soc_psci_ops.cmd_commit(&cmd);
-
- /* Adjust ret to be an error. */
- if (ret == PSCI_RET_SUCCESS)
- ret = PSCI_RET_INTERNAL_FAILURE;
-
- /* Turn things back on. */
- psci_lock();
- psci_set_hierarchy_state(e, cmd.ancestor, PSCI_STATE_ON);
- psci_unlock();
-
- return ret;
-}
-
-int psci_turn_off_self(void)
-{
- struct psci_node *e = node_self();
-
- if (e == NULL) {
- printk(BIOS_ERR, "No PSCI node for MPIDR %llx.\n",
- cpu_info()->mpidr);
- return PSCI_RET_INTERNAL_FAILURE;
- }
-
- /* -1 state id indicates to SoC to make its own decision for
- * internal state when powering off the node. */
- return psci_turn_off_node(e, PSCI_AFFINITY_LEVEL_HIGHEST, -1);
-}
-
-static int psci_handler(struct smc_call *smc)
-{
- struct psci_func pf_storage;
- struct psci_func *pf = &pf_storage;
-
- psci_func_init(pf, smc);
-
- switch (pf->id) {
- case PSCI_CPU_SUSPEND64:
- psci_cpu_suspend(pf);
- break;
- case PSCI_CPU_ON64:
- psci_cpu_on(pf);
- break;
- case PSCI_CPU_OFF32:
- psci32_return(pf, psci_turn_off_self());
- break;
- default:
- psci32_return(pf, PSCI_RET_NOT_SUPPORTED);
- break;
- }
-
- return 0;
-}
-
-static void psci_link_cpu_info(void *arg)
-{
- struct psci_node *e = node_self();
-
- if (e == NULL) {
- printk(BIOS_ERR, "No PSCI node for MPIDR %llx.\n",
- cpu_info()->mpidr);
- return;
- }
-
- e->cpu_state.ci = cpu_info();
-}
-
-static int psci_init_node(struct psci_node *e,
- struct psci_node *parent,
- int level, uint64_t mpidr)
-{
- size_t i;
- uint64_t mpidr_inc;
- struct psci_node_group *ng;
- size_t num_children;
-
- memset(e, 0, sizeof(*e));
- e->mpidr = mpidr;
- psci_set_state_locked(e, PSCI_STATE_OFF);
- e->parent = parent;
- e->level = level;
-
- if (level == PSCI_AFFINITY_LEVEL_0)
- return 0;
-
- num_children = soc_psci_ops.children_at_level(level, mpidr);
-
- if (num_children == 0)
- return 0;
-
- ng = &e->children;
- ng->num = num_children;
- ng->nodes = malloc(ng->num * sizeof(struct psci_node));
- if (ng->nodes == NULL) {
- printk(BIOS_DEBUG, "PSCI: Allocation failure at level %d\n",
- level);
- return -1;
- }
-
- /* Switch to next level below. */
- level = psci_level_below(level);
- mpidr_inc = mpidr_mask(!!(level == PSCI_AFFINITY_LEVEL_3),
- !!(level == PSCI_AFFINITY_LEVEL_2),
- !!(level == PSCI_AFFINITY_LEVEL_1),
- !!(level == PSCI_AFFINITY_LEVEL_0));
-
- for (i = 0; i < ng->num; i++) {
- struct psci_node *c = &ng->nodes[i];
-
- /* Recursively initialize the nodes. */
- if (psci_init_node(c, e, level, mpidr))
- return -1;
- mpidr += mpidr_inc;
- }
-
- return 0;
-}
-
-static size_t psci_count_children(struct psci_node *e)
-{
- size_t i;
- size_t count;
-
- if (e->level == PSCI_AFFINITY_LEVEL_0)
- return 0;
-
- count = e->children.num;
- for (i = 0; i < e->children.num; i++)
- count += psci_count_children(&e->children.nodes[i]);
-
- return count;
-}
-
-static size_t psci_write_nodes(struct psci_node *e, size_t index)
-{
- size_t i;
-
- /*
- * Recursively save node pointers in array. Node pointers are
- * ordered in ascending mpidr and descending level within same mpidr.
- * i.e. each node is saved in depth-first order of the tree.
- */
- if (e->level != PSCI_AFFINITY_ROOT) {
- psci_nodes[index] = e;
- index++;
- }
-
- if (e->level == PSCI_AFFINITY_LEVEL_0)
- return index;
-
- for (i = 0; i < e->children.num; i++)
- index = psci_write_nodes(&e->children.nodes[i], index);
-
- return index;
-}
-
-static int psci_allocate_nodes(void)
-{
- int level;
- size_t num_children;
- uint64_t mpidr;
- struct psci_node *e;
-
- mpidr = 0;
- level = PSCI_AFFINITY_ROOT;
-
- /* Find where the root should start. */
- while (psci_level_below(level) >= PSCI_AFFINITY_LEVEL_0) {
- num_children = soc_psci_ops.children_at_level(level, mpidr);
-
- if (num_children == 0) {
- printk(BIOS_ERR, "PSCI: No children at level %d!\n",
- level);
- return -1;
- }
-
- /* The root starts where the affinity levels branch. */
- if (num_children > 1)
- break;
-
- level = psci_level_below(level);
- }
-
- if (psci_init_node(&psci_root, NULL, level, mpidr)) {
- printk(BIOS_ERR, "PSCI init node failure.\n");
- return -1;
- }
-
- num_children = psci_count_children(&psci_root);
- /* Count the root node if isn't a fake node. */
- if (psci_root.level != PSCI_AFFINITY_ROOT)
- num_children++;
-
- psci_nodes = malloc(num_children * sizeof(void *));
- psci_num_nodes = num_children;
-
- if (psci_nodes == NULL) {
- printk(BIOS_ERR, "PSCI node pointer array failure.\n");
- return -1;
- }
-
- num_children = psci_write_nodes(&psci_root, 0);
- if (num_children != psci_num_nodes) {
- printk(BIOS_ERR, "Wrong nodes written: %zd vs %zd.\n",
- num_children, psci_num_nodes);
- return -1;
- }
-
- /*
- * By default all nodes are set to PSCI_STATE_OFF. In order not
- * to race with other CPUs turning themselves off set the BSPs
- * affinity node to ON.
- */
- e = node_self();
- if (e == NULL) {
- printk(BIOS_ERR, "No PSCI node for BSP.\n");
- return -1;
- }
- psci_set_state_locked(e, PSCI_STATE_ON);
-
- return 0;
-}
-
-void psci_init(uintptr_t cpu_on_entry)
-{
- struct cpu_action action = {
- .run = &psci_link_cpu_info,
- };
-
- if (psci_allocate_nodes()) {
- printk(BIOS_ERR, "PSCI support not enabled.\n");
- return;
- }
-
- if (arch_run_on_all_cpus_async(&action))
- printk(BIOS_ERR, "Error linking cpu_info to PSCI nodes.\n");
-
- /* Register PSCI handlers. */
- if (smc_register_range(PSCI_CPU_SUSPEND32, PSCI_CPU_ON32,
- &psci_handler))
- printk(BIOS_ERR, "Couldn't register PSCI handler.\n");
-
- if (smc_register_range(PSCI_CPU_SUSPEND64, PSCI_CPU_ON64,
- &psci_handler))
- printk(BIOS_ERR, "Couldn't register PSCI handler.\n");
-
- /* Inform SoC layer of CPU_ON entry point. */
- psci_soc_init(cpu_on_entry);
-}
diff --git a/src/arch/arm64/armv8/secmon/secmon.h b/src/arch/arm64/armv8/secmon/secmon.h
deleted file mode 100644
index 26ce9fc22f..0000000000
--- a/src/arch/arm64/armv8/secmon/secmon.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.
- */
-
-#ifndef __SECMON_SECMON_H__
-#define __SECMON_SECMON_H__
-
-/*
- * The secmon_trampoline() switches mode to EL3t, reinitializing both
- * EL3t and EL3h stacks.
- */
-void secmon_trampoline(void *entry, void *arg);
-
-/* Wait for action to take place. */
-void secmon_wait_for_action(void);
-
-#endif /* __SECMON_SECMON_H__ */
diff --git a/src/arch/arm64/armv8/secmon/secmon_init.c b/src/arch/arm64/armv8/secmon/secmon_init.c
deleted file mode 100644
index 2ac59fbb5f..0000000000
--- a/src/arch/arm64/armv8/secmon/secmon_init.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.
- */
-
-#include <arch/barrier.h>
-#include <arch/cache.h>
-#include <arch/io.h>
-#include <arch/exception.h>
-#include <arch/lib_helpers.h>
-#include <arch/psci.h>
-#include <arch/secmon.h>
-#include <arch/smc.h>
-#include <arch/startup.h>
-#include <console/console.h>
-#include <stddef.h>
-#include "secmon.h"
-
-static void secmon_init(struct secmon_params *params, int bsp);
-
-static void secmon_init_bsp(void *arg)
-{
- secmon_init(arg, 1);
-}
-
-static void secmon_init_nonbsp(void *arg)
-{
- secmon_init(arg, 0);
-}
-
-/*
- * 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[2])(void *) = { &secmon_init_bsp, &secmon_init_nonbsp };
-
-static void cpu_resume(void *unused)
-{
- psci_cpu_entry();
-}
-
-static void cpu_resume_init(void)
-{
- /* Change entry points into secmon. */
- c_entry[0] = c_entry[1] = cpu_resume;
- dcache_clean_by_mva(&c_entry, sizeof(c_entry));
-
- /* Back up state. */
- startup_save_cpu_data();
-}
-
-static void start_up_cpu(void *arg)
-{
- struct secmon_params *params = arg;
- struct cpu_action *action;
-
- if (cpu_is_bsp())
- action = &params->bsp;
- else
- action = &params->secondary;
-
-
- if (action->run == NULL)
- psci_turn_off_self();
-
- psci_turn_on_self(action);
-}
-
-static void cpu_init(int bsp)
-{
- struct cpu_info *ci = cpu_info();
-
- ci->id = smp_processor_id();
- cpu_mark_online(ci);
-
- if (bsp)
- cpu_set_bsp();
-}
-
-static void wait_for_all_cpus(size_t expected)
-{
- while (cpus_online() != expected)
- ;
-}
-
-static void secmon_init(struct secmon_params *params, int bsp)
-{
- struct cpu_action action = {
- .run = start_up_cpu,
- .arg = params,
- };
-
- exception_hwinit();
- cpu_init(bsp);
-
- if (!cpu_is_bsp())
- secmon_wait_for_action();
-
- /* Wait for all CPUs to enter secmon. */
- wait_for_all_cpus(params->online_cpus);
-
- smc_init();
- psci_init((uintptr_t)arm64_cpu_startup_resume);
-
- /* Initialize the resume path. */
- cpu_resume_init();
-
- /* Make sure all non-BSP CPUs take action before the BSP. */
- arch_run_on_all_cpus_but_self_async(&action);
- /* Turn on BSP. */
- start_up_cpu(params);
-
- printk(BIOS_ERR, "CPU turn on failed for BSP.\n");
-
- secmon_wait_for_action();
-}
-
-void secmon_wait_for_action(void)
-{
- arch_cpu_wait_for_action();
-}
diff --git a/src/arch/arm64/armv8/secmon/smc.c b/src/arch/arm64/armv8/secmon/smc.c
deleted file mode 100644
index 6fa6294933..0000000000
--- a/src/arch/arm64/armv8/secmon/smc.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * 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.
- */
-
-#include <string.h>
-#include <stdlib.h>
-#include <arch/cpu.h>
-#include <arch/smc.h>
-#include <arch/exception.h>
-#include <arch/lib_helpers.h>
-#include <console/console.h>
-
-enum {
- /* SMC called from AARCH32 */
- EC_SMC_AARCH32 = 0x13,
- /* SMC called from AARCH64 */
- EC_SMC_AARCH64 = 0x17,
-
- SMC_NUM_RANGES = 8,
-};
-
-struct smc_range {
- uint32_t func_begin;
- uint32_t func_end;
- int (*handler)(struct smc_call *);
-};
-
-struct smc_ranges {
- size_t used;
- struct smc_range handlers[SMC_NUM_RANGES];
-};
-
-static struct smc_ranges smc_functions;
-
-static struct smc_range *smc_handler_by_function(uint32_t fid)
-{
- int i;
-
- for (i = 0; i < smc_functions.used; i++) {
- struct smc_range *r = &smc_functions.handlers[i];
-
- if (fid >= r->func_begin && fid <= r->func_end)
- return r;
- }
-
- return NULL;
-}
-
-int smc_register_range(uint32_t min, uint32_t max, int (*h)(struct smc_call *))
-{
- struct smc_range *r;
-
- if (smc_functions.used == SMC_NUM_RANGES)
- return -1;
-
- if (min > max)
- return -1;
-
- /* This check isn't exhaustive but it's fairly quick. */
- if (smc_handler_by_function(min) || smc_handler_by_function(max))
- return -1;
-
- r = &smc_functions.handlers[smc_functions.used];
- r->func_begin = min;
- r->func_end = max;
- r->handler = h;
- smc_functions.used++;
-
- return 0;
-}
-
-static int smc_cleanup(struct exc_state *state, struct smc_call *smc, int ret)
-{
- memcpy(&state->regs.x, &smc->results, sizeof(smc->results));
-
- return ret;
-}
-
-static int smc_return_with_error(struct exc_state *state, struct smc_call *smc)
-{
- smc32_return(smc, SMC_UNKNOWN_FUNC);
- return smc_cleanup(state, smc, EXC_RET_HANDLED);
-}
-
-static int smc_handler(struct exc_state *state, uint64_t vector_id)
-{
- struct smc_call smc_storage;
- struct smc_call *smc = &smc_storage;
- uint32_t exception_class;
- uint32_t esr;
- struct smc_range *r;
-
- memcpy(&smc->args, &state->regs.x, sizeof(smc->args));
- memcpy(&smc->results, &state->regs.x, sizeof(smc->results));
-
- esr = raw_read_esr_el3();
- exception_class = (esr >> 26) & 0x3f;
-
- /* No support for SMC calls from AARCH32 */
- if (exception_class == EC_SMC_AARCH32)
- return smc_return_with_error(state, smc);
-
- /* Check to ensure this is an SMC from AARCH64. */
- if (exception_class != EC_SMC_AARCH64)
- return EXC_RET_IGNORED;
-
- /* Ensure immediate value is 0. */
- if ((esr & 0xffff) != 0)
- return smc_return_with_error(state, smc);
-
- r = smc_handler_by_function(smc_function_id(smc));
-
- if (r != NULL) {
- if (!r->handler(smc))
- return smc_cleanup(state, smc, EXC_RET_HANDLED);
- }
-
- return smc_return_with_error(state, smc);
-}
-
-/* SMC calls can be generated by 32-bit or 64-bit code. */
-static struct exception_handler smc_handler64 = {
- .handler = &smc_handler,
-};
-
-static struct exception_handler smc_handler32 = {
- .handler = &smc_handler,
-};
-
-static void enable_smc(void *arg)
-{
- uint32_t scr;
-
- /* Enable SMC */
- scr = raw_read_scr_el3();
- scr &= ~(SCR_SMC_MASK);
- scr |= SCR_SMC_ENABLE;
- raw_write_scr_el3(scr);
-}
-
-void smc_init(void)
-{
- struct cpu_action action = {
- .run = enable_smc,
- };
-
- arch_run_on_all_cpus_async(&action);
-
- /* Register SMC handlers. */
- exception_handler_register(EXC_VID_LOW64_SYNC, &smc_handler64);
- exception_handler_register(EXC_VID_LOW32_SYNC, &smc_handler32);
-}
diff --git a/src/arch/arm64/armv8/secmon/trampoline.S b/src/arch/arm64/armv8/secmon/trampoline.S
deleted file mode 100644
index 5db904a429..0000000000
--- a/src/arch/arm64/armv8/secmon/trampoline.S
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * 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.
- */
-
-#include <arch/asm.h>
-
-/*
- * Call entry(arg) after reinitializing stack state.
- * void secmon_trampoline(void *entry, void *arg);
- */
-ENTRY(secmon_trampoline)
- mov x22, x0 /* x22 = function pointer */
- mov x23, x1 /* x23 = argument */
- bl smp_processor_id /* x0 = cpu */
- mov x24, x0
-
- /* Set the exception stack for this cpu. */
- bl cpu_get_exception_stack
- msr SPSel, #1
- isb
- mov sp, x0
-
- /* Have stack pointer use SP_EL0. */
- msr SPSel, #0
- isb
-
- /* Set stack for this cpu. */
- mov x0, x24 /* x0 = cpu */
- bl cpu_get_stack
- mov sp, x0
-
- /* Call the function with specified argument. */
- mov x1, x22
- mov x0, x23
- br x1
-ENDPROC(secmon_trampoline)
diff --git a/src/arch/arm64/armv8/secmon_loader.c b/src/arch/arm64/armv8/secmon_loader.c
deleted file mode 100644
index 946ca0f9e9..0000000000
--- a/src/arch/arm64/armv8/secmon_loader.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * 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.
- *
- * secmon_loader.c: Responsible for loading the rmodule, providing entry point
- * and parameter location for the rmodule.
- */
-
-#include <arch/cache.h>
-#include <arch/lib_helpers.h>
-#include <arch/secmon.h>
-#include <arch/spintable.h>
-#include <arch/stages.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);
-}
-
-struct secmon_runit {
- secmon_entry_t entry;
- struct secmon_params params;
-};
-
-static void secmon_start(void *arg)
-{
- uint32_t scr;
- secmon_entry_t entry;
- struct secmon_params *p;
- struct secmon_runit *r = arg;
-
- entry = r->entry;
- p = &r->params;
-
- /* Obtain secondary entry point for non-BSP CPUs. */
- if (!cpu_is_bsp())
- entry = secondary_entry_point(entry);
-
- printk(BIOS_DEBUG, "CPU%x entering secure monitor %p.\n",
- cpu_info()->id, entry);
-
- /* 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);
-
- /* Invalidate instruction cache. Necessary for non-BSP. */
- icache_invalidate_all();
- entry(p);
-}
-
-static void fill_secmon_params(struct secmon_params *p,
- void (*bsp_entry)(void *), void *bsp_arg)
-{
- const struct spintable_attributes *spin_attrs;
-
- memset(p, 0, sizeof(*p));
-
- p->online_cpus = cpus_online();
-
- spin_attrs = spintable_get_attributes();
-
- if (spin_attrs != NULL) {
- p->secondary.run = spin_attrs->entry;
- p->secondary.arg = spin_attrs->addr;
- }
-
- p->bsp.run = bsp_entry;
- p->bsp.arg = bsp_arg;
-}
-
-void secmon_run(void (*entry)(void *), void *cb_tables)
-{
- static struct secmon_runit runit;
- struct cpu_action action = {
- .run = secmon_start,
- .arg = &runit,
- };
-
- 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;
- }
-
- runit.entry = secmon_load_rmodule();
-
- if (runit.entry == NULL)
- die("ARM64 Error: secmon load error");
-
- printk(BIOS_DEBUG, "ARM64: Loaded the el3 monitor...jumping to %p\n",
- runit.entry);
-
- fill_secmon_params(&runit.params, entry, cb_tables);
-
- arch_run_on_all_cpus_but_self_async(&action);
- secmon_start(&runit);
-}