memory: Add separate mappings for EL0 data access

This unborks stack and constant pool accesses from el0_call.

Signed-off-by: Hector Martin <marcan@marcan.st>
This commit is contained in:
Hector Martin 2021-05-13 17:36:02 +09:00
parent 7685800b45
commit 3e1ea2d503
5 changed files with 41 additions and 8 deletions

View file

@ -4,13 +4,14 @@
#include "cpu_regs.h"
#include "gxf.h"
#include "iodev.h"
#include "memory.h"
#include "uart.h"
#include "utils.h"
#define EL0_STACK_SIZE 0x4000
u8 el0_stack[EL0_STACK_SIZE] ALIGNED(64);
void *el0_stack_base = &el0_stack[EL0_STACK_SIZE];
void *el0_stack_base = (void *)((u64)(&el0_stack[EL0_STACK_SIZE]) + REGION_RW_EL0);
extern char _vectors_start[0];
extern char _el1_vectors_start[0];

View file

@ -1,5 +1,7 @@
/* SPDX-License-Identifier: MIT */
#include "memory.h"
.globl exc_sync
.globl exc_irq
.globl exc_fiq
@ -102,6 +104,9 @@ el0_call:
ldr x5, =_el0_thunk
msr elr_el1, x5
mov x5, #REGION_RWX_EL0
orr x0, x0, x5
ldr x5, =el0_stack_base
ldr x5, [x5]
msr spsel, #0

View file

@ -57,10 +57,12 @@ static inline void write_sctlr(u64 val)
#define PERM_RO_EL0 PTE_AP_EL0 | PTE_AP_RO | PTE_PXN | PTE_UXN
#define PERM_RW_EL0 PTE_AP_EL0 | PTE_PXN | PTE_UXN
#define PERM_RX_EL0 PTE_AP_EL0 | PTE_AP_RO
#define PERM_RWX_EL0 PTE_AP_EL0
#define PERM_RO PTE_AP_RO | PTE_PXN | PTE_UXN
#define PERM_RW PTE_PXN | PTE_UXN
#define PERM_RX PTE_AP_RO | PTE_UXN
#define PERM_RWX 0
/*
@ -245,7 +247,7 @@ static void mmu_add_mapping(uintptr_t from, uintptr_t to, size_t size, u8 attrib
static void mmu_add_default_mappings(void)
{
/*
* create MMIO mappings. PCIe has to be mapped as nGnRE while MMIO needs nGnRnE.
* Create MMIO mappings. PCIe has to be mapped as nGnRE while MMIO needs nGnRnE.
* see https://lore.kernel.org/linux-arm-kernel/c1bc2a087747c4d9@bloch.sibelius.xs4all.nl/
*/
mmu_add_mapping(0x0200000000, 0x0200000000, 0x0200000000, MAIR_IDX_DEVICE_nGnRnE, PERM_RW_EL0);
@ -256,19 +258,35 @@ static void mmu_add_default_mappings(void)
mmu_add_mapping(0x06a0000000, 0x06a0000000, 0x0060000000, MAIR_IDX_DEVICE_nGnRE, PERM_RW_EL0);
/*
* create identity mapping for 16GB RAM from 0x08_0000_0000 to
* 0x0c_0000_0000
* Create identity mapping for 16GB RAM from 0x08_0000_0000 to 0x0c_0000_0000
* With SPRR enabled, this becomes RW.
*/
mmu_add_mapping(0x0800000000, 0x0800000000, 0x0400000000, MAIR_IDX_NORMAL, PERM_RWX);
/*
* create identity mapping for 16GB RAM from 0x88_0000_0000 to
* 0x8c_0000_0000, writable by EL0 (but not executable by EL1)
* Create mapping for 16GB RAM from 0x88_0000_0000 to 0x8c_0000_0000,
* read/writable/exec by EL0 (but not executable by EL1)
* With SPRR enabled, this becomes RX_EL0.
*/
mmu_add_mapping(0x8800000000, 0x0800000000, 0x0400000000, MAIR_IDX_NORMAL, PERM_RWX_EL0);
mmu_add_mapping(0x0800000000 | REGION_RWX_EL0, 0x0800000000, 0x0400000000, MAIR_IDX_NORMAL,
PERM_RWX_EL0);
/*
* Create mapping for 16GB RAM from 0x98_0000_0000 to 0x9c_0000_0000,
* read/writable by EL0 (but not executable by EL1)
* With SPRR enabled, this becomes RW_EL0.
*/
mmu_add_mapping(0x0800000000 | REGION_RW_EL0, 0x0800000000, 0x0400000000, MAIR_IDX_NORMAL,
PERM_RW_EL0);
/*
* Create mapping for 16GB RAM from 0xa8_0000_0000 to 0xac_0000_0000,
* read/executable by EL1
* This allows executing from dynamic regions in EL1
*/
mmu_add_mapping(0x0800000000 | REGION_RX_EL1, 0x0800000000, 0x0400000000, MAIR_IDX_NORMAL,
PERM_RX);
/*
* create two seperate nGnRnE and nGnRE full mappings of MMIO space
* Create two seperate nGnRnE and nGnRE full mappings of MMIO space
*/
mmu_add_mapping(0xe000000000, 0x0000000000, 0x0800000000, MAIR_IDX_DEVICE_nGnRnE, PERM_RW_EL0);
mmu_add_mapping(0xf000000000, 0x0000000000, 0x0800000000, MAIR_IDX_DEVICE_nGnRE, PERM_RW_EL0);

View file

@ -5,6 +5,12 @@
#include "types.h"
#define REGION_RWX_EL0 0x8000000000
#define REGION_RW_EL0 0x9000000000
#define REGION_RX_EL1 0xa000000000
#ifndef __ASSEMBLER__
void ic_ivau_range(void *addr, size_t length);
void dc_ivac_range(void *addr, size_t length);
void dc_zva_range(void *addr, size_t length);
@ -24,3 +30,5 @@ u64 mmu_disable(void);
void mmu_restore(u64 state);
#endif
#endif

View file

@ -319,6 +319,7 @@ static inline int is_primary_core(void)
}
extern char _base[];
extern char _rodata_end[];
extern char _end[];
extern char _payload_start[];
extern char _payload_end[];