ref: f35d5ee5b036b7b4fa59b1839f52fca15b7f99f9
parent: 3fc8d1bdae10955e0b31ee1766d17367e0d0caa1
author: cinap_lenrek <[email protected]>
date: Sun Aug 18 17:16:30 EDT 2019
bcm64: add support for more than 1GB of ram (untested) this adds a 4GB KMAP window into the kernel address space so we can access all physical ram on raspberry pi 4 for user pages. note that kernel memory above KZERO is still limited to 1GB because of DMA restrictions.
--- a/sys/src/9/bcm64/archbcm4.c
+++ b/sys/src/9/bcm64/archbcm4.c
@@ -17,7 +17,7 @@
#define POWERREGS (VIRTIO+0x100000)
Soc soc = {
- .dramsize = 0x40000000,
+ .dramsize = 0xFC000000,
.busdram = 0xC0000000,
.iosize = 0x03000000,
.busio = 0x7C000000,
--- a/sys/src/9/bcm64/mem.h
+++ b/sys/src/9/bcm64/mem.h
@@ -39,7 +39,8 @@
#define STACKALIGN(sp) ((sp) & ~7) /* bug: assure with alloc */
#define TRAPFRAMESIZE (38*8)
-#define KSEG0 (0xFFFFFFFF00000000ULL)
+#define KSEG0 (0xFFFFFFFE00000000ULL)
+#define KMAP (0xFFFFFFFE00000000ULL)
#define FRAMEBUFFER (0xFFFFFFFF00000000ULL|PTEWT)
#define VGPIO 0 /* virtual gpio for pi3 ACT LED */
@@ -54,7 +55,6 @@
#define SPINTABLE (KZERO+0xd8)
#define CONFADDR (KZERO+0x100)
-#define VECTORSEL2 (0x1000)
#define REBOOTADDR (0x1c00) /* reboot code - physical address */
#define VCBUFFER (KZERO+0x3400) /* videocore mailbox buffer */
--- a/sys/src/9/bcm64/mmu.c
+++ b/sys/src/9/bcm64/mmu.c
@@ -28,11 +28,30 @@
}
if(PTLEVELS > 2)
for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
- l1[PTL1X(pa, 2)] = (uintptr)&l1[L1TABLEX(pa, 1)] | PTEVALID | PTETABLE;
+ l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
if(PTLEVELS > 3)
for(pa = PHYSDRAM, va = KZERO; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
- l1[PTL1X(pa, 3)] = (uintptr)&l1[L1TABLEX(pa, 2)] | PTEVALID | PTETABLE;
+ l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
+ /* KMAP */
+ attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTEPXN | PTESH(SHARE_INNER);
+ pe = PHYSDRAM + soc.dramsize;
+ for(pa = PHYSDRAM, va = KMAP; pa < pe; pa += PGLSZ(1), va += PGLSZ(1)){
+ if(pe - pa < PGLSZ(1)){
+ l1[PTL1X(va, 1)] = (uintptr)l1 | PTEVALID | PTETABLE;
+ for(; pa < pe; pa += PGLSZ(0), va += PGLSZ(0))
+ l1[PTLX(va, 0)] = pa | PTEVALID | PTEPAGE | attr;
+ break;
+ }
+ l1[PTL1X(va, 1)] = pa | PTEVALID | PTEBLOCK | attr;
+ }
+ if(PTLEVELS > 2)
+ for(pa = PHYSDRAM, va = KMAP; pa < pe; pa += PGLSZ(2), va += PGLSZ(2))
+ l1[PTL1X(va, 2)] = (uintptr)&l1[L1TABLEX(va, 1)] | PTEVALID | PTETABLE;
+ if(PTLEVELS > 3)
+ for(pa = PHYSDRAM, va = KMAP; pa < pe; pa += PGLSZ(3), va += PGLSZ(3))
+ l1[PTL1X(va, 3)] = (uintptr)&l1[L1TABLEX(va, 2)] | PTEVALID | PTETABLE;
+
/* VIRTIO */
attr = PTEWRITE | PTEAF | PTEKERNEL | PTEUXN | PTEPXN | PTESH(SHARE_OUTER) | PTEDEVICE;
pe = soc.physio + soc.iosize;
@@ -130,6 +149,7 @@
mmuswitch(nil);
}
+/* KZERO maps the first 1GB of ram */
uintptr
paddr(void *va)
{
@@ -156,15 +176,19 @@
return nil;
}
-void
-kmapinval(void)
+/* KMAP maps all of ram (up to 4GB) */
+static void*
+kmapaddr(uintptr pa)
{
+ if(pa < (uintptr)-KZERO)
+ return (void*)(pa + KZERO);
+ return (void*)(pa + KMAP);
}
KMap*
kmap(Page *p)
{
- return kaddr(p->pa);
+ return kmapaddr(p->pa);
}
void
@@ -172,6 +196,11 @@
{
}
+void
+kmapinval(void)
+{
+}
+
uintptr
mmukmap(uintptr va, uintptr pa, usize size)
{
@@ -228,7 +257,6 @@
if(pte & (0xFFFFULL<<48))
iprint("strange pte %#p va %#p\n", pte, va);
pte &= ~(0xFFFFULL<<48 | BY2PG-1);
- table = KADDR(pte);
} else {
pg = up->mmufree;
if(pg == nil)
@@ -238,11 +266,12 @@
if((pg->next = up->mmuhead[i+1]) == nil)
up->mmutail[i+1] = pg;
up->mmuhead[i+1] = pg;
- memset(KADDR(pg->pa), 0, BY2PG);
+ pte = pg->pa;
+ memset(kmapaddr(pte), 0, BY2PG);
coherence();
- table[x] = pg->pa | PTEVALID | PTETABLE;
- table = KADDR(pg->pa);
+ table[x] = pte | PTEVALID | PTETABLE;
}
+ table = kmapaddr(pte);
x = PTLX(va, (uintptr)i);
}
return &table[x];
@@ -333,7 +362,7 @@
*pte = pa | PTEPAGE | PTEUSER | PTEPXN | PTENG | PTEAF | PTESH(SHARE_INNER);
if(pg->txtflush & (1UL<<m->machno)){
/* pio() sets PG_TXTFLUSH whenever a text pg has been written */
- cachedwbinvse((void*)KADDR(pg->pa), BY2PG);
+ cachedwbinvse(kmap(pg), BY2PG);
cacheiinvse((void*)va, BY2PG);
pg->txtflush &= ~(1UL<<m->machno);
}