arm64: secmon: add entry point for turned on CPUs

Newly turned on CPUs need a place to go bring its EL3
state inline with expectations. Plumb this path in for
CPUs turning on as well as waking up from a power down
state. Some of the infrastructure declarations were
moved around for easier consumption in ramstage and
secmon. Lastly, a psci_soc_init() is added to
inform the SoC of the CPU's entry point as well do
any initialization.

BUG=chrome-os-partner:32112
BRANCH=None
TEST=Built and booted. On entry point not actually utilized.

Change-Id: I2af424c2906df159f78ed5e0a26a6bc0ba2ba24f
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: dbefec678a111e8b42acf2ae162c1ccdd7f9fd40
Original-Change-Id: I7b8c8c828ffb73752ca3ac1117cd895a5aa275d8
Original-Signed-off-by: Aaron Durbin <adurbin@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/228296
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9422
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Tested-by: build bot (Jenkins)
This commit is contained in:
Aaron Durbin 2014-11-06 15:17:33 -06:00 committed by Patrick Georgi
parent 1f4db4046f
commit 6cdacb37f0
8 changed files with 117 additions and 36 deletions

View File

@ -34,6 +34,8 @@ secmon-y += secmon_init.c
secmon-y += psci.c secmon-y += psci.c
secmon-y += smc.c secmon-y += smc.c
secmon-y += trampoline.S secmon-y += trampoline.S
secmon-y += ../cache.c
secmon-y += ../cpu.S
secmon-y += ../exception.c secmon-y += ../exception.c
secmon-y += ../../cpu.c secmon-y += ../../cpu.c
secmon-y += ../../transition_asm.S ../../transition.c secmon-y += ../../transition_asm.S ../../transition.c

View File

@ -220,6 +220,15 @@ void psci_turn_on_self(const struct cpu_action *action)
psci_schedule_cpu_on(e); psci_schedule_cpu_on(e);
} }
void psci_cpu_entry(void)
{
/*
* Just wait for an action to be performed. Only CPU_ON is supported
* initially. i.e. no power down then wake.
*/
secmon_wait_for_action();
}
static void psci_cpu_on(struct psci_func *pf) static void psci_cpu_on(struct psci_func *pf)
{ {
uint64_t entry; uint64_t entry;
@ -483,7 +492,7 @@ static int psci_allocate_nodes(void)
return 0; return 0;
} }
void psci_init(void) void psci_init(uintptr_t cpu_on_entry)
{ {
struct cpu_action action = { struct cpu_action action = {
.run = &psci_link_cpu_info, .run = &psci_link_cpu_info,

View File

@ -20,6 +20,7 @@
*/ */
#include <arch/barrier.h> #include <arch/barrier.h>
#include <arch/cache.h>
#include <arch/io.h> #include <arch/io.h>
#include <arch/exception.h> #include <arch/exception.h>
#include <arch/lib_helpers.h> #include <arch/lib_helpers.h>
@ -30,6 +31,74 @@
#include <stddef.h> #include <stddef.h>
#include "secmon.h" #include "secmon.h"
/* Common CPU state for all CPUs running in secmon. */
struct cpu_resume_data {
uint64_t mair;
uint64_t tcr;
uint64_t ttbr0;
uint64_t scr;
};
static struct cpu_resume_data resume_data;
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)
{
uint32_t sctlr;
/* Re-enable exception vector. */
exception_hwinit();
tlbiall_el3();
raw_write_mair_el3(resume_data.mair);
raw_write_tcr_el3(resume_data.tcr);
raw_write_ttbr0_el3(resume_data.ttbr0);
dsb();
isb();
/* Enable MMU */
sctlr = raw_read_sctlr_el3();
sctlr |= SCTLR_C | SCTLR_M | SCTLR_I;
raw_write_sctlr_el3(sctlr);
isb();
raw_write_scr_el3(resume_data.scr);
isb();
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. */
resume_data.mair = raw_read_mair_el3();
resume_data.tcr = raw_read_tcr_el3();
resume_data.ttbr0 = raw_read_ttbr0_el3();
resume_data.scr = raw_read_scr_el3();
dcache_clean_by_mva(&resume_data, sizeof(resume_data));
}
static void start_up_cpu(void *arg) static void start_up_cpu(void *arg)
{ {
struct secmon_params *params = arg; struct secmon_params *params = arg;
@ -81,7 +150,10 @@ static void secmon_init(struct secmon_params *params, int bsp)
wait_for_all_cpus(params->online_cpus); wait_for_all_cpus(params->online_cpus);
smc_init(); smc_init();
psci_init(); psci_init((uintptr_t)arm64_cpu_startup);
/* Initialize the resume path. */
cpu_resume_init();
/* Make sure all non-BSP CPUs take action before the BSP. */ /* Make sure all non-BSP CPUs take action before the BSP. */
arch_run_on_all_cpus_but_self_async(&action); arch_run_on_all_cpus_but_self_async(&action);
@ -89,27 +161,11 @@ static void secmon_init(struct secmon_params *params, int bsp)
start_up_cpu(params); start_up_cpu(params);
printk(BIOS_ERR, "CPU turn on failed for BSP.\n"); printk(BIOS_ERR, "CPU turn on failed for BSP.\n");
while (1)
; secmon_wait_for_action();
} }
void secmon_wait_for_action(void) void secmon_wait_for_action(void)
{ {
arch_cpu_wait_for_action(); arch_cpu_wait_for_action();
} }
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 };

View File

@ -70,8 +70,6 @@ static void secondary_cpu_start(void)
*/ */
void (*c_entry[2])(void) = { &arm64_init, &secondary_cpu_start }; void (*c_entry[2])(void) = { &arm64_init, &secondary_cpu_start };
extern void arm64_cpu_startup(void);
void *prepare_secondary_cpu_startup(void) void *prepare_secondary_cpu_startup(void)
{ {
return secondary_entry_point(&arm64_cpu_startup); return secondary_entry_point(&arm64_cpu_startup);

View File

@ -187,10 +187,13 @@ static inline void psci64_return(struct psci_func *pf, int64_t val)
psci64_result(pf, 0, val); psci64_result(pf, 0, val);
} }
void psci_init(void); void psci_init(uintptr_t cpu_on_entry);
void psci_soc_init(uintptr_t cpu_on_entry);
/* Turn on the current CPU within the PSCI subsystem. */ /* Turn on the current CPU within the PSCI subsystem. */
void psci_turn_on_self(const struct cpu_action *action); void psci_turn_on_self(const struct cpu_action *action);
int psci_turn_off_self(void); int psci_turn_off_self(void);
/* Entry point for CPUs just turning on or waking up. */
void psci_cpu_entry(void);
#endif /* __ARCH_PSCI_H__ */ #endif /* __ARCH_PSCI_H__ */

View File

@ -33,17 +33,4 @@ void jmp_to_elf_entry(void *entry, unsigned long buffer, unsigned long size);
* be available to be used (such as console). */ * be available to be used (such as console). */
void arm64_soc_init(void); void arm64_soc_init(void);
/*
* Stages and rmodules have 2 entry points: BSP and non-BSP. Provided
* a pointer the correct non-BSP entry point will be returned. The
* first instruction is for BSP and the 2nd is for non-BSP. Instructions
* are all 32-bit on arm64.
*/
static inline void *secondary_entry_point(void *e)
{
uintptr_t nonbsp = (uintptr_t)e;
return (void *)(nonbsp + sizeof(uint32_t));
}
#endif #endif

View File

@ -148,4 +148,26 @@ void arch_cpu_wait_for_action(void);
*/ */
unsigned int smp_processor_id(void); unsigned int smp_processor_id(void);
/*
* Stages and rmodules have 2 entry points: BSP and non-BSP. Provided
* a pointer the correct non-BSP entry point will be returned. The
* first instruction is for BSP and the 2nd is for non-BSP. Instructions
* are all 32-bit on arm64.
*/
static inline void *secondary_entry_point(void *e)
{
uintptr_t nonbsp = (uintptr_t)e;
return (void *)(nonbsp + sizeof(uint32_t));
}
/*
* The arm64_cpu_startup() initializes a CPU's exception stack and regular
* stack as well initializing the C environment for the processor. It
* calls into the array of function pointers at symbol c_entry depending
* on BSP state. Note that arm64_cpu_startup contains secondary entry
* point which can be obtained by secondary_entry_point().
*/
void arm64_cpu_startup(void);
#endif /* __ARCH_CPU_H__ */ #endif /* __ARCH_CPU_H__ */

View File

@ -19,6 +19,10 @@
#include <arch/psci.h> #include <arch/psci.h>
void psci_soc_init(uintptr_t cpu_on_entry)
{
}
static size_t children_at_level(int parent_level, uint64_t mpidr) static size_t children_at_level(int parent_level, uint64_t mpidr)
{ {
if (mpidr != 0) if (mpidr != 0)