| plan 9 kernel history: overview | file list | diff list |
1991/0711/pc/mmu.c (diff list | history)
| 1991/0612/sys/src/9/pc/mmu.c:5,13 – 1991/0613/sys/src/9/pc/mmu.c:5,20 (short | long) | ||
| 1991/0612 | #include "fns.h" #include "io.h" | |
| 1991/0613 | /* * global descriptor table describing all segments */ Segdesc gdt[1024] = | |
| 1991/0612 | { | |
| 1991/0613 | [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 */ }; | |
| 1991/0613/sys/src/9/pc/mmu.c:6,11 – 1991/0625/sys/src/9/pc/mmu.c:6,86 (short | long) | ||
| 1991/0612 | #include "io.h" | |
| 1991/0613 | /* | |
| 1991/0625 | * 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 */ }; /* | |
| 1991/0613 | * global descriptor table describing all segments */ Segdesc gdt[1024] = | |
| 1991/0613/sys/src/9/pc/mmu.c:16,20 – 1991/0625/sys/src/9/pc/mmu.c:91,94 | ||
| 1991/0613 | [UESEG] EXECSEG(3), /* user code */ [UDSEG] DATASEG(3), /* user data/stack */ [SYSGATE] CALLGATE(KESEG, syscall, 3), /* call gate for system calls */ | |
| 1991/0625/sys/src/9/pc/mmu.c:14,33 – 1991/0627/sys/src/9/pc/mmu.c:14,19 (short | long) | ||
| 1991/0625 | ulong d0; ulong d1; }; | |
| 1991/0627/sys/src/9/pc/mmu.c:6,34 – 1991/0703/sys/src/9/pc/mmu.c:6,11 (short | long) | ||
| 1991/0612 | #include "io.h" | |
| 1991/0613 | /* | |
| 1991/0625 |
| |
| 1991/0627/sys/src/9/pc/mmu.c:67,80 – 1991/0703/sys/src/9/pc/mmu.c:44,78 | ||
| 1991/0625 | }; /* | |
| 1991/0703 | * 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 } /* | |
| 1991/0613 | * global descriptor table describing all segments */ | |
| 1991/0703 | Segdesc gdt[6] = | |
| 1991/0612 | { | |
| 1991/0613 | [NULLSEG] { 0, 0}, /* null descriptor */ | |
| 1991/0703 | [KESEG] EXECSEG(0), /* kernel code */ | |
| 1991/0613 | [UDSEG] DATASEG(3), /* user data/stack */ | |
| 1991/0703 | [UESEG] EXECSEG(3), /* user code */ [SYSGATE] CALLGATE(KESEL,0,3), /* call gate for system calls */ | |
| 1991/0613 | }; | |
| 1991/0703 | 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"); } | |
| 1991/0703/sys/src/9/pc/mmu.c:49,59 – 1991/0706/sys/src/9/pc/mmu.c:49,61 (short | long) | ||
| 1991/0703 | #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 } | |
| 1991/0706 | #define D16SEG(p) { 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW } #define E16SEG(p) { 0xFFFF, (0x0<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR } | |
| 1991/0703 | /* | |
| 1991/0613 | * global descriptor table describing all segments */ | |
| 1991/0703 |
| |
| 1991/0706 | Segdesc gdt[] = | |
| 1991/0612 | { | |
| 1991/0613 | [NULLSEG] { 0, 0}, /* null descriptor */ [KDSEG] DATASEG(0), /* kernel data/stack */ | |
| 1991/0703/sys/src/9/pc/mmu.c:61,66 – 1991/0706/sys/src/9/pc/mmu.c:63,70 | ||
| 1991/0613 | [UDSEG] DATASEG(3), /* user data/stack */ | |
| 1991/0703 | [UESEG] EXECSEG(3), /* user code */ [SYSGATE] CALLGATE(KESEL,0,3), /* call gate for system calls */ | |
| 1991/0706 | [RDSEG] D16SEG(0), /* reboot data/stack */ [RESEG] E16SEG(0), /* reboot code */ | |
| 1991/0613 | }; | |
| 1991/0703 | void | |
| 1991/0706/sys/src/9/pc/mmu.c:67,78 – 1991/0711/sys/src/9/pc/mmu.c:67,106 (short | long) | ||
| 1991/0706 | [RESEG] E16SEG(0), /* reboot code */ | |
| 1991/0613 | }; | |
| 1991/0703 | ||
| 1991/0711 | extern ulong tpt[]; | |
| 1991/0703 | void mmuinit(void) { | |
| 1991/0711 | ||
| 1991/0703 | gdt[SYSGATE].d0 = ((ulong)systrap)&0xFFFF|(KESEL<<16); gdt[SYSGATE].d1 = ((ulong)systrap)&0xFFFF0000|SEGP|SEGPL(3)|SEGCG; lgdt(gdt, sizeof gdt); | |
| 1991/0711 | } void mapstack(Proc *p) { } void flushmmu(void) { } void mmurelease(Proc *p) { } void putmmu(ulong x, ulong y, Page*z) { } void invalidateu(void) { | |
| 1991/0703 | } void | |
| 1991/0711/sys/src/9/pc/mmu.c:72,81 – 1991/0716/sys/src/9/pc/mmu.c:72,91 (short | long) | ||
| 1991/0703 | void mmuinit(void) { | |
| 1991/0711 | ||
| 1991/0716 | /* * set up the global descriptor table */ | |
| 1991/0703 | gdt[SYSGATE].d0 = ((ulong)systrap)&0xFFFF|(KESEL<<16); gdt[SYSGATE].d1 = ((ulong)systrap)&0xFFFF0000|SEGP|SEGPL(3)|SEGCG; lgdt(gdt, sizeof gdt); | |
| 1991/0716 | /* * set up system page tables */ /* * set up the task segment */ | |
| 1991/0711 | } void | |
| 1991/0716/sys/src/9/pc/mmu.c:16,26 – 1991/0717/sys/src/9/pc/mmu.c:16,26 (short | long) | ||
| 1991/0625 | struct Tss { ulong backlink; /* unused */ | |
| 1991/0717 | ulong sp0; /* pl0 stack pointer */ | |
| 1991/0625 | ulong ss0; /* pl0 stack selector */ | |
| 1991/0717 | ulong sp1; /* pl1 stack pointer */ | |
| 1991/0625 | ulong ss1; /* pl1 stack selector */ | |
| 1991/0717 | ulong sp2; /* pl2 stack pointer */ | |
| 1991/0625 | ulong ss2; /* pl2 stack selector */ ulong cr3; /* page table descriptor */ ulong eip; /* instruction pointer */ | |
| 1991/0716/sys/src/9/pc/mmu.c:42,56 – 1991/0717/sys/src/9/pc/mmu.c:42,59 | ||
| 1991/0625 | ulong ldt; /* local descriptor table */ ulong iomap; /* io map base */ }; | |
| 1991/0717 | Tss tss; | |
| 1991/0625 | /* | |
| 1991/0703 | * segment descriptor initializers */ | |
| 1991/0706 |
| |
| 1991/0717 | #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 } | |
| 1991/0703 | /* | |
| 1991/0613 | * global descriptor table describing all segments | |
| 1991/0716/sys/src/9/pc/mmu.c:58,96 – 1991/0717/sys/src/9/pc/mmu.c:61,145 | ||
| 1991/0706 | Segdesc gdt[] = | |
| 1991/0612 | { | |
| 1991/0613 | [NULLSEG] { 0, 0}, /* null descriptor */ | |
| 1991/0703 |
| |
| 1991/0613 |
| |
| 1991/0703 |
| |
| 1991/0717 | [KDSEG] DATASEGM(0), /* kernel data/stack */ [KESEG] EXECSEGM(0), /* kernel code */ [UDSEG] DATASEGM(3), /* user data/stack */ [UESEG] EXECSEGM(3), /* user code */ | |
| 1991/0703 | [SYSGATE] CALLGATE(KESEL,0,3), /* call gate for system calls */ | |
| 1991/0706 |
| |
| 1991/0717 | [RDSEG] D16SEGM(0), /* reboot data/stack */ [RESEG] E16SEGM(0), /* reboot code */ [TSSSEG] TSSSEGM(0,0), /* tss segment */ | |
| 1991/0613 | }; | |
| 1991/0703 | ||
| 1991/0711 |
| |
| 1991/0717 | static ulong *toppt; /* top level page table */ static ulong *kpt; /* kernel level page tables */ static ulong *upt; /* page table for struct User */ | |
| 1991/0711 | ||
| 1991/0717 | #define ROUNDUP(s,v) (((s)+(v-1))&~(v-1)) | |
| 1991/0703 | void mmuinit(void) { | |
| 1991/0717 | int i, n, nkpt; ulong x; ulong y; | |
| 1991/0716 | /* * set up the global descriptor table */ | |
| 1991/0703 |
| |
| 1991/0717 | 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; | |
| 1991/0703 | lgdt(gdt, sizeof gdt); | |
| 1991/0716 | /* | |
| 1991/0717 | * set up system page tables. * map all of physical memory to start at KZERO. * leave a map for a user area. | |
| 1991/0716 | */ | |
| 1991/0717 | /* 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<<PGSHIFT)|PTEVALID|PTEKERNEL|PTEWRITE; } /* allocate page table for u-> */ 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); | |
| 1991/0716 | /* * set up the task segment */ | |
| 1991/0717 | tss.sp0 = USERADDR; tss.ss0 = KDSEL; tss.cr3 = (ulong)toppt; ltr(TSSSEL); | |
| 1991/0711 | } void mapstack(Proc *p) { | |
| 1991/0717 | ||
| 1991/0711 | } void | |
| 1991/0716/sys/src/9/pc/mmu.c:104,110 – 1991/0717/sys/src/9/pc/mmu.c:153,159 | ||
| 1991/0711 | } void | |
| 1991/0717 | putmmu(ulong x, ulong y, Page *z) | |
| 1991/0711 | { } | |
| 1991/0716/sys/src/9/pc/mmu.c:117,120 – 1991/0717/sys/src/9/pc/mmu.c:166,181 | ||
| 1991/0703 | systrap(void) { panic("system trap from user"); | |
| 1991/0717 | } void exit(void) { int i; u = 0; print("exiting\n"); for(i = 0; i < WD2PG; i++) toppt[i] = 0; lcr3(((ulong)toppt)&~KZERO); | |
| 1991/0703 | } | |
| 1991/0717/sys/src/9/pc/mmu.c:76,82 – 1991/0718/sys/src/9/pc/mmu.c:76,93 (short | long) | ||
| 1991/0717 | static ulong *upt; /* page table for struct User */ | |
| 1991/0711 | ||
| 1991/0717 | #define ROUNDUP(s,v) (((s)+(v-1))&~(v-1)) | |
| 1991/0718 | /* * offset of virtual address into * top level page table */ #define TOPOFF(v) ((v)>>(2*PGSHIFT-2)) | |
| 1991/0717 | ||
| 1991/0718 | /* * offset of virtual address into * bottom level page table */ #define BTMOFF(v) (((v)>>(PGSHIFT))&(BY2PG-1)) | |
| 1991/0703 | void mmuinit(void) { | |
| 1991/0717/sys/src/9/pc/mmu.c:90,99 – 1991/0718/sys/src/9/pc/mmu.c:101,110 | ||
| 1991/0717 | x = (ulong)systrap; gdt[SYSGATE].d0 = (x&0xFFFF)|(KESEL<<16); gdt[SYSGATE].d1 = (x&0xFFFF0000)|SEGP|SEGPL(3)|SEGCG; | |
| 1991/0718 | x = (ulong)&tss; | |
| 1991/0717 | gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss); gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP; | |
| 1991/0703 |
| |
| 1991/0718 | putgdt(gdt, sizeof gdt); | |
| 1991/0716 | /* | |
| 1991/0717 | * set up system page tables. | |
| 1991/0717/sys/src/9/pc/mmu.c:107,115 – 1991/0718/sys/src/9/pc/mmu.c:118,125 | ||
| 1991/0717 | kpt = ialloc(nkpt*BY2PG, 1); n = ROUNDUP(conf.npage0+conf.npage1, 1*1024*1024); n = n/(4*1024); | |
| 1991/0718 | for(i = 0; i < n; i++) kpt[i] = (i<<PGSHIFT) | PTEVALID | PTEKERNEL | PTEWRITE; | |
| 1991/0717 | /* allocate page table for u-> */ upt = ialloc(BY2PG, 1); | |
| 1991/0717/sys/src/9/pc/mmu.c:116,165 – 1991/0718/sys/src/9/pc/mmu.c:126,259 | ||
| 1991/0717 | /* allocate top level table and put pointers to lower tables in it */ toppt = ialloc(BY2PG, 1); | |
| 1991/0718 | x = TOPOFF(KZERO); | |
| 1991/0717 | y = ((ulong)kpt)&~KZERO; | |
| 1991/0718 | for(i = 0; i < nkpt; i++) toppt[x+i] = (y+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; x = TOPOFF(USERADDR); | |
| 1991/0717 | y = ((ulong)upt)&~KZERO; | |
| 1991/0718 | toppt[x] = y | PTEVALID | PTEKERNEL | PTEWRITE; putcr3(((ulong)toppt)&~KZERO); | |
| 1991/0717 | ||
| 1991/0716 | /* * set up the task segment */ | |
| 1991/0717 |
| |
| 1991/0718 | tss.sp0 = USERADDR+BY2PG; | |
| 1991/0717 | tss.ss0 = KDSEL; tss.cr3 = (ulong)toppt; | |
| 1991/0718 | puttr(TSSSEL); | |
| 1991/0711 | } void mapstack(Proc *p) { | |
| 1991/0717 | ||
| 1991/0718 | 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; | |
| 1991/0711 | } void flushmmu(void) { | |
| 1991/0718 | int s; if(u == 0) return; u->p->mmuvalid = 0; s = splhi(); mapstack(u->p); splx(s); | |
| 1991/0711 | } void mmurelease(Proc *p) { | |
| 1991/0718 | p->mmuvalid = 0; | |
| 1991/0711 | } void | |
| 1991/0717 |
| |
| 1991/0718 | putmmu(ulong va, ulong pa, Page *pg) | |
| 1991/0711 | { | |
| 1991/0718 | 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); | |
| 1991/0711 | } void invalidateu(void) { | |
| 1991/0718 | /* unmap u area */ upt[0] = 0; /* flush cached mmu entries */ putcr3(((ulong)toppt)&~KZERO); | |
| 1991/0703 | } void | |
| 1991/0717/sys/src/9/pc/mmu.c:177,181 – 1991/0718/sys/src/9/pc/mmu.c:271,275 | ||
| 1991/0717 | print("exiting\n"); for(i = 0; i < WD2PG; i++) toppt[i] = 0; | |
| 1991/0718 | putcr3(((ulong)toppt)&~KZERO); | |
| 1991/0703 | } | |
| 1991/0718/sys/src/9/pc/mmu.c:66,73 – 1991/0719/sys/src/9/pc/mmu.c:66,71 (short | long) | ||
| 1991/0717 | [UDSEG] DATASEGM(3), /* user data/stack */ [UESEG] EXECSEGM(3), /* user code */ | |
| 1991/0703 | [SYSGATE] CALLGATE(KESEL,0,3), /* call gate for system calls */ | |
| 1991/0717 |
| |
| 1991/0613 | }; | |
| 1991/0703 | ||
| 1991/0718/sys/src/9/pc/mmu.c:86,94 – 1991/0719/sys/src/9/pc/mmu.c:84,105 | ||
| 1991/0718 | * offset of virtual address into * bottom level page table */ | |
| 1991/0719 | #define BTMOFF(v) (((v)>>(PGSHIFT))&(WD2PG-1)) | |
| 1991/0718 | ||
| 1991/0703 | void | |
| 1991/0719 | 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 | |
| 1991/0703 | mmuinit(void) { | |
| 1991/0717 | int i, n, nkpt; | |
| 1991/0718/sys/src/9/pc/mmu.c:112,123 – 1991/0719/sys/src/9/pc/mmu.c:123,133 | ||
| 1991/0717 | * leave a map for a user area. | |
| 1991/0716 | */ | |
| 1991/0717 |
| |
| 1991/0719 | /* allocate and fill low level page tables for kernel mem */ nkpt = ROUNDUP(conf.npage, 4*1024); nkpt = nkpt/(4*1024); | |
| 1991/0717 | kpt = ialloc(nkpt*BY2PG, 1); | |
| 1991/0719 | n = ROUNDUP(conf.npage, 1024); | |
| 1991/0718 | for(i = 0; i < n; i++) kpt[i] = (i<<PGSHIFT) | PTEVALID | PTEKERNEL | PTEWRITE; | |
| 1991/0717 | ||
| 1991/0718/sys/src/9/pc/mmu.c:150,157 – 1991/0719/sys/src/9/pc/mmu.c:160,165 | ||
| 1991/0718 | ulong tlbphys; int i; | |
| 1991/0718/sys/src/9/pc/mmu.c:210,216 – 1991/0719/sys/src/9/pc/mmu.c:218,224 | ||
| 1991/0718 | Proc *p; int i; | |
| 1991/0719 | print("putmmu %lux %lux\n", va, pa); /**/ | |
| 1991/0718 | if(u==0) panic("putmmu"); p = u->p; | |
| 1991/0718/sys/src/9/pc/mmu.c:232,239 – 1991/0719/sys/src/9/pc/mmu.c:240,248 | ||
| 1991/0718 | pg = p->mmu[i]; if(pg == 0){ pg = p->mmu[i] = newpage(1, 0, 0); | |
| 1991/0719 | p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; | |
| 1991/0718 | toppt[topoff] = p->mmue[i]; | |
| 1991/0719 | print("toppt[%d] = %lux\n", topoff, p->mmue[i]); | |
| 1991/0718 | } /* | |
| 1991/0718/sys/src/9/pc/mmu.c:241,246 – 1991/0719/sys/src/9/pc/mmu.c:250,256 | ||
| 1991/0718 | */ pt = (ulong*)(p->mmu[i]->pa|KZERO); pt[BTMOFF(va)] = pa | PTEUSER; | |
| 1991/0719 | print("%lux[%d] = %lux\n", pt, BTMOFF(va), pa | PTEUSER); | |
| 1991/0718 | /* flush cached mmu entries */ putcr3(((ulong)toppt)&~KZERO); | |
| 1991/0718/sys/src/9/pc/mmu.c:260,275 – 1991/0719/sys/src/9/pc/mmu.c:270,273 | ||
| 1991/0703 | systrap(void) { panic("system trap from user"); | |
| 1991/0717 |
| |
| 1991/0718 |
| |
| 1991/0703 | } | |
| 1991/0719/sys/src/9/pc/mmu.c:242,256 – 1991/0720/sys/src/9/pc/mmu.c:242,257 (short | long) | ||
| 1991/0718 | pg = p->mmu[i] = newpage(1, 0, 0); | |
| 1991/0719 | p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; | |
| 1991/0718 | toppt[topoff] = p->mmue[i]; | |
| 1991/0719 |
| |
| 1991/0720 | print("toppt[%d] = %lux\n", topoff, toppt[topoff]); | |
| 1991/0718 | } /* * fill in the bottom level page table */ | |
| 1991/0720 | print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); | |
| 1991/0718 | pt = (ulong*)(p->mmu[i]->pa|KZERO); pt[BTMOFF(va)] = pa | PTEUSER; | |
| 1991/0719 |
| |
| 1991/0720 | print("%lux[%d] now %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); | |
| 1991/0718 | /* flush cached mmu entries */ putcr3(((ulong)toppt)&~KZERO); | |
| 1991/0720/sys/src/9/pc/mmu.c:178,185 – 1991/0723/sys/src/9/pc/mmu.c:178,185 (short | long) | ||
| 1991/0718 | /* * point top level page table to bottom level ones */ | |
| 1991/0723 | memmove(toppt, p->mmue, MAXMMU*sizeof(ulong)); memmove(&toppt[TOPOFF(USTKBTM)], &p->mmue[MAXMMU], MAXSMMU*sizeof(ulong)); | |
| 1991/0718 | /* map in u area */ upt[0] = PPN(p->upage->pa) | PTEVALID | PTEKERNEL | PTEWRITE; | |
| 1991/0720/sys/src/9/pc/mmu.c:216,222 – 1991/0723/sys/src/9/pc/mmu.c:216,222 | ||
| 1991/0718 | int topoff; ulong *pt; Proc *p; | |
| 1991/0723 | int i = 0; | |
| 1991/0718 | ||
| 1991/0719 | print("putmmu %lux %lux\n", va, pa); /**/ | |
| 1991/0718 | if(u==0) | |
| 1991/0720/sys/src/9/pc/mmu.c:238,255 – 1991/0723/sys/src/9/pc/mmu.c:238,256 | ||
| 1991/0718 | * if bottom level page table missing, allocate one */ pg = p->mmu[i]; | |
| 1991/0723 | print("toppt[%d] was %lux\n", topoff, toppt[topoff]); | |
| 1991/0718 | if(pg == 0){ pg = p->mmu[i] = newpage(1, 0, 0); | |
| 1991/0719 | p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; | |
| 1991/0718 | toppt[topoff] = p->mmue[i]; | |
| 1991/0720 |
| |
| 1991/0723 | print("toppt[%d] now %lux\n", topoff, toppt[topoff]); | |
| 1991/0718 | } /* * fill in the bottom level page table */ | |
| 1991/0720 |
| |
| 1991/0718 | pt = (ulong*)(p->mmu[i]->pa|KZERO); | |
| 1991/0723 | print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); | |
| 1991/0718 | pt[BTMOFF(va)] = pa | PTEUSER; | |
| 1991/0720 | print("%lux[%d] now %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]); | |
| 1991/0718 | ||
| 1991/0723/sys/src/9/pc/mmu.c:218,224 – 1991/0801/sys/src/9/pc/mmu.c:218,224 (short | long) | ||
| 1991/0718 | Proc *p; | |
| 1991/0723 | int i = 0; | |
| 1991/0718 | ||
| 1991/0719 |
| |
| 1991/0801 | /*print("putmmu %lux %lux\n", va, pa); /**/ | |
| 1991/0718 | if(u==0) panic("putmmu"); p = u->p; | |
| 1991/0723/sys/src/9/pc/mmu.c:238,249 – 1991/0801/sys/src/9/pc/mmu.c:238,249 | ||
| 1991/0718 | * if bottom level page table missing, allocate one */ pg = p->mmu[i]; | |
| 1991/0723 |
| |
| 1991/0801 | /*print("toppt[%d] was %lux\n", topoff, toppt[topoff]);/**/ | |
| 1991/0718 | if(pg == 0){ pg = p->mmu[i] = newpage(1, 0, 0); | |
| 1991/0719 | p->mmue[i] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; | |
| 1991/0718 | toppt[topoff] = p->mmue[i]; | |
| 1991/0723 |
| |
| 1991/0801 | /*print("toppt[%d] now %lux\n", topoff, toppt[topoff]);/**/ | |
| 1991/0718 | } /* | |
| 1991/0723/sys/src/9/pc/mmu.c:250,258 – 1991/0801/sys/src/9/pc/mmu.c:250,258 | ||
| 1991/0718 | * fill in the bottom level page table */ pt = (ulong*)(p->mmu[i]->pa|KZERO); | |
| 1991/0723 |
| |
| 1991/0801 | /*print("%lux[%d] was %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);/**/ | |
| 1991/0718 | pt[BTMOFF(va)] = pa | PTEUSER; | |
| 1991/0720 |
| |
| 1991/0801 | /*print("%lux[%d] now %lux\n", pt, BTMOFF(va), pt[BTMOFF(va)]);/**/ | |
| 1991/0718 | /* flush cached mmu entries */ putcr3(((ulong)toppt)&~KZERO); | |
| 1991/0801/sys/src/9/pc/mmu.c:102,108 – 1991/0821/sys/src/9/pc/mmu.c:102,108 (short | long) | ||
| 1991/0719 | void | |
| 1991/0703 | mmuinit(void) { | |
| 1991/0717 |
| |
| 1991/0821 | int i, nkpt, npage, nbytes; | |
| 1991/0717 | ulong x; ulong y; | |
| 1991/0801/sys/src/9/pc/mmu.c:124,135 – 1991/0821/sys/src/9/pc/mmu.c:124,137 | ||
| 1991/0716 | */ | |
| 1991/0719 | /* allocate and fill low level page tables for kernel mem */ | |
| 1991/0717 |
| |
| 1991/0719 |
| |
| 1991/0718 |
| |
| 1991/0821 | 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++) | |
| 1991/0718 | kpt[i] = (i<<PGSHIFT) | PTEVALID | PTEKERNEL | PTEWRITE; | |
| 1991/0821 | print("%d low level pte's, %d high level pte's\n", npage, nkpt); | |
| 1991/0717 | /* allocate page table for u-> */ upt = ialloc(BY2PG, 1); | |
| 1991/0821/sys/src/9/pc/mmu.c:124,130 – 1991/0827/sys/src/9/pc/mmu.c:124,130 (short | long) | ||
| 1991/0716 | */ | |
| 1991/0719 | /* allocate and fill low level page tables for kernel mem */ | |
| 1991/0821 |
| |
| 1991/0827 | npage = conf.base1/BY2PG + conf.npage1; | |
| 1991/0821 | nbytes = PGROUND(npage*BY2WD); /* words of page map */ nkpt = nbytes/BY2PG; /* pages of page map */ kpt = ialloc(nbytes, 1); | |
| 1991/0827/sys/src/9/pc/mmu.c:69,74 – 1991/0922/sys/src/9/pc/mmu.c:69,77 (short | long) | ||
| 1991/0717 | [TSSSEG] TSSSEGM(0,0), /* tss segment */ | |
| 1991/0613 | }; | |
| 1991/0703 | ||
| 1991/0922 | static ulong *ktoppt; /* prototype top level page table * containing kernel mappings */ | |
| 1991/0717 | static ulong *toppt; /* top level page table */ static ulong *kpt; /* kernel level page tables */ static ulong *upt; /* page table for struct User */ | |
| 1991/0922/sys/src/9/pc/mmu.c:165,171 – 1991/0928/sys/src/9/pc/mmu.c:165,171 (short | long) | ||
| 1991/0718 | ulong tlbphys; int i; | |
| 1991/0928 | if(p->upage->va != (USERADDR|(p->pid&0xFFFF)) && p->pid != 0) | |
| 1991/0718 | panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va); /* | |
| 1991/0928/sys/src/9/pc/mmu.c:159,164 – 1991/1003/sys/src/9/pc/mmu.c:159,165 (short | long) | ||
| 1991/0718 | puttr(TSSSEL); | |
| 1991/0711 | } | |
| 1991/1003 | ||
| 1991/0711 | void mapstack(Proc *p) { | |
| 1991/1003/sys/src/9/pc/mmu.c:69,80 – 1991/1004/sys/src/9/pc/mmu.c:69,78 (short | long) | ||
| 1991/0717 | [TSSSEG] TSSSEGM(0,0), /* tss segment */ | |
| 1991/0613 | }; | |
| 1991/0703 | ||
| 1991/0922 |
| |
| 1991/0717 |
| |
| 1991/1004 | 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 */ | |
| 1991/0711 | ||
| 1991/0717 | #define ROUNDUP(s,v) (((s)+(v-1))&~(v-1)) | |
| 1991/0718 | /* | |
| 1991/1003/sys/src/9/pc/mmu.c:102,107 – 1991/1004/sys/src/9/pc/mmu.c:100,111 | ||
| 1991/0719 | panic("done"); } | |
| 1991/1004 | /* * 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. */ | |
| 1991/0719 | void | |
| 1991/0703 | mmuinit(void) { | |
| 1991/1003/sys/src/9/pc/mmu.c:108,113 – 1991/1004/sys/src/9/pc/mmu.c:112,118 | ||
| 1991/0821 | int i, nkpt, npage, nbytes; | |
| 1991/0717 | ulong x; ulong y; | |
| 1991/1004 | ulong *top; | |
| 1991/0717 | ||
| 1991/0716 | /* * set up the global descriptor table | |
| 1991/1003/sys/src/9/pc/mmu.c:123,129 – 1991/1004/sys/src/9/pc/mmu.c:128,134 | ||
| 1991/0716 | /* | |
| 1991/0717 | * set up system page tables. * map all of physical memory to start at KZERO. | |
| 1991/1004 | * leave a map entry for a user area. | |
| 1991/0716 | */ | |
| 1991/0719 | /* allocate and fill low level page tables for kernel mem */ | |
| 1991/1003/sys/src/9/pc/mmu.c:140,154 – 1991/1004/sys/src/9/pc/mmu.c:145,161 | ||
| 1991/0717 | upt = ialloc(BY2PG, 1); /* allocate top level table and put pointers to lower tables in it */ | |
| 1991/1004 | top = ialloc(BY2PG, 1); ktoppg.va = (ulong)top; ktoppg.pa = ktoppg.va & ~KZERO; | |
| 1991/0718 | x = TOPOFF(KZERO); | |
| 1991/0717 | y = ((ulong)kpt)&~KZERO; | |
| 1991/0718 | for(i = 0; i < nkpt; i++) | |
| 1991/1004 | top[x+i] = (y+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; | |
| 1991/0718 | x = TOPOFF(USERADDR); | |
| 1991/0717 | y = ((ulong)upt)&~KZERO; | |
| 1991/0718 |
| |
| 1991/1004 | top[x] = y | PTEVALID | PTEKERNEL | PTEWRITE; putcr3(ktoppg.pa); | |
| 1991/0717 | ||
| 1991/0716 | /* * set up the task segment | |
| 1991/1003/sys/src/9/pc/mmu.c:155,267 – 1991/1004/sys/src/9/pc/mmu.c:162,343 | ||
| 1991/0716 | */ | |
| 1991/0718 | tss.sp0 = USERADDR+BY2PG; | |
| 1991/0717 | tss.ss0 = KDSEL; | |
| 1991/1004 | tss.cr3 = ktoppg.pa; | |
| 1991/0718 | puttr(TSSSEL); | |
| 1991/0711 | } | |
| 1991/1004 | /* * 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; | |
| 1991/1003 | ||
| 1991/1004 | 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. */ | |
| 1991/0711 | void | |
| 1991/1004 | 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 | |
| 1991/0711 | mapstack(Proc *p) { | |
| 1991/0718 | ulong tlbphys; int i; | |
| 1991/1004 | Page *pg; | |
| 1991/0718 | ||
| 1991/0928 | if(p->upage->va != (USERADDR|(p->pid&0xFFFF)) && p->pid != 0) | |
| 1991/0718 | panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va); | |
| 1991/1004 | if(p->mmutop) pg = p->mmutop; else pg = &ktoppg; | |
| 1991/0718 |
| |
| 1991/0723 |
| |
| 1991/0718 |
| |
| 1991/1004 | /* tell processor about new page table (flushes cached entries) */ putcr3(pg->pa); | |
| 1991/0718 | u = (User*)USERADDR; | |
| 1991/0711 | } | |
| 1991/1004 | /* * give all page table pages back to the free pool. This is called in sched() * with palloc locked. */ | |
| 1991/0711 | void | |
| 1991/1004 | mmurelease(Proc *p) | |
| 1991/0711 | { | |
| 1991/0718 |
| |
| 1991/1004 | Page *pg; Page *next; | |
| 1991/0718 |
| |
| 1991/1004 | /* point 386 to protoype page map */ putcr3(ktoppg.pa); | |
| 1991/0718 |
| |
| 1991/1004 | /* 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; | |
| 1991/0711 | } | |
| 1991/1004 | /* * Add an entry into the mmu. */ #define FOURMEG (4*1024*1024) | |
| 1991/0711 | void | |
| 1991/0718 |
| |
| 1991/0711 |
| |
| 1991/0718 | putmmu(ulong va, ulong pa, Page *pg) | |
| 1991/0711 | { | |
| 1991/0718 | int topoff; | |
| 1991/1004 | ulong *top; | |
| 1991/0718 | ulong *pt; Proc *p; | |
| 1991/0723 |
| |
| 1991/1004 | char err[64]; | |
| 1991/0718 | ||
| 1991/0801 |
| |
| 1991/0718 | if(u==0) panic("putmmu"); | |
| 1991/1004 | ||
| 1991/0718 | p = u->p; | |
| 1991/1004 | 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); | |
| 1991/0718 | /* | |
| 1991/1004 | * if no top level page, allocate one and copy the prototype * into it. | |
| 1991/0718 | */ | |
| 1991/1004 | if(p->mmutop == 0){ p->mmutop = mmugetpage(0); memmove((void*)p->mmutop->va, (void*)ktoppg.va, BY2PG); } top = (ulong*)p->mmutop->va; | |
| 1991/0718 | /* | |
| 1991/1004 | * if bottom level page table missing, allocate one and point * the top level page at it. | |
| 1991/0718 | */ | |
| 1991/0801 |
| |
| 1991/0718 |
| |
| 1991/0719 |
| |
| 1991/0718 |
| |
| 1991/0801 |
| |
| 1991/1004 | 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; | |
| 1991/0718 | } /* | |
| 1991/1004 | * put in new mmu entry | |
| 1991/0718 | */ | |
| 1991/0801 |
| |
| 1991/1004 | pt = (ulong*)(PPN(top[topoff])|KZERO); | |
| 1991/0718 | pt[BTMOFF(va)] = pa | PTEUSER; | |
| 1991/0801 |
| |
| 1991/0718 | /* flush cached mmu entries */ | |
| 1991/1004 | putcr3(p->mmutop->pa); | |
| 1991/0711 | } void | |
| 1991/1003/sys/src/9/pc/mmu.c:271,277 – 1991/1004/sys/src/9/pc/mmu.c:347,353 | ||
| 1991/0718 | upt[0] = 0; /* flush cached mmu entries */ | |
| 1991/1004 | putcr3(ktoppg.pa); | |
| 1991/0703 | } void | |
| 1991/1004/sys/src/9/pc/mmu.c:297,302 – 1991/1005/sys/src/9/pc/mmu.c:297,303 (short | long) | ||
| 1991/0718 | ulong *pt; Proc *p; | |
| 1991/1004 | char err[64]; | |
| 1991/1005 | int x; | |
| 1991/0718 | if(u==0) panic("putmmu"); | |
| 1991/1004/sys/src/9/pc/mmu.c:313,320 – 1991/1005/sys/src/9/pc/mmu.c:314,329 | ||
| 1991/1004 | * into it. | |
| 1991/0718 | */ | |
| 1991/1004 | if(p->mmutop == 0){ | |
| 1991/1005 | /* * 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; | |
| 1991/1004 | } top = (ulong*)p->mmutop->va; | |
| 1991/0718 | ||
| 1991/1005/sys/src/9/pc/mmu.c:128,160 – 1991/1210/sys/src/9/pc/mmu.c:128,160 (short | long) | ||
| 1991/0716 | /* | |
| 1991/0717 | * set up system page tables. * map all of physical memory to start at KZERO. | |
| 1991/1210 | * map ROM BIOS at the usual place (F0000000). | |
| 1991/1004 | * leave a map entry for a user area. | |
| 1991/0716 | */ | |
| 1991/0719 |
| |
| 1991/1210 | /* allocate top level table */ top = ialloc(BY2PG, 1); ktoppg.va = (ulong)top; ktoppg.pa = ktoppg.va & ~KZERO; /* map all memory to KZERO */ | |
| 1991/0827 | npage = conf.base1/BY2PG + conf.npage1; | |
| 1991/0821 | 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++) | |
| 1991/0718 |
| |
| 1991/0821 |
| |
| 1991/0717 |
| |
| 1991/1004 |
| |
| 1991/1210 | kpt[i] = (0+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; | |
| 1991/0718 | x = TOPOFF(KZERO); | |
| 1991/0717 | y = ((ulong)kpt)&~KZERO; | |
| 1991/0718 | for(i = 0; i < nkpt; i++) | |
| 1991/1004 | top[x+i] = (y+i*BY2PG) | PTEVALID | PTEKERNEL | PTEWRITE; | |
| 1991/1210 | /* page table for u-> */ upt = ialloc(BY2PG, 1); | |
| 1991/0718 | x = TOPOFF(USERADDR); | |
| 1991/0717 | y = ((ulong)upt)&~KZERO; | |
| 1991/1004 | top[x] = y | PTEVALID | PTEKERNEL | PTEWRITE; | |
| 1991/1210 | ||
| 1991/1004 | putcr3(ktoppg.pa); | |
| 1991/0717 | ||
| 1991/0716 | /* | |
| 1991/1210/sys/src/9/pc/mmu.c:160,165 – 1991/1211/sys/src/9/pc/mmu.c:160,166 (short | long) | ||
| 1991/0716 | /* * set up the task segment */ | |
| 1991/1211 | memset(&tss, 0, sizeof(tss)); | |
| 1991/0718 | tss.sp0 = USERADDR+BY2PG; | |
| 1991/0717 | tss.ss0 = KDSEL; | |
| 1991/1004 | tss.cr3 = ktoppg.pa; | |
| 1991/1211/sys/src/9/pc/mmu.c:65,71 – 1991/1214/sys/src/9/pc/mmu.c:65,70 (short | long) | ||
| 1991/0717 | [KESEG] EXECSEGM(0), /* kernel code */ [UDSEG] DATASEGM(3), /* user data/stack */ [UESEG] EXECSEGM(3), /* user code */ | |
| 1991/0703 |
| |
| 1991/0717 | [TSSSEG] TSSSEGM(0,0), /* tss segment */ | |
| 1991/0613 | }; | |
| 1991/0703 | ||
| 1991/1211/sys/src/9/pc/mmu.c:87,105 – 1991/1214/sys/src/9/pc/mmu.c:86,91 | ||
| 1991/0718 | */ | |
| 1991/0719 | #define BTMOFF(v) (((v)>>(PGSHIFT))&(WD2PG-1)) | |
| 1991/0718 | ||
| 1991/0703 |
| |
| 1991/0719 |
| |
| 1991/1004 | /* * Create a prototype page map that maps all of memory into * kernel (KZERO) space. This is the default map. It is used | |
| 1991/1211/sys/src/9/pc/mmu.c:115,125 – 1991/1214/sys/src/9/pc/mmu.c:101,110 | ||
| 1991/1004 | ulong *top; | |
| 1991/0717 | ||
| 1991/0716 | /* | |
| 1991/1214 | * 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. | |
| 1991/0716 | */ | |
| 1991/0717 |
| |
| 1991/0718 | x = (ulong)&tss; | |
| 1991/0717 | gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss); gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP; | |
| 1991/1211/sys/src/9/pc/mmu.c:128,134 – 1991/1214/sys/src/9/pc/mmu.c:113,118 | ||
| 1991/0716 | /* | |
| 1991/0717 | * set up system page tables. * map all of physical memory to start at KZERO. | |
| 1991/1210 |
| |
| 1991/1004 | * leave a map entry for a user area. | |
| 1991/0716 | */ | |
| 1991/1211/sys/src/9/pc/mmu.c:358,367 – 1991/1214/sys/src/9/pc/mmu.c:342,345 | ||
| 1991/0718 | /* flush cached mmu entries */ | |
| 1991/1004 | putcr3(ktoppg.pa); | |
| 1991/0703 |
| |
| 1991/1214/sys/src/9/pc/mmu.c:53,59 – 1992/0116/sys/src/9/pc/mmu.c:53,59 (short | long) | ||
| 1991/0717 | #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),\ | |
| 1992/0116 | ((b)&0xFF000000)|(((b)>>16)&0xFF)|SEGTSS|SEGPL(p)|SEGP } | |
| 1991/0703 | /* | |
| 1991/0613 | * global descriptor table describing all segments | |
| 1992/0116/sys/src/9/pc/mmu.c:183,191 – 1992/0131/sys/src/9/pc/mmu.c:183,194 (short | long) | ||
| 1991/1004 | } /* | |
| 1992/0131 | * Put all bottom level page map pages on the process's free list and | |
| 1991/1004 | * call mapstack to set up the prototype page map. This * effectively forgets all of the process's mappings. | |
| 1992/0131 | * * Don't free the top level page. Just zero the used entries. This * avoids a 4k copy each flushmmu. | |
| 1991/1004 | */ | |
| 1991/0711 | void | |
| 1991/1004 | flushmmu(void) | |
| 1992/0116/sys/src/9/pc/mmu.c:193,198 – 1992/0131/sys/src/9/pc/mmu.c:196,202 | ||
| 1991/1004 | int s; Proc *p; Page *pg; | |
| 1992/0131 | ulong *top; | |
| 1991/1004 | if(u == 0) return; | |
| 1992/0116/sys/src/9/pc/mmu.c:199,211 – 1992/0131/sys/src/9/pc/mmu.c:203,215 | ||
| 1991/1004 | p = u->p; s = splhi(); | |
| 1992/0131 | 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; | |
| 1991/1004 | p->mmuused = 0; } mapstack(u->p); | |
| 1992/0116/sys/src/9/pc/mmu.c:227,241 – 1992/0131/sys/src/9/pc/mmu.c:231,244 | ||
| 1991/0928 | if(p->upage->va != (USERADDR|(p->pid&0xFFFF)) && p->pid != 0) | |
| 1991/0718 | panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va); | |
| 1991/1004 |
| |
| 1991/0718 |
| |
| 1991/1004 | /* tell processor about new page table (flushes cached entries) */ | |
| 1992/0131 | if(p->mmutop) pg = p->mmutop; else pg = &ktoppg; | |
| 1991/1004 | putcr3(pg->pa); | |
| 1991/0718 | u = (User*)USERADDR; | |
| 1992/0116/sys/src/9/pc/mmu.c:322,327 – 1992/0131/sys/src/9/pc/mmu.c:325,331 | ||
| 1991/1004 | top[topoff] = PPN(pg->pa) | PTEVALID | PTEUSER | PTEWRITE; pg->next = p->mmuused; p->mmuused = pg; | |
| 1992/0131 | pg->daddr = topoff; | |
| 1991/0718 | } /* | |
| Too many diffs (26 > 25). Stopping. | ||