mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-14 00:56:35 +00:00
Use the boot critical section
This commit is contained in:
parent
92d2abaf1c
commit
93864f2289
6 changed files with 69 additions and 18 deletions
|
@ -7,24 +7,14 @@
|
||||||
|
|
||||||
extern uint8_t __pk2ldr_start__[], __pk2ldr_end__[];
|
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) {
|
void coldboot_main(void) {
|
||||||
uintptr_t *mmu_l3_table = (uintptr_t *)TZRAM_GET_SEGMENT_ADDRESS(TZRAM_SEGMENT_ID_L3_TRANSLATION_TABLE);
|
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 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) */
|
/* Clear and unmap pk2ldr (which is reused as exception entry stacks) */
|
||||||
memset((void *)pk2ldr, 0, __pk2ldr_end__ - __pk2ldr_start__);
|
memset((void *)pk2ldr, 0, __pk2ldr_end__ - __pk2ldr_start__);
|
||||||
mmu_unmap_range(3, mmu_l3_table, pk2ldr, __pk2ldr_end__ - __pk2ldr_start__);
|
mmu_unmap_range(3, mmu_l3_table, pk2ldr, __pk2ldr_end__ - __pk2ldr_start__);
|
||||||
tlb_invalidate_all_inner_shareable();
|
tlb_invalidate_all_inner_shareable();
|
||||||
|
|
||||||
use_core_entrypoint_and_argument(get_core_id(), &ep, &arg);
|
core_jump_to_lower_el();
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
#include "smc_api.h"
|
#include "smc_api.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "synchronization.h"
|
||||||
#include "preprocessor.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)
|
#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_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);
|
#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};
|
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) {
|
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;
|
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) {
|
uint32_t cpu_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument) {
|
||||||
/* Is core valid? */
|
/* Is core valid? */
|
||||||
if (core >= NUM_CPU_CORES) {
|
if (core >= NUM_CPU_CORES) {
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
#ifndef EXOSPHERE_CPU_CTX_H
|
#ifndef EXOSPHERE_CPU_CTX_H
|
||||||
#define EXOSPHERE_CPU_CTX_H
|
#define EXOSPHERE_CPU_CTX_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include "utils.h"
|
||||||
#include <stdbool.h>
|
#include "synchronization.h"
|
||||||
|
|
||||||
/* Exosphere CPU Management functionality. */
|
/* Exosphere CPU Management functionality. */
|
||||||
|
|
||||||
|
extern critical_section_t g_boot_critical_section;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint64_t argument;
|
uint64_t argument;
|
||||||
uint64_t ELR_EL3;
|
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 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 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_on(uint32_t core, uintptr_t entrypoint_addr, uint64_t argument);
|
||||||
uint32_t cpu_off(void);
|
uint32_t cpu_off(void);
|
||||||
|
|
|
@ -76,6 +76,11 @@
|
||||||
__start_cold:
|
__start_cold:
|
||||||
ERRATUM_INVALIDATE_BTB_AT_BOOT
|
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
|
msr spsel, #0
|
||||||
bl get_coldboot_crt0_stack_address
|
bl get_coldboot_crt0_stack_address
|
||||||
mov sp, x0
|
mov sp, x0
|
||||||
|
@ -96,8 +101,22 @@ __start_cold:
|
||||||
__start_warm:
|
__start_warm:
|
||||||
ERRATUM_INVALIDATE_BTB_AT_BOOT
|
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
|
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
|
bl get_warmboot_crt0_stack_address
|
||||||
mov sp, x0
|
mov sp, x0
|
||||||
mov fp, #0
|
mov fp, #0
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
#include "arm.h"
|
#include "arm.h"
|
||||||
|
|
||||||
|
#include "synchronization.h"
|
||||||
|
|
||||||
/* start.s */
|
/* start.s */
|
||||||
void __set_memory_registers(uintptr_t ttbr0, uintptr_t vbar, uint64_t cpuectlr, uint32_t scr,
|
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);
|
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;
|
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) {
|
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 vbar = TZRAM_GET_SEGMENT_PA(TZRAM_SEGEMENT_ID_SECMON_EVT) + 0x800;
|
||||||
static const uintptr_t ttbr0 = vbar - 64;
|
static const uintptr_t ttbr0 = vbar - 64;
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "mmu.h"
|
#include "mmu.h"
|
||||||
#include "memory_map.h"
|
#include "memory_map.h"
|
||||||
|
#include "cpu_context.h"
|
||||||
/* start.s */
|
|
||||||
void __jump_to_lower_el(uint64_t arg, uintptr_t ep, unsigned int el);
|
|
||||||
|
|
||||||
void warmboot_main(void) {
|
void warmboot_main(void) {
|
||||||
/* TODO */
|
/* TODO: lots of stuff */
|
||||||
|
core_jump_to_lower_el();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue