9os

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 34d10a8b093f008ee0b396ed45db9e13789210c2
parent 4d52f7a28108ba4c22b3b5802c49e65f39a2353f
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 13 Oct 2020 07:48:04 +0200

arm64: Add first version of the kernel mapping

After this commit mmu works in high memory
and all the addresses are valid.

Change-Id: I72638e884770c77090a62193269a7f6957b58ae9

Diffstat:
Mconfig/arm64-os9.mk | 2+-
Mconfig/toolchain/armclang.ld | 1-
Mconfig/toolchain/gnu.ld | 1-
Minclude/bits/arm64/arch/types.h | 48++++++++++++++++++++++++++++++++++++++++++++++++
Minclude/os9/os9.h | 45++++++++++++++++++++++++++-------------------
Msrc/os9/arch/arm64/arch.h | 49++++---------------------------------------------
Msrc/os9/arch/arm64/arch.s | 66+++++++++++++++++++++++++++++++++++++++++++++---------------------
Msrc/os9/arch/arm64/crt.s | 28++++++++++++++++++++--------
Msrc/os9/arch/arm64/fvp.c | 46+++++++++++++++++++++++++++++++++++++++++++++-
Msrc/os9/arch/arm64/lock.s | 14+++++++++++---
Msrc/os9/arch/arm64/main.c | 53+++--------------------------------------------------
Msrc/os9/arch/arm64/mmu.c | 325++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Msrc/os9/arch/arm64/panic.c | 4+++-
Msrc/os9/arch/arm64/sysreg.lst | 1+
14 files changed, 454 insertions(+), 229 deletions(-)

diff --git a/config/arm64-os9.mk b/config/arm64-os9.mk @@ -3,5 +3,5 @@ SYS = os9 MODE = native SYSASFLAGS = $(ARMV81_ASFLAGS) SYSCFLAGS = $(OS9_CFLAGS) -SYSLDFLAGS = -Ttext=0xFFFF000000000000 +SYSLDFLAGS = -Ttext=0xFFFFFF0000000000 OS9 = 9fvp diff --git a/config/toolchain/armclang.ld b/config/toolchain/armclang.ld @@ -16,7 +16,6 @@ SECTIONS .bss : { *(.bss) *(COMMON) - . = ALIGN(0x1000); end = .; } } diff --git a/config/toolchain/gnu.ld b/config/toolchain/gnu.ld @@ -16,7 +16,6 @@ SECTIONS .bss : { *(.bss) *(COMMON) - . = ALIGN(0x1000); end = .; } } diff --git a/include/bits/arm64/arch/types.h b/include/bits/arm64/arch/types.h @@ -1,4 +1,52 @@ +enum regidx { + X0, + X1, + X2, + X3, + X4, + X5, + X6, + X7, + X8, + X9, + X10, + X11, + X12, + X13, + X14, + X15, + X16, + X17, + X18, + X19, + X20, + X21, + X22, + X23, + X24, + X25, + X26, + X27, + X28, + X29, + ELR, + X30, + SPSR, + ESR, + SP, + FAR, + TTBR0, + TTBR1, + NR_REGS , +}; + +struct context { + unsigned long long r[NR_REGS]; +}; + + typedef int atomic_t; typedef unsigned long mutex_t; typedef unsigned long long pte_t; typedef unsigned long long phyaddr_t; +typedef struct context Context; diff --git a/include/os9/os9.h b/include/os9/os9.h @@ -87,17 +87,19 @@ enum start_reason { }; enum map_attr { - MR, - MW, - MX, - MD, + MR = 1 << 0, + MW = 1 << 1, + MX = 1 << 2, + MD = 1 << 3, }; struct map { + char *name; + unsigned perm; + phyaddr_t pa; uintptr_t va; size_t siz; - int attr; }; /* @@ -112,9 +114,7 @@ struct mach { phyaddr_t tables; long ntables; - Map stack; - Map data; - Map text; + Map *maps; }; struct qid { @@ -143,10 +143,11 @@ struct chan { struct task { int tid; + int pid; + mutex_t m; char *name; void *entry; - size_t stack; int prio; int baseprio; int retainprio; @@ -160,14 +161,17 @@ struct task { int state; unsigned long affinity; - int flags; - /* Context ctx; */ + Map text; + Map data; + Map stack; + Context ctx; }; struct proc { int pid; + char *name; /* memory requirements */ long period; @@ -193,15 +197,13 @@ struct win { Proc *proc; }; -extern noreturn void halt(void); -extern noreturn void panic(const char *msg); -extern noreturn void swtch(Context *ctx); -extern noreturn void trap(Context *ctx); -extern int debug(void); -extern void idev(Mach *); +/* alloc.c */ extern void *alloc(size_t size); -/* architectural functions */ +/* dlang.c */ +extern int debug(void); + +/* arch functions */ extern Context *getctx(Context *ctx); extern void interrupt(int); extern uint8_t inm8(void *addr); @@ -214,8 +216,13 @@ extern void lock(mutex_t *m); extern void unlock(mutex_t *m); extern int trylock(mutex_t *m); extern void barrier(int); +extern noreturn void halt(void); +extern noreturn void panic(const char *msg); +extern noreturn void swtch(Context *ctx); +extern noreturn void trap(Context *ctx); -/* devices functions */ +/* dev functions */ +extern void idev(Mach *); extern Chan *devopen(char *name, int mode); extern int devwrite(Chan *c, void *buf, int n); extern int devread(Chan *c, void *buf, int n); diff --git a/src/os9/arch/arm64/arch.h b/src/os9/arch/arm64/arch.h @@ -20,58 +20,17 @@ #define EE (1ul << 25) #define UCI (1ul << 26) -enum regidx { - X0, - X1, - X2, - X3, - X4, - X5, - X6, - X7, - X8, - X9, - X10, - X11, - X12, - X13, - X14, - X15, - X16, - X17, - X18, - X19, - X20, - X21, - X22, - X23, - X24, - X25, - X26, - X27, - X28, - X29, - ELR, - X30, - SPSR, - ESR, - SP, - FAR, - NR_REGS -}; - -struct context { - unsigned long long r[NR_REGS]; -}; +extern Mach mach; extern void main(Mach *); extern void syswr(int, unsigned long long); extern unsigned long long sysrd(int); extern void invicache(void); -extern void invtlb(void); +extern void invalltlb(void); +extern void invtlb(uintptr_t); extern void invdcachesetway(void *); extern void icache(Mach *); -extern void immu(Mach *); +extern void immu(void); extern void ifpu(Mach *); extern void igic(Mach *); diff --git a/src/os9/arch/arm64/arch.s b/src/os9/arch/arm64/arch.s @@ -26,9 +26,21 @@ barrier: RET .TEXT + .GLOBL invalltlb +invalltlb: + TLBI VMALLE1IS + DSB ISH + ISB + RET + + .TEXT .GLOBL invtlb invtlb: - TLBI VMALLE1IS + LSR X9,X0,#12 + DSB ISHST + TLBI VAE1,X9 + DC CVAU,X0 + DSB ISH RET .TEXT @@ -116,39 +128,47 @@ getctx: MRS X10,FAR_EL1 STP X9,X10,[X0,#16*17] + MRS X9,TTBR0_EL1 + MRS X10,TTBR1_EL1 + STP X9,X10,[X0,#16*18] + RET .TEXT EXCEPTION: - MSR SPSEL,#1 - STP X0,X1,[SP,#-16*(17-0)] - STP X2,X3,[SP,#-16*(17-1)] - STP X4,X5,[SP,#-16*(17-2)] - STP X6,X7,[SP,#-16*(17-3)] - STP X8,X9,[SP,#-16*(17-4)] - STP X10,X11,[SP,#-16*(17-5)] - STP X12,X13,[SP,#-16*(17-6)] - STP X14,X15,[SP,#-16*(17-7)] - STP X16,X17,[SP,#-16*(17-8)] - STP X18,X19,[SP,#-16*(17-9)] - STP X20,X21,[SP,#-16*(17-10)] - STP X22,X23,[SP,#-16*(17-11)] - STP X24,X25,[SP,#-16*(17-12)] - STP X26,X27,[SP,#-16*(17-13)] - STP X28,X29,[SP,#-16*(17-14)] + MOV SP,SP + STP X0,X1,[SP,#-16*(19-0)] + STP X2,X3,[SP,#-16*(19-1)] + STP X4,X5,[SP,#-16*(19-2)] + STP X6,X7,[SP,#-16*(19-3)] + STP X8,X9,[SP,#-16*(19-4)] + STP X10,X11,[SP,#-16*(19-5)] + STP X12,X13,[SP,#-16*(19-6)] + STP X14,X15,[SP,#-16*(19-7)] + STP X16,X17,[SP,#-16*(19-8)] + STP X18,X19,[SP,#-16*(19-9)] + STP X20,X21,[SP,#-16*(19-10)] + STP X22,X23,[SP,#-16*(19-11)] + STP X24,X25,[SP,#-16*(19-12)] + STP X26,X27,[SP,#-16*(19-13)] + STP X28,X29,[SP,#-16*(19-14)] MRS X9,ELR_EL1 - STP X9,X30,[SP,#-16*(17-15)] + STP X9,X30,[SP,#-16*(19-15)] MRS X9,SPSR_EL1 MRS X10,ESR_EL1 - STP X9,X10,[SP,#-16*(17-16)] + STP X9,X10,[SP,#-16*(19-16)] MOV X9,SP MRS X10,FAR_EL1 - STP X9,X10,[SP,#-16*(17-17)] + STP X9,X10,[SP,#-16*(19-17)] - SUB SP,SP,#16*17 + MRS X9,TTBR0_EL1 + MRS X10,TTBR1_EL1 + STP X9,X10,[SP,#-16*(19-18)] + + SUB SP,SP,#16*19 MOV X0,SP MOV X29,#0 BL trap @@ -162,6 +182,10 @@ OUTSYN: .TEXT .GLOBL swtch swtch: + LDP X9,X10,[X0,#16*18] + MSR TTBR0_EL1,X9 + MSR TTBR1_EL1,X10 + LDP X9,X10,[X0,#16*17] MSR FAR_EL1,X10 MOV SP,X9 diff --git a/src/os9/arch/arm64/crt.s b/src/os9/arch/arm64/crt.s @@ -10,6 +10,7 @@ _start: CMP X10,1 BEQ EL1 +EL2: MOV X10,A | D | IRQ | FIQ | EL1h MSR SPSR_EL2,X10 @@ -24,6 +25,17 @@ _start: ERET EL1: + LDR W10,=SCTLR | SA0 | SA | A + MSR SCTLR_EL1,X10 + ISB + + MSR SPSEL,#1 + ISB + + ADR X10,vectbl + MSR VBAR_EL1,X10 + ISB + ADR X0,mach LDR X9,[X0] MOV SP,X9 @@ -36,15 +48,15 @@ EL1: LSR X11,X11,3 SUB X10,X10,X9 -.L1: +1: STR XZR,[X10],8 SUB X11,X11,1 - CBNZ X11,.L1 + CBNZ X11,1b - BL main - ADR X0,OUTSYN - B panic + BL imach + BL icache + BL initmap + BL immu + BL kernelmap + B swtch - .DATA -OUTSYN: - .ASCIZ "out of sync" diff --git a/src/os9/arch/arm64/fvp.c b/src/os9/arch/arm64/fvp.c @@ -1,18 +1,62 @@ #include <os9/os9.h> +#include <string.h> + #include "arch.h" static uint32_t *early = (uint32_t *) 0x1C090000; + +/* + * FIXME: ptable is aligned to 512MB, but this is not needed + * because it only has to be aligned to 64K + */ Mach mach = { .phystack = 0x80080000, .phytext = 0x80000000, - .ktzero = 0xFFFF000000000000 - 0x80000000, + .ktzero = 0xFFFFFF0000000000- 0x80000000, .tables = 0x80080000, .ptable = 0xA0000000, .ntables = 128, }; +void +imach(void) +{ + char *bp, *p; + Map *textp, *datap, *stackp; + static Map maps[4]; + extern char text[], etext[], end[]; + + mach.maps = maps; + textp = &maps[0]; + datap = &maps[1]; + stackp = &maps[2]; + + textp->name = "text"; + textp->pa = mach.phytext; + textp->va = mach.phytext + mach.ktzero; + textp->siz = etext - text; + textp->perm = MR | MX; + + datap->name = "data"; + datap->pa = textp->pa +textp->siz; + datap->va = datap->pa + mach.ktzero; + datap->siz = end - etext; + datap->perm = MR | MW; + + stackp->name = "stack"; + stackp->pa = mach.phystack - 4*KiB; + stackp->va = datap->va + datap->siz + 4*KiB; + stackp->siz = 4*KiB; + stackp->perm = MR | MW; + + bp = (char *) mach.tables; + for (p = bp; p <&bp[mach.ntables]; p+= 4*KiB) + memset(p, 0, 4*KiB); + barrier(DATA); +} + int getch(void) { diff --git a/src/os9/arch/arm64/lock.s b/src/os9/arch/arm64/lock.s @@ -1,12 +1,14 @@ - .GLOBL lock,unlock,trylock - + .file "lock.s" /* * Those functions are currently not used for two reasons: * 1- We don't have caches and mmu enabled * 2- We are executing only one execution thread. */ -LOCK: + .TEXT + .GLOBL lock + +lock: MOV W2,#1 SEVL 1: @@ -16,11 +18,17 @@ LOCK: CBNZ W1,1B RET + .TEXT + .GLOBL unlock + unlock: STLR WZR,[X0] SEV RET + .TEXT + .GLOBL trylock + trylock: // TODO: implement trylock MOV W0,#1 RET diff --git a/src/os9/arch/arm64/main.c b/src/os9/arch/arm64/main.c @@ -1,8 +1,5 @@ #include <os9/os9.h> -#include <stdint.h> -#include <string.h> - #include <libk.h> #include "version.h" @@ -12,46 +9,9 @@ Chan *console; static void -iarch(Mach *m) -{ - extern void *vectbl(void); - - syswr(VBAR_EL1, (phyaddr_t) vectbl); - syswr(SCTLR_EL1, SCTLR | SA0 | SA | A); - barrier(CODE); -} - -static void -imach(Mach *m) -{ - char *bp, *p; - extern char text[], etext[], end[]; - - m->text.pa = m->phytext; - m->text.va = m->phytext + m->ktzero; - m->text.siz = etext - text; - m->text.attr = MR | MX; - - m->data.pa = m->text.pa + m->text.siz; - m->data.va = m->data.pa + m->ktzero; - m->data.siz = end - etext; - m->text.attr = MR | MW; - - m->stack.pa = m->phystack - 4*KiB; - m->stack.va = m->data.va + m->data.siz + 4*KiB; - m->stack.siz = 4*KiB; - m->stack.attr = MR | MW; - - bp = (char *) m->tables; - for (p = bp; p <&bp[m->ntables]; p+= 4*KiB) - memset(p, 0, 4*KiB); - barrier(DATA); -} - -static void info(Mach *m) { - dbg("os9: version %s\n", + kprint("os9: version %s\n", OS9VERSION); } @@ -86,16 +46,9 @@ main(Mach *m) { kprint("Booting os9\n"); - iarch(m); - icache(m); - imach(m); - immu(m); - halt(); ifpu(m); igic(m); - - idev(m); - icons(m); info(m); - debug(); + + panic("out of sync"); } diff --git a/src/os9/arch/arm64/mmu.c b/src/os9/arch/arm64/mmu.c @@ -1,5 +1,7 @@ #include <os9/os9.h> +#include <assert.h> +#include <errno.h> #include <string.h> #include <libk.h> @@ -19,14 +21,17 @@ #define G4K 2ull #define G64K 3ull +#define I4GB 0ull +#define I64GB 1ull +#define I1TB 2ull +#define I4TB 3ull +#define I16TB 4ull +#define I256TB 5ull + #define TBI1 (1ull << 38) #define TBI0 (1ull << 37) #define AS (1ull << 36) -#define IPS4GB (0ull << 32) -#define IPS64GB (1ull << 32) -#define IPS1TB (2ull << 32) -#define IPS4TB (3ull << 32) -#define IPS16TB (4ull << 32) +#define IPS(x) ((x) << 32) #define TG1(x) ((x) << 30) #define SH1(x) ((x) << 28) #define ORGN1(x) ((x) << 26) @@ -42,30 +47,95 @@ #define T0SZ(x) ((x) << 0) /* MMU */ -#define UXN(x) ((pte_t) (x) << 54) -#define PXN(x) ((pte_t) (x) << 53) -#define CONT(x) ((pte_t) (x) << 52) - #define RDWR 0 #define EL0 1 #define RD 2 + +/* table attributes */ +#define APTable(x) ((pte_t) (x) << 62) +#define UXNTable(x) ((pte_t) (x) << 60) +#define PXNTable(x) ((pte_t) (x) << 59) + +/* page high attributes */ +#define UXN ((pte_t) 1 << 54) +#define PXN ((pte_t) 1 << 53) +#define CONT ((pte_t) 1 << 52) + +/* page low attributes */ +/* + * TODO: Define macros for OS(), because we are using + * the same macros than in OSx() but Non shareable has + * a different representation + */ #define NG(x) ((pte_t) (x) << 11) #define AF(x) ((pte_t) (x) << 10) #define SH(x) ((pte_t) (x) << 8) #define AP(x) ((pte_t) (x) << 6) #define IDX(x) ((pte_t) (x) << 2) +#define VASIZE 40 +#define MASK(pa) ((pa) & (-1ull>>(64-VASIZE) & ~0ull<<12)) #define INVALID 0 -#define BLOCK64(pa) (((pa) & (-1ull>>(64-47) | ~0ull<<47)) | 1) -#define TABLE(pa) (((pa) & (-1ull>>(64-47) & ~0ull<<12)) | 3) -#define PAGE(pa) ((pa) & (-1ull>>(64-47) & ~0ull<<12)) -#define PTABLE(pa) (pte_t *) ((pa) & (-1ull>>(64-47) & ~0ull<<12)) -#define TTBR(x) ((x) & ~3) +#define BLOCK 1 +#define TABLE 3 +#define PAGE 3 + +#define TINDEX(lvl, va) ((va)>>(39-(lvl)*9) & 0x1FF) #define DEV 7 #define MEM 0 +/* ID_AA64MMFR0_EL1 */ +#define TGRAN4(x) ((x)>>28 & 0xf) +#define TGRAN64(x) ((x)>>24 & 0xf) +#define TGRAN16(x) ((x>>20 & 0xf) +#define PAR(x) ((x) & 0xf) + +/* SPSR */ +#define NF(x) ((unsigned long) (x) << 31) +#define ZF(x) ((unsigned long) (x) << 30) +#define CF(x) ((unsigned long) (x) << 29) +#define VF(x) ((unsigned long) (x) << 28) +#define SS(x) ((unsigned long) (x) << 21) +#define IL(x) ((unsigned long) (x) << 20) + +#define DAIF(x) ((unsigned long) (x) << 6) +#define MODE(x) ((unsigned long) (x) << 0) + +#define A64 0 +#define A32 1 + +#define AARCH(x) ((unsigned long) (x) << 4) + +#define EL0t 0 +#define EL1t 4 +#define EL1h 5 + +/* MAIR */ +#define DEVICE(x) (x) +#define NORMAL(c, t, a) ((c) | (t) | (a)) + +#define nGnRnE 0ull +#define nGnRE 2ull +#define nGRE 4ull +#define GRE 8ull + +/* + * TODO: Improve these macros + */ +#define ONC 4ull +#define OWT 0ull +#define OWB 4ull + +#define NTRANSIENT 8ull +#define RALLOC 2ull +#define WALLOC 1ull + +#define TRANSIENT 0ull +#define NRALLOC 0ull +#define NWALLOC 0ull + static long ntables; static phyaddr_t tables; @@ -76,119 +146,218 @@ newtab(void) static long n; static mutex_t m; + /* + * TODO: define tables as an assembler symbol + */ lock(&m); - if (n == ntables) - panic("out of memory"); - addr = tables + n*4ll*KiB; - n++; + if (n == ntables) { + errno = ENOMEM; + addr = INVALID; + } else { + addr = tables + n*4ll*KiB; + n++; + } unlock(&m); - return addr; + dbg("allocate page table at %llx\n", addr); + + if (MASK(addr) != addr) + panic("invalid page table"); + + memset((void *) addr, 0, 4*KiB); + + return addr ; } static pte_t * -walker(pte_t ttbr, uintptr_t va) +walker(uintptr_t va) { pte_t *bp, e; - int idx, i; + int lvl; + pte_t ttbr; + + ttbr = (va & 1ull<<63) ? sysrd(TTBR1_EL1) : sysrd(TTBR0_EL1); + bp = (pte_t *) MASK(ttbr); + va = MASK(va); + + for (lvl = 0; lvl < 3; lvl++) { + int n = TINDEX(lvl, va); - bp = PTABLE(ttbr); - for (i = 0; i < 3; i++) { - idx = va>>(38-i*9) & 0x1FF; - e = bp[idx]; + e = bp[n]; if (e == INVALID) { - e = TABLE(newtab()); - bp[idx] = e; + if ((e = newtab()) == INVALID) + return NULL; + bp[n] = e | TABLE; + barrier(DATA); } - bp = PTABLE(e); + dbg("va = %llx, level=%d, bp=%p, n=%d, e=%llx\n", va, lvl, bp, n, e); + bp = (pte_t *) MASK(e); } - return &bp[va>>11 & 0x1FF]; + dbg("va = %llx, level=%d, n=%d\n", va, 3, TINDEX(3, va)); + return &bp[TINDEX(3, va)]; +} + +int +vmap(phyaddr_t pa, uintptr_t va, int perm) +{ + static mutex_t m; + pte_t *p, attr; + + attr = AF(1) | SH(OS) | PAGE; + attr |= (perm & MW) ? AP(RDWR) : AP(RD); + attr |= (perm & MD) ? IDX(DEV) : IDX(MEM); + + if ((perm & MX) == 0) + attr |= UXN|PXN; + + if (va & 1ull<<63) + attr |= EL0; + + if ((p = walker(va)) == NULL) + return -1; + + /* + * locking is needed if we are in a system + * with SMMUv3 and page tables are shared. + * TODO: use spinlocks here + * TODO: Add information about destroy before make + */ + lock(&m); + *p = INVALID; + invtlb(va); + + *p = MASK(pa) | attr; + invtlb(va); + unlock(&m); + + dbg("page %p: %llx\n", p, MASK(pa) | attr); + + return 0; } -static void -mapseg(pte_t ttbr, Map *mp) +int +mapseg(Map *mp) { - uintptr_t va, lim; phyaddr_t pa; - pte_t attr; + uintptr_t va; + unsigned long i, n; + + assert(mp->perm & MR); - attr = AF(1) | SH(OS); - attr |= (mp->attr & MW) ? AP(RDWR) : AP(RD); - attr |= (mp->attr & MD) ? IDX(DEV) : IDX(MEM); + dbg("map %s: %llx -> %llx %c %c%c%c (%llu)\n", + (mp->name) ? mp->name : "unnamed", + mp->va, mp->pa, + (mp->perm & MD) ? 'd' : 'n', + (mp->perm & MR) ? 'r' : '-', + (mp->perm & MW) ? 'w' : '-', + (mp->perm & MX) ? 'x' : '-', + mp->siz); - pa = mp->pa; - lim = mp->va + mp->siz; - for (va = mp->va; va <lim; va += 4*KiB) { - pte_t *p = walker(ttbr, va); - *p = PAGE(pa) | attr; + pa = mp->pa; + va = mp->va; + + n = (mp->siz + 4*KiB-1)/(4*KiB); + + for (i = 0; i < n; i++) { + if (vmap(pa, va, mp->perm) < 0) + return -1; pa += 4*KiB; + va += 4*KiB; } + + return 0; } -static uint64_t -kernelmap(Mach *m) +Context * +kernelmap(void) { - pte_t ttbr; + Map *mp; + static Context ctx = { + .r[ELR] = (uintptr_t) main, + }; + + /* + * FIXME: We are using a full page when + * we only need 16 bytes with 16 byte alignment. + */ + syswr(TTBR1_EL1, newtab()); + + dbg("TTBR_EL1=%llx\n", sysrd(TTBR1_EL1)); + + for (mp = mach.maps; mp->siz != 0; mp++) { + if (mapseg(mp) < 0) + panic("invalid mach map"); + } + barrier(DATA); + barrier(CODE); + + ctx.r[SP] = mach.phystack; + ctx.r[TTBR0] = sysrd(TTBR0_EL1); + ctx.r[TTBR1] = sysrd(TTBR1_EL1); + ctx.r[SPSR] = DAIF(0xf) | AARCH(A64) | MODE(EL1h); - ttbr = TTBR(newtab()); - mapseg(ttbr, &m->text); - mapseg(ttbr, &m->data); - mapseg(ttbr, &m->stack); + dbg("end of kernelmap\n"); - return ttbr; + return &ctx; } -static uint64_t -firstmap(Mach *m) +void +initmap(void) { pte_t *bp; - phyaddr_t pa, ttbr; - pte_t attr = CONT(1) | AF(1) | SH(OS) | AP(RDWR) | IDX(DEV); + phyaddr_t pa; + pte_t attr = CONT | AF(1) | SH(OS) | AP(RDWR) | IDX(DEV) | BLOCK; - bp = (pte_t *) m->ptable; + bp = (pte_t *) mach.ptable; for (pa = 0; pa < 4*GiB; pa += 512*MiB) - *bp++ = BLOCK64(pa) | attr; + *bp++ = pa | attr; - ttbr = m->ptable; - ttbr &= -1ull>>47 | ~0ull<<28 ; - - return ttbr; + syswr(TTBR0_EL1, mach.ptable); + barrier(DATA); + barrier(CODE); } void -immu(Mach *m) +immu(void) { - uint64_t tcr, sctlr, ttbr; + uint64_t sctlr, tcr, mair, id; - ntables = m->ntables; - tables = m->tables; + id = sysrd(ID_AA64MMFR0_EL1); + if (TGRAN4(id) != 0 || TGRAN64(id) != 0 || PAR(id) < I1TB) + panic("unsupported mmu"); + + ntables = mach.ntables; + tables = mach.tables; + + mair = + DEVICE(nGnRnE) << 56 | + DEVICE(nGnRE) << 48 | + DEVICE(nGRE) << 40 | + DEVICE(GRE) << 32 | + NORMAL(OWT, TRANSIENT, RALLOC|WALLOC) << 24 | + NORMAL(OWB, TRANSIENT, RALLOC|WALLOC) << 16 | + NORMAL(OWT, NTRANSIENT, RALLOC|WALLOC) << 8 | + NORMAL(OWB, NTRANSIENT, RALLOC|WALLOC) << 0; - sctlr = sysrd(SCTLR_EL1); tcr = - IPS4GB | + IPS(I1TB) | TG1(G4K) | TG0(G64K) | SH1(OS) | SH0(OS) | ORGN1(WBA) | ORGN0(WBA) | IRGN1(WBA) | IRGN0(WBA) | - T1SZ(42) | T0SZ(32); + T1SZ(24) | T0SZ(32); - invtlb(); - ttbr = firstmap(m); - syswr(TTBR0_EL1, ttbr); - syswr(MAIR_EL1, 0xFF); + /* + * TODO: setup SCTLR_EL1.WXN + */ + invalltlb(); + syswr(MAIR_EL1, mair); syswr(TCR_EL1, tcr); - barrier(DATA); barrier(CODE); + sctlr = sysrd(SCTLR_EL1); sctlr |= M; syswr(SCTLR_EL1, sctlr); barrier(CODE); - - ttbr = kernelmap(m); - barrier(DATA); - - syswr(TTBR1_EL1, ttbr); - barrier(DATA); - barrier(CODE); } diff --git a/src/os9/arch/arm64/panic.c b/src/os9/arch/arm64/panic.c @@ -3,7 +3,7 @@ #include "arch.h" -static const char const regnames[][5] = { +static const char const regnames[][8] = { [X0] = "x0", [X1] = "x1", [X2] = "x2", @@ -40,6 +40,8 @@ static const char const regnames[][5] = { [ESR] = "esr", [SP] = "sp", [FAR] = "far", + [TTBR0] = "ttbr0", + [TTBR1] = "ttbr1", }; void diff --git a/src/os9/arch/arm64/sysreg.lst b/src/os9/arch/arm64/sysreg.lst @@ -13,3 +13,4 @@ MAIR_EL1 S3_0_C10_C2_0 TTBR0_EL1 S3_0_C2_C0_0 TTBR1_EL1 S3_0_C2_C0_1 TCR_EL1 S3_0_C2_C0_2 +ID_AA64MMFR0_EL1 S3_0_C0_C7_0