Add spsr_el3 to cpu_context

This commit is contained in:
TuxSH 2018-03-11 12:53:52 +01:00
parent f624cccd0d
commit 52f7adfc50
5 changed files with 27 additions and 16 deletions

View file

@ -177,12 +177,12 @@ void setup_4x_mmio(void) {
/* TODO */ /* TODO */
} }
#define SET_SYSREG(reg, val) do { temp_reg = val; __asm__ __volatile__ ("msr " #reg ", %0" :: "r"(temp_reg) : "memory"); } while(false)
void setup_current_core_state(void) { void setup_current_core_state(void) {
uint64_t temp_reg; uint64_t temp_reg;
/* Setup system registers. */ /* Setup system registers. */
SET_SYSREG(spsr_el3, 0b1111 << 6 | 0b1001); /* use EL2h+DAIF set initially, may be overwritten later. Not in official code */
SET_SYSREG(actlr_el3, 0x73ull); SET_SYSREG(actlr_el3, 0x73ull);
SET_SYSREG(actlr_el2, 0x73ull); SET_SYSREG(actlr_el2, 0x73ull);
SET_SYSREG(hcr_el2, 0x80000000ull); SET_SYSREG(hcr_el2, 0x80000000ull);

View file

@ -21,7 +21,7 @@
#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 */ /* start.s */
void __attribute__((noreturn)) __jump_to_lower_el(uint64_t arg, uintptr_t ep, unsigned int el); void __attribute__((noreturn)) __jump_to_lower_el(uint64_t arg, uintptr_t ep, uint32_t spsr);
/* See notes in start.s */ /* See notes in start.s */
critical_section_t g_boot_critical_section = {{{.ticket_number = 1}}}; critical_section_t g_boot_critical_section = {{{.ticket_number = 1}}};
@ -51,14 +51,15 @@ void __attribute__((noreturn)) core_jump_to_lower_el(void) {
uintptr_t ep; uintptr_t ep;
uint64_t arg; uint64_t arg;
unsigned int core_id = get_core_id(); unsigned int core_id = get_core_id();
uint32_t spsr = get_spsr();
use_core_entrypoint_and_argument(core_id, &ep, &arg); use_core_entrypoint_and_argument(core_id, &ep, &arg);
critical_section_leave(&g_boot_critical_section); 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 */ flush_dcache_range(&g_boot_critical_section, (uint8_t *)&g_boot_critical_section + sizeof(g_boot_critical_section)); /* already does a dsb sy */
__sev(); __sev();
/* Nintendo jumps to EL1, we jump to EL2. Both are supported with all current packages2. */ /* Nintendo hardcodes EL1, but we can boot fine using other EL1/EL2 modes as well */
__jump_to_lower_el(arg, ep, 2); __jump_to_lower_el(arg, ep, 0b1111 << 6 | (spsr & 0b1101)); /* only keep EL, SPSel, set DAIF */
} }
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) {
@ -148,6 +149,7 @@ void save_current_core_context(void) {
SAVE_SYSREG32(SDER32_EL3); SAVE_SYSREG32(SDER32_EL3);
SAVE_SYSREG32(MDCR_EL2); SAVE_SYSREG32(MDCR_EL2);
SAVE_SYSREG32(MDCR_EL3); SAVE_SYSREG32(MDCR_EL3);
SAVE_SYSREG32(SPSR_EL3);
EVAL(REPEAT(6, SAVE_BP_REG, ~)); EVAL(REPEAT(6, SAVE_BP_REG, ~));
EVAL(REPEAT(4, SAVE_WP_REG, ~)); EVAL(REPEAT(4, SAVE_WP_REG, ~));
@ -170,6 +172,7 @@ void restore_current_core_context(void) {
RESTORE_SYSREG32(SDER32_EL3); RESTORE_SYSREG32(SDER32_EL3);
RESTORE_SYSREG32(MDCR_EL2); RESTORE_SYSREG32(MDCR_EL2);
RESTORE_SYSREG32(MDCR_EL3); RESTORE_SYSREG32(MDCR_EL3);
RESTORE_SYSREG32(SPSR_EL3);
EVAL(REPEAT(6, RESTORE_BP_REG, ~)); EVAL(REPEAT(6, RESTORE_BP_REG, ~));
EVAL(REPEAT(4, RESTORE_WP_REG, ~)); EVAL(REPEAT(4, RESTORE_WP_REG, ~));

View file

@ -23,6 +23,7 @@ typedef struct {
uint32_t SDER32_EL3; uint32_t SDER32_EL3;
uint32_t MDCR_EL2; uint32_t MDCR_EL2;
uint32_t MDCR_EL3; uint32_t MDCR_EL3;
uint32_t SPSR_EL3; /* not in official code */
uint64_t DBGBVR0_EL1; uint64_t DBGBVR0_EL1;
uint64_t DBGBCR0_EL1; uint64_t DBGBCR0_EL1;
uint64_t DBGBVR1_EL1; uint64_t DBGBVR1_EL1;

View file

@ -210,12 +210,11 @@ __set_exception_entry_stack_pointer:
.global __jump_to_lower_el .global __jump_to_lower_el
.type __jump_to_lower_el, %function .type __jump_to_lower_el, %function
__jump_to_lower_el: __jump_to_lower_el:
/* x0: arg (context ID), x1: entrypoint, w2: exception level */ /* x0: arg (context ID), x1: entrypoint, w2: spsr */
msr elr_el3, x1 mov w2, w2
mov w1, #(0b1111 << 6 | 1) /* DAIF set and SP = SP_ELx*/ msr elr_el3, x1
orr w1, w1, w2, lsl#2 msr spsr_el3, x2
msr spsr_el3, x1
bl __set_exception_entry_stack_pointer bl __set_exception_entry_stack_pointer

View file

@ -21,6 +21,8 @@
#define ALINLINE __attribute__((always_inline)) #define ALINLINE __attribute__((always_inline))
#define SET_SYSREG(reg, val) do { temp_reg = (val); __asm__ __volatile__ ("msr " #reg ", %0" :: "r"(temp_reg) : "memory"); } while(false)
/* Custom stuff below */ /* Custom stuff below */
/* For warmboot (and coldboot crt0) */ /* For warmboot (and coldboot crt0) */
@ -110,6 +112,12 @@ static inline uint64_t get_debug_authentication_status(void) {
return debug_auth; return debug_auth;
} }
static inline uint32_t get_spsr(void) {
uint32_t spsr;
__asm__ __volatile__ ("mrs %0, spsr_el3" : "=r"(spsr));
return spsr;
}
static inline bool check_32bit_additive_overflow(uint32_t a, uint32_t b) { static inline bool check_32bit_additive_overflow(uint32_t a, uint32_t b) {
return __builtin_add_overflow_p(a, b, (uint32_t)0); return __builtin_add_overflow_p(a, b, (uint32_t)0);
} }