| plan 9 kernel history: overview | file list | diff list |
1993/0812/power/mmu.c (diff list | history)
| power/mmu.c on 1990/0227 | ||
| 1990/0227 | #include "u.h" | |
| 1992/0321 | #include "../port/lib.h" | |
| 1990/0227 | #include "mem.h" #include "dat.h" #include "fns.h" void | |
| 1993/0501 | mmuswitch(Proc *p) | |
| 1990/0227 | { | |
| 1991/0705 | if(p->newtlb) { memset(p->pidonmach, 0, sizeof p->pidonmach); p->newtlb = 0; } | |
| 1993/0501 | if(p->pidonmach[m->machno] == 0) newtlbpid(p); | |
| 1991/0705 | ||
| 1993/0501 | putcontext(p->pidonmach[m->machno]); | |
| 1990/0227 | } | |
| 1991/0507 | void mmurelease(Proc *p) { memset(p->pidonmach, 0, sizeof p->pidonmach); } | |
| 1990/0227 | /* * Process must be non-interruptible */ int newtlbpid(Proc *p) { | |
| 1991/0425 | int i, s; | |
| 1990/0227 | Proc *sp; | |
| 1991/0425 | char *h; | |
| 1991/0426 | ||
| 1991/0425 | s = m->lastpid; if(s >= NTLBPID) s = 1; i = s; | |
| 1991/0501 | h = m->pidhere; do{ i++; if(i >= NTLBPID) i = 1; }while(h[i] && i != s); | |
| 1991/0425 | if(i == s){ | |
| 1991/0426 | i++; if(i >= NTLBPID) i = 1; | |
| 1991/0425 | } | |
| 1991/0501 | if(h[i]) purgetlb(i); | |
| 1992/1130 | ||
| 1990/0227 | sp = m->pidproc[i]; | |
| 1991/0501 | if(sp && sp->pidonmach[m->machno] == i) sp->pidonmach[m->machno] = 0; | |
| 1991/0430 | m->pidproc[i] = p; p->pidonmach[m->machno] = i; | |
| 1991/0501 | m->lastpid = i; | |
| 1990/0227 | return i; } void | |
| 1991/0705 | putmmu(ulong tlbvirt, ulong tlbphys, Page *pg) | |
| 1990/0227 | { short tp; | |
| 1991/0705 | char *ctl; | |
| 1990/0227 | splhi(); | |
| 1991/0705 | ctl = &pg->cachectl[m->machno]; | |
| 1993/0812 | if(*ctl == PG_TXTFLUSH) { | |
| 1991/0705 | dcflush((void*)pg->pa, BY2PG); icflush((void*)pg->pa, BY2PG); | |
| 1993/0806 | *ctl &= ~PG_TXTFLUSH; | |
| 1991/0705 | } | |
| 1993/0501 | tp = up->pidonmach[m->machno]; | |
| 1991/0430 | if(tp == 0) | |
| 1993/0501 | tp = newtlbpid(up); | |
| 1992/1130 | ||
| 1990/0227 | tlbvirt |= PTEPID(tp); | |
| 1991/0425 | putstlb(tlbvirt, tlbphys); | |
| 1990/0227 | puttlb(tlbvirt, tlbphys); m->pidhere[tp] = 1; spllo(); } void purgetlb(int pid) { | |
| 1991/0425 | Softtlb *entry, *etab; | |
| 1991/0501 | char *pidhere; | |
| 1991/0430 | Proc *sp, **pidproc; int i, rpid, mno; | |
| 1991/0501 | char dead[NTLBPID]; | |
| 1990/0227 | ||
| 1991/0425 | m->tlbpurge++; | |
| 1991/0501 | /* * find all pid entries that are no longer used by processes */ mno = m->machno; pidproc = m->pidproc; memset(dead, 0, sizeof dead); for(i=1; i<NTLBPID; i++){ sp = pidproc[i]; if(!sp || sp->pidonmach[mno] != i){ pidproc[i] = 0; dead[i] = 1; } } dead[pid] = 1; /* * clean out all dead pids from the stlb; | |
| 1992/1130 | * garbage collect pids with no entries | |
| 1991/0501 | */ | |
| 1991/0426 | memset(m->pidhere, 0, sizeof m->pidhere); | |
| 1991/0501 | pidhere = m->pidhere; | |
| 1991/0425 | entry = m->stb; etab = &entry[STLBSIZE]; for(; entry < etab; entry++){ rpid = TLBPID(entry->virt); | |
| 1991/0501 | if(dead[rpid]) | |
| 1991/0425 | entry->virt = 0; | |
| 1991/0501 | else pidhere[rpid] = 1; | |
| 1990/0227 | } | |
| 1991/0501 | /* * clean up the hardware */ | |
| 1991/0430 | for(i=TLBROFF; i<NTLB; i++) | |
| 1991/0501 | if(!pidhere[TLBPID(gettlbvirt(i))]) | |
| 1991/0430 | puttlbx(i, KZERO | PTEPID(i), 0); | |
| 1990/0227 | } void flushmmu(void) { splhi(); | |
| 1993/0501 | up->newtlb = 1; mmuswitch(up); | |
| 1990/0227 | spllo(); } | |
| 1990/1211 | void clearmmucache(void) { | |
| 1991/0425 | } void putstlb(ulong tlbvirt, ulong tlbphys) { Softtlb *entry; | |
| 1992/1130 | /* This hash function is also coded into utlbmiss in l.s */ | |
| 1991/0425 | entry = &m->stb[((tlbvirt<<1) ^ (tlbvirt>>12)) & (STLBSIZE-1)]; entry->phys = tlbphys; entry->virt = tlbvirt; if(tlbphys == 0) entry->virt = 0; | |
| 1990/1211 | } | |