--- /sys/src/9k/k10/asm.c +++ /sys/src/9k/k10/asm.c @@ -327,9 +327,9 @@ asmmeminit(void) { Asm* asm; PTE *pte; - int i, j, l; + int i, j, l, first; uintptr va; - uintmem hi, lo, mem, nextmem, pa, ksize; + uintmem hi, lo, mem, nextmem, pa, ksize, vmgap; Pallocmem *pm; /* @@ -351,7 +351,18 @@ asmmeminit(void) if((pa = mmuphysaddr(sys->vmunused)) == ~0) panic("asmmeminit 1"); pa += sys->vmunmapped - sys->vmunused; - mem = asmalloc(pa, sys->vmend - sys->vmunmapped, AsmMEMORY, 0); + first = 1; + vmgap = sys->vmend - sys->vmunmapped; + while((mem = asmalloc(pa, vmgap, AsmMEMORY, 0)) != pa && kernmem >= 300*MiB){ + if(first){ + print("asmmeminit: can't get %#P bytes at %#P for unmapped vm, reducing kernmem\n", + vmgap, pa); + first = 0; + } + kernmem -= 50*MiB; + sys->vmend = ROUNDUP(sys->vmstart + kernmem, PGLSZ(1)); + vmgap = sys->vmend - sys->vmunmapped; + } if(mem != pa) panic("asmmeminit 2"); DBG("asmmeminit: mem %#P\n", mem); --- /sys/src/9k/k10/dat.h +++ /sys/src/9k/k10/dat.h @@ -266,7 +266,8 @@ struct Sys { uchar ptrpage[4*KiB]; }; - uchar _57344_[2][4*KiB]; /* unused */ + PTE pd2g[PTSZ/sizeof(PTE)]; /* PD for KSEG0's 2nd GB (PDP[511]) */ + uchar _61440_[4*KiB]; /* unused */ }; extern Sys* sys; @@ -316,6 +317,7 @@ extern register Mach* m; /* R15 */ extern register Proc* up; /* R14 */ extern uintptr kseg0; +extern uintptr kernmem; /* * Horrid. --- /sys/src/9k/k10/l32p.s +++ /sys/src/9k/k10/l32p.s @@ -132,6 +132,10 @@ TEXT _warp64<>(SB), 1, $-4 MOVL DX, PDO(KZERO)(AX) /* PDE for KZERO 0-[24]MiB */ ADDL $PGLSZ(1), DX MOVL DX, PDO(KZERO+PGLSZ(1))(AX) /* PDE for KZERO [24]-[48]MiB */ + ADDL $PGLSZ(1), DX + MOVL DX, PDO(KZERO+2*PGLSZ(1))(AX) /* PDE for KZERO 4-6MiB */ + ADDL $PGLSZ(1), DX + MOVL DX, PDO(KZERO+3*PGLSZ(1))(AX) /* PDE for KZERO 6-8MiB */ MOVL AX, DX /* */ ADDL $(PTSZ|PteRW|PteP), DX /* PT at PML4 + 3*PTSZ */ --- /sys/src/9k/k10/main.c +++ /sys/src/9k/k10/main.c @@ -66,6 +66,31 @@ options(int argc, char* argv[]) vflag = dbgflg['v']; } +enum { + Minmb = 128, /* minimum sane memory in MB */ + Kernfract = 32, /* fraction of memory for the kernel */ +}; + +static void +setkernmem(void) +{ + uintptr pmsize; + + pmsize = sys->pmend; + if(pmsize < Minmb*MB){ + print("setkernmem: mem %llud, assuming %d MB\n", (uvlong)pmsize, Minmb); + pmsize = Minmb*MB; + sys->pmend = pmsize; + } + if(pmsize <= KSEG0SIZE) + kernmem = 200*MB; + if(kernmem >= pmsize/Kernfract + Minmb*MB){ + kernmem = PGROUND(pmsize/Kernfract + Minmb*MB); + if(kernmem < Minmb*MB/3) + kernmem = Minmb*MB/3; + } +} + void squidboy(int apicno) { @@ -205,6 +230,7 @@ main(u32int ax, u32int bx) * makes mappings and * flushes the TLB via m->pml4->pa. */ + setkernmem(); mmuinit(); ioinit(); --- /sys/src/9k/k10/map.c +++ /sys/src/9k/k10/map.c @@ -13,7 +13,7 @@ KADDR(uintptr pa) u8int* va; va = UINT2PTR(pa); - if(pa < TMFM) + if(pa < kernmem) return KSEG0+va; return KSEG2+va; } @@ -24,7 +24,7 @@ PADDR(void* va) uintmem pa; pa = PTR2UINT(va); - if(pa >= KSEG0 && pa < KSEG0+TMFM) + if(pa >= KSEG0 && pa < KSEG0+kernmem) return pa-KSEG0; if(pa > KSEG2) return pa-KSEG2; --- /sys/src/9k/k10/mem.h +++ /sys/src/9k/k10/mem.h @@ -53,30 +53,33 @@ /* * Address spaces * - * Kernel gets loaded at 1*MiB+64*KiB; + * Kernel gets loaded at 1*MiB+128*KiB; * Memory from 0 to 1MiB is not used for other things; - * 1*MiB to 1MiB+64KiB is used to hold the Sys and + * 1*MiB to 1MiB+128KiB is used to hold the Sys and * Mach0 datastructures. * * User is at low addresses; kernel vm starts at KZERO; - * KSEG0 maps the first TMFM bytes, one to one, (i.e KZERO); + * KSEG0 maps the first kernmem bytes, one to one (i.e. KZERO); * KSEG1 maps the PML4 into itself; * KSEG2 maps all remaining physical memory. */ #define UTZERO (0+2*MiB) /* first address in user text */ #define UTROUND(t) ROUNDUP((t), 2*MiB) -#define USTKTOP 0x00007ffffffff000ull +#define ADDRSPCSZ (1ull<<(48-1)) /* high bit selects user vs kernel */ +#define USTKTOP (ADDRSPCSZ-PGSZ) /* 0x00007ffffffff000 */ #define USTKSIZE (16*1024*1024) /* size of user stack */ #define TSTKTOP (USTKTOP-USTKSIZE) /* end of new stack in sysexec */ -#define KSEG0 (0xfffffffff0000000ull) /* 256MB - this is confused */ -#define KSEG1 (0xffffff0000000000ull) /* 512GB - embedded PML4 */ -#define KSEG2 (0xfffffe0000000000ull) /* 1TB - KMAP */ +#define KSEG0SIZE (2ull*GB) /* kernel direct-map window; l32p.s/mkfile know this */ +#define VZERO 0ull /* top of kernel address space + 1 */ +#define KSEG0 (VZERO-KSEG0SIZE) /* 2GB direct map (was 0xfffffffff0000000) */ +#define KSEG1 (VZERO-TB) /* 512GB - embedded PML4 */ +#define KSEG2 (VZERO-ADDRSPCSZ) /* KMAP - all remaining physical memory */ -#define PMAPADDR (0xffffffffffe00000ull) /* unused as of yet (KMAP?) */ +#define PMAPADDR (VZERO-(2*MiB)) /* unused as of yet (KMAP?) */ -#define KZERO (0xfffffffff0000000ull) -#define KTZERO (KZERO+1*MiB+64*KiB) +#define KZERO KSEG0 +#define KTZERO (KZERO+1*MiB+128*KiB) /* * virtual MMU @@ -109,8 +112,6 @@ #define PTLX(v, l) (((v)>>(((l)*PTSHFT)+PGSHFT)) & ((1<pml4->pa|PteRW|PteP; sys->vmstart = KSEG0; sys->vmunused = sys->vmstart + ROUNDUP(o, 4*KiB); sys->vmunmapped = sys->vmstart + o + sz; - sys->vmend = sys->vmstart + TMFM; + sys->vmend = ROUNDUP(sys->vmstart + kernmem, PGLSZ(1)); print("mmuinit: vmstart %#p vmunused %#p vmunmapped %#p vmend %#p\n", sys->vmstart, sys->vmunused, sys->vmunmapped, sys->vmend); /* - * Set up the map for PD entry access by inserting - * the relevant PDP entry into the PD. It's equivalent - * to PADDR(sys->pd)|PteRW|PteP. + * Set up the map for PD entry access. KSEG0 spans two PDP + * entries now, and PDMAP lives in the top one (PDP[511]), + * which gets its own PD page sys->pd2g. Point that PDP entry + * at pd2g, then self-map pd2g through PDMAP. * * Change code that uses this to use the KSEG1PML4 * map below. */ - sys->pd[PDX(PDMAP)] = sys->pdp[PDPX(PDMAP)] & ~(PteD|PteA); - print("sys->pd %#p %#p\n", sys->pd[PDX(PDMAP)], sys->pdp[PDPX(PDMAP)]); + sys->pdp[PDPX(PDMAP)] = PADDR(sys->pd2g)|PteRW|PteP; + sys->pd2g[PDX(PDMAP)] = sys->pdp[PDPX(PDMAP)] & ~(PteD|PteA); + print("sys->pd2g %#p %#p\n", sys->pd2g[PDX(PDMAP)], sys->pdp[PDPX(PDMAP)]); - assert((pdeget(PDMAP) & ~(PteD|PteA)) == (PADDR(sys->pd)|PteRW|PteP)); + assert((pdeget(PDMAP) & ~(PteD|PteA)) == (PADDR(sys->pd2g)|PteRW|PteP)); /* * Set up the map for PTE access by inserting