162641Shibler #ifndef lint
262641Shibler static char sccsid[] = "@(#)access.c 4.8 10/13/84";
362641Shibler #endif
462641Shibler /*
562641Shibler * Adb: access data in file/process address space.
662641Shibler *
762641Shibler * The routines in this file access referenced data using
862641Shibler * the maps to access files, ptrace to access subprocesses,
962641Shibler * or the system page tables when debugging the kernel,
1062641Shibler * to translate virtual to physical addresses.
1162641Shibler */
1262641Shibler
1362641Shibler #include "defs.h"
1462641Shibler
1562641Shibler
1662641Shibler MAP txtmap;
1762641Shibler MAP datmap;
1862641Shibler INT wtflag;
1962641Shibler STRING errflg;
2062641Shibler int errno;
2162641Shibler
2262641Shibler INT pid;
2362641Shibler
2462641Shibler /*
2562641Shibler * Primitives: put a value in a space, get a value from a space
2662641Shibler * and get a word or byte not returning if an error occurred.
2762641Shibler */
put(addr,space,value)2862641Shibler put(addr, space, value)
2962641Shibler off_t addr; { (void) access(WT, addr, space, value); }
3062641Shibler
3162641Shibler #if vax || pdp11
3262641Shibler u_int
get(addr,space)3362641Shibler get(addr, space)
3462641Shibler off_t addr; { return (access(RD, addr, space, 0)); }
3562641Shibler
3662641Shibler u_int
lchkget(addr,space)3762641Shibler lchkget(addr, space)
3862641Shibler off_t addr; { u_int w = get(addr, space); chkerr(); return(w); }
3962641Shibler #endif
4062641Shibler
4162641Shibler #ifdef mc68000
4262641Shibler /*
4362641Shibler * 68000 Unices don't like odd addresses.
4462641Shibler */
4562641Shibler u_int
get(addr,space)4662641Shibler get(addr, space)
4762641Shibler off_t addr;
4862641Shibler {
4962641Shibler u_int data;
5062641Shibler
5162641Shibler if (addr & 1) {
5262641Shibler data = access(RD, addr - 1, space, 0);
5362641Shibler return ((data >> 8) & 0xffff);
5462641Shibler }
5562641Shibler data = access(RD, addr, space, 0);
5662641Shibler return ((data >> 16) & 0xffff);
5762641Shibler }
5862641Shibler
5962641Shibler u_int
lget(addr,space)6062641Shibler lget(addr, space)
6162641Shibler off_t addr;
6262641Shibler {
6362641Shibler if (addr & 1) {
6462641Shibler u_int data = get(addr, space);
6562641Shibler return (get(addr + 2, space) | (data << 16));
6662641Shibler }
6762641Shibler return (access(RD, addr, space, 0));
6862641Shibler }
6962641Shibler
7062641Shibler u_int
lchkget(addr,space)7162641Shibler lchkget(addr, space)
7262641Shibler off_t addr; { u_int w = lget(addr, space); chkerr(); return(w); }
7362641Shibler #endif
7462641Shibler
7562641Shibler #if !pdp11 && !vax && !mc68000
7662641Shibler help!
7762641Shibler #endif
7862641Shibler
7962641Shibler u_int
chkget(addr,space)8062641Shibler chkget(addr, space)
8162641Shibler off_t addr; { u_int w = get(addr, space); chkerr(); return(w); }
8262641Shibler
8362641Shibler u_int
bchkget(addr,space)8462641Shibler bchkget(addr, space)
8562641Shibler off_t addr; { return(lobyte(chkget(addr, space))); }
8662641Shibler
8762641Shibler /*
8862641Shibler * Read/write according to mode at address addr in i/d space.
8962641Shibler * Value is quantity to be written, if write.
9062641Shibler *
9162641Shibler * This routine decides whether to get the data from the subprocess
9262641Shibler * address space with ptrace, or to get it from the files being
9362641Shibler * debugged.
9462641Shibler *
9562641Shibler * When the kernel is being debugged with the -k flag we interpret
9662641Shibler * the system page tables for data space, mapping p0 and p1 addresses
9762641Shibler * relative to the ``current'' process (as specified by its p_addr in
9862641Shibler * <p) and mapping system space addresses through the system page tables.
9962641Shibler */
access(mode,addr,space,value)10062641Shibler access(mode, addr, space, value)
10162641Shibler int mode, space, value;
10262641Shibler off_t addr;
10362641Shibler {
10462641Shibler int rd = mode == RD;
10562641Shibler int file, w;
10662641Shibler
10762641Shibler if (space == NSP)
10862641Shibler return(0);
10962641Shibler if (pid) {
11062641Shibler int pmode = (space&DSP ?
11162641Shibler (rd ? PT_READ_D : PT_WRITE_D) :
11262641Shibler (rd ? PT_READ_I : PT_WRITE_I));
11362641Shibler
11462641Shibler w = ptrace(pmode, pid, addr, value);
11562641Shibler if (errno)
11662641Shibler rwerr(space);
11762641Shibler return (w);
11862641Shibler }
11962641Shibler w = 0;
12062641Shibler if (mode==WT && wtflag==0)
12162641Shibler error("not in write mode");
12262641Shibler if (!chkmap(&addr, space))
12362641Shibler return (0);
12462641Shibler file = mapptr(space)->ufd;
12562641Shibler if (kernel && space == DSP) {
12662641Shibler addr = vtophys(addr);
12762641Shibler if (addr == -1)
12862641Shibler return (0);
12962641Shibler }
13062641Shibler if (physrw(file, addr, rd ? &w : &value, rd) < 0)
13162641Shibler rwerr(space);
13262641Shibler return (w);
13362641Shibler }
13462641Shibler
13562641Shibler #ifdef vax
13662641Shibler /*
13762641Shibler * When looking at kernel data space through /dev/mem or
13862641Shibler * with a core file, do virtual memory mapping.
13962641Shibler */
vtophys(addr)14062641Shibler vtophys(addr)
14162641Shibler off_t addr;
14262641Shibler {
14362641Shibler int oldaddr = addr;
14462641Shibler int v;
14562641Shibler struct pte pte;
14662641Shibler
14762641Shibler addr &= ~0xc0000000;
14862641Shibler v = btop(addr);
14962641Shibler switch (oldaddr&0xc0000000) {
15062641Shibler
15162641Shibler case 0xc0000000:
15262641Shibler case 0x80000000:
15362641Shibler /*
15462641Shibler * In system space get system pte. If
15562641Shibler * valid or reclaimable then physical address
15662641Shibler * is combination of its page number and the page
15762641Shibler * offset of the original address.
15862641Shibler */
15962641Shibler if (v >= slr)
16062641Shibler goto oor;
16162641Shibler addr = ((long)(sbr+v)) &~ 0x80000000;
16262641Shibler goto simple;
16362641Shibler
16462641Shibler case 0x40000000:
16562641Shibler /*
16662641Shibler * In p1 space must not be in shadow region.
16762641Shibler */
16862641Shibler if (v < pcb.pcb_p1lr)
16962641Shibler goto oor;
17062641Shibler addr = pcb.pcb_p1br+v;
17162641Shibler break;
17262641Shibler
17362641Shibler case 0x00000000:
17462641Shibler /*
17562641Shibler * In p0 space must not be off end of region.
17662641Shibler */
17762641Shibler if (v >= pcb.pcb_p0lr)
17862641Shibler goto oor;
17962641Shibler addr = pcb.pcb_p0br+v;
18062641Shibler break;
18162641Shibler oor:
18262641Shibler errflg = "address out of segment";
18362641Shibler return (-1);
18462641Shibler }
18562641Shibler /*
18662641Shibler * For p0/p1 address, user-level page table should
18762641Shibler * be in kernel vm. Do second-level indirect by recursing.
18862641Shibler */
18962641Shibler if ((addr & 0x80000000) == 0) {
19062641Shibler errflg = "bad p0br or p1br in pcb";
19162641Shibler return (-1);
19262641Shibler }
19362641Shibler addr = vtophys(addr);
19462641Shibler simple:
19562641Shibler /*
19662641Shibler * Addr is now address of the pte of the page we
19762641Shibler * are interested in; get the pte and paste up the
19862641Shibler * physical address.
19962641Shibler */
20062641Shibler if (physrw(fcor, addr, (int *)&pte, 1) < 0) {
20162641Shibler errflg = "page table botch";
20262641Shibler return (-1);
20362641Shibler }
20462641Shibler /* SHOULD CHECK NOT I/O ADDRESS; NEED CPU TYPE! */
20562641Shibler if (pte.pg_v == 0 && (pte.pg_fod || pte.pg_pfnum == 0)) {
20662641Shibler errflg = "page not valid/reclaimable";
20762641Shibler return (-1);
20862641Shibler }
20962641Shibler return (ptob(pte.pg_pfnum) + (oldaddr & PGOFSET));
21062641Shibler }
21162641Shibler #endif
21262641Shibler
21362641Shibler #ifdef hp300
21462641Shibler
21562641Shibler #ifdef NEWVM
21662641Shibler #ifndef btop
21762641Shibler #define btop hp300_btop
21862641Shibler #endif
21962641Shibler #ifndef ptob
22062641Shibler #define ptob hp300_ptob
22162641Shibler #endif
22262641Shibler #endif
22362641Shibler
22462641Shibler int is68040 = 0;
22562641Shibler
22662641Shibler /*
22762641Shibler * When looking at kernel data space through /dev/mem or
22862641Shibler * with a core file, do virtual memory mapping.
22962641Shibler */
vtophys(addr)23062641Shibler vtophys(addr)
23162641Shibler off_t addr;
23262641Shibler {
23362641Shibler int v;
23462641Shibler struct pte pte;
23562641Shibler int oldaddr = addr;
23662641Shibler
23762641Shibler if (INKERNEL(addr)) {
23862641Shibler /*
23962641Shibler * In system space get system pte. If
24062641Shibler * valid or reclaimable then physical address
24162641Shibler * is combination of its page number and the page
24262641Shibler * offset of the original address.
24362641Shibler */
24462641Shibler #ifdef NEWVM
24562641Shibler /* locate PTE page in segtab */
24662641Shibler if (is68040) {
24762641Shibler int steaddr;
24862641Shibler
24962641Shibler steaddr = KVTOPH((int)(sbr+(addr>>SG4_SHIFT1)));
25062641Shibler lseek(fcor, (off_t)steaddr, 0);
25162641Shibler read(fcor, &pte, sizeof pte);
25262641Shibler #if 0
25362641Shibler printf("va %X: ste1 %X@%X",
25462641Shibler addr, *(int *)&pte, steaddr);
25562641Shibler #endif
25662641Shibler if (*(int *)&pte == SG_NV)
25762641Shibler goto bad;
25862641Shibler steaddr = (int)(((int *)(*(int *)&pte & SG4_ADDR1)) +
25962641Shibler ((addr & SG4_MASK2) >> SG4_SHIFT2));
26062641Shibler physrw(fcor, steaddr, (int *)&pte, 1);
26162641Shibler #if 0
26262641Shibler printf(" ste2 %X@%X", *(int *)&pte, steaddr);
26362641Shibler #endif
26462641Shibler } else {
26562641Shibler lseek(fcor,
26662641Shibler (off_t)KVTOPH((int)(sbr+(addr>>SG_ISHIFT))), 0);
26762641Shibler read(fcor, &pte, sizeof pte);
26862641Shibler #if 0
26962641Shibler printf("va %X: ste %X@%X",
27062641Shibler addr, *(int *)&pte, sbr+(addr>>SG_ISHIFT));
27162641Shibler #endif
27262641Shibler }
27362641Shibler /* see if STE is valid */
27462641Shibler if (*(int *)&pte == SG_NV) {
27562641Shibler bad:
27662641Shibler errflg = "address out of segment";
27762641Shibler return(-1);
27862641Shibler }
27962641Shibler /* desired PTE is within that page */
28062641Shibler v = btop(addr & SG_PMASK);
28162641Shibler addr = (pte.pg_pfnum << PGSHIFT) + (v * sizeof pte);
28262641Shibler #else
28362641Shibler v = btop(addr - KERNOFF);
28462641Shibler addr = (long)(sbr+v) + lowram;
28562641Shibler #endif
28662641Shibler }
28762641Shibler else if (INUDOT(addr)) {
28862641Shibler addr -= kernudot;
28962641Shibler addr += masterpcbb;
29062641Shibler return(vtophys(addr));
29162641Shibler }
29262641Shibler else /* user space */ {
29362641Shibler #ifdef NEWVM
29462641Shibler errflg = "cannot translate user addresses";
29562641Shibler return (-1);
29662641Shibler #else
29762641Shibler v = btop(addr);
29862641Shibler /*
29962641Shibler * Must be within bounds of p0 or p1 regions.
30062641Shibler */
30162641Shibler if (v < pcb.pcb_p0lr)
30262641Shibler addr = pcb.pcb_p0br+v;
30362641Shibler else if (v >= pcb.pcb_p1lr)
30462641Shibler addr = pcb.pcb_p1br+v;
30562641Shibler else {
30662641Shibler errflg = "address out of segment";
30762641Shibler return (-1);
30862641Shibler }
30962641Shibler /*
31062641Shibler * For p0/p1 address, user-level page table should
31162641Shibler * be in kernel vm. Do second-level indirect by recursing.
31262641Shibler */
31362641Shibler if (!INKERNEL(addr)) {
31462641Shibler errflg = "bad p0br or p1br in pcb";
31562641Shibler return (-1);
31662641Shibler }
31762641Shibler addr = vtophys(addr);
31862641Shibler #endif
31962641Shibler }
32062641Shibler /*
32162641Shibler * Addr is now address of the pte of the page we
32262641Shibler * are interested in; get the pte and paste up the
32362641Shibler * physical address.
32462641Shibler */
32562641Shibler if (physrw(fcor, addr, (int *)&pte, 1) < 0) {
32662641Shibler errflg = "page table botch";
32762641Shibler return (-1);
32862641Shibler }
32962641Shibler if (pte.pg_v == 0 &&
33062641Shibler #ifdef NEWVM
33162641Shibler pte.pg_pfnum == 0
33262641Shibler #else
33362641Shibler (pte.pg_fod || pte.pg_pfnum == 0)
33462641Shibler #endif
33562641Shibler ) {
33662641Shibler errflg = "page not valid/reclaimable";
33762641Shibler return (-1);
33862641Shibler }
33962641Shibler #if 0
34062641Shibler printf(" -> pte %X@%X -> addr %X\n",
34162641Shibler *(int *)&pte, addr, ptob(pte.pg_pfnum) + (oldaddr & PGOFSET));
34262641Shibler #endif
34362641Shibler return (ptob(pte.pg_pfnum) + (oldaddr & PGOFSET));
34462641Shibler }
34562641Shibler #endif
34662641Shibler
34762641Shibler #if !vax && !hp300
34862641Shibler help!
34962641Shibler #endif
35062641Shibler
rwerr(space)35162641Shibler rwerr(space)
35262641Shibler int space;
35362641Shibler {
35462641Shibler
35562641Shibler if (space & DSP)
35662641Shibler errflg = "data address not found";
35762641Shibler else if (space & PSP)
35862641Shibler errflg = "physical address not found";
35962641Shibler else
36062641Shibler errflg = "text address not found";
36162641Shibler }
36262641Shibler
physrw(file,addr,aw,rd)36362641Shibler physrw(file, addr, aw, rd)
36462641Shibler off_t addr;
36562641Shibler int *aw, rd;
36662641Shibler {
36762641Shibler
36862641Shibler #ifdef hp300
36962641Shibler if (kcore && !kmem && file == fcor)
37062641Shibler addr -= lowram;
37162641Shibler #endif
37262641Shibler if (longseek(file,addr)==0 ||
37362641Shibler (rd ? read(file,aw,sizeof(int)) : write(file,aw,sizeof(int))) < 1)
37462641Shibler return (-1);
37562641Shibler return (0);
37662641Shibler }
37762641Shibler
chkmap(addr,space)37862641Shibler chkmap(addr,space)
37962641Shibler REG L_INT *addr;
38062641Shibler REG INT space;
38162641Shibler {
38262641Shibler REG MAPPTR amap;
38362641Shibler amap = mapptr(space);
38462641Shibler IF space&STAR ORF !within(*addr,amap->b1,amap->e1)
38562641Shibler THEN IF within(*addr,amap->b2,amap->e2)
38662641Shibler THEN *addr += (amap->f2)-(amap->b2);
38762641Shibler ELSE rwerr(space); return(0);
38862641Shibler FI
38962641Shibler ELSE *addr += (amap->f1)-(amap->b1);
39062641Shibler FI
39162641Shibler return(1);
39262641Shibler }
39362641Shibler
within(addr,lbd,ubd)39462641Shibler within(addr,lbd,ubd)
39562641Shibler u_int addr, lbd, ubd; { return(addr>=lbd && addr<ubd); }
39662641Shibler
longseek(f,a)39762641Shibler longseek(f, a)
39862641Shibler off_t a; { return(lseek(f, a, 0) != -1); }
399*62649Shibler
400*62649Shibler #ifdef NEWVM
401*62649Shibler #undef lseek
402*62649Shibler #undef off_t
Lseek(f,o,w)403*62649Shibler Lseek(f, o, w)
404*62649Shibler int f, w; Ooff_t o; { return(lseek(f, (off_t)o, w)); }
405*62649Shibler #endif
406