commit 9bae75d2f7e86454b549bed34f2fefd59fba0911
parent 9d8e279acb98c81dc2e828817e83d89d58b42b9c
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Sun, 4 Oct 2020 01:30:54 +0200
os9/arm64: Add 4k page functions
Change-Id: I24fa6e2177dcf40b02032e8f7a2cfc43757f1358
Diffstat:
17 files changed, 432 insertions(+), 209 deletions(-)
diff --git a/config/toolchain/armclang.ld b/config/toolchain/armclang.ld
@@ -1,13 +1,22 @@
SECTIONS
{
.text : {
- *crt-none.o(.text*)
+ text = .;
+ *crt.o(.text*)
*(.text)
+ . = ALIGN(0x1000);
+ etext = .;
}
+
.data : {
*(.data)
+ edata = .;
}
+
.bss : {
*(.bss)
+ *(COMMON)
+ . = ALIGN(0x1000);
+ end = .;
}
}
diff --git a/config/toolchain/gnu.ld b/config/toolchain/gnu.ld
@@ -1,17 +1,22 @@
SECTIONS
{
.text : {
+ text = .;
*crt.o(.text*)
*(.text)
+ . = ALIGN(0x1000);
etext = .;
}
+
.data : {
*(.data)
edata = .;
}
+
.bss : {
*(.bss)
*(COMMON)
+ . = ALIGN(0x1000);
end = .;
}
}
diff --git a/include/bits/arm64/arch/types.h b/include/bits/arm64/arch/types.h
@@ -1,2 +1,4 @@
typedef int atomic_t;
typedef unsigned long mutex_t;
+typedef unsigned long long pte_t;
+typedef unsigned long long phyaddr_t;
diff --git a/include/os9/os9.h b/include/os9/os9.h
@@ -28,10 +28,6 @@
#define QID(t, v, p) ((Qid) {.type = (t), .vers = (v), .path = (p)})
-#ifdef SEEK_SET
-#error stdio included
-#endif
-
#define SEEK_SET 0
#define SEEK_CUR 1
#define SEEK_END 2
@@ -44,6 +40,8 @@ typedef struct win Win;
typedef struct chan Chan;
typedef struct qid Qid;
typedef struct dir Dir;
+typedef struct mach Mach;
+typedef struct map Map;
enum devflags {
O_READ = 1 << 0,
@@ -83,6 +81,37 @@ enum start_reason {
SNORMAL,
};
+enum map_attr {
+ MR,
+ MW,
+ MX,
+ MD,
+};
+
+struct map {
+ phyaddr_t pa;
+ uintptr_t va;
+ size_t siz;
+ int attr;
+};
+
+/*
+ * phystack and ktzero must be the first two fields of Mach
+ * because crt.s expects that.
+ */
+struct mach {
+ phyaddr_t phystack;
+ phyaddr_t ktzero;
+ phyaddr_t phytext;
+ phyaddr_t ptable;
+ phyaddr_t tables;
+ long ntables;
+
+ Map stack;
+ Map data;
+ Map text;
+};
+
struct qid {
unsigned long long path;
unsigned long vers;
@@ -164,7 +193,7 @@ 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(void);
+extern void idev(Mach *);
extern void *alloc(size_t size);
/* architectural functions */
@@ -194,7 +223,6 @@ extern Task *gettask(Proc *, int);
extern void sched(void);
/* globals */
-extern const char *const regnames[];
extern Chan *console;
/* per cpu globals */
diff --git a/src/os9/arch/arm64/Makefile b/src/os9/arch/arm64/Makefile
@@ -3,16 +3,19 @@ PROJECTDIR = ../../../..
include $(PROJECTDIR)/scripts/rules.mk
OBJS =\
- svc.o\
+ trap.o\
ecstr.o\
main.o\
arch.o\
debug_lock.o\
sysreg.o\
- cache.o\
panic.o\
fvp.o\
crt.o\
+ fpu.o\
+ mmu.o\
+ cache.o\
+ gic.o\
$(SRCDIR)/os9/builtin.o \
TARGET = $(BINDIR)/os9.bin
@@ -22,8 +25,9 @@ all: $(TARGET)
ecstr.c: ec.h
mkecstr ec.h
-main.o: sysreg.h version.h
-cache.o: sysreg.h
+$(OBJS): sysreg.h
+
+main.o: version.h
sysreg.h: sysreg.lst
mksysreg -h sysreg.lst
diff --git a/src/os9/arch/arm64/arch.h b/src/os9/arch/arm64/arch.h
@@ -1,8 +1,3 @@
-enum barrier_type {
- ISB,
- DSB_SY,
-};
-
/* SCTLR_EL1 */
#define SCTLR (3ul<<28 | 3ul<<22 | 1ul<<20 | 1ul<<11)
#define M (1ul << 0)
@@ -25,58 +20,10 @@ enum barrier_type {
#define EE (1ul << 25)
#define UCI (1ul << 26)
-/* TCR_EL1 */
-#define NS 1ull
-#define OS 2ull
-#define IS 3ull
-#define NC 0ull
-#define WBA 1ull
-#define WTA 2ull
-#define WT 3ull
-#define G16K 1ull
-#define G4K 2ull
-#define G64K 3ull
-
-#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 TG1(x) ((x) << 30)
-#define SH1(x) ((x) << 28)
-#define ORGN1(x) ((x) << 26)
-#define IRGN1(x) ((x) << 24)
-#define EDP1 (1ull << 23)
-#define A1 (1ull << 22)
-#define T1SZ(x) ((x) << 16)
-#define TG0(x) ((x) << 14)
-#define SH0(x) ((x) << 12)
-#define ORGN0(x) ((x) << 10)
-#define IRGN0(x) ((x) << 8)
-#define EDP0 (1ull << 7)
-#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 RDONLY 2
-
-#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 BLOCK64(pa) (((pa) & (-1ull>>64-47 | ~0ull<<47)) | 1)
-
-typedef struct mach Mach;
-typedef unsigned long long pte_t, phyaddr_t;
+enum barrier_type {
+ ISB,
+ DSB_SY,
+};
enum regidx {
X0,
@@ -118,12 +65,6 @@ enum regidx {
NR_REGS
};
-struct mach {
- phyaddr_t phystack;
- phyaddr_t ktzero;
- phyaddr_t ptable;
-};
-
struct context {
unsigned long long r[NR_REGS];
};
@@ -132,7 +73,11 @@ extern void main(Mach *);
extern void syswr(int, unsigned long long);
extern unsigned long long sysrd(int);
extern void barrier(int);
-extern void invdcachesetway(void *);
-extern void invdcache(void);
extern void invicache(void);
extern void invtlb(void);
+extern void invdcachesetway(void *);
+
+extern void icache(Mach *);
+extern void immu(Mach *);
+extern void ifpu(Mach *);
+extern void igic(Mach *);
diff --git a/src/os9/arch/arm64/cache.c b/src/os9/arch/arm64/cache.c
@@ -7,18 +7,19 @@
/* clidr_el1 */
#define LOC_SHIFT 24
-#define LOC_MASK 0x7 /* level of coherence */
-#define CTYPE_MASK 0x7 /* cache type */
+#define LOC_MASK 0x7
+#define CTYPE_MASK 0x7
/* ccsidr_el1 */
#define NSETS_SHIFT 13
-#define NSETS_MASK 0x7fff /* (number of sets in cache) - 1 */
+#define NSETS_MASK 0x7fff
#define NWAYS_SHIFT 3
-#define NWAYS_MASK 0x3ff /* (associativty of cache) - 1 */
-#define LINE_MASK 0x7 /* log2(cache line in bytes) - 4 */
+#define NWAYS_MASK 0x3ff
+#define LINE_MASK 0x7
/* csselr_el1 */
-#define LEVEL_SHIFT 1 /* cache level required */
+#define LEVEL_SHIFT 1
+
static unsigned
log2(unsigned long long v, unsigned width)
@@ -58,7 +59,7 @@ invdcachelvl(unsigned l)
barrier(DSB_SY);
}
-void
+static void
invdcache(void)
{
unsigned long long clidr;
@@ -86,3 +87,16 @@ invdcache(void)
clidr >>= 3;
}
}
+
+void
+icache(Mach *m)
+{
+ uint64_t sctlr;
+
+ invicache();
+ invdcache();
+
+ sctlr = sysrd(SCTLR_EL1);
+ sctlr |= C | I;
+ syswr(SCTLR_EL1, sctlr);
+}
diff --git a/src/os9/arch/arm64/fpu.c b/src/os9/arch/arm64/fpu.c
@@ -0,0 +1,25 @@
+#include <os9/os9.h>
+
+#include "arch.h"
+#include "sysreg.h"
+
+void
+fpon(void)
+{
+ syswr(CPACR_EL1, 3<<20);
+}
+
+void
+fpoff(void)
+{
+ syswr(CPACR_EL1, 0<<20);
+}
+
+void
+ifpu(Mach *m)
+{
+ syswr(FPCR, 0);
+ syswr(FPSR, 0);
+ fpoff();
+ barrier(ISB);
+}
diff --git a/src/os9/arch/arm64/fvp.c b/src/os9/arch/arm64/fvp.c
@@ -1,7 +1,44 @@
+#include <os9/os9.h>
+
#include "arch.h"
Mach mach = {
- .phystack = 0x80020000,
+ .phystack = 0x80080000,
+ .phytext = 0x80000000,
.ktzero = 0xFFFF000000000000 - 0x80000000,
+ .tables = 0x80080000,
.ptable = 0xA0000000,
+ .ntables = 128,
};
+
+int
+getch(void)
+{
+ char ch;
+
+ if (console) {
+ devread(console, &ch, 1);
+ return ch;
+ } else {
+ return *(char *) 0x1C090000;
+ }
+}
+
+void
+putch(int c)
+{
+ char ch;
+
+ if (console) {
+ ch = c;
+ devwrite(console, &ch, 1);
+ } else {
+ while (inm32((void *) 0x1C090000 + 6*4) & 1<<5)
+ ;
+ outm32(c, (void *) 0x1C090000);
+ if (c == '\n')
+ putch('\r');
+ }
+ barrier(ISB);
+ barrier(DSB_SY);
+}
diff --git a/src/os9/arch/arm64/gic.c b/src/os9/arch/arm64/gic.c
@@ -0,0 +1,11 @@
+#include <os9/os9.h>
+
+#include "sysreg.h"
+#include "arch.h"
+
+void
+igic(Mach *m)
+{
+ interrupt(ENABLE);
+ barrier(ISB);
+}
diff --git a/src/os9/arch/arm64/main.c b/src/os9/arch/arm64/main.c
@@ -1,6 +1,5 @@
#include <os9/os9.h>
-#include <errno.h>
#include <stdint.h>
#include <string.h>
@@ -10,104 +9,54 @@
#include "sysreg.h"
#include "arch.h"
-#define DEVICE 7
-#define NORMAL 0
-
Chan *console;
-int
-getch(void)
-{
- char ch;
-
- if (console) {
- devread(console, &ch, 1);
- return ch;
- } else {
- return *(char *) 0x1C090000;
- }
-}
-
-void
-putch(int c)
-{
- char ch;
-
- if (console) {
- ch = c;
- devwrite(console, &ch, 1);
- } else {
- *(char *) 0x1C090000 = c;
- }
-}
-
-static unsigned long long
-firstmap(Mach *m)
+static void
+iarch(Mach *m)
{
- pte_t *bp;
- phyaddr_t pa, ttbr;
- pte_t attr = CONT(1) | AF(1) | SH(OS) | AP(RDWR) | IDX(DEVICE);
+ extern void *vectbl(void);
- bp = (pte_t *) m->ptable;
- for (pa = 0; pa < 4*GiB; pa += 512*MiB)
- *bp++ = BLOCK64(pa) | attr;
-
- ttbr = m->ptable;
- ttbr &= -1ull>>47 | ~0ull<<28 ;
-
- return ttbr;
+ syswr(VBAR_EL1, (phyaddr_t) vectbl);
+ syswr(SCTLR_EL1, SCTLR | SA0 | SA | A);
+ barrier(ISB);
}
static void
imach(Mach *m)
{
- extern void *vectbl;
- uint64_t tcr, sctlr, ttbr;
-
- syswr(VBAR_EL1, (phyaddr_t) vectbl);
- barrier(ISB);
-
- sctlr = sysrd(SCTLR_EL1);
- tcr =
- IPS4GB |
- TG1(G64K) | TG0(G64K) |
- SH1(OS) | SH0(OS) |
- ORGN1(WBA) | ORGN0(WBA) |
- IRGN1(WBA) | IRGN0(WBA) |
- T1SZ(32) | T0SZ(32);
- ttbr = firstmap(m);
-
- invtlb();
- invicache();
- invdcache();
-
- sctlr |= C | I;
- syswr(SCTLR_EL1, sctlr);
- syswr(MAIR_EL1, 0xFF);
- syswr(TTBR0_EL1, ttbr);
- syswr(TCR_EL1, tcr);
+ 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(DSB_SY);
- barrier(ISB);
-
- sctlr |= M;
- syswr(SCTLR_EL1, sctlr);
- barrier(ISB);
-
- syswr(CPACR_EL1, 3<<20);
- syswr(FPCR, 0);
- syswr(FPSR, 0);
- barrier(ISB);
}
static void
-info(void)
+info(Mach *m)
{
dbg("os9: version %s\n",
OS9VERSION);
}
static void
-icons(void)
+icons(Mach *m)
{
static char setin[] = "addin #t0/raw\n";
static char setout[] = "addout #t0/raw\n";
@@ -135,13 +84,16 @@ icons(void)
void
main(Mach *m)
{
+ iarch(m);
+ icache(m);
imach(m);
+ immu(m);
halt();
- idev();
- interrupt(ENABLE);
- barrier(ISB);
- icons();
- info();
+ 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
@@ -0,0 +1,194 @@
+#include <os9/os9.h>
+
+#include <string.h>
+
+#include <libk.h>
+
+#include "sysreg.h"
+#include "arch.h"
+
+/* TCR_EL1 */
+#define NS 1ull
+#define OS 2ull
+#define IS 3ull
+#define NC 0ull
+#define WBA 1ull
+#define WTA 2ull
+#define WT 3ull
+#define G16K 1ull
+#define G4K 2ull
+#define G64K 3ull
+
+#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 TG1(x) ((x) << 30)
+#define SH1(x) ((x) << 28)
+#define ORGN1(x) ((x) << 26)
+#define IRGN1(x) ((x) << 24)
+#define EDP1 (1ull << 23)
+#define A1 (1ull << 22)
+#define T1SZ(x) ((x) << 16)
+#define TG0(x) ((x) << 14)
+#define SH0(x) ((x) << 12)
+#define ORGN0(x) ((x) << 10)
+#define IRGN0(x) ((x) << 8)
+#define EDP0 (1ull << 7)
+#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
+
+#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 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 DEV 7
+#define MEM 0
+
+static long ntables;
+static phyaddr_t tables;
+
+static pte_t
+newtab(void)
+{
+ phyaddr_t addr;
+ static long n;
+ static mutex_t m;
+
+ lock(&m);
+ if (n == ntables)
+ panic("out of memory");
+ addr = tables + n*4ll*KiB;
+ n++;
+ unlock(&m);
+
+ return addr;
+}
+
+static pte_t *
+walker(pte_t ttbr, uintptr_t va)
+{
+ pte_t *bp, e;
+ int idx, i;
+
+ bp = PTABLE(ttbr);
+ for (i = 0; i < 3; i++) {
+ idx = va>>(38-i*9) & 0x1FF;
+ e = bp[idx];
+ if (e == INVALID) {
+ e = TABLE(newtab());
+ bp[idx] = e;
+ }
+ bp = PTABLE(e);
+ }
+
+ return &bp[va>>11 & 0x1FF];
+}
+
+static void
+mapseg(pte_t ttbr, Map *mp)
+{
+ uintptr_t va, lim;
+ phyaddr_t pa;
+ pte_t attr;
+
+ attr = AF(1) | SH(OS);
+ attr |= (mp->attr & MW) ? AP(RDWR) : AP(RD);
+ attr |= (mp->attr & MD) ? IDX(DEV) : IDX(MEM);
+
+ 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 += 4*KiB;
+ }
+}
+
+static uint64_t
+kernelmap(Mach *m)
+{
+ pte_t ttbr;
+
+ ttbr = TTBR(newtab());
+ mapseg(ttbr, &m->text);
+ mapseg(ttbr, &m->data);
+ mapseg(ttbr, &m->stack);
+
+ return ttbr;
+}
+
+static uint64_t
+firstmap(Mach *m)
+{
+ pte_t *bp;
+ phyaddr_t pa, ttbr;
+ pte_t attr = CONT(1) | AF(1) | SH(OS) | AP(RDWR) | IDX(DEV);
+
+ bp = (pte_t *) m->ptable;
+ for (pa = 0; pa < 4*GiB; pa += 512*MiB)
+ *bp++ = BLOCK64(pa) | attr;
+
+ ttbr = m->ptable;
+ ttbr &= -1ull>>47 | ~0ull<<28 ;
+
+ return ttbr;
+}
+
+void
+immu(Mach *m)
+{
+ uint64_t tcr, sctlr, ttbr;
+
+ ntables = m->ntables;
+ tables = m->tables;
+
+ sctlr = sysrd(SCTLR_EL1);
+ tcr =
+ IPS4GB |
+ TG1(G4K) | TG0(G64K) |
+ SH1(OS) | SH0(OS) |
+ ORGN1(WBA) | ORGN0(WBA) |
+ IRGN1(WBA) | IRGN0(WBA) |
+ T1SZ(42) | T0SZ(32);
+
+ invtlb();
+ ttbr = firstmap(m);
+ syswr(TTBR0_EL1, ttbr);
+ syswr(MAIR_EL1, 0xFF);
+ syswr(TCR_EL1, tcr);
+ barrier(DSB_SY);
+ barrier(ISB);
+
+ sctlr |= M;
+ syswr(SCTLR_EL1, sctlr);
+ barrier(ISB);
+
+ ttbr = kernelmap(m);
+ barrier(DSB_SY);
+
+ syswr(TTBR1_EL1, ttbr);
+ barrier(DSB_SY);
+ barrier(ISB);
+}
diff --git a/src/os9/arch/arm64/panic.c b/src/os9/arch/arm64/panic.c
@@ -3,7 +3,7 @@
#include "arch.h"
-const char *const regnames[] = {
+static const char const regnames[][5] = {
[X0] = "x0",
[X1] = "x1",
[X2] = "x2",
@@ -40,7 +40,6 @@ const char *const regnames[] = {
[ESR] = "esr",
[SP] = "sp",
[FAR] = "far",
- NULL
};
void
@@ -53,7 +52,7 @@ dumpregs(Context *ctx)
(i > 0 && i % 3 == 0) ? '\n' : ' ');
}
if (i % 4 != 3)
- kprint("\n'");
+ kprint("\n");
}
static void
diff --git a/src/os9/arch/arm64/svc.c b/src/os9/arch/arm64/svc.c
@@ -1,34 +0,0 @@
-#include <setjmp.h>
-#include <stdint.h>
-
-#include <libk.h>
-#include <os9/os9.h>
-
-#include "ec.h"
-#include "arch.h"
-
-static void
-svc(int numsvc)
-{
-}
-
-void
-trap(Context *ctx)
-{
- enum ecvals ec;
- const char *msg;
- int numsvc;
-
- dbg("exception handler\n");
- ec = (ctx->r[ESR] >> 26) & 0x3f;
-
- if (ec != SVC) {
- msg = (ec < NR_EC_VALS) ? ecstr[ec] : "unknown reason";
- panic(msg);
- }
-
- numsvc = ctx->r[ESR] & 0xff;
-
- svc(numsvc);
- swtch(ctx);
-}
diff --git a/src/os9/arch/arm64/trap.c b/src/os9/arch/arm64/trap.c
@@ -0,0 +1,33 @@
+#include <setjmp.h>
+#include <stdint.h>
+
+#include <libk.h>
+#include <os9/os9.h>
+
+#include "ec.h"
+#include "arch.h"
+
+static void
+svc(int numsvc)
+{
+}
+
+void
+trap(Context *ctx)
+{
+ enum ecvals ec;
+ const char *msg;
+ int numsvc;
+
+ ec = (ctx->r[ESR] >> 26) & 0x3f;
+
+ if (ec != SVC) {
+ msg = (ec < NR_EC_VALS) ? ecstr[ec] : "unknown reason";
+ panic("unknown reason");
+ }
+
+ numsvc = ctx->r[ESR] & 0xff;
+
+ svc(numsvc);
+ swtch(ctx);
+}
diff --git a/src/os9/dev/dev.c b/src/os9/dev/dev.c
@@ -724,7 +724,7 @@ err0:
}
void
-idev(void)
+idev(Mach *m)
{
Chan *c;
diff --git a/src/os9/hosted/main.c b/src/os9/hosted/main.c
@@ -79,5 +79,4 @@ main(int argc, char *argv[])
idev();
icons();
debug();
- panic("out of sync");
}