Skip to content

Commit

Permalink
Almost complete pmap module for AArch64 (#743)
Browse files Browse the repository at this point in the history
What's missing:

 * pmap_growkernel
 * empty page table for TTBR0 when no user-space is mapped
 * referenced & modified bits handling
 * testing

Co-authored-by: Krystian Bacławski <[email protected]>
  • Loading branch information
pj1031999 and cahirwpz authored Oct 2, 2020
1 parent 7e6a2ab commit 6405b1a
Show file tree
Hide file tree
Showing 11 changed files with 528 additions and 59 deletions.
12 changes: 7 additions & 5 deletions include/aarch64/pmap.h
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
#ifndef _AARCH64_PMAP_H_
#define _AARCH64_PMAP_H_

#include <sys/types.h>

typedef uint8_t asid_t;
typedef uint64_t pte_t;
typedef uint64_t pde_t;
#include <aarch64/pte.h>

typedef struct pmap pmap_t;

Expand All @@ -15,4 +11,10 @@ typedef struct pmap pmap_t;
/* Number of page table entries. */
#define PT_ENTRIES (PAGESIZE / (int)sizeof(pte_t))

#define PMAP_KERNEL_BEGIN 0xffff000000000000L
#define PMAP_KERNEL_END 0xffffffffffffffffL

#define PMAP_USER_BEGIN 0x0000000000400000L
#define PMAP_USER_END 0x0000800000000000L

#endif /* !_AARCH64_PMAP_H_ */
15 changes: 15 additions & 0 deletions include/aarch64/pte.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,16 @@
#ifndef _MACHINE_PTE_H_
#define _MACHINE_PTE_H_

#include <sys/types.h>

typedef uint8_t asid_t;
typedef uint64_t pte_t;
typedef uint64_t pde_t;

#define PAGE_SHIFT 12
#define ASID_SHIFT 48
#define MAX_ASID 0xFF

/* Block and Page attributes */
#define ATTR_MASK_H UINT64_C(0xfff0000000000000)
#define ATTR_MASK_L UINT64_C(0x0000000000000fff)
Expand Down Expand Up @@ -66,6 +76,11 @@
#define ATTR_NORMAL_MEM_WB 2
#define ATTR_NORMAL_MEM_WT 3

#define ATTR_S2_S2AP(x) ((x) << 6)
#define ATTR_S2_S2AP_MASK 3
#define ATTR_S2_S2AP_READ 1
#define ATTR_S2_S2AP_WRITE 2

/* Level 0 table, 512GiB per entry */
#define L0_SHIFT 39
#define L0_SIZE (1ul << L0_SHIFT)
Expand Down
13 changes: 13 additions & 0 deletions include/aarch64/tlb.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#ifndef _AARCH64_TLB_H_
#define _AARCH64_TLB_H_

#ifndef _MACHDEP
#error "Do not use this header file outside kernel machine dependent code!"
#endif

#include <aarch64/pte.h>

void tlb_invalidate(pte_t pte, asid_t asid);
void tlb_invalidate_asid(asid_t asid);

#endif /* !_AARCH64_TLB_H_ */
1 change: 0 additions & 1 deletion include/sys/pmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ vaddr_t pmap_end(pmap_t *pmap);
void init_pmap(void);

pmap_t *pmap_new(void);
void pmap_reset(pmap_t *pmap);
void pmap_delete(pmap_t *pmap);

void pmap_enter(pmap_t *pmap, vaddr_t va, vm_page_t *pg, vm_prot_t prot,
Expand Down
1 change: 1 addition & 0 deletions sys/aarch64/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ SOURCES = boot.c \
start.S \
switch.S \
thread.c \
tlb.c \
trap.c \
ucontext.c

Expand Down
26 changes: 18 additions & 8 deletions sys/aarch64/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
/* Last physical address used by kernel for boot memory allocation. */
__boot_data void *_bootmem_end;
/* Kernel page directory entries. */
alignas(PAGESIZE) pte_t _kernel_pmap_pde[PD_ENTRIES];
paddr_t _kernel_pmap_pde;
alignas(PAGESIZE) uint8_t _atags[PAGESIZE];

extern char exception_vectors[];
Expand Down Expand Up @@ -140,9 +140,9 @@ __boot_text static void clear_bss(void) {
#define DMAP_L2_SIZE roundup(DMAP_L2_ENTRIES * sizeof(pde_t), PAGESIZE)
#define DMAP_L3_SIZE roundup(DMAP_L3_ENTRIES * sizeof(pte_t), PAGESIZE)

__boot_text static void build_page_table(void) {
__boot_text static paddr_t build_page_table(void) {
/* l0 entry is 512GB */
volatile pde_t *l0 = (pde_t *)AARCH64_PHYSADDR(_kernel_pmap_pde);
volatile pde_t *l0 = bootmem_alloc(PAGESIZE);
/* l1 entry is 1GB */
volatile pde_t *l1 = bootmem_alloc(PAGESIZE);
/* l2 entry is 2MB */
Expand All @@ -159,6 +159,13 @@ __boot_text static void build_page_table(void) {
l1[L1_INDEX(va)] = (pde_t)l2 | L1_TABLE;
l2[L2_INDEX(va)] = (pde_t)l3 | L2_TABLE;

/* TODO(pj) imitate pmap_growkernel from NetBSD */
l2[L2_INDEX(0)] = (pde_t)bootmem_alloc(PAGESIZE) | L2_TABLE;
for (int i = 0; i < 32; i++) {
l2[L2_INDEX(0xffff000000400000 + i * PAGESIZE * PT_ENTRIES)] =
(pde_t)bootmem_alloc(PAGESIZE) | L2_TABLE;
}

const pte_t pte_default =
L3_PAGE | ATTR_AF | ATTR_SH(ATTR_SH_IS) | ATTR_IDX(ATTR_NORMAL_MEM_WB);

Expand Down Expand Up @@ -191,15 +198,17 @@ __boot_text static void build_page_table(void) {
l1d[i] = (pde_t)&l2d[i * PT_ENTRIES] | L1_TABLE;

l0[L0_INDEX(DMAP_BASE)] = (pde_t)l1d | L0_TABLE;

return (paddr_t)l0;
}

/* Based on locore.S from FreeBSD. */
__boot_text static void enable_mmu(void) {
__boot_text static void enable_mmu(paddr_t pde) {
__dsb("sy");

WRITE_SPECIALREG(VBAR_EL1, exception_vectors);
WRITE_SPECIALREG(TTBR0_EL1, AARCH64_PHYSADDR(_kernel_pmap_pde));
WRITE_SPECIALREG(TTBR1_EL1, AARCH64_PHYSADDR(_kernel_pmap_pde));
WRITE_SPECIALREG(TTBR0_EL1, pde);
WRITE_SPECIALREG(TTBR1_EL1, pde);
__isb();

/* Clear the Monitor Debug System control register. */
Expand Down Expand Up @@ -251,6 +260,8 @@ __boot_text static void enable_mmu(void) {
*/
WRITE_SPECIALREG(sctlr_el1, SCTLR_M | SCTLR_I | SCTLR_C);
__isb();

_kernel_pmap_pde = pde;
}

__boot_text static void atags_copy(atag_tag_t *atags) {
Expand All @@ -274,8 +285,7 @@ __boot_text void *aarch64_init(atag_tag_t *atags) {
_bootmem_end = (void *)align(AARCH64_PHYSADDR(__ebss), PAGESIZE);
atags_copy(atags);

build_page_table();
enable_mmu();
enable_mmu(build_page_table());
return _atags;
}

Expand Down
Loading

0 comments on commit 6405b1a

Please sign in to comment.