commit cd323a673a99270ad88f44cab30710e235248190
parent 8b42b98721e026b97cee7cfd7031167838ac2ff2
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Sun, 27 Sep 2020 09:50:47 +0200
os9/arm64: Enable MMU
This commit enables the MMU with a 1:1 mapping. It assumes that
the physical memory is in the lower 4GB of the physical space, which
is a plausible assumption.
Change-Id: Id86eba6e44ed29df780275dfd36d299eaa076baf
Diffstat:
11 files changed, 299 insertions(+), 99 deletions(-)
diff --git a/README b/README
@@ -16,7 +16,7 @@ Building TF-A with a preloaded BL33
===================================
export CROSS_COMPILE=aarch64-linux-gnu
-make PLAT=fvp DEBUG=1 RESET_TO_BL31=1 PRELOADED_BL33_BASE=0x880000000 all
+make PLAT=fvp DEBUG=1 RESET_TO_BL31=1 PRELOADED_BL33_BASE=0x80000000 all
Running 9os
=============
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=0x880000000
+SYSLDFLAGS = -Ttext=0xFFFF000000000000
OS9 = 9fvp
diff --git a/scripts/fvp.sh b/scripts/fvp.sh
@@ -11,9 +11,7 @@ $FVP_PATH/FVP_Base_RevC-2xAEMv8A \
-C pctl.startup=0.0.0.0 \
-C cache_state_modelled=1 \
-C bp.pl011_uart0.uart_enable=1 \
- -C bp.pl011_uart0.out_file=$uart0 \
-C bp.pl011_uart3.uart_enable=1 \
- -C bp.pl011_uart3.out_file=$uart3 \
-C cluster0.cpu0.RVBAR=0x04001000 \
-C cluster0.cpu1.RVBAR=0x04001000 \
-C cluster0.cpu2.RVBAR=0x04001000 \
@@ -23,4 +21,8 @@ $FVP_PATH/FVP_Base_RevC-2xAEMv8A \
-C cluster1.cpu2.RVBAR=0x04001000 \
-C cluster1.cpu3.RVBAR=0x04001000 \
--data cluster0.cpu0=$bl31@0x04001000 \
- --data cluster0.cpu0=$os@0x880000000 \
+ --data cluster0.cpu0=$os@0x80000000 \
+
+# --plugin /home/k0ga/models/FVP_Base_RevC-2xAEMv8A/plugins/Linux64_GCC-6.4/TarmacTrace.so \
+# -C bp.pl011_uart0.out_file=$uart0 \
+# -C bp.pl011_uart3.out_file=$uart3 \
diff --git a/src/os9/arch/arm64/Makefile b/src/os9/arch/arm64/Makefile
@@ -11,6 +11,7 @@ OBJS =\
debug_lock.o \
sysreg.o \
cache.o \
+ fvp.o\
$(SRCDIR)/os9/builtin.o \
TARGET = $(BINDIR)/os9.bin
diff --git a/src/os9/arch/arm64/arch.h b/src/os9/arch/arm64/arch.h
@@ -3,9 +3,96 @@ enum barrier_type {
DSB_SY,
};
-extern void wsysreg(enum sysreg, unsigned long long v);
+/* SCTLR_EL1 */
+#define SCTLR (3ul<<28 | 3ul<<22 | 1ul<<20 | 1ul<<11)
+#define M (1ul << 0)
+#define A (1ul << 1)
+#define C (1ul << 2)
+#define SA (1ul << 3)
+#define SA0 (1ul << 4)
+#define CP15BEN (1ul << 5)
+#define THEE (1ul << 6)
+#define ITD (1ul << 7)
+#define SED (1ul << 8)
+#define UMA (1ul << 9)
+#define I (1ul << 12)
+#define DZE (1ul << 14)
+#define UCT (1ul << 15)
+#define nTWI (1ul << 16)
+#define nTWE (1ul << 18)
+#define WXM (1ul << 19)
+#define E0E (1ul << 24)
+#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 KiB 1024u
+#define MiB (1024u * KiB)
+#define GiB (1024ul * MiB)
+
+#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;
+
+struct mach {
+ phyaddr_t phystack;
+ phyaddr_t ktzero;
+ phyaddr_t ptable;
+};
+
+extern void main(Mach *);
+extern void wsysreg(enum sysreg, unsigned long long);
extern unsigned long long rsysreg(enum sysreg);
-extern void barrier(enum barrier_type type);
-extern void invdcachesetway(void *addr);
+extern void barrier(int);
+extern void invdcachesetway(void *);
extern void invdcache(void);
extern void invicache(void);
+extern void invtlb(void);
diff --git a/src/os9/arch/arm64/arch.s b/src/os9/arch/arm64/arch.s
@@ -1,15 +1,14 @@
.FILE "arch.s"
- .TEXT
.GLOBL panic,halt,intr,swtch,getcontext
.GLOBL barrier,vectbl,doswtch,inm8,inm16,inm32
.GLOBL outm8,outm16,outm32
- .GLOBL invdcachesetway,invicache,vectbl
+ .GLOBL invdcachesetway,invicache,vectbl,invtlb
.GLOBL inm8,inm16,inm32,outm8,outm16,outm32
+ .TEXT
intr:
- CMP X0,#0
- B.NE 1f
+ CBNZ X0,1f
MSR DAIFSET,#15
RET
1:
@@ -23,11 +22,16 @@ barrier:
BR X1
1:
- ISb
+ ISB
RET
+
DSB SY
RET
+invtlb:
+ TLBI VMALLE1IS
+ RET
+
invdcachesetway:
DC ISW,X0
RET
@@ -36,15 +40,6 @@ invicache:
IC IALLU
RET
-badinst:
- ADR X0,badimsg
- B panic
-
- .SECTION .rodata
-badimsg:
- .ASCIZ "invalid instruction"
-
- .TEXT
inm8:
LDRB W0,[X0]
RET
diff --git a/src/os9/arch/arm64/crt.s b/src/os9/arch/arm64/crt.s
@@ -1,58 +1,50 @@
.FILE "crt.s"
+
+ .INCLUDE "defines.inc"
+
.TEXT
.GLOBL _start
-
_start:
- MRS X0,CURRENTEL
- UBFX X0,X0,#2,#2
- CMP X0,1
- BEQ el1
+ MRS X10,CURRENTEL
+ UBFX X10,X10,#2,#2
+ CMP X10,1
+ BEQ EL1
- /* small bootloader for fvp */
- LDR W0,=0x3C5
- MSR SPSR_EL2,X0
+ MOV X10,A | D | IRQ | FIQ | EL1h
+ MSR SPSR_EL2,X10
- LDR W0,=0x30D00830
- MSR SCTLR_EL1,X0
+ LDR W10,=SCTLR | SA0 | SA | A
+ MSR SCTLR_EL1,X10
- LDR W0,=0x80000000
- MSR HCR_EL2,X0
+ LDR W10,=RW
+ MSR HCR_EL2,X10
- LDR X0,=_start
- MSR ELR_EL2,X0
+ ADR X10,EL1
+ MSR ELR_EL2,X10
ERET
-el1:
- ADR X0,vectbl
- MSR VBAR_EL1,X0
- ISB
-
- /* Differentiate between cold and warm boot (FVP only) */
- MRS X2,MPIDR_EL1
- LDR X1,=0x1C100000
- STR W2,[X1,0x10]
- LDR W2,[X1,0x10]
- UBFX W2,W2,24,2
- CMP W2,2
- BEQ warm
- CMP W2,3
- BEQ warm
-
- LDR X0,=0x880080000 /* Set initial stack */
- MOV SP,X0
-
- LDR X0,=edata /* BSS clean */
- MOV X1,#0
- LDR X2,=end
- SUB X2,X2,X0
- BL memset
-
- SUB X29,X29,X29
+EL1:
+ ADR X0,mach
+ LDR X9,[X0]
+ MOV SP,X9
+ MOV X29,0
+
+ LDR X9,[X0,8]
+ LDR X10,=edata
+ LDR X11,=end
+ SUB X11,X11,X10
+ LSR X11,X11,3
+ SUB X10,X10,X9
+
+.L1:
+ STR XZR,[X10],8
+ SUB X11,X11,1
+ CBNZ X11,.L1
+
BL main
-warm:
- ADR X0,outsync
+ ADR X0,OUTSYN
B panic
.DATA
-outsync:
+OUTSYN:
.ASCIZ "out of sync"
diff --git a/src/os9/arch/arm64/defines.inc b/src/os9/arch/arm64/defines.inc
@@ -0,0 +1,74 @@
+// SCTLR_EL1
+ .set SCTLR,3<<28 | 3<<22 | 1<<20 | 1<<11
+ .set M,1<<0
+ .set A,1<<1
+ .set C,1<<2
+ .set SA,1<<3
+ .set SA0,1<<4
+ .set CP15BEN,1<<5
+ .set THEE,1<<6
+ .set ITD,1<<7
+ .set SED,1<<8
+ .set UMA,1<<9
+ .set I,1<<12
+ .set DZE,1<<14
+ .set UCT,1<<15
+ .set nTWI,1<<16
+ .set nTWE,1<<18
+ .set WXN,1<<19
+ .set E0E,1<<24
+ .set EE,1<<25
+ .set UCI,1<<26
+
+// HCR_EL2
+ .set ID,1<<33
+ .set CD,1<<32
+ .set RW,1<<31
+ .set TRVM,1<<30
+ .set HCD,1<<29
+ .set TDZ,1<<28
+ .set TGE,1<<27
+ .set TVM,1<<26
+ .set TTLB,1<<24
+ .set TPU,1<<23
+ .set TPC,1<<22
+ .set TSW,1<<21
+ .set TACR,1<<20
+ .set TIDCP,1<<19
+ .set TSC,1<<18
+ .set TID3,1<<17
+ .set TID2,1<<16
+ .set TID1,1<<15
+ .set TID0,1<<14
+ .set TWE,1<<13
+ .set TWI,1<<12
+ .set DC,1<<11
+ .set BSU,1<<10
+ .set FB,1<<9
+ .set VSE,1<<8
+ .set VI,1<<7
+ .set VF,1<<6
+ .set AMO,1<<5
+ .set IMO,1<<4
+ .set FMO,1<<3
+ .set PTW,1<<2
+ .set SWIO,1<<1
+ .set VM,1<<0
+
+//SPSR_EL2
+ .set NFLAG,1<<31
+ .set ZFLAG,1<<30
+ .set CFLAG,1<<29
+ .set VFLAG,1<<28
+ .set SS,1<<21
+ .set IL,1<<20
+ .set D,1<<9
+ .set A,1<<8
+ .set IRQ,1<<7
+ .set FIQ,1<<7
+ .set M32,1<<4
+ .set EL0t,0
+ .set EL1t,4
+ .set EL1h,5
+ .set EL2t,8
+ .set EL2h,9
diff --git a/src/os9/arch/arm64/fvp.c b/src/os9/arch/arm64/fvp.c
@@ -0,0 +1,7 @@
+#include "arch.h"
+
+Mach mach = {
+ .phystack = 0x80020000,
+ .ktzero = 0xFFFF000000000000 - 0x80000000,
+ .ptable = 0xA0000000,
+};
diff --git a/src/os9/arch/arm64/main.c b/src/os9/arch/arm64/main.c
@@ -1,4 +1,5 @@
#include <errno.h>
+#include <stdint.h>
#include <stdlib.h>
#include <string.h>
@@ -10,68 +11,106 @@
#include "sysreg.h"
#include "arch.h"
-#define STACKSIZ 1792
-#define HEAPSIZ 1792
+#define HEAPSIZ (512 *KiB)
-typedef struct mach Mach;
+#define DEVICE 7
+#define NORMAL 0
-struct mach {
- void *sp;
- size_t stacksiz;
+union bucket {
+ long long ll;
+ uintptr_t up;
};
-Context ctx;
-
void *
alloc(size_t size)
{
- static char heap[HEAPSIZ];
- static char *base = heap;
+ static union bucket heap[HEAPSIZ / sizeof(union bucket)];
+ static union bucket *base = heap;
static int lock;
- char *bp;
+ size_t n;
+ union bucket *bp;
if (size == 0) {
lock = 1;
return NULL;
}
+ n = size-1 / sizeof(union bucket) + 1;
if (lock)
- panic("alloc");
+ panic("alloc with lock");
bp = base;
if (&bp[size] > &heap[HEAPSIZ])
- return NULL;
- base += size;
+ panic("out of memory");
+ base += n;
+
return bp;
}
+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(DEVICE);
+
+ 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;
+}
+
static void
-imach(Mach *mp, void *stackp)
+imach(Mach *m)
{
- memset(&ctx, 0, sizeof(ctx));
+ extern void *vectbl;
+ uint64_t tcr, sctlr, ttbr;
+
+ wsysreg(VBAR_EL1, (phyaddr_t) vectbl);
+ barrier(ISB);
- mp->sp = stackp;
- mp->stacksiz = STACKSIZ;
+ invtlb();
+ invicache();
+ invdcache();
+
+ sctlr = rsysreg(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);
+
+ sctlr |= C | I;
+ wsysreg(SCTLR_EL1, sctlr);
+ wsysreg(MAIR_EL1, 0xFF);
+ wsysreg(TTBR0_EL1, ttbr);
+ wsysreg(TCR_EL1, tcr);
+ barrier(DSB_SY);
+ barrier(ISB);
+
+ sctlr |= M;
+ wsysreg(SCTLR_EL1, sctlr);
+ barrier(ISB);
- ctx.r[SP] = (unsigned long long) mp->sp;
- ctx.r[ELR] = 0x4022000;
- ctx.r[SPSR] = 0xf << 6 | 0xd;
wsysreg(CPACR_EL1, 3<<20);
wsysreg(FPCR, 0);
wsysreg(FPSR, 0);
-
- invicache();
- invdcache();
+ barrier(ISB);
}
static void
-info(Mach *mp)
+info(void)
{
dbg(kout,
- "os9: version %s\n"
- "sp = %p, stacksiz = 0x%zx\n",
- OS9VERSION,
- mp->sp, mp->stacksiz);
+ "os9: version %s\n",
+ OS9VERSION);
}
static void
@@ -117,16 +156,15 @@ namespace(void)
}
void
-main(void *stackp)
+main(Mach *m)
{
- Mach mach;
-
- imach(&mach, stackp);
+ imach(m);
+ halt();
idev();
intr(IENABLE);
barrier(ISB);
namespace();
- info(&mach);
+ info();
debug();
panic("main");
}
diff --git a/src/os9/arch/arm64/sysreg.lst b/src/os9/arch/arm64/sysreg.lst
@@ -9,3 +9,7 @@ CSSELR_EL1 S3_2_C0_C0_0
CPACR_EL1 S3_0_C1_C0_2
FPCR S3_3_C4_C4_0
FPSR S3_3_C4_C4_1
+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