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:
parent
1f4db4046f
commit
6cdacb37f0
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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 };
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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__ */
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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__ */
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue