9os

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

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:
Mconfig/toolchain/armclang.ld | 11++++++++++-
Mconfig/toolchain/gnu.ld | 5+++++
Minclude/bits/arm64/arch/types.h | 2++
Minclude/os9/os9.h | 40++++++++++++++++++++++++++++++++++------
Msrc/os9/arch/arm64/Makefile | 12++++++++----
Msrc/os9/arch/arm64/arch.h | 75++++++++++-----------------------------------------------------------------
Msrc/os9/arch/arm64/cache.c | 28+++++++++++++++++++++-------
Asrc/os9/arch/arm64/fpu.c | 25+++++++++++++++++++++++++
Msrc/os9/arch/arm64/fvp.c | 39++++++++++++++++++++++++++++++++++++++-
Asrc/os9/arch/arm64/gic.c | 11+++++++++++
Msrc/os9/arch/arm64/main.c | 124++++++++++++++++++++++++-------------------------------------------------------
Asrc/os9/arch/arm64/mmu.c | 194+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/os9/arch/arm64/panic.c | 5++---
Dsrc/os9/arch/arm64/svc.c | 34----------------------------------
Asrc/os9/arch/arm64/trap.c | 33+++++++++++++++++++++++++++++++++
Msrc/os9/dev/dev.c | 2+-
Msrc/os9/hosted/main.c | 1-
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"); }