- IF pid /* tracing on? */
- THEN
-#ifndef vax
- IF adr&01 ANDF !rd THEN error(ODDADR); FI
-#endif
- pmode = (space&DSP?(rd?RDUSER:WDUSER):(rd?RIUSER:WIUSER));
- w = ptrace(pmode, pid, adr, value);
-#ifndef vax
- IF adr&01
- THEN w1 = ptrace(pmode, pid, shorten(adr+1), value);
- w = (w>>8)&LOBYTE | (w1<<8);
- FI
-#endif
- IF errno
- THEN errflg = (space&DSP ? BADDAT : BADTXT);
- FI
- return(w);
- FI
- w = 0;
- IF mode==WT ANDF wtflag==0
- THEN error("not in write mode");
- FI
- IF !chkmap(&adr,space)
- THEN return(0);
- FI
- file=(space&DSP?datmap.ufd:txtmap.ufd);
- IF kernel && space == DSP THEN
- int oadr = adr;
- int v;
- adr &= ~0x80000000;
- IF oadr&0x80000000 THEN /* system space */
- v = btop(adr);
- dprintf("system addr %X, v %X\n", adr, v);
- IF v >= slr THEN errflg="bad system space addr"; return (0); FI
- adr = vtoa(file, adr);
- IF adr == -1 THEN
- errflg="sys page table page not valid"; return (0); FI
- ELIF adr&0x40000000 THEN /* p1 space */
- v = btop(adr&~0x40000000);
- dprintf("p1 addr %X, v %X, p1br %X p1lr %X\n", adr, v,
- pcb.pcb_p1br, pcb.pcb_p1lr);
- IF v < pcb.pcb_p1lr THEN
- errflg="bad p1 space addr"; return (0); FI
- adr = vtoa(file, pcb.pcb_p1br+v);
- IF adr == -1 THEN
- errflg="p1 page table page not valid"; return (0); FI
- goto get;
- ELSE /* p0 space */
- dprintf("p0 addr %X, v %X, p0br %X p0lr %X\n", adr,
- v, pcb.pcb_p0br, pcb.pcb_p0lr);
- IF v >= pcb.pcb_p0lr THEN
- errflg="bad p0 space addr"; return (0); FI
- adr = vtoa(file, pcb.pcb_p0br+v);
- IF adr == -1 THEN
- errflg="p0 page table page not valid"; return (0); FI
-get:
- dprintf("addr for pt page %X\n", adr);
- IF physrw(file, adr, &adr, 1) < 0 THEN
- errflg = "page tables botched"; return (0); FI
- dprintf("user pte value %X\n", adr);
- IF (adr & PG_V) == 0 &&
- ((adr & PG_FOD) || (adr & PG_PFNUM) == 0) THEN
- errflg = "user page not resident"; return (0);
- FI
- adr = ((adr & 0xfffff) << 9) | (oadr & 0x1ff);
- FI
- FI
- IF physrw(file, adr, &w, rd) < 0 THEN
- errflg=(space&DSP?BADDAT:BADTXT);
- FI
- return(w);
+ addr &= ~0xc0000000;
+ v = btop(addr);
+ switch (oldaddr&0xc0000000) {
+
+ case 0xc0000000:
+ case 0x80000000:
+ /*
+ * In system space get system pte. If
+ * valid or reclaimable then physical address
+ * is combination of its page number and the page
+ * offset of the original address.
+ */
+ if (v >= slr)
+ goto oor;
+ addr = ((long)(sbr+v)) &~ 0x80000000;
+ goto simple;
+
+ case 0x40000000:
+ /*
+ * In p1 space must not be in shadow region.
+ */
+ if (v < pcb.pcb_p1lr)
+ goto oor;
+ addr = pcb.pcb_p1br+v;
+ break;
+
+ case 0x00000000:
+ /*
+ * In p0 space must not be off end of region.
+ */
+ if (v >= pcb.pcb_p0lr)
+ goto oor;
+ addr = pcb.pcb_p0br+v;
+ break;
+ oor:
+ errflg = "address out of segment";
+ return (-1);
+ }
+ /*
+ * For p0/p1 address, user-level page table should
+ * be in kernel vm. Do second-level indirect by recursing.
+ */
+ if ((addr & 0x80000000) == 0) {
+ errflg = "bad p0br or p1br in pcb";
+ return (-1);
+ }
+ addr = vtophys(addr);
+simple:
+ /*
+ * Addr is now address of the pte of the page we
+ * are interested in; get the pte and paste up the
+ * physical address.
+ */
+ if (physrw(fcor, addr, (int *)&pte, 1) < 0) {
+ errflg = "page table botch";
+ return (-1);
+ }
+ /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */
+ if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) {
+ errflg = "page not valid/reclaimable";
+ return (-1);
+ }
+ return (ptob(pte.pg_pfnum) + (oldaddr & PGOFSET));