#include "sys/param.h" #include "sys/systm.h" #include "sys/dir.h" #include "sys/user.h" #include "sys/inode.h" #include "sys/proc.h" #include "sys/seg.h" #include "sys/map.h" #include "sys/reg.h" #include "sys/psl.h" #include "sys/utsname.h" #include "sys/mtpr.h" #include "sys/clock.h" #include "sys/page.h" /* * Machine-dependent startup code */ startup(firstaddr) { register i, n; register mbase; extern long mempte[]; /* * Initialize maps */ printf("\nUNIX/%s: %s%s\n", utsname.release, utsname.sysname, utsname.version); printf("real mem = %d\n", maxmem*ctob(1) ); n = (maxmem + 0xfff) >> 12; mbase = firstaddr + USIZE; for (i=0; i<n; i++) mempte[i] = PG_V|PG_KW|mbase++; meminit(mbase, maxmem); maxmem -= mbase + 1; printf("avail mem = %d\n", maxmem*ctob(1)); if(MAXMEM < maxmem) maxmem = MAXMEM; mfree(swapmap, nswap, 1); swplo--; mbainit(); /* setup mba mapping regs map */ ubainit(); /* setup uba mapping regs map */ } /* * Start clock */ clkstart() { mtpr(NICR, -16667); /* 16.667 milli-seconds */ mtpr(ICCS,ICCS_RUN+ICCS_IE+ICCS_TRANS+ICCS_INT+ICCS_ERR); } clkset(oldtime) time_t oldtime; { time = udiv(mfpr(TODR),100); while (time < oldtime) time += SECYR; } clkreld() { mtpr(ICCS, ICCS_RUN + ICCS_IE + ICCS_INT + ICCS_ERR); } /* * Send an interrupt to process */ sendsig(p, n) { register int *usp, *regs; register int mask, r, spa, t; int *s; regs = u.u_ar0; usp = (int *)regs[SP]; grow((unsigned)(usp-20)); mask = (fuword(p) & 0xfff) | 0x3f; /* get register save mask (save r0-r5) */ suword( (caddr_t) --usp, n); /* sig # as param */ suword( (caddr_t) --usp, 1); /* one parameters */ s = usp; spa = ((int) usp) & 0x3; if (spa) usp = (int *)((int) (usp - 1) & ~ 0x3); t = 11; for (r=0x800; r; r>>=1) { if (mask & r) suword((caddr_t) --usp, regs[t]); t--; } suword( (caddr_t) --usp, regs[PC]); suword( (caddr_t) --usp, regs[FP]); suword( (caddr_t) --usp, regs[AP]); suword( (caddr_t) --usp, (spa << 30) | (0x2 << 28) | (mask << 16) | (regs[PS] & 0xffff)); suword( (caddr_t) --usp, 0); regs[SP] = (int)usp; regs[FP] = (int)usp; regs[AP] = (int)s; regs[PC] = p + 2; regs[PS] &= ~(PS_CM|PS_FPD|PS_T|PS_N|PS_Z|PS_V|PS_C); } mtpr(regno, value) { asm(" mtpr 8(ap),4(ap)"); } mfpr(regno) { asm(" mfpr 4(ap),r0"); } /* * copy count bytes from from to to. */ bcopy(from, to, count) caddr_t from, to; { asm(" movc3 12(ap),*4(ap),*8(ap)"); } /* * create a duplicate copy of a process */ procdup(p) register struct proc *p; { extern int forkutl[], Forkmap[]; register int i, *ip, *jp, *kp; if (memall(Forkmap,USIZE) == 0) return(NULL); /* no memory available */ /* make u-area and page tables addressable */ for( i=USIZE; --i>=0; ) { Forkmap[i] |= PG_V|PG_KW; mtpr(TBIS, forkutl + 128*i); } if (u.u_dsize) if (memall(&forkutl[UPAGES*128+u.u_tsize],u.u_dsize) == 0) { memfree(Forkmap,USIZE); return(NULL); } if (u.u_ssize) if (memall(&forkutl[USIZE*128-u.u_ssize],u.u_ssize) == 0) { memfree(&forkutl[UPAGES*128+u.u_tsize],u.u_dsize); memfree(Forkmap,USIZE); return(NULL); } /* copy the u-area */ bcopy(&u, forkutl, ctob(UPAGES)); /* copy the data segment */ ip = ((int *)&u) + UPAGES*128 + u.u_tsize; jp = ip + u.u_dsize; kp = forkutl + UPAGES*128 + u.u_tsize; while(ip < jp) { copyseg(*ip++&PG_PFNUM, *kp); *kp++ |= PG_V|PG_UW; } /* copy stack segment */ jp = ((int *)&u) + USIZE*128; ip = jp - u.u_ssize; kp = forkutl + USIZE*128 - u.u_ssize; while(ip < jp) { copyseg(*ip++&PG_PFNUM, *kp); *kp++ |= PG_V|PG_UW; } /* copy text page table entries */ bcopy( ((int *)&u) + UPAGES*128, forkutl + UPAGES*128, sizeof(struct pt_entry)*u.u_tsize); /* clear unused page taple entries */ ip = forkutl + UPAGES*128 + u.u_tsize + u.u_dsize; jp = forkutl + USIZE*128 - u.u_ssize; while(ip < jp) *ip++ = 0; /* store page numbers of new page table in new u-area */ for(i=u.u_pcb.pcb_szpt; --i>=0; ) ((struct user *)forkutl)->u_ptable[i] = (Forkmap+UPAGES)[i] & PG_PFNUM; /* store page numbers of new u-area in proc */ for(i=UPAGES; --i>=0; ) p->p_addr[i] = Forkmap[i]; return(1); } /* * change protection codes of a segment */ chgprot(text, data, stack) { register *ptaddr, i; if (text || data) { ptaddr = (int *)mfpr(P0BR); if (text) for(i=0; i<u.u_tsize; i++) { ptaddr[i] &= ~PG_PROT; /* clear prot bits */ ptaddr[i] |= PG_V|text; mtpr(TBIS, ctob(i)); } if (data) for(i=u.u_tsize; i<u.u_tsize+u.u_dsize; i++) { ptaddr[i] &= ~PG_PROT; /* clear prot bits */ ptaddr[i] |= PG_V|data; mtpr(TBIS, ctob(i)); } } if (stack) { ptaddr = (int *)(mfpr(P1BR) + 4 * mfpr(P1LR)); for(i=0; i<u.u_ssize; i++) { ptaddr[i] &= ~PG_PROT; /* clear prot bits */ ptaddr[i] |= PG_V|stack; mtpr(TBIS, 0x80000000-ctob(u.u_ssize-i)); } } } chksize(text, data, stack) { if ((text + data + stack) > MAXUMEM || text + data + stack + UPAGES + MAXUMEM/128 > maxmem) { u.u_error = ENOMEM; return(-1); } return(0); } /* * expand a page table */ ptexpand(change) register int change; { register int *p1, *p2, i, movept; int newpt[MAXUMEM/128]; extern int Umap[]; if (change <= 0) return(change); if (change > MAXUMEM/128 || memall(newpt,change) == 0) return(-1); /* calculate where stack entries start */ movept = (0x200000 - mfpr(P1LR))/128; /* copy the stack page table pages down */ for(i=0; i<movept; i++) { Umap[USIZE+change-1-i] = Umap[USIZE-1-i]; mtpr(TBIS, ((int)&u) + 512*(USIZE+change-1-i)); } /* insert and clear new pages */ for(i=0; i<change; i++) { Umap[USIZE-movept+i] = newpt[i] | (PG_V|PG_KW); mtpr(TBIS,((int)&u) + 512*(USIZE-movept+i)); clearseg(newpt[i]); } /* copy any stack entries to new page, then clear entry */ p1 = (int *)mfpr(P1BR); p1 += mfpr(P1LR); p2 = p1 + 128*change; while ((int)p1 & 0x1ff) { *p2++ = *p1; *p1++ = 0; } /* fixup page table numbers in u-area */ for(i=u.u_pcb.pcb_szpt+change; --i>=0; ) u.u_ptable[i] = (Umap+UPAGES)[i] & PG_PFNUM; u.u_pcb.pcb_szpt += change; /* new number of page tables */ u.u_pcb.pcb_p1br = mfpr(P1BR) + 512*change; mtpr(P1BR, u.u_pcb.pcb_p1br); mtpr(TBIA,0); return(change); } /* * make u-area and page tables addressable */ ptaccess(p, map, addr) register struct proc *p; register int map[], addr[]; { register int i; /* make u-area addressable */ for(i=UPAGES; --i>=0; ) { map[i] = p->p_addr[i] | (PG_V|PG_KW); mtpr(TBIS, addr + 128*i); } /* make page tables addressable */ for(i=((struct user *)addr)->u_pcb.pcb_szpt; --i>=0; ) { (map+UPAGES)[i] = ((struct user *)addr)->u_ptable[i] | (PG_V|PG_KW); mtpr(TBIS, addr + 128*(i+UPAGES)); } } char *macher[] = { "CP Read Timeout", "-", "CP Translation Buffer Parity Error", "CP Cache Parity Error", "-", "CP Read Data Substitute", "-", "-", "-", "-", "IB Translation Buffer Parity Error", "-", "IB Read Data Substitute", "IB Read Timeout", "-", "IB Cache Parity Error", "Control Store Parity Error", "CP Translation Buffer Parity Error", "CP Cache Parity Error", "CP Read Timeout", "CP Read Data Substitute", "Microcode lost" }; macheck(type,ces,upc,vaddr,dr,tb0,tb1,paddr,par,sbi,pc,psl) { printf("\nMachine check, type %x\n",type); if ((type&0xf0)==0) printf("%s Fault\n",macher[type&0xf]); else printf("%s Abort\n",macher[16+(type&0xf)]); printf("pc = %x, psl = %x\n",pc, psl); printf("virtual/physical addr = %x/%x\n",vaddr,paddr<<2); printf("ces = %x, sbi = %x\n",ces,sbi); }