1*62641Shibler #ifndef lint 2*62641Shibler static char sccsid[] = "@(#)access.c 4.8 10/13/84"; 3*62641Shibler #endif 4*62641Shibler /* 5*62641Shibler * Adb: access data in file/process address space. 6*62641Shibler * 7*62641Shibler * The routines in this file access referenced data using 8*62641Shibler * the maps to access files, ptrace to access subprocesses, 9*62641Shibler * or the system page tables when debugging the kernel, 10*62641Shibler * to translate virtual to physical addresses. 11*62641Shibler */ 12*62641Shibler 13*62641Shibler #include "defs.h" 14*62641Shibler 15*62641Shibler 16*62641Shibler MAP txtmap; 17*62641Shibler MAP datmap; 18*62641Shibler INT wtflag; 19*62641Shibler STRING errflg; 20*62641Shibler int errno; 21*62641Shibler 22*62641Shibler INT pid; 23*62641Shibler 24*62641Shibler /* 25*62641Shibler * Primitives: put a value in a space, get a value from a space 26*62641Shibler * and get a word or byte not returning if an error occurred. 27*62641Shibler */ 28*62641Shibler put(addr, space, value) 29*62641Shibler off_t addr; { (void) access(WT, addr, space, value); } 30*62641Shibler 31*62641Shibler #if vax || pdp11 32*62641Shibler u_int 33*62641Shibler get(addr, space) 34*62641Shibler off_t addr; { return (access(RD, addr, space, 0)); } 35*62641Shibler 36*62641Shibler u_int 37*62641Shibler lchkget(addr, space) 38*62641Shibler off_t addr; { u_int w = get(addr, space); chkerr(); return(w); } 39*62641Shibler #endif 40*62641Shibler 41*62641Shibler #ifdef mc68000 42*62641Shibler /* 43*62641Shibler * 68000 Unices don't like odd addresses. 44*62641Shibler */ 45*62641Shibler u_int 46*62641Shibler get(addr, space) 47*62641Shibler off_t addr; 48*62641Shibler { 49*62641Shibler u_int data; 50*62641Shibler 51*62641Shibler if (addr & 1) { 52*62641Shibler data = access(RD, addr - 1, space, 0); 53*62641Shibler return ((data >> 8) & 0xffff); 54*62641Shibler } 55*62641Shibler data = access(RD, addr, space, 0); 56*62641Shibler return ((data >> 16) & 0xffff); 57*62641Shibler } 58*62641Shibler 59*62641Shibler u_int 60*62641Shibler lget(addr, space) 61*62641Shibler off_t addr; 62*62641Shibler { 63*62641Shibler if (addr & 1) { 64*62641Shibler u_int data = get(addr, space); 65*62641Shibler return (get(addr + 2, space) | (data << 16)); 66*62641Shibler } 67*62641Shibler return (access(RD, addr, space, 0)); 68*62641Shibler } 69*62641Shibler 70*62641Shibler u_int 71*62641Shibler lchkget(addr, space) 72*62641Shibler off_t addr; { u_int w = lget(addr, space); chkerr(); return(w); } 73*62641Shibler #endif 74*62641Shibler 75*62641Shibler #if !pdp11 && !vax && !mc68000 76*62641Shibler help! 77*62641Shibler #endif 78*62641Shibler 79*62641Shibler u_int 80*62641Shibler chkget(addr, space) 81*62641Shibler off_t addr; { u_int w = get(addr, space); chkerr(); return(w); } 82*62641Shibler 83*62641Shibler u_int 84*62641Shibler bchkget(addr, space) 85*62641Shibler off_t addr; { return(lobyte(chkget(addr, space))); } 86*62641Shibler 87*62641Shibler /* 88*62641Shibler * Read/write according to mode at address addr in i/d space. 89*62641Shibler * Value is quantity to be written, if write. 90*62641Shibler * 91*62641Shibler * This routine decides whether to get the data from the subprocess 92*62641Shibler * address space with ptrace, or to get it from the files being 93*62641Shibler * debugged. 94*62641Shibler * 95*62641Shibler * When the kernel is being debugged with the -k flag we interpret 96*62641Shibler * the system page tables for data space, mapping p0 and p1 addresses 97*62641Shibler * relative to the ``current'' process (as specified by its p_addr in 98*62641Shibler * <p) and mapping system space addresses through the system page tables. 99*62641Shibler */ 100*62641Shibler access(mode, addr, space, value) 101*62641Shibler int mode, space, value; 102*62641Shibler off_t addr; 103*62641Shibler { 104*62641Shibler int rd = mode == RD; 105*62641Shibler int file, w; 106*62641Shibler 107*62641Shibler if (space == NSP) 108*62641Shibler return(0); 109*62641Shibler if (pid) { 110*62641Shibler int pmode = (space&DSP ? 111*62641Shibler (rd ? PT_READ_D : PT_WRITE_D) : 112*62641Shibler (rd ? PT_READ_I : PT_WRITE_I)); 113*62641Shibler 114*62641Shibler w = ptrace(pmode, pid, addr, value); 115*62641Shibler if (errno) 116*62641Shibler rwerr(space); 117*62641Shibler return (w); 118*62641Shibler } 119*62641Shibler w = 0; 120*62641Shibler if (mode==WT && wtflag==0) 121*62641Shibler error("not in write mode"); 122*62641Shibler if (!chkmap(&addr, space)) 123*62641Shibler return (0); 124*62641Shibler file = mapptr(space)->ufd; 125*62641Shibler if (kernel && space == DSP) { 126*62641Shibler addr = vtophys(addr); 127*62641Shibler if (addr == -1) 128*62641Shibler return (0); 129*62641Shibler } 130*62641Shibler if (physrw(file, addr, rd ? &w : &value, rd) < 0) 131*62641Shibler rwerr(space); 132*62641Shibler return (w); 133*62641Shibler } 134*62641Shibler 135*62641Shibler #ifdef vax 136*62641Shibler /* 137*62641Shibler * When looking at kernel data space through /dev/mem or 138*62641Shibler * with a core file, do virtual memory mapping. 139*62641Shibler */ 140*62641Shibler vtophys(addr) 141*62641Shibler off_t addr; 142*62641Shibler { 143*62641Shibler int oldaddr = addr; 144*62641Shibler int v; 145*62641Shibler struct pte pte; 146*62641Shibler 147*62641Shibler addr &= ~0xc0000000; 148*62641Shibler v = btop(addr); 149*62641Shibler switch (oldaddr&0xc0000000) { 150*62641Shibler 151*62641Shibler case 0xc0000000: 152*62641Shibler case 0x80000000: 153*62641Shibler /* 154*62641Shibler * In system space get system pte. If 155*62641Shibler * valid or reclaimable then physical address 156*62641Shibler * is combination of its page number and the page 157*62641Shibler * offset of the original address. 158*62641Shibler */ 159*62641Shibler if (v >= slr) 160*62641Shibler goto oor; 161*62641Shibler addr = ((long)(sbr+v)) &~ 0x80000000; 162*62641Shibler goto simple; 163*62641Shibler 164*62641Shibler case 0x40000000: 165*62641Shibler /* 166*62641Shibler * In p1 space must not be in shadow region. 167*62641Shibler */ 168*62641Shibler if (v < pcb.pcb_p1lr) 169*62641Shibler goto oor; 170*62641Shibler addr = pcb.pcb_p1br+v; 171*62641Shibler break; 172*62641Shibler 173*62641Shibler case 0x00000000: 174*62641Shibler /* 175*62641Shibler * In p0 space must not be off end of region. 176*62641Shibler */ 177*62641Shibler if (v >= pcb.pcb_p0lr) 178*62641Shibler goto oor; 179*62641Shibler addr = pcb.pcb_p0br+v; 180*62641Shibler break; 181*62641Shibler oor: 182*62641Shibler errflg = "address out of segment"; 183*62641Shibler return (-1); 184*62641Shibler } 185*62641Shibler /* 186*62641Shibler * For p0/p1 address, user-level page table should 187*62641Shibler * be in kernel vm. Do second-level indirect by recursing. 188*62641Shibler */ 189*62641Shibler if ((addr & 0x80000000) == 0) { 190*62641Shibler errflg = "bad p0br or p1br in pcb"; 191*62641Shibler return (-1); 192*62641Shibler } 193*62641Shibler addr = vtophys(addr); 194*62641Shibler simple: 195*62641Shibler /* 196*62641Shibler * Addr is now address of the pte of the page we 197*62641Shibler * are interested in; get the pte and paste up the 198*62641Shibler * physical address. 199*62641Shibler */ 200*62641Shibler if (physrw(fcor, addr, (int *)&pte, 1) < 0) { 201*62641Shibler errflg = "page table botch"; 202*62641Shibler return (-1); 203*62641Shibler } 204*62641Shibler /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */ 205*62641Shibler if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) { 206*62641Shibler errflg = "page not valid/reclaimable"; 207*62641Shibler return (-1); 208*62641Shibler } 209*62641Shibler return (ptob(pte.pg_pfnum) + (oldaddr & PGOFSET)); 210*62641Shibler } 211*62641Shibler #endif 212*62641Shibler 213*62641Shibler #ifdef hp300 214*62641Shibler 215*62641Shibler #ifdef NEWVM 216*62641Shibler #ifndef btop 217*62641Shibler #define btop hp300_btop 218*62641Shibler #endif 219*62641Shibler #ifndef ptob 220*62641Shibler #define ptob hp300_ptob 221*62641Shibler #endif 222*62641Shibler #endif 223*62641Shibler 224*62641Shibler int is68040 = 0; 225*62641Shibler 226*62641Shibler /* 227*62641Shibler * When looking at kernel data space through /dev/mem or 228*62641Shibler * with a core file, do virtual memory mapping. 229*62641Shibler */ 230*62641Shibler vtophys(addr) 231*62641Shibler off_t addr; 232*62641Shibler { 233*62641Shibler int v; 234*62641Shibler struct pte pte; 235*62641Shibler int oldaddr = addr; 236*62641Shibler 237*62641Shibler if (INKERNEL(addr)) { 238*62641Shibler /* 239*62641Shibler * In system space get system pte. If 240*62641Shibler * valid or reclaimable then physical address 241*62641Shibler * is combination of its page number and the page 242*62641Shibler * offset of the original address. 243*62641Shibler */ 244*62641Shibler #ifdef NEWVM 245*62641Shibler /* locate PTE page in segtab */ 246*62641Shibler if (is68040) { 247*62641Shibler int steaddr; 248*62641Shibler 249*62641Shibler steaddr = KVTOPH((int)(sbr+(addr>>SG4_SHIFT1))); 250*62641Shibler lseek(fcor, (off_t)steaddr, 0); 251*62641Shibler read(fcor, &pte, sizeof pte); 252*62641Shibler #if 0 253*62641Shibler printf("va %X: ste1 %X@%X", 254*62641Shibler addr, *(int *)&pte, steaddr); 255*62641Shibler #endif 256*62641Shibler if (*(int *)&pte == SG_NV) 257*62641Shibler goto bad; 258*62641Shibler steaddr = (int)(((int *)(*(int *)&pte & SG4_ADDR1)) + 259*62641Shibler ((addr & SG4_MASK2) >> SG4_SHIFT2)); 260*62641Shibler physrw(fcor, steaddr, (int *)&pte, 1); 261*62641Shibler #if 0 262*62641Shibler printf(" ste2 %X@%X", *(int *)&pte, steaddr); 263*62641Shibler #endif 264*62641Shibler } else { 265*62641Shibler lseek(fcor, 266*62641Shibler (off_t)KVTOPH((int)(sbr+(addr>>SG_ISHIFT))), 0); 267*62641Shibler read(fcor, &pte, sizeof pte); 268*62641Shibler #if 0 269*62641Shibler printf("va %X: ste %X@%X", 270*62641Shibler addr, *(int *)&pte, sbr+(addr>>SG_ISHIFT)); 271*62641Shibler #endif 272*62641Shibler } 273*62641Shibler /* see if STE is valid */ 274*62641Shibler if (*(int *)&pte == SG_NV) { 275*62641Shibler bad: 276*62641Shibler errflg = "address out of segment"; 277*62641Shibler return(-1); 278*62641Shibler } 279*62641Shibler /* desired PTE is within that page */ 280*62641Shibler v = btop(addr & SG_PMASK); 281*62641Shibler addr = (pte.pg_pfnum << PGSHIFT) + (v * sizeof pte); 282*62641Shibler #else 283*62641Shibler v = btop(addr - KERNOFF); 284*62641Shibler addr = (long)(sbr+v) + lowram; 285*62641Shibler #endif 286*62641Shibler } 287*62641Shibler else if (INUDOT(addr)) { 288*62641Shibler addr -= kernudot; 289*62641Shibler addr += masterpcbb; 290*62641Shibler return(vtophys(addr)); 291*62641Shibler } 292*62641Shibler else /* user space */ { 293*62641Shibler #ifdef NEWVM 294*62641Shibler errflg = "cannot translate user addresses"; 295*62641Shibler return (-1); 296*62641Shibler #else 297*62641Shibler v = btop(addr); 298*62641Shibler /* 299*62641Shibler * Must be within bounds of p0 or p1 regions. 300*62641Shibler */ 301*62641Shibler if (v < pcb.pcb_p0lr) 302*62641Shibler addr = pcb.pcb_p0br+v; 303*62641Shibler else if (v >= pcb.pcb_p1lr) 304*62641Shibler addr = pcb.pcb_p1br+v; 305*62641Shibler else { 306*62641Shibler errflg = "address out of segment"; 307*62641Shibler return (-1); 308*62641Shibler } 309*62641Shibler /* 310*62641Shibler * For p0/p1 address, user-level page table should 311*62641Shibler * be in kernel vm. Do second-level indirect by recursing. 312*62641Shibler */ 313*62641Shibler if (!INKERNEL(addr)) { 314*62641Shibler errflg = "bad p0br or p1br in pcb"; 315*62641Shibler return (-1); 316*62641Shibler } 317*62641Shibler addr = vtophys(addr); 318*62641Shibler #endif 319*62641Shibler } 320*62641Shibler /* 321*62641Shibler * Addr is now address of the pte of the page we 322*62641Shibler * are interested in; get the pte and paste up the 323*62641Shibler * physical address. 324*62641Shibler */ 325*62641Shibler if (physrw(fcor, addr, (int *)&pte, 1) < 0) { 326*62641Shibler errflg = "page table botch"; 327*62641Shibler return (-1); 328*62641Shibler } 329*62641Shibler if (pte.pg_v == 0 && 330*62641Shibler #ifdef NEWVM 331*62641Shibler pte.pg_pfnum == 0 332*62641Shibler #else 333*62641Shibler (pte.pg_fod || pte.pg_pfnum == 0) 334*62641Shibler #endif 335*62641Shibler ) { 336*62641Shibler errflg = "page not valid/reclaimable"; 337*62641Shibler return (-1); 338*62641Shibler } 339*62641Shibler #if 0 340*62641Shibler printf(" -> pte %X@%X -> addr %X\n", 341*62641Shibler *(int *)&pte, addr, ptob(pte.pg_pfnum) + (oldaddr & PGOFSET)); 342*62641Shibler #endif 343*62641Shibler return (ptob(pte.pg_pfnum) + (oldaddr & PGOFSET)); 344*62641Shibler } 345*62641Shibler #endif 346*62641Shibler 347*62641Shibler #if !vax && !hp300 348*62641Shibler help! 349*62641Shibler #endif 350*62641Shibler 351*62641Shibler rwerr(space) 352*62641Shibler int space; 353*62641Shibler { 354*62641Shibler 355*62641Shibler if (space & DSP) 356*62641Shibler errflg = "data address not found"; 357*62641Shibler else if (space & PSP) 358*62641Shibler errflg = "physical address not found"; 359*62641Shibler else 360*62641Shibler errflg = "text address not found"; 361*62641Shibler } 362*62641Shibler 363*62641Shibler physrw(file, addr, aw, rd) 364*62641Shibler off_t addr; 365*62641Shibler int *aw, rd; 366*62641Shibler { 367*62641Shibler 368*62641Shibler #ifdef hp300 369*62641Shibler if (kcore && !kmem && file == fcor) 370*62641Shibler addr -= lowram; 371*62641Shibler #endif 372*62641Shibler if (longseek(file,addr)==0 || 373*62641Shibler (rd ? read(file,aw,sizeof(int)) : write(file,aw,sizeof(int))) < 1) 374*62641Shibler return (-1); 375*62641Shibler return (0); 376*62641Shibler } 377*62641Shibler 378*62641Shibler chkmap(addr,space) 379*62641Shibler REG L_INT *addr; 380*62641Shibler REG INT space; 381*62641Shibler { 382*62641Shibler REG MAPPTR amap; 383*62641Shibler amap = mapptr(space); 384*62641Shibler IF space&STAR ORF !within(*addr,amap->b1,amap->e1) 385*62641Shibler THEN IF within(*addr,amap->b2,amap->e2) 386*62641Shibler THEN *addr += (amap->f2)-(amap->b2); 387*62641Shibler ELSE rwerr(space); return(0); 388*62641Shibler FI 389*62641Shibler ELSE *addr += (amap->f1)-(amap->b1); 390*62641Shibler FI 391*62641Shibler return(1); 392*62641Shibler } 393*62641Shibler 394*62641Shibler within(addr,lbd,ubd) 395*62641Shibler u_int addr, lbd, ubd; { return(addr>=lbd && addr<ubd); } 396*62641Shibler 397*62641Shibler longseek(f, a) 398*62641Shibler off_t a; { return(lseek(f, a, 0) != -1); } 399