xref: /csrg-svn/old/adb/adb.hp300/access.c (revision 62641)
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