exception,memory: s/EL2/EL1/

Since we're in VHE mode, we can pretend to be in EL1 - but this will
allow us to really run in EL1 if we want to in the future.

Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
Hector Martin 2021-03-04 20:25:16 +09:00
parent 4282cd0578
commit 16cff51bd4
3 changed files with 29 additions and 29 deletions

View file

@ -71,7 +71,7 @@ static char *ec_table[0x40] = {
void exception_initialize(void)
{
msr(VBAR_EL2, _vectors_start);
msr(VBAR_EL1, _vectors_start);
msr(DAIF, 0 << 6); // Enable SError, IRQ and FIQ
}
@ -84,7 +84,7 @@ void print_regs(u64 *regs)
{
u64 sp = ((u64)(regs)) + 256;
const char *m_desc = m_table[mrs(SPSR_EL2) & 0xf];
const char *m_desc = m_table[mrs(SPSR_EL1) & 0xf];
printf("Exception taken from %s\n", m_desc ? m_desc : "?");
printf("Running in EL%d\n", mrs(CurrentEL) >> 2);
@ -99,15 +99,15 @@ void print_regs(u64 *regs)
printf("x24-x27: %016lx %016lx %016lx %016lx\n", regs[24], regs[25], regs[26], regs[27]);
printf("x28-x30: %016lx %016lx %016lx\n", regs[28], regs[29], regs[30]);
u64 elr = mrs(elr_el2);
u64 elr = mrs(elr_el1);
printf("PC: 0x%lx (rel: 0x%lx)\n", elr, elr - (u64)_base);
printf("SP: 0x%lx\n", sp);
printf("SPSR_EL2: 0x%lx\n", mrs(SPSR_EL2));
printf("FAR_EL2: 0x%lx\n", mrs(FAR_EL2));
printf("SPSR_EL1: 0x%lx\n", mrs(SPSR_EL1));
printf("FAR_EL1: 0x%lx\n", mrs(FAR_EL1));
const char *ec_desc = ec_table[(mrs(ESR_EL2) >> 26) & 0x3f];
printf("ESR_EL2: 0x%lx (%s)\n", mrs(ESR_EL2), ec_desc ? ec_desc : "?");
const char *ec_desc = ec_table[(mrs(ESR_EL1) >> 26) & 0x3f];
printf("ESR_EL1: 0x%lx (%s)\n", mrs(ESR_EL1), ec_desc ? ec_desc : "?");
u64 l2c_err_sts = mrs(SYS_APL_L2C_ERR_STS);
@ -133,14 +133,14 @@ void exc_sync(u64 *regs)
u64 elr;
u32 insn;
u64 spsr = mrs(SPSR_EL2);
u64 esr = mrs(ESR_EL2);
u64 spsr = mrs(SPSR_EL1);
u64 esr = mrs(ESR_EL1);
if ((spsr & 0xf) == 0 && ((esr >> 26) & 0x3f) == 0x3c) {
// On clean EL0 return, let the normal exception return
// path take us back to the return thunk.
msr(spsr_el2, 0x09); // EL2h
msr(elr_el2, el0_ret);
msr(SPSR_EL1, 0x09); // EL2h
msr(ELR_EL1, el0_ret);
return;
}
@ -155,13 +155,13 @@ void exc_sync(u64 *regs)
switch (exc_guard & GUARD_TYPE_MASK) {
case GUARD_SKIP:
elr = mrs(ELR_EL2) + 4;
elr = mrs(ELR_EL1) + 4;
break;
case GUARD_MARK:
// Assuming this is a load or store, dest reg is in low bits
insn = read32(mrs(ELR_EL2));
insn = read32(mrs(ELR_EL1));
regs[insn & 0x1f] = 0xacce5515abad1dea;
elr = mrs(ELR_EL2) + 4;
elr = mrs(ELR_EL1) + 4;
break;
case GUARD_RETURN:
regs[0] = 0xacce5515abad1dea;
@ -177,7 +177,7 @@ void exc_sync(u64 *regs)
if (!(exc_guard & GUARD_SILENT))
printf("Recovering from exception (ELR=0x%lx)\n", elr);
msr(ELR_EL2, elr);
msr(ELR_EL1, elr);
sysop("isb");
sysop("dsb sy");

View file

@ -89,10 +89,10 @@ el0_call:
mrs x5, daif
msr daifclr, 3
msr spsr_el2, x5
msr spsr_el1, x5
ldr x5, =_el0_thunk
msr elr_el2, x5
msr elr_el1, x5
ldr x5, =el0_stack_base
ldr x5, [x5]

View file

@ -27,12 +27,12 @@ CACHE_RANGE_OP(dc_civac_range, "dc civac")
static inline u64 read_sctlr(void)
{
sysop("isb");
return mrs(SCTLR_EL2);
return mrs(SCTLR_EL1);
}
static inline void write_sctlr(u64 val)
{
msr(SCTLR_EL2, val);
msr(SCTLR_EL1, val);
sysop("isb");
}
@ -61,7 +61,7 @@ static inline void write_sctlr(u64 val)
#define PERM_RWX 0
/*
* https://developer.arm.com/docs/ddi0595/g/aarch64-system-registers/sctlr_el2
* https://developer.arm.com/docs/ddi0595/g/aarch64-system-registers/sctlr_el1
* SCTLR_SPAN disables PAN getting enabled on exceptions.
* SCTLR_I enables instruction caches.
* SCTLR_C enables data caches.
@ -73,7 +73,7 @@ static inline void write_sctlr(u64 val)
#define SCTLR_M BIT(0)
/*
* https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/tcr_el2
* https://developer.arm.com/docs/ddi0595/h/aarch64-system-registers/tcr_el1
* TCR_IPS_1TB selects 40 bits/1TB intermediate physical address size
* TCR_PS_1TB selects 40 bits/1TB physical address size
* TCR_TG0_16K selects 16K pages
@ -293,7 +293,7 @@ static void mmu_add_default_mappings(void)
/*
* create identity mapping for 16GB RAM from 0x88_0000_0000 to
* 0x8c_0000_0000, writable by EL0 (but not executable by EL2)
* 0x8c_0000_0000, writable by EL0 (but not executable by EL1)
*/
mmu_add_mapping(0x8800000000, 0x0800000000, 0x0400000000, MAIR_IDX_NORMAL, PERM_RWX_EL0);
@ -306,14 +306,14 @@ static void mmu_add_default_mappings(void)
static void mmu_configure(void)
{
msr(MAIR_EL2, (MAIR_ATTR_NORMAL_DEFAULT << MAIR_SHIFT_NORMAL) |
msr(MAIR_EL1, (MAIR_ATTR_NORMAL_DEFAULT << MAIR_SHIFT_NORMAL) |
(MAIR_ATTR_DEVICE_nGnRnE << MAIR_SHIFT_DEVICE_nGnRnE) |
(MAIR_ATTR_DEVICE_nGnRE << MAIR_SHIFT_DEVICE_nGnRE));
msr(TCR_EL2, TCR_IPS_1TB | TCR_TG1_16K | TCR_SH1_IS | TCR_ORGN1_WBWA | TCR_IRGN1_WBWA |
msr(TCR_EL1, TCR_IPS_1TB | TCR_TG1_16K | TCR_SH1_IS | TCR_ORGN1_WBWA | TCR_IRGN1_WBWA |
TCR_T1SZ_48BIT | TCR_TG0_16K | TCR_SH0_IS | TCR_ORGN0_WBWA | TCR_IRGN0_WBWA |
TCR_T0SZ_48BIT);
msr(TTBR0_EL2, (uintptr_t)pagetable_L0);
msr(TTBR1_EL2, (uintptr_t)pagetable_L0);
msr(TTBR0_EL1, (uintptr_t)pagetable_L0);
msr(TTBR1_EL1, (uintptr_t)pagetable_L0);
// Armv8-A Address Translation, 100940_0101_en, page 28
sysop("dsb ishst");
@ -330,13 +330,13 @@ void mmu_init(void)
mmu_add_default_mappings();
mmu_configure();
// Enable EL0 memory access by EL2
msr(pan, 0);
// Enable EL0 memory access by EL1
msr(PAN, 0);
u64 sctlr_old = read_sctlr();
u64 sctlr_new = sctlr_old | SCTLR_I | SCTLR_C | SCTLR_M | SCTLR_SPAN;
printf("MMU: SCTLR_EL2: %x -> %x\n", sctlr_old, sctlr_new);
printf("MMU: SCTLR_EL1: %x -> %x\n", sctlr_old, sctlr_new);
write_sctlr(sctlr_new);
printf("MMU: running with MMU and caches enabled!\n");
}