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:
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