## diffname pc/mmu.c 1991/0612 ## diff -e /dev/null /n/bootesdump/1991/0612/sys/src/9/safari/mmu.c 0a #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" void mapstack(Proc *p) { } . ## diffname pc/mmu.c 1991/0613 ## diff -e /n/bootesdump/1991/0612/sys/src/9/safari/mmu.c /n/bootesdump/1991/0613/sys/src/9/safari/mmu.c 13c [NULLSEG] { 0, 0}, /* null descriptor */ [KESEG] EXECSEG(0), /* kernel code */ [KDSEG] DATASEG(0), /* kernel data/stack */ [UESEG] EXECSEG(3), /* user code */ [UDSEG] DATASEG(3), /* user data/stack */ [SYSGATE] CALLGATE(KESEG, syscall, 3), /* call gate for system calls */ { 0, 0}, /* the rest */ }; . 8,11c /* * global descriptor table describing all segments */ Segdesc gdt[1024] = . ## diffname pc/mmu.c 1991/0625 ## diff -e /n/bootesdump/1991/0613/sys/src/9/safari/mmu.c /n/bootesdump/1991/0625/sys/src/9/safari/mmu.c 19d 8a * segment descriptor/gate */ typedef struct Segdesc Segdesc; struct Segdesc { ulong d0; ulong d1; }; #define SEGDATA (0x10<<8) /* data/stack segment */ #define SEGEXEC (0x18<<8) /* executable segment */ #define SEGCG (0x0C<<8) /* call gate */ #define SEGIG (0x0E<<8) /* interrupt gate */ #define SEGTG (0x0F<<8) /* task gate */ #define SEGP (1<<15) /* segment present */ #define SEGPL(x) ((x)<<13) /* priority level */ #define SEGB (1<<22) /* granularity 1==4k (for expand-down) */ #define SEGG (1<<23) /* granularity 1==4k (for other) */ #define SEGE (1<<10) /* expand down */ #define SEGW (1<<9) /* writable (for data/stack) */ #define SEGR (1<<9) /* readable (for code) */ #define SEGD (1<<22) /* default 1==32bit (for code) */ /* * gate initializers */ #define TRAPGATE(s,o,p) { (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGTG, (o)&0xFFFF|((s)<<16) } #define INTRGATE(s,o,p) { (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGIG, (o)&0xFFFF|((s)<<16) } #define CALLGATE(s,o,p) { (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGCG, (o)&0xFFFF|((s)<<16) } /* * segment descriptor initializers */ #define DATASEG(p) { SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW, 0xFFFF } #define EXECSEG(p) { SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR, 0xFFFF } /* * task state segment. Plan 9 ignores all the task switching goo and just * uses the tss for esp0 and ss0 on gate's into the kernel, interrupts, * and exceptions. The rest is completely ignored. * * This means that we only need one tss in the whole system. */ typedef struct Tss Tss; struct Tss { ulong backlink; /* unused */ ulong esp0; /* pl0 stack pointer */ ulong ss0; /* pl0 stack selector */ ulong esp1; /* pl1 stack pointer */ ulong ss1; /* pl1 stack selector */ ulong esp2; /* pl2 stack pointer */ ulong ss2; /* pl2 stack selector */ ulong cr3; /* page table descriptor */ ulong eip; /* instruction pointer */ ulong eflags; /* processor flags */ ulong eax; /* general (hah?) registers */ ulong ecx; ulong edx; ulong ebx; ulong esp; ulong ebp; ulong esi; ulong edi; ulong es; /* segment selectors */ ulong cs; ulong ss; ulong ds; ulong fs; ulong gs; ulong ldt; /* local descriptor table */ ulong iomap; /* io map base */ }; /* . ## diffname pc/mmu.c 1991/0627 ## diff -e /n/bootesdump/1991/0625/sys/src/9/safari/mmu.c /n/bootesdump/1991/0627/sys/src/9/safari/mmu.c 17,30d ## diffname pc/mmu.c 1991/0703 ## diff -e /n/bootesdump/1991/0627/sys/src/9/safari/mmu.c /n/bootesdump/1991/0703/sys/src/9/safari/mmu.c 80a void mmuinit(void) { gdt[SYSGATE].d0 = ((ulong)systrap)&0xFFFF|(KESEL<<16); gdt[SYSGATE].d1 = ((ulong)systrap)&0xFFFF0000|SEGP|SEGPL(3)|SEGCG; lgdt(gdt, sizeof gdt); } void systrap(void) { panic("system trap from user"); } . 79c [UESEG] EXECSEG(3), /* user code */ [SYSGATE] CALLGATE(KESEL,0,3), /* call gate for system calls */ . 77c [KESEG] EXECSEG(0), /* kernel code */ . 75d 72c Segdesc gdt[6] = . 69a * segment descriptor initializers */ #define DATASEG(p) { 0xFFFF, SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } #define EXECSEG(p) { 0xFFFF, SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } #define CALLGATE(s,o,p) { (o)&0xFFFF|((s)<<16), (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGCG } /* . 9,31d ## diffname pc/mmu.c 1991/0706 ## diff -e /n/bootesdump/1991/0703/sys/src/9/safari/mmu.c /n/bootesdump/1991/0706/sys/src/9/safari/mmu.c 63a [RDSEG] D16SEG(0), /* reboot data/stack */ [RESEG] E16SEG(0), /* reboot code */ . 56c Segdesc gdt[] = . 51a #define D16SEG(p) { 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } #define E16SEG(p) { 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } . ## diffname pc/mmu.c 1991/0711 ## diff -e /n/bootesdump/1991/0706/sys/src/9/safari/mmu.c /n/bootesdump/1991/0711/sys/src/9/safari/mmu.c 75a } void mapstack(Proc *p) { } void flushmmu(void) { } void mmurelease(Proc *p) { } void putmmu(ulong x, ulong y, Page*z) { } void invalidateu(void) { . 72a . 69a extern ulong tpt[]; . ## diffname pc/mmu.c 1991/0716 ## diff -e /n/bootesdump/1991/0711/sys/src/9/safari/mmu.c /n/bootesdump/1991/0716/sys/src/9/safari/mmu.c 78a /* * set up system page tables */ /* * set up the task segment */ . 75c /* * set up the global descriptor table */ . ## diffname pc/mmu.c 1991/0717 ## diff -e /n/bootesdump/1991/0716/sys/src/9/safari/mmu.c /n/bootesdump/1991/0717/sys/src/9/safari/mmu.c 119a } void exit(void) { int i; u = 0; print("exiting\n"); for(i = 0; i < WD2PG; i++) toppt[i] = 0; lcr3(((ulong)toppt)&~KZERO); . 107c putmmu(ulong x, ulong y, Page *z) . 93a . 88a tss.sp0 = USERADDR; tss.ss0 = KDSEL; tss.cr3 = (ulong)toppt; ltr(TSSSEL); . 85a /* allocate and fill low level page tables for physical mem */ nkpt = ROUNDUP(conf.npage0+conf.npage1, 4*1024*1024); nkpt = nkpt/(4*1024*1024); kpt = ialloc(nkpt*BY2PG, 1); n = ROUNDUP(conf.npage0+conf.npage1, 1*1024*1024); n = n/(4*1024); for(i = 0; i < n; i++){ kpt[i] = (i< */ upt = ialloc(BY2PG, 1); /* allocate top level table and put pointers to lower tables in it */ toppt = ialloc(BY2PG, 1); x = KZERO>>(2*PGSHIFT-2); y = ((ulong)kpt)&~KZERO; for(i = 0; i < nkpt; i++){ /* toppt[i] = (y+i*BY2PG)|PTEVALID|PTEKERNEL|PTEWRITE;/**/ toppt[x+i] = (y+i*BY2PG)|PTEVALID|PTEKERNEL|PTEWRITE; } x = USERADDR>>(2*PGSHIFT-2); y = ((ulong)upt)&~KZERO; toppt[x] = y|PTEVALID|PTEKERNEL|PTEWRITE; lcr3(((ulong)toppt)&~KZERO); . 83c * set up system page tables. * map all of physical memory to start at KZERO. * leave a map for a user area. . 78,79c x = (ulong)systrap; gdt[SYSGATE].d0 = (x&0xFFFF)|(KESEL<<16); gdt[SYSGATE].d1 = (x&0xFFFF0000)|SEGP|SEGPL(3)|SEGCG; x = (long)&tss; gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss); gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP; . 74a int i, n, nkpt; ulong x; ulong y; . 71a #define ROUNDUP(s,v) (((s)+(v-1))&~(v-1)) . 70c static ulong *toppt; /* top level page table */ static ulong *kpt; /* kernel level page tables */ static ulong *upt; /* page table for struct User */ . 66,67c [RDSEG] D16SEGM(0), /* reboot data/stack */ [RESEG] E16SEGM(0), /* reboot code */ [TSSSEG] TSSSEGM(0,0), /* tss segment */ . 61,64c [KDSEG] DATASEGM(0), /* kernel data/stack */ [KESEG] EXECSEGM(0), /* kernel code */ [UDSEG] DATASEGM(3), /* user data/stack */ [UESEG] EXECSEGM(3), /* user code */ . 49,53c #define DATASEGM(p) { 0xFFFF, SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } #define EXECSEGM(p) { 0xFFFF, SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } #define CALLGATE(s,o,p) { ((o)&0xFFFF)|((s)<<16), (o)&0xFFFF0000|SEGP|SEGPL(p)|SEGCG } #define D16SEGM(p) { 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } #define E16SEGM(p) { 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } #define TSSSEGM(b,p) { ((b)<<16)|sizeof(Tss),\ ((b)&0xFF000000)|(((b)<<16)&0xFF)|SEGTSS|SEGPL(p)|SEGP } . 44a Tss tss; . 23c ulong sp2; /* pl2 stack pointer */ . 21c ulong sp1; /* pl1 stack pointer */ . 19c ulong sp0; /* pl0 stack pointer */ . ## diffname pc/mmu.c 1991/0718 ## diff -e /n/bootesdump/1991/0717/sys/src/9/safari/mmu.c /n/bootesdump/1991/0718/sys/src/9/safari/mmu.c 180c putcr3(((ulong)toppt)&~KZERO); . 162a /* unmap u area */ upt[0] = 0; /* flush cached mmu entries */ putcr3(((ulong)toppt)&~KZERO); . 157a int topoff; ulong *pt; Proc *p; int i; print("putmmu %lux %lux USTKTOP %lux\n", va, pa, USTKTOP); /**/ if(u==0) panic("putmmu"); p = u->p; /* * check for exec/data vs stack vs illegal */ topoff = TOPOFF(va); if(topoff < TOPOFF(TSTKTOP) && topoff >= TOPOFF(USTKBTM)) i = MAXMMU + topoff - TOPOFF(USTKBTM); else if(topoff < MAXMMU) i = topoff; else panic("putmmu bad addr %lux", va); /* * if bottom level page table missing, allocate one */ pg = p->mmu[i]; if(pg == 0){ pg = p->mmu[i] = newpage(1, 0, 0); p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEKERNEL | PTEWRITE; toppt[topoff] = p->mmue[i]; } /* * fill in the bottom level page table */ pt = (ulong*)(p->mmu[i]->pa|KZERO); pt[BTMOFF(va)] = pa | PTEUSER; /* flush cached mmu entries */ putcr3(((ulong)toppt)&~KZERO); . 156c putmmu(ulong va, ulong pa, Page *pg) . 152a p->mmuvalid = 0; . 147a int s; if(u == 0) return; u->p->mmuvalid = 0; s = splhi(); mapstack(u->p); splx(s); . 142c ulong tlbphys; int i; print("mapstack\n"); if(p->upage->va != (USERADDR|(p->pid&0xFFFF))) panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va); /* * dump any invalid mappings */ if(p->mmuvalid == 0){ for(i = 0; i < MAXMMU+MAXSMMU; i++){ if(p->mmu[i]==0) continue; memset(kmap(p->mmu[i]), 0, BY2PG); } p->mmuvalid = 1; } /* * point top level page table to bottom level ones */ memmove(toppt, p->mmu, MAXMMU*sizeof(ulong)); memmove(&toppt[TOPOFF(USTKBTM)], &p->mmu[MAXMMU], MAXSMMU*sizeof(ulong)); /* map in u area */ upt[0] = PPN(p->upage->pa) | PTEVALID | PTEKERNEL | PTEWRITE; /* flush cached mmu entries */ putcr3(((ulong)toppt)&~KZERO); u = (User*)USERADDR; . 136c puttr(TSSSEL); . 133c tss.sp0 = USERADDR+BY2PG; . 127,128c toppt[x] = y | PTEVALID | PTEKERNEL | PTEWRITE; putcr3(((ulong)toppt)&~KZERO); . 121,125c for(i = 0; i < nkpt; i++) toppt[x+i] = (y+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; x = TOPOFF(USERADDR); . 119c x = TOPOFF(KZERO); . 110,112c for(i = 0; i < n; i++) kpt[i] = (i<>(PGSHIFT))&(BY2PG-1)) . 78a /* * offset of virtual address into * top level page table */ #define TOPOFF(v) ((v)>>(2*PGSHIFT-2)) . ## diffname pc/mmu.c 1991/0719 ## diff -e /n/bootesdump/1991/0718/sys/src/9/safari/mmu.c /n/bootesdump/1991/0719/sys/src/9/safari/mmu.c 263,274d 243a print("%lux[%d] = %lux\n", pt, BTMOFF(va), pa | PTEUSER); . 236a print("toppt[%d] = %lux\n", topoff, p->mmue[i]); . 235c p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; . 213c print("putmmu %lux %lux\n", va, pa); /**/ . 153,154d 119,120c n = ROUNDUP(conf.npage, 1024); . 115,117c /* allocate and fill low level page tables for kernel mem */ nkpt = ROUNDUP(conf.npage, 4*1024); nkpt = nkpt/(4*1024); . 91a mmudump(void) { int i; ulong *z; z = (ulong*)gdt; for(i = 0; i < sizeof(gdt)/4; i+=2) print("%8.8lux %8.8lux\n", *z++, *z++); print("UESEL %lux UDSEL %lux\n", UESEL, UDSEL); print("KESEL %lux KDSEL %lux\n", KESEL, KDSEL); panic("done"); } void . 89c #define BTMOFF(v) (((v)>>(PGSHIFT))&(WD2PG-1)) . 69,70d ## diffname pc/mmu.c 1991/0720 ## diff -e /n/bootesdump/1991/0719/sys/src/9/safari/mmu.c /n/bootesdump/1991/0720/sys/src/9/safari/mmu.c 253c print("%lux[%d] now %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); . 250a print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); . 245c print("toppt[%d] = %lux\n", topoff, toppt[topoff]); . ## diffname pc/mmu.c 1991/0723 ## diff -e /n/bootesdump/1991/0720/sys/src/9/safari/mmu.c /n/bootesdump/1991/0723/sys/src/9/safari/mmu.c 252a print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); . 251d 245c print("toppt[%d] now %lux\n", topoff, toppt[topoff]); . 240a print("toppt[%d] was %lux\n", topoff, toppt[topoff]); . 219c int i = 0; . 181,182c memmove(toppt, p->mmue, MAXMMU*sizeof(ulong)); memmove(&toppt[TOPOFF(USTKBTM)], &p->mmue[MAXMMU], MAXSMMU*sizeof(ulong)); . ## diffname pc/mmu.c 1991/0801 ## diff -e /n/bootesdump/1991/0723/sys/src/9/safari/mmu.c /n/bootesdump/1991/0801/sys/src/9/safari/mmu.c 255c /*print("%lux[%d] now %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);/**/ . 253c /*print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);/**/ . 246c /*print("toppt[%d] now %lux\n", topoff, toppt[topoff]);/**/ . 241c /*print("toppt[%d] was %lux\n", topoff, toppt[topoff]);/**/ . 221c /*print("putmmu %lux %lux\n", va, pa); /**/ . ## diffname pc/mmu.c 1991/0821 ## diff -e /n/bootesdump/1991/0801/sys/src/9/safari/mmu.c /n/bootesdump/1991/0821/sys/src/9/safari/mmu.c 132a print("%d low level pte's, %d high level pte's\n", npage, nkpt); . 127,131c npage = (1024*1024)/BY2PG + conf.npage1; nbytes = PGROUND(npage*BY2WD); /* words of page map */ nkpt = nbytes/BY2PG; /* pages of page map */ kpt = ialloc(nbytes, 1); for(i = 0; i < npage; i++) . 105c int i, nkpt, npage, nbytes; . ## diffname pc/mmu.c 1991/0827 ## diff -e /n/bootesdump/1991/0821/sys/src/9/safari/mmu.c /n/bootesdump/1991/0827/sys/src/9/safari/mmu.c 127c npage = conf.base1/BY2PG + conf.npage1; . ## diffname pc/mmu.c 1991/0922 ## diff -e /n/bootesdump/1991/0827/sys/src/9/safari/mmu.c /n/bootesdump/1991/0922/sys/src/9/safari/mmu.c 71a static ulong *ktoppt; /* prototype top level page table * containing kernel mappings */ . ## diffname pc/mmu.c 1991/0928 ## diff -e /n/bootesdump/1991/0922/sys/src/9/safari/mmu.c /n/bootesdump/1991/0928/sys/src/9/safari/mmu.c 168c if(p->upage->va != (USERADDR|(p->pid&0xFFFF)) && p->pid != 0) . ## diffname pc/mmu.c 1991/1003 ## diff -e /n/bootesdump/1991/0928/sys/src/9/safari/mmu.c /n/bootesdump/1991/1003/sys/src/9/safari/mmu.c 161a . ## diffname pc/mmu.c 1991/1004 ## diff -e /n/bootesdump/1991/1003/sys/src/9/safari/mmu.c /n/bootesdump/1991/1004/sys/src/9/safari/mmu.c 274c putcr3(ktoppg.pa); . 264c putcr3(p->mmutop->pa); . 261d 258,259c pt = (ulong*)(PPN(top[topoff])|KZERO); . 256c * put in new mmu entry . 246,252c topoff = TOPOFF(va); if(top[topoff] == 0){ pg = mmugetpage(1); top[topoff] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; pg->next = p->mmuused; p->mmuused = pg; . 244c * if bottom level page table missing, allocate one and point * the top level page at it. . 235,241c if(p->mmutop == 0){ p->mmutop = mmugetpage(0); memmove((void*)p->mmutop->va, (void*)ktoppg.va, BY2PG); } top = (ulong*)p->mmutop->va; . 233c * if no top level page, allocate one and copy the prototype * into it. . 231a if(va >= USERADDR && va < USERADDR + FOURMEG) print("putmmu in USERADDR page table 0x%lux\n", va); if((va & 0xF0000000) == KZERO) print("putmmu in kernel page table 0x%lux\n", va); . 229a . 227d 225c char err[64]; . 222a ulong *top; . 214,219d 212a /* * Add an entry into the mmu. */ #define FOURMEG (4*1024*1024) . 207,210c /* give away page table pages */ for(pg = p->mmufree; pg; pg = next){ next = pg->next; simpleputpage(pg); } p->mmufree = 0; for(pg = p->mmuused; pg; pg = next){ next = pg->next; simpleputpage(pg); } p->mmuused = 0; if(p->mmutop) simpleputpage(p->mmutop); p->mmutop = 0; . 204,205c /* point 386 to protoype page map */ putcr3(ktoppg.pa); . 202c Page *pg; Page *next; . 200c mmurelease(Proc *p) . 198a /* * give all page table pages back to the free pool. This is called in sched() * with palloc locked. */ . 193,194c /* tell processor about new page table (flushes cached entries) */ putcr3(pg->pa); . 184,189d 172,182c if(p->mmutop) pg = p->mmutop; else pg = &ktoppg; . 167a Page *pg; . 163a flushmmu(void) { int s; Proc *p; Page *pg; if(u == 0) return; p = u->p; s = splhi(); if(p->mmutop){ p->mmutop->next = p->mmufree; p->mmufree = p->mmutop; for(pg = p->mmufree; pg->next; pg = pg->next) ; pg->next = p->mmuused; p->mmutop = 0; p->mmuused = 0; } mapstack(u->p); splx(s); } /* * Switch to a process's memory map. If the process doesn't * have a map yet, just use the prototype one that contains * mappings for only the kernel and the User struct. */ void . 162a if(p->mmufree){ pg = p->mmufree; p->mmufree = pg->next; if(clear) memset((void*)pg->va, 0, BY2PG); } else { pg = newpage(clear, 0, 0); pg->va = VA(kmap(pg)); } return pg; } /* * Put all page map pages on the process's free list and * call mapstack to set up the prototype page map. This * effectively forgets all of the process's mappings. */ . 161a /* * Get a page for a process's page map. * * Each process maintains its own free list of page * table pages. All page table pages are put on * this list in flushmmu(). flushmmu() doesn't * putpage() the pages since the process will soon need * them back. Also, this avoids worrying about deadlocks * twixt flushmmu() and putpage(). * * mmurelease() will give back the pages when the process * exits. */ static Page* mmugetpage(int clear) { Proc *p = u->p; Page *pg; . 158c tss.cr3 = ktoppg.pa; . 150,151c top[x] = y | PTEVALID | PTEKERNEL | PTEWRITE; putcr3(ktoppg.pa); . 147c top[x+i] = (y+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; . 143c top = ialloc(BY2PG, 1); ktoppg.va = (ulong)top; ktoppg.pa = ktoppg.va & ~KZERO; . 126c * leave a map entry for a user area. . 110a ulong *top; . 104a /* * Create a prototype page map that maps all of memory into * kernel (KZERO) space. This is the default map. It is used * whenever the processor not running a process or whenever running * a process which does not yet have its own map. */ . 72,77c static Page ktoppg; /* prototype top level page table * containing kernel mappings */ static ulong *kpt; /* 2nd level page tables for kernel mem */ static ulong *upt; /* 2nd level page table for struct User */ . ## diffname pc/mmu.c 1991/1005 ## diff -e /n/bootesdump/1991/1004/sys/src/9/safari/mmu.c /n/bootesdump/1991/1005/sys/src/9/safari/mmu.c 316,317c /* * N.B. The assignment to pg is neccessary. * We can't assign to p->mmutop until after * copying ktoppg into the new page since we might * get scheded in this code and p->mmutop will be * pointing to a bad map. */ pg = mmugetpage(0); memmove((void*)pg->va, (void*)ktoppg.va, BY2PG); p->mmutop = pg; . 299a int x; . ## diffname pc/mmu.c 1991/1210 ## diff -e /n/bootesdump/1991/1005/sys/src/9/safari/mmu.c /n/bootesdump/1991/1210/sys/src/9/safari/mmu.c 157a . 154a /* page table for u-> */ upt = ialloc(BY2PG, 1); . 140,150c kpt[i] = (0+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; . 134c /* allocate top level table */ top = ialloc(BY2PG, 1); ktoppg.va = (ulong)top; ktoppg.pa = ktoppg.va & ~KZERO; /* map all memory to KZERO */ . 130a * map ROM BIOS at the usual place (F0000000). . ## diffname pc/mmu.c 1991/1211 ## diff -e /n/bootesdump/1991/1210/sys/src/9/safari/mmu.c /n/bootesdump/1991/1211/sys/src/9/safari/mmu.c 162a memset(&tss, 0, sizeof(tss)); . ## diffname pc/mmu.c 1991/1214 ## diff -e /n/bootesdump/1991/1211/sys/src/9/safari/mmu.c /n/bootesdump/1991/1214/sys/src/9/safari/mmu.c 361,366d 131d 120,122d 118c * set up the global descriptor table. we make the tss entry here * since it requires arithmetic on an address and hence cannot * be a compile or link time constant. . 90,102d 68d ## diffname pc/mmu.c 1992/0116 ## diff -e /n/bootesdump/1991/1214/sys/src/9/safari/mmu.c /n/bootesdump/1992/0116/sys/src/9/safari/mmu.c 56c ((b)&0xFF000000)|(((b)>>16)&0xFF)|SEGTSS|SEGPL(p)|SEGP } . ## diffname pc/mmu.c 1992/0131 ## diff -e /n/bootesdump/1992/0116/sys/src/9/safari/mmu.c /n/bootesdump/1992/0131/sys/src/9/safari/mmu.c 324a pg->daddr = topoff; . 238a if(p->mmutop) pg = p->mmutop; else pg = &ktoppg; . 230,234d 202,208c if(p->mmutop && p->mmuused){ top = (ulong*)p->mmutop->va; for(pg = p->mmuused; pg->next; pg = pg->next) top[pg->daddr] = 0; top[pg->daddr] = 0; pg->next = p->mmufree; p->mmufree = p->mmuused; . 195a ulong *top; . 188a * * Don't free the top level page. Just zero the used entries. This * avoids a 4k copy each flushmmu. . 186c * Put all bottom level page map pages on the process's free list and . ## diffname pc/mmu.c 1992/0321 ## diff -e /n/bootesdump/1992/0131/sys/src/9/safari/mmu.c /n/bootesdump/1992/0321/sys/src/9/safari/mmu.c 87c #define BTMOFF(v) ((((ulong)(v))>>(PGSHIFT))&(WD2PG-1)) . 81c #define TOPOFF(v) (((ulong)(v))>>(2*PGSHIFT-2)) . 2c #include "../port/lib.h" . ## diffname pc/mmu.c 1992/0617 ## diff -e /n/bootesdump/1992/0321/sys/src/9/safari/mmu.c /n/bootesdump/1992/0617/sys/src/9/safari/mmu.c 232a if(p->newtlb){ /* * bin the current second level page tables. newtlb * set means that they are inconsistent with the segment.c * data structures. */ if(p->mmutop && p->mmuused){ top = (ulong*)p->mmutop->va; for(pg = p->mmuused; pg->next; pg = pg->next) top[pg->daddr] = 0; top[pg->daddr] = 0; pg->next = p->mmufree; p->mmufree = p->mmuused; p->mmuused = 0; } p->newtlb = 0; } . 229a ulong *top; . 206,215c mapstack(p); . 204a p->newtlb = 1; . 203d 198,199d ## diffname pc/mmu.c 1992/0625 ## diff -e /n/bootesdump/1992/0617/sys/src/9/safari/mmu.c /n/bootesdump/1992/0625/sys/src/9/safari/mmu.c 137c upt = xspanalloc(BY2PG, BY2PG, 0); . 128c kpt = xspanalloc(nbytes, BY2PG, 0); . 125c npage = conf.topofmem/BY2PG; . 120c top = xspanalloc(BY2PG, BY2PG, 0); . ## diffname pc/mmu.c 1992/0711 ## diff -e /n/bootesdump/1992/0625/sys/src/9/safari/mmu.c /n/bootesdump/1992/0711/sys/src/9/safari/mmu.c 295,296d 216,217d ## diffname pc/mmu.c 1992/0804 ## diff -e /n/bootesdump/1992/0711/sys/src/9/safari/mmu.c /n/bootesdump/1992/0804/sys/src/9/safari/mmu.c 342a splx(s); . 332d 326,328c s = splhi(); if(PPN(top[topoff]) == 0){ if(p->mmufree == 0){ spllo(); pg = newpage(1, 0, 0); pg->va = VA(kmap(pg)); splhi(); } else { pg = p->mmufree; p->mmufree = pg->next; memset((void*)pg->va, 0, BY2PG); } . 323,324c * if bottom level page table missing, allocate one * and point the top level page at it. . 320a topoff = TOPOFF(va); . 309,316c pg = newpage(0, 0, 0); pg->va = VA(kmap(pg)); . 305,306c * create a top level page if we don't already have one. * copy the kernel top level page into it for kernel mappings. . 299,303d 296d 292a int s; . 285d 228,236c if(p->mmutop) memmove((void*)p->mmutop->va, (void*)ktoppg.va, BY2PG); l = &p->mmufree; for(pg = p->mmufree; pg; pg = pg->next) l = &pg->next; *l = p->mmuused; p->mmuused = 0; . 224,226c * bin the current second level page tables. * newtlb set means that they are inconsistent * with the segment.c data structures. . 216,217c Page *pg, **l; . 204c if(u){ u->p->newtlb = 1; mapstack(u->p); } else putcr3(ktoppg.pa); . 199,202d 197d 167,192d 155,165c * Mark the mmu and tlb as inconsistent and call mapstack to fix it up. . 88a #define MAXUMEG 64 /* maximum memory per user process in megabytes */ #define ONEMEG (1024*1024) . ## diffname pc/mmu.c 1992/0805 ## diff -e /n/bootesdump/1992/0804/sys/src/9/safari/mmu.c /n/bootesdump/1992/0805/sys/src/9/safari/mmu.c 291a pg->daddr = topoff; . 194,200c if(p->mmutop && p->mmuused){ top = (ulong*)p->mmutop->va; for(pg = p->mmuused; pg->next; pg = pg->next) top[pg->daddr] = 0; top[pg->daddr] = 0; pg->next = p->mmufree; p->mmufree = p->mmuused; p->mmuused = 0; } . 192a * * bin the current second level page tables and * the pointers to them in the top level page. * pg->daddr is used by putmmu to save the offset into * the top level page. . 190d 183c Page *pg; ulong *top; . ## diffname pc/mmu.c 1992/0929 ## diff -e /n/bootesdump/1992/0808/sys/src/9/safari/mmu.c /n/bootesdump/1992/0929/sys/src/9/pc/mmu.c 322a } /* * allocate some address space (already mapped into the kernel) * for ISA bus memory. */ ulong isamem(int len) { ulong a, x; lock(&isamemalloc); len = PGROUND(len); x = isamemalloc.addr + len; if(x > isamemalloc.end) panic("isamem"); a = isamemalloc.addr; isamemalloc.addr = x; unlock(&isamemalloc); return a; . 129a if(conf.topofmem < 64*MB){ /* for ISA bus memory */ isamemalloc.addr = conf.topofmem; isamemalloc.end = conf.topofmem + 2*MB; if(isamemalloc.end > 64*MB) isamemalloc.end = 64*MB; npage += (isamemalloc.end - isamemalloc.addr)/BY2PG; } . 128c /* map all memory to KZERO (plus 1 meg for PCMCIA window) */ . 91a struct { ulong addr; /* next available address for isa bus memory */ ulong end; /* one past available isa bus memory */ } isamemalloc; . ## diffname pc/mmu.c 1992/0930 ## diff -e /n/bootesdump/1992/0929/sys/src/9/pc/mmu.c /n/bootesdump/1992/0930/sys/src/9/pc/mmu.c 133,142c /* map all memory to KZERO (add some address space for ISA memory) */ isamemalloc.addr = conf.topofmem; isamemalloc.end = conf.topofmem + ISAMEMSIZE; if(isamemalloc.end > 64*MB) isamemalloc.end = 64*MB; /* ISA can only access 64 meg */ npage = isamemalloc.end/BY2PG; . ## diffname pc/mmu.c 1992/1004 ## diff -e /n/bootesdump/1992/0930/sys/src/9/pc/mmu.c /n/bootesdump/1992/1004/sys/src/9/pc/mmu.c 93a Lock; . ## diffname pc/mmu.c 1993/0120 ## diff -e /n/bootesdump/1992/1004/sys/src/9/pc/mmu.c /n/bootesdump/1993/0120/sys/src/9/pc/mmu.c 353a /* * mapping for user access to d segment (access to TARGA) */ Page* dsegalloc(Segment *s, ulong va) { Page *pg; pg = smalloc(sizeof(Page)); memset(pg, 0, sizeof(Page)); pg->va = va; pg->pa = 0xd0000 + (va - s->base); pg->ref = 1; return pg; } void dsegfree(Page *pg) { int x; lock(pg); x = --pg->ref; unlock(pg); if(x <= 0) free(pg); } . ## diffname pc/mmu.c 1993/0210 ## diff -e /n/bootesdump/1993/0120/sys/src/9/pc/mmu.c /n/bootesdump/1993/0210/sys/src/9/pc/mmu.c 354,381d ## diffname pc/mmu.c 1993/0915 ## diff -e /n/bootesdump/1993/0210/sys/src/9/pc/mmu.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/mmu.c 352a } /* * used to map a page into 16 meg - BY2PG for confinit(). tpt is the temporary * page table set up by l.s. */ long* mapaddr(ulong addr) { ulong base; ulong off; static ulong *pte, top; extern ulong tpt[]; if(pte == 0){ top = (((ulong)tpt)+(BY2PG-1))&~(BY2PG-1); pte = (ulong*)top; top &= ~KZERO; top += BY2PG; pte += (4*1024*1024-BY2PG)>>PGSHIFT; } base = off = addr; base &= ~(KZERO|(BY2PG-1)); off &= BY2PG-1; *pte = base|PTEVALID|PTEKERNEL|PTEWRITE; /**/ putcr3((ulong)top); return (long*)(KZERO | 4*1024*1024-BY2PG | off); . 325,334d 321c taskswitch(up->mmutoup->pa, up->kstack); . 310,311c pg->next = up->mmuused; up->mmuused = pg; . 304,305c pg = up->mmufree; up->mmufree = pg->next; . 298c if(up->mmufree == 0){ . 289c top = (ulong*)up->mmutoup->va; . 287c up->mmutop = pg; . 283c if(up->mmutop == 0){ . 275,278d 272d 244,245c /* point 386 to protoype page map and m->stack */ taskswitch(ktoppg.pa, BY2PG + (ulong)m); . 228,231c taskswitch(ktoppg.pa, p->kstack+KSTACK); . 226c taskswitch(p->mmutop->pa, p->kstack+KSTACK); . 221,223d 196,198d 191c mmuswitch(Proc *p) . 188c * mappings for only the kernel. . 177,181c up->newtlb = 1; mmuswitch(up); . 162,164c taskswitch(ktoppg.pa, BY2BG + (ulong)m); . 150,157d 99a * Change current page table and the stack to use for exceptions * (traps & interrupts). The exception stack comes from the tss. * Since we use only one tss, (we hope) there's no need for a * puttr(). */ static void taskswitch(ulong pagetbl, ulong stack) { putcr3(pagetbl); tss.ss0 = KDSEL; tss.sp0 = stack; tss.cr3 = pagetbl; } /* . 74d ## diffname pc/mmu.c 1993/1013 ## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/mmu.c /n/fornaxdump/1993/1013/sys/src/brazil/pc/mmu.c 308c taskswitch(up->mmutop->pa, (ulong)up->kstack); . 276c top = (ulong*)up->mmutop->va; . 223c taskswitch(ktoppg.pa, (ulong)(p->kstack+KSTACK)); . 221c taskswitch(p->mmutop->pa, (ulong)(p->kstack+KSTACK)); . 168c taskswitch(ktoppg.pa, BY2PG + (ulong)m); . ## diffname pc/mmu.c 1993/1113 ## diff -e /n/fornaxdump/1993/1013/sys/src/brazil/pc/mmu.c /n/fornaxdump/1993/1113/sys/src/brazil/pc/mmu.c 308c /*taskswitch(up->mmutop->pa, (ulong)(up->kstack+KSTACK));/**/ putcr3(up->mmutop->pa);/**/ . 225a void simpleputpage(Page *pg) { Rendez *r; if(pg->ref != 1) panic("simpleputpage"); pg->ref = 0; if(palloc.head){ pg->next = palloc.head; palloc.head->prev = pg; } else { palloc.tail = pg; pg->next = 0; } palloc.head = pg; pg->prev = 0; palloc.freecol[pg->color]++; r = &palloc.r[pg->color]; if(r->p != 0) wakeup(r); } . 173c * Mark the mmu and tlb as inconsistent and call mmuswitch to fix it up. . 169c puttr(TSSSEL);/**/ . 110a putcr3(pagetbl); . 107d ## diffname pc/mmu.c 1993/1115 ## diff -e /n/fornaxdump/1993/1113/sys/src/brazil/pc/mmu.c /n/fornaxdump/1993/1115/sys/src/brazil/pc/mmu.c 108a tss.ss1 = KDSEL; tss.sp1 = stack; tss.ss2 = KDSEL; tss.sp2 = stack; . ## diffname pc/mmu.c 1993/1124 ## diff -e /n/fornaxdump/1993/1115/sys/src/brazil/pc/mmu.c /n/fornaxdump/1993/1124/sys/src/brazil/pc/mmu.c 250,253c palloc.freecount++; if(palloc.r.p != 0) wakeup(&palloc.r); . 233,234d 230c static void . ## diffname pc/mmu.c 1994/0707 ## diff -e /n/fornaxdump/1993/1124/sys/src/brazil/pc/mmu.c /n/fornaxdump/1994/0707/sys/src/brazil/pc/mmu.c 120c * whenever the processor is not running a process or whenever running . ## diffname pc/mmu.c 1994/0819 ## diff -e /n/fornaxdump/1994/0707/sys/src/brazil/pc/mmu.c /n/fornaxdump/1994/0819/sys/src/brazil/pc/mmu.c 154,156c isamemalloc.end = 64*MB; . ## diffname pc/mmu.c 1994/1209 ## diff -e /n/fornaxdump/1994/0819/sys/src/brazil/pc/mmu.c /n/fornaxdump/1994/1209/sys/src/brazil/pc/mmu.c 153,155c isamemalloc.addr = 0xd8000; isamemalloc.end = 0xe0000; npage = 64*MB/BY2PG; . ## diffname pc/mmu.c 1994/1210 ## diff -e /n/fornaxdump/1994/1209/sys/src/brazil/pc/mmu.c /n/fornaxdump/1994/1210/sys/src/brazil/pc/mmu.c 347,355c lock(&isaalloc); os = s = e = 0; for(i = 0; i < Nisa; i++){ s = os = isaalloc.s[i]; if(s == 0) continue; e = isaalloc.e[i]; if(addr && addr >= s && addr < isaalloc.e[i]) break; if(align > 0) s = ((s + align - 1)/align)*align; if(e - s >= len) break; } if(i >= Nisa){ unlock(&isaalloc); return 0; } /* remove */ isaalloc.s[i] = 0; unlock(&isaalloc); /* give back edges */ if(s != os) putisa(os, s - os); os = s + len; if(os != e) putisa(os, e - os); return KZERO|s; . 345c int i; ulong os, s, e; . 343c getisa(ulong addr, int len, int align) . 338a * make isa address space available */ void putisa(ulong addr, int len) { ulong e; int i, hole; addr &= ~KZERO; e = addr + len; lock(&isaalloc); hole = -1; for(i = 0; i < Nisa; i++){ if(isaalloc.s[i] == e){ isaalloc.s[i] = addr; break; } if(isaalloc.e[i] == addr){ isaalloc.e[i] = e; break; } if(isaalloc.s[i] == 0) hole = i; } if(i >= Nisa && hole >= 0){ isaalloc.s[hole] = addr; isaalloc.e[hole] = e; } unlock(&isaalloc); } /* . 152,155c /* map all memory to KZERO */ npage = 128*MB/BY2PG; . 94,96c ulong s[Nisa]; ulong e[Nisa]; } isaalloc; . 90a enum { Nisa= 256, }; . ## diffname pc/mmu.c 1995/0209 ## diff -e /n/fornaxdump/1994/1210/sys/src/brazil/pc/mmu.c /n/fornaxdump/1995/0209/sys/src/brazil/pc/mmu.c 389c if(addr && addr >= s && addr < e) . 380c long os, s, e; . ## diffname pc/mmu.c 1995/0406 ## diff -e /n/fornaxdump/1995/0209/sys/src/brazil/pc/mmu.c /n/fornaxdump/1995/0406/sys/src/brazil/pc/mmu.c 442a } /* * get non-ISA memory space */ ulong getspace(int len, int span) { ulong x; lock(&msalloc); x = msalloc.s; if(span) x = ROUND(x, span); if(len > msalloc.e - x){ unlock(&msalloc); return 0; } msalloc.s = x + len; unlock(&msalloc); return x | KZERO; . 172a /* * allocatable, non ISA memory */ if(conf.topofmem > 16*1024*1024) msalloc.s = conf.topofmem; else msalloc.s = 16*1024*1024; msalloc.e = 128*1024*1024; . 100a /* unallocated space */ struct { Lock; ulong s; ulong e; } msalloc; . 90a /* unallocated ISA space */ . ## diffname pc/mmu.c 1995/0418 ## diff -e /n/fornaxdump/1995/0406/sys/src/brazil/pc/mmu.c /n/fornaxdump/1995/0418/sys/src/brazil/pc/mmu.c 170a for(i = 0xa0000/BY2PG; i < 0xC0000/BY2PG; i++) kpt[i] = (0+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE | PTEWT; for(i = 0xC0000/BY2PG; i < MB/BY2PG; i++) kpt[i] = (0+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE | PTEUNCACHED; for(i = conf.topofmem/BY2PG; i < 128*MB/BY2PG; i++) kpt[i] = (0+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE | PTEUNCACHED; . ## diffname pc/mmu.c 1997/0327 ## diff -e /n/fornaxdump/1995/0418/sys/src/brazil/pc/mmu.c /n/emeliedump/1997/0327/sys/src/brazil/pc/mmu.c 361,488d 357,359c s = splhi(); pdb[PDX(MACHADDR)] = ((ulong*)m->pdb)[PDX(MACHADDR)]; putcr3(up->mmupdb->pa); . 351,355c pt = (ulong*)(PPN(pdb[pdbx])|KZERO); pt[PTX(va)] = pa|ptebits|PTEUSER; . 345,346c pdb[pdbx] = PPN(pg->pa)|ptebits|PTEUSER|PTEWRITE|PTEVALID; pg->daddr = pdbx; . 339,340c } else { . 336d 329,334c if(PPN(pdb[pdbx]) == 0){ . 316,327c if(up->mmupdb == 0) up->mmupdb = mmupdballoc(); pdb = (ulong*)up->mmupdb->va; pdbx = PDX(va); . 311,313c int pdbx; ulong *pdb, *pt; . 305,307d 299,302c splx(s); return pg; . 294,297c else{ pg = m->pdbpool; m->pdbpool = pg->next; m->pdbcnt--; . 286,292c s = splhi(); if(m->pdbpool == 0){ spllo(); pg = newpage(0, 0, 0); pg->va = VA(kmap(pg)); memmove((void*)pg->va, m->pdb, BY2PG); . 284d 282a int s; . 276,281c static Page* mmupdballoc(void) . 273a p->mmufree = 0; . 271,272c for(pg = p->mmufree; pg; pg = next){ next = pg->next; if(--pg->ref) panic("mmurelease: pg->ref %d\n", pg->ref); pg->ref = 0; if(palloc.head){ pg->next = palloc.head; palloc.head->prev = pg; } else{ palloc.tail = pg; pg->next = 0; } palloc.head = pg; pg->prev = 0; palloc.freecount++; } if(p->mmufree && palloc.r.p) . 264,269d 259,262c /* * Release any pages allocated for a page directory base or page-tables * for this process: * switch to the prototype pdb for this processor (m->pdb); * call mmuptefree() to place all pages used for page-tables (p->mmuused) * onto the process' free list (p->mmufree). This has the side-effect of * cleaning any user entries in the pdb (p->mmupdb); * if there's a pdb put it in the cache of pre-initialised pdb's * for this processor (m->pdbpool) or on the process' free list; * finally, place any pages freed back into the free pool (palloc). * This routine is only called from sched() with palloc locked. */ taskswitch(PADDR(m->pdb), (ulong)m + BY2PG); mmuptefree(p); if(p->mmupdb){ if(m->pdbcnt > 10){ p->mmupdb->next = p->mmufree; p->mmufree = p->mmupdb; } else{ p->mmupdb->next = m->pdbpool; m->pdbpool = p->mmupdb; m->pdbcnt++; } p->mmupdb = 0; . 256,257c Page *pg, *next; . 253,254c void mmurelease(Proc *p) . 250c taskswitch(PADDR(m->pdb), (ulong)(p->kstack+KSTACK)); . 246,248c if(p->mmupdb){ top = (ulong*)p->mmupdb->va; top[PDX(MACHADDR)] = ((ulong*)m->pdb)[PDX(MACHADDR)]; taskswitch(p->mmupdb->pa, (ulong)(p->kstack+KSTACK)); } . 225,242c mmuptefree(p); . 221d 213,217c static void mmuptefree(Proc *p) { ulong *pdb; Page **lpg, *pg; if(p->mmupdb && p->mmuused){ pdb = (ulong*)p->mmupdb->va; lpg = &p->mmuused; for(pg = *lpg; pg; pg = pg->next){ pdb[pg->daddr] = 0; lpg = &pg->next; } *lpg = p->mmufree; p->mmufree = p->mmuused; p->mmuused = 0; } } . 199,201d 189,196c ulong* mmuwalk(ulong *pdb, ulong va, int create) { ulong *table, x; table = &pdb[PDX(va)]; if(*table == 0){ if(create == 0) return 0; x = PADDR((ulong)xspanalloc(BY2PG, BY2PG, 0)); *table = x|ptebits|PTEWRITE|PTEVALID; } table = (ulong*)(KZERO|PPN(*table)); va = PTX(va); return &table[va]; . 182,187c taskswitch(PADDR(m->pdb), (ulong)m + BY2PG); ltr(TSSSEL); } . 164,180c ptr[0] = sizeof(Segdesc)*256; x = IDTADDR; ptr[1] = x & 0xFFFF; ptr[2] = (x>>16) & 0xFFFF; lidt(ptr); . 159,162c ptr[0] = sizeof(m->gdt); x = (ulong)m->gdt; ptr[1] = x & 0xFFFF; ptr[2] = (x>>16) & 0xFFFF; lgdt(ptr); . 153,157c memmove(m->gdt, gdt, sizeof(m->gdt)); x = (ulong)m->tss; m->gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss); m->gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP; . 143,151c m->tss = malloc(sizeof(Tss)); memset(m->tss, 0, sizeof(Tss)); . 140,141c ushort ptr[3]; . 138d 129,134d 119,125c Tss *tss; tss = m->tss; tss->ss0 = KDSEL; tss->esp0 = stack; tss->ss1 = KDSEL; tss->esp1 = stack; tss->ss2 = KDSEL; tss->esp2 = stack; tss->cr3 = pagetbl; . 82,115d 75,80c static int ptebits = 0; . 71,73c #define PDX(va) ((((ulong)(va))>>22) & 0x03FF) #define PTX(va) ((((ulong)(va))>>12) & 0x03FF) . 58,61c Segdesc gdt[6] = . 52,54d 8,49d ## diffname pc/mmu.c 1997/1011 ## diff -e /n/emeliedump/1997/0327/sys/src/brazil/pc/mmu.c /n/emeliedump/1997/1011/sys/src/brazil/pc/mmu.c 252a } ulong* mmuwalk(ulong* pdb, ulong va, int create) { ulong pa, *table; table = &pdb[PDX(va)]; if(*table == 0){ if(create == 0) return 0; pa = PADDR((ulong)xspanalloc(BY2PG, BY2PG, 0)); *table = pa|PTEWRITE|PTEVALID; } if(*table & PTESIZE) return table; table = (ulong*)(KZERO|PPN(*table)); va = PTX(va); return &table[va]; } static Lock mmukmaplock; int mmukmapsync(ulong va) { Mach *mach0; ulong entry; mach0 = MACHP(0); lock(&mmukmaplock); if(mmuwalk(mach0->pdb, va, 0) == nil){ unlock(&mmukmaplock); return 0; } entry = ((ulong*)mach0->pdb)[PDX(va)]; if(!(((ulong*)m->pdb)[PDX(va)] & PTEVALID)) ((ulong*)m->pdb)[PDX(va)] = entry; if(up && up->mmupdb){ ((ulong*)up->mmupdb->va)[PDX(va)] = entry; mmuflushtlb(up->mmupdb->pa); } else mmuflushtlb(PADDR(m->pdb)); unlock(&mmukmaplock); return 1; } ulong mmukmap(ulong pa, ulong va, int size) { Mach *mach0; ulong ova, pae, *table, pgsz, *pte; pa &= ~(BY2PG-1); if(va == 0) va = (ulong)KADDR(pa); va &= ~(BY2PG-1); ova = va; pae = pa + size; mach0 = MACHP(0); lock(&mmukmaplock); while(pa < pae){ table = &((ulong*)mach0->pdb)[PDX(va)]; if((pa % (4*MB)) == 0 && (mach0->cpuiddx & 0x08)){ *table = pa|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID; pgsz = 4*MB; } else{ pte = mmuwalk(mach0->pdb, va, 1); *pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID; pgsz = BY2PG; } pa += pgsz; va += pgsz; } unlock(&mmukmaplock); mmukmapsync(ova); return pa; . 251c mmuflushtlb(up->mmupdb->pa); . 247c pt[PTX(va)] = pa|PTEUSER; . 240c pdb[pdbx] = PPN(pg->pa)|PTEUSER|PTEWRITE|PTEVALID; . 219c putmmu(ulong va, ulong pa, Page* pg) . 141c mmurelease(Proc* p) . 122c mmuswitch(Proc* p) . 103c mmuptefree(Proc* p) . 74,90d 26,27d ## diffname pc/mmu.c 1997/1101 ## diff -e /n/emeliedump/1997/1011/sys/src/brazil/pc/mmu.c /n/emeliedump/1997/1101/sys/src/brazil/pc/mmu.c 321c /* * If something was added * then need to sync up. */ if(sync) mmukmapsync(ova); . 317a sync++; . 312c pte = mmuwalk(mach0->pdb, va, 2, 1); . 306,307c table = &mach0->pdb[PDX(va)]; /* * Possibly already mapped. */ if(*table & PTEVALID){ if(*table & PTESIZE){ /* * Big page. Does it fit within? * If it does, adjust pgsz so the correct end can be * returned and get out. * If not, adjust pgsz up to the next 4MB boundary * and continue. */ x = PPN(*table); if(x != pa) panic("mmukmap1: pa %ux entry %uX\n", pa, *table); x += 4*MB; if(pae <= x){ pa = pae; break; } pgsz = x - pa; pa += pgsz; va += pgsz; continue; } else{ /* * Little page. Walk to the entry. * If the entry is valid, set pgsz and continue. * If not, make it so, set pgsz, sync and continue. */ pte = mmuwalk(mach0->pdb, va, 2, 0); if(pte && *pte & PTEVALID){ x = PPN(*pte); if(x != pa) panic("mmukmap2: pa %ux entry %uX\n", pa, *pte); pgsz = BY2PG; pa += pgsz; va += pgsz; sync++; continue; } } } /* * Not mapped. Check if it can be mapped using a big page - * starts on a 4MB boundary, size >= 4MB and processor can do it. * If not a big page, walk the walk, talk the talk. * Sync is set. */ if(pse && (pa % (4*MB)) == 0 && (pae >= pa+4*MB)){ . 303d 299c else va = PPN(va); . 296c mach0 = MACHP(0); if((mach0->cpuiddx & 0x08) && (getcr4() & 0x10)) pse = 1; else pse = 0; sync = 0; pa = PPN(pa); . 294c ulong ova, pae, *table, pgsz, *pte, x; int pse, sync; . 275,276c if(!(m->pdb[PDX(va)] & PTEVALID)) m->pdb[PDX(va)] = entry; . 273c if(!(*pte & PTESIZE) && mmuwalk(mach0->pdb, va, 2, 0) == nil){ unlock(&mmukmaplock); return 0; } entry = *pte; . 269c if((pte = mmuwalk(mach0->pdb, va, 1, 0)) == nil){ . 263c ulong entry, *pte; . 254c return &table[PTX(va)]; } . 251,252c case 2: if(*table & PTESIZE) panic("mmuwalk2: va %uX entry %uX\n", va, *table); if(!(*table & PTEVALID)){ pa = PADDR(xspanalloc(BY2PG, BY2PG, 0)); *table = pa|PTEWRITE|PTEVALID; } table = KADDR(PPN(*table)); . 242,248c if(!(*table & PTEVALID) && create == 0) return 0; switch(level){ default: return 0; case 1: . 240a /* * Walk the page-table pointed to by pdb and return a pointer * to the entry for virtual address va at the requested level. * If the entry is invalid and create isn't requested then bail * out early. Otherwise, for the 2nd level walk, allocate a new * page-table page and register it in the 1st level. */ . 237c mmuwalk(ulong* pdb, ulong va, int level, int create) . 231c pdb[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)]; . 227c pt = KADDR(PPN(pdb[pdbx])); . 114c top[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)]; . ## diffname pc/mmu.c 1998/0605 ## diff -e /n/emeliedump/1997/1101/sys/src/brazil/pc/mmu.c /n/emeliedump/1998/0605/sys/src/brazil/pc/mmu.c 227,228c pte = KADDR(PPN(pdb[pdbx])); pte[PTX(va)] = pa|PTEUSER; . 221,224c pdb[pdbx] = PPN(page->pa)|PTEUSER|PTEWRITE|PTEVALID; page->daddr = pdbx; page->next = up->mmuused; up->mmuused = page; . 217,219c page = up->mmufree; up->mmufree = page->next; memset((void*)page->va, 0, BY2PG); . 213,214c page = newpage(1, 0, 0); page->va = VA(kmap(page)); . 203c Page *page; ulong *pdb, *pte; . 200c putmmu(ulong va, ulong pa, Page*) . 196c return page; . 191,192c page = m->pdbpool; m->pdbpool = page->next; . 186,188c page = newpage(0, 0, 0); page->va = VA(kmap(page)); memmove((void*)page->va, m->pdb, BY2PG); . 181c Page *page; . 174c proc->mmufree = 0; . 172c if(proc->mmufree && palloc.r.p) . 154,170c for(page = proc->mmufree; page; page = next){ next = page->next; if(--page->ref) panic("mmurelease: page->ref %d\n", page->ref); pagechainhead(page); . 151c proc->mmupdb = 0; . 147,148c proc->mmupdb->next = m->pdbpool; m->pdbpool = proc->mmupdb; . 143,144c proc->mmupdb->next = proc->mmufree; proc->mmufree = proc->mmupdb; . 141c if(proc->mmupdb){ . 139c mmuptefree(proc); . 130,132c * call mmuptefree() to place all pages used for page-tables (proc->mmuused) * onto the process' free list (proc->mmufree). This has the side-effect of * cleaning any user entries in the pdb (proc->mmupdb); . 124c Page *page, *next; . 122c mmurelease(Proc* proc) . 118c taskswitch(PADDR(m->pdb), (ulong)(proc->kstack+KSTACK)); . 112,115c if(proc->mmupdb){ pdb = (ulong*)proc->mmupdb->va; pdb[PDX(MACHADDR)] = m->pdb[PDX(MACHADDR)]; taskswitch(proc->mmupdb->pa, (ulong)(proc->kstack+KSTACK)); . 107,109c if(proc->newtlb){ mmuptefree(proc); proc->newtlb = 0; . 105c ulong *pdb; . 103c mmuswitch(Proc* proc) . 96,98c *last = proc->mmufree; proc->mmufree = proc->mmuused; proc->mmuused = 0; . 89,94c if(proc->mmupdb && proc->mmuused){ pdb = (ulong*)proc->mmupdb->va; last = &proc->mmuused; for(page = *last; page; page = page->next){ pdb[page->daddr] = 0; last = &page->next; . 87c Page **last, *page; . 84c mmuptefree(Proc* proc) . 38,39c tss->cr3 = pdb; putcr3(pdb); . 27c taskswitch(ulong pdb, ulong stack) . ## diffname pc/mmu.c 1998/0906 ## diff -e /n/emeliedump/1998/0605/sys/src/brazil/pc/mmu.c /n/emeliedump/1998/0906/sys/src/brazil/pc/mmu.c 361c panic("mmukmap2: pa %uX entry %uX\n", . 338c panic("mmukmap1: pa %uX entry %uX\n", . ## diffname pc/mmu.c 1999/0216 ## diff -e /n/emeliedump/1998/0906/sys/src/brazil/pc/mmu.c /n/emeliedump/1999/0216/sys/src/brazil/pc/mmu.c 66a /* make kernel text unwritable */ for(x = KTZERO; x < (ulong)etext; x += BY2PG){ p = mmuwalk(m->pdb, x, 2, 0); if(p == nil) panic("mmuinit"); *p &= ~PTEWRITE; } . 45c ulong x, *p; . ## diffname pc/mmu.c 2001/0223 ## diff -e /n/emeliedump/1999/0216/sys/src/brazil/pc/mmu.c /n/emeliedump/2001/0223/sys/src/9/pc/mmu.c 228a coherence(); . 38a coherence(); . ## diffname pc/mmu.c 2001/0224 ## diff -e /n/emeliedump/2001/0223/sys/src/9/pc/mmu.c /n/emeliedump/2001/0224/sys/src/9/pc/mmu.c 230c coherence(); // *** See note at beginning of file *** . 39c coherence(); // *** See note at beginning of file *** . 7a /* * There are 2 coherence calls in this file, before each putcr3() (mmuflushtlb * is really a putcr3() call). They are there because of my IBM 570 and ehg's * IBM 600E. We found that when the coherence() instructions were removed from * unlock and iunlock, the processors would hang and/or get spurious interrupts. * I posited that we were getting hit by some interaction between the tlb, * cache flushing, and tlb flushing, so I moved the calls here and it seems * to work. * * I don't really understand why they'ld change anything since the putcr3 is * supposed to be a serializing instruction. Also, reads and writes are supposed * to be ordered in the view of the processing core. This is just desperation. * I can only believe that the coherence() is fixing something else. * * The 570 is a Celeron and the 600E is a PentiumII/Xeon. Both screw up when * pounding on PCMCIA devices. * * -- presotto */ . ## diffname pc/mmu.c 2001/0527 ## diff -e /n/emeliedump/2001/0224/sys/src/9/pc/mmu.c /n/emeliedump/2001/0527/sys/src/9/pc/mmu.c 250d 59d 8,27d ## diffname pc/mmu.c 2002/0109 ## diff -e /n/emeliedump/2001/0527/sys/src/9/pc/mmu.c /n/emeliedump/2002/0109/sys/src/9/pc/mmu.c 62c ptr[0] = sizeof(Segdesc)*256-1; . 56c ptr[0] = sizeof(m->gdt)-1; . 42a gdtinit(void) { ulong x; ushort ptr[3]; memmove(m->gdt, gdt, sizeof(m->gdt)); ptr[0] = sizeof(m->gdt)-1; x = (ulong)m->gdt; ptr[1] = x & 0xFFFF; ptr[2] = (x>>16) & 0xFFFF; lgdt(ptr); } void . 23,25d 13c Segdesc gdt[NGDT] = . ## diffname pc/mmu.c 2002/0114 ## diff -e /n/emeliedump/2002/0109/sys/src/9/pc/mmu.c /n/emeliedump/2002/0114/sys/src/9/pc/mmu.c 381c panic("mmukmap2: pa %luX entry %luX\n", . 358c panic("mmukmap1: pa %luX entry %luX\n", . 271c panic("mmuwalk2: va %luX entry %luX\n", va, *table); . ## diffname pc/mmu.c 2002/0412 ## diff -e /n/emeliedump/2002/0114/sys/src/9/pc/mmu.c /n/emeliedump/2002/0412/sys/src/9/pc/mmu.c 405a if((va&KZERO) && m->havepge) *pte |= PTEGLOBAL; . 400a if((va&KZERO) && m->havepge) *table |= PTEGLOBAL; . 397a * * If we're creating a kernel mapping, we know that it will never * expire and thus we can set the PTEGLOBAL bit to make the entry * persist in the TLB across flushes. If we do add support later for * unmapping kernel addresses, see devarch.c for instructions on * how to do a full TLB flush. . 68c ptr[0] = sizeof(gdt)-1; . 63c /* * We used to keep the GDT in the Mach structure, but it * turns out that that slows down access to the rest of the * page. Since the Mach structure is accessed quite often, * it pays off anywhere from a factor of 1.25 to 2 on real * hardware to separate them (the AMDs are more sensitive * than Intels in this regard). Under VMware it pays off * a factor of about 10 to 100. */ memmove(m->gdt, gdt, sizeof gdt); . 59a memglobal(); . 47,51c if(!m->havepge) return; pde = m->pdb; for(i=512; i<1024; i++){ /* 512: start at entry for virtual 0x80000000 */ if(pde[i] & PTEVALID){ pde[i] |= PTEGLOBAL; if(!(pde[i] & PTESIZE)){ pte = KADDR(pde[i]&~(BY2PG-1)); for(j=0; j<1024; j++) if(pte[j] & PTEVALID) pte[j] |= PTEGLOBAL; } } } . 45c /* only need to do this once, on bootstrap processor */ if(m->machno != 0) return; . 42,43c int i, j; ulong *pde, *pte; . 39,40c /* * On processors that support it, we set the PTEGLOBAL bit in * page table and page directory entries that map kernel memory. * Doing this tells the processor not to bother flushing them * from the TLB when doing the TLB flush associated with a * context switch (write to CR3). Since kernel memory mappings * are never removed, this is safe. (If we ever remove kernel memory * mappings, we can do a full flush by turning off the PGE bit in CR4, * writing to CR3, and then turning the PGE bit back on.) * * See also mmukmap below. * * Processor support for the PTEGLOBAL bit is enabled in devarch.c. */ static void memglobal(void) . ## diffname pc/mmu.c 2002/0430 ## diff -e /n/emeliedump/2002/0412/sys/src/9/pc/mmu.c /n/emeliedump/2002/0430/sys/src/9/pc/mmu.c 58a return; . ## diffname pc/mmu.c 2002/0501 ## diff -e /n/emeliedump/2002/0430/sys/src/9/pc/mmu.c /n/emeliedump/2002/0501/sys/src/9/pc/mmu.c 59d ## diffname pc/mmu.c 2003/0405 ## diff -e /n/emeliedump/2002/0501/sys/src/9/pc/mmu.c /n/emeliedump/2003/0405/sys/src/9/pc/mmu.c 460c iunlock(&mmukmaplock); . 379c ilock(&mmukmaplock); . 352c iunlock(&mmukmaplock); . 337c iunlock(&mmukmaplock); . 333c iunlock(&mmukmaplock); . 330c ilock(&mmukmaplock); .