Use the boot critical section

This commit is contained in:
TuxSH 2018-03-03 03:43:46 +01:00
parent 92d2abaf1c
commit 93864f2289
6 changed files with 69 additions and 18 deletions

View file

@ -7,24 +7,14 @@
extern uint8_t __pk2ldr_start__[], __pk2ldr_end__[];
/* start.s */
void __attribute__((noreturn)) __jump_to_lower_el(uint64_t arg, uintptr_t ep, unsigned int el);
void coldboot_main(void) {
uintptr_t *mmu_l3_table = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE);
uintptr_t pk2ldr = TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_PK2LDR);
uintptr_t ep;
uint64_t arg;
/* Clear and unmap pk2ldr (which is reused as exception entry stacks) */
memset((void *)pk2ldr, 0, __pk2ldr_end__ - __pk2ldr_start__);
mmu_unmap_range(3, mmu_l3_table, pk2ldr, __pk2ldr_end__ - __pk2ldr_start__);
tlb_invalidate_all_inner_shareable();
use_core_entrypoint_and_argument(get_core_id(), &ep, &arg);
/* Nintendo jumps to EL1, we jump to EL2. Both are supported with all current packages2. */
/* TODO: Remove this panic() when we're ready to test Kernel handoff. */
panic(0x7A700001);
__jump_to_lower_el(arg, ep, 2);
core_jump_to_lower_el();
}

View file

@ -7,6 +7,7 @@
#include "timers.h"
#include "smc_api.h"
#include "utils.h"
#include "synchronization.h"
#include "preprocessor.h"
#define SAVE_SYSREG64(reg) do { __asm__ __volatile__ ("mrs %0, " #reg : "=r"(temp_reg) :: "memory"); g_cpu_contexts[current_core].reg = temp_reg; } while(false)
@ -19,6 +20,12 @@
#define RESTORE_BP_REG(i, _) RESTORE_SYSREG64(DBGBVR##i##_EL1); RESTORE_SYSREG64(DBGBCR##i##_EL1);
#define RESTORE_WP_REG(i, _) RESTORE_SYSREG64(DBGBVR##i##_EL1); RESTORE_SYSREG64(DBGBCR##i##_EL1);
/* start.s */
void __attribute__((noreturn)) __jump_to_lower_el(uint64_t arg, uintptr_t ep, unsigned int el);
/* See notes in start.s */
critical_section_t g_boot_critical_section = {{{.ticket_number = 1}}};
static saved_cpu_context_t g_cpu_contexts[NUM_CPU_CORES] = {0};
void use_core_entrypoint_and_argument(uint32_t core, uintptr_t *entrypoint_addr, uint64_t *argument) {
@ -40,6 +47,22 @@ void set_core_entrypoint_and_argument(uint32_t core, uintptr_t entrypoint_addr,
g_cpu_contexts[core].argument = argument;
}
void core_jump_to_lower_el(void) {
uintptr_t ep;
uint64_t arg;
unsigned int core_id = get_core_id();
use_core_entrypoint_and_argument(core_id, &ep, &arg);
critical_section_leave(&g_boot_critical_section);
flush_dcache_range(&g_boot_critical_section, (uint8_t *)&g_boot_critical_section + sizeof(g_boot_critical_section)); /* already does a dsb sy */
__sev();
/* Nintendo jumps to EL1, we jump to EL2. Both are supported with all current packages2. */
/* TODO: Remove this panic() when we're ready to test Kernel handoff. */
panic(0x7A700001);
__jump_to_lower_el(arg, ep, 2);
}
uint32_t cpu_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument) {
/* Is core valid? */
if (core >= NUM_CPU_CORES) {

View file

@ -1,11 +1,13 @@
#ifndef EXOSPHERE_CPU_CTX_H
#define EXOSPHERE_CPU_CTX_H
#include <stdint.h>
#include <stdbool.h>
#include "utils.h"
#include "synchronization.h"
/* Exosphere CPU Management functionality. */
extern critical_section_t g_boot_critical_section;
typedef struct {
uint64_t argument;
uint64_t ELR_EL3;
@ -54,6 +56,7 @@ void set_current_core_inactive(void);
void use_core_entrypoint_and_argument(uint32_t core, uintptr_t *entrypoint_addr, uint64_t *argument);
void set_core_entrypoint_and_argument(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument);
void core_jump_to_lower_el(void);
uint32_t cpu_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument);
uint32_t cpu_off(void);

View file

@ -76,6 +76,11 @@
__start_cold:
ERRATUM_INVALIDATE_BTB_AT_BOOT
/*
This coldboot crt0 doesn't enter the boot critical section in the official monitor.
However we'll initialize g_boot_critical_section so that it acts like core0 has entered it,
for it to be in .data and for safety.
*/
msr spsel, #0
bl get_coldboot_crt0_stack_address
mov sp, x0
@ -96,8 +101,22 @@ __start_cold:
__start_warm:
ERRATUM_INVALIDATE_BTB_AT_BOOT
/* For some reasons, Nintendo uses spsel, #1 here, causing issues if an exception occurs */
/* For some reasons, Nintendo uses spsel, #1 around here, causing issues if an exception occurs */
msr spsel, #0
/* Nintendo doesn't use anything like the following two lines, but their critical section algo is borked */
/* FWIW this function doesn't use a stack atm, with latest GCC, but that might change. */
bl get_warmboot_crt0_stack_address_critsec_enter
mov sp, x0
/* PA(__main_start__) = __warmboot_crt0_start__ + 0x800 (refer to the linker script) */
ldr x0, =g_boot_critical_section
ldr x1, =__main_start__
sub x0, x0, x1
ldr x1, =(__start_warm + 0x800)
add x0, x0, x1
bl warmboot_crt0_critical_section_enter
bl get_warmboot_crt0_stack_address
mov sp, x0
mov fp, #0

View file

@ -2,6 +2,8 @@
#include "memory_map.h"
#include "arm.h"
#include "synchronization.h"
/* start.s */
void __set_memory_registers(uintptr_t ttbr0, uintptr_t vbar, uint64_t cpuectlr, uint32_t scr,
uint32_t tcr, uint32_t cptr, uint64_t mair, uint32_t sctlr);
@ -10,6 +12,21 @@ uintptr_t get_warmboot_crt0_stack_address(void) {
return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE012_STACK) + 0x800;
}
uintptr_t get_warmboot_crt0_stack_address_critsec_enter(void) {
unsigned int core_id = get_core_id();
if (core_id) {
return TZRAM_GET_SEGMENT_PA(TZRAM_SEGMENT_ID_CORE3_STACK) + 0x1000;
}
else {
return TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x80 * (core_id + 1);
}
}
void warmboot_crt0_critical_section_enter(volatile critical_section_t *critical_section) {
critical_section_enter(critical_section);
}
void set_memory_registers_enable_mmu(void) {
static const uintptr_t vbar = TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800;
static const uintptr_t ttbr0 = vbar - 64;

View file

@ -1,10 +1,9 @@
#include "utils.h"
#include "mmu.h"
#include "memory_map.h"
/* start.s */
void __jump_to_lower_el(uint64_t arg, uintptr_t ep, unsigned int el);
#include "cpu_context.h"
void warmboot_main(void) {
/* TODO */
/* TODO: lots of stuff */
core_jump_to_lower_el();
}