xref: /plan9/sys/src/cmd/qi/mem.c (revision 7d9195a7bc3493d7fc3e1166ef25bf446be66b1a)
1*7d9195a7SDavid du Colombier #include <u.h>
2*7d9195a7SDavid du Colombier #include <libc.h>
3*7d9195a7SDavid du Colombier #include <bio.h>
4*7d9195a7SDavid du Colombier #include <mach.h>
5*7d9195a7SDavid du Colombier #define Extern extern
6*7d9195a7SDavid du Colombier #include "power.h"
7*7d9195a7SDavid du Colombier 
8*7d9195a7SDavid du Colombier extern ulong	textbase;
9*7d9195a7SDavid du Colombier 
10*7d9195a7SDavid du Colombier ulong
ifetch(ulong addr)11*7d9195a7SDavid du Colombier ifetch(ulong addr)
12*7d9195a7SDavid du Colombier {
13*7d9195a7SDavid du Colombier 	uchar *va;
14*7d9195a7SDavid du Colombier 	ulong px;
15*7d9195a7SDavid du Colombier 
16*7d9195a7SDavid du Colombier 	if(addr&3) {
17*7d9195a7SDavid du Colombier 		Bprint(bioout, "instruction_address_not_aligned [addr %.8lux]\n", addr);
18*7d9195a7SDavid du Colombier 		longjmp(errjmp, 0);
19*7d9195a7SDavid du Colombier 	}
20*7d9195a7SDavid du Colombier 
21*7d9195a7SDavid du Colombier 	if(icache.on)
22*7d9195a7SDavid du Colombier 		updateicache(addr);
23*7d9195a7SDavid du Colombier 
24*7d9195a7SDavid du Colombier 	va = vaddr(addr);
25*7d9195a7SDavid du Colombier 	px = (addr-textbase)/PROFGRAN;
26*7d9195a7SDavid du Colombier 	if(px < iprofsize)
27*7d9195a7SDavid du Colombier 		iprof[px]++;
28*7d9195a7SDavid du Colombier 
29*7d9195a7SDavid du Colombier 	va += addr&(BY2PG-1);
30*7d9195a7SDavid du Colombier 
31*7d9195a7SDavid du Colombier 	return va[0]<<24 | va[1]<<16 | va[2]<<8 | va[3];
32*7d9195a7SDavid du Colombier }
33*7d9195a7SDavid du Colombier 
34*7d9195a7SDavid du Colombier ulong
getmem_4(ulong addr)35*7d9195a7SDavid du Colombier getmem_4(ulong addr)
36*7d9195a7SDavid du Colombier {
37*7d9195a7SDavid du Colombier 	ulong val;
38*7d9195a7SDavid du Colombier 	int i;
39*7d9195a7SDavid du Colombier 
40*7d9195a7SDavid du Colombier 	val = 0;
41*7d9195a7SDavid du Colombier 	for(i = 0; i < 4; i++)
42*7d9195a7SDavid du Colombier 		val = val<<8 | getmem_b(addr++);
43*7d9195a7SDavid du Colombier 	return val;
44*7d9195a7SDavid du Colombier }
45*7d9195a7SDavid du Colombier 
46*7d9195a7SDavid du Colombier ulong
getmem_2(ulong addr)47*7d9195a7SDavid du Colombier getmem_2(ulong addr)
48*7d9195a7SDavid du Colombier {
49*7d9195a7SDavid du Colombier 	ulong val;
50*7d9195a7SDavid du Colombier 
51*7d9195a7SDavid du Colombier 	val = getmem_b(addr);
52*7d9195a7SDavid du Colombier 	val = val<<8 | getmem_b(addr+1);
53*7d9195a7SDavid du Colombier 
54*7d9195a7SDavid du Colombier 	return val;
55*7d9195a7SDavid du Colombier }
56*7d9195a7SDavid du Colombier 
57*7d9195a7SDavid du Colombier uvlong
getmem_v(ulong addr)58*7d9195a7SDavid du Colombier getmem_v(ulong addr)
59*7d9195a7SDavid du Colombier {
60*7d9195a7SDavid du Colombier 	if(addr&3) {	/* 7? */
61*7d9195a7SDavid du Colombier 		Bprint(bioout, "mem_address_not_aligned [load addr %.8lux]\n", addr);
62*7d9195a7SDavid du Colombier 		longjmp(errjmp, 0);
63*7d9195a7SDavid du Colombier 	}
64*7d9195a7SDavid du Colombier 
65*7d9195a7SDavid du Colombier 	return ((uvlong)getmem_w(addr) << 32) | getmem_w(addr+4);
66*7d9195a7SDavid du Colombier }
67*7d9195a7SDavid du Colombier 
68*7d9195a7SDavid du Colombier ulong
getmem_w(ulong addr)69*7d9195a7SDavid du Colombier getmem_w(ulong addr)
70*7d9195a7SDavid du Colombier {
71*7d9195a7SDavid du Colombier 	uchar *va;
72*7d9195a7SDavid du Colombier 
73*7d9195a7SDavid du Colombier 	if(addr&3) {
74*7d9195a7SDavid du Colombier 		Bprint(bioout, "mem_address_not_aligned [load addr %.8lux]\n", addr);
75*7d9195a7SDavid du Colombier 		longjmp(errjmp, 0);
76*7d9195a7SDavid du Colombier 	}
77*7d9195a7SDavid du Colombier 	if(membpt)
78*7d9195a7SDavid du Colombier 		brkchk(addr, Read);
79*7d9195a7SDavid du Colombier 
80*7d9195a7SDavid du Colombier 	va = vaddr(addr);
81*7d9195a7SDavid du Colombier 	va += addr&(BY2PG-1);
82*7d9195a7SDavid du Colombier 
83*7d9195a7SDavid du Colombier 	return va[0]<<24 | va[1]<<16 | va[2]<<8 | va[3];
84*7d9195a7SDavid du Colombier }
85*7d9195a7SDavid du Colombier 
86*7d9195a7SDavid du Colombier ushort
getmem_h(ulong addr)87*7d9195a7SDavid du Colombier getmem_h(ulong addr)
88*7d9195a7SDavid du Colombier {
89*7d9195a7SDavid du Colombier 	uchar *va;
90*7d9195a7SDavid du Colombier 
91*7d9195a7SDavid du Colombier 	if(addr&1) {
92*7d9195a7SDavid du Colombier 		Bprint(bioout, "mem_address_not_aligned [load addr %.8lux]\n", addr);
93*7d9195a7SDavid du Colombier 		longjmp(errjmp, 0);
94*7d9195a7SDavid du Colombier 	}
95*7d9195a7SDavid du Colombier 	if(membpt)
96*7d9195a7SDavid du Colombier 		brkchk(addr, Read);
97*7d9195a7SDavid du Colombier 
98*7d9195a7SDavid du Colombier 	va = vaddr(addr);
99*7d9195a7SDavid du Colombier 	va += addr&(BY2PG-1);
100*7d9195a7SDavid du Colombier 
101*7d9195a7SDavid du Colombier 	return va[0]<<8 | va[1];
102*7d9195a7SDavid du Colombier }
103*7d9195a7SDavid du Colombier 
104*7d9195a7SDavid du Colombier uchar
getmem_b(ulong addr)105*7d9195a7SDavid du Colombier getmem_b(ulong addr)
106*7d9195a7SDavid du Colombier {
107*7d9195a7SDavid du Colombier 	uchar *va;
108*7d9195a7SDavid du Colombier 
109*7d9195a7SDavid du Colombier 	if(membpt)
110*7d9195a7SDavid du Colombier 		brkchk(addr, Read);
111*7d9195a7SDavid du Colombier 
112*7d9195a7SDavid du Colombier 	va = vaddr(addr);
113*7d9195a7SDavid du Colombier 	va += addr&(BY2PG-1);
114*7d9195a7SDavid du Colombier 	return va[0];
115*7d9195a7SDavid du Colombier }
116*7d9195a7SDavid du Colombier 
117*7d9195a7SDavid du Colombier void
putmem_v(ulong addr,uvlong data)118*7d9195a7SDavid du Colombier putmem_v(ulong addr, uvlong data)
119*7d9195a7SDavid du Colombier {
120*7d9195a7SDavid du Colombier 	if(addr&3) {	/* 7? */
121*7d9195a7SDavid du Colombier 		Bprint(bioout, "mem_address_not_aligned [store addr %.8lux]\n", addr);
122*7d9195a7SDavid du Colombier 		longjmp(errjmp, 0);
123*7d9195a7SDavid du Colombier 	}
124*7d9195a7SDavid du Colombier 
125*7d9195a7SDavid du Colombier 	putmem_w(addr, data>>32);	/* two stages, to catch brkchk */
126*7d9195a7SDavid du Colombier 	putmem_w(addr+4, data);
127*7d9195a7SDavid du Colombier }
128*7d9195a7SDavid du Colombier 
129*7d9195a7SDavid du Colombier void
putmem_w(ulong addr,ulong data)130*7d9195a7SDavid du Colombier putmem_w(ulong addr, ulong data)
131*7d9195a7SDavid du Colombier {
132*7d9195a7SDavid du Colombier 	uchar *va;
133*7d9195a7SDavid du Colombier 
134*7d9195a7SDavid du Colombier 	if(addr&3) {
135*7d9195a7SDavid du Colombier 		Bprint(bioout, "mem_address_not_aligned [store addr %.8lux]\n", addr);
136*7d9195a7SDavid du Colombier 		longjmp(errjmp, 0);
137*7d9195a7SDavid du Colombier 	}
138*7d9195a7SDavid du Colombier 
139*7d9195a7SDavid du Colombier 	va = vaddr(addr);
140*7d9195a7SDavid du Colombier 	va += addr&(BY2PG-1);
141*7d9195a7SDavid du Colombier 
142*7d9195a7SDavid du Colombier 	va[0] = data>>24;
143*7d9195a7SDavid du Colombier 	va[1] = data>>16;
144*7d9195a7SDavid du Colombier 	va[2] = data>>8;
145*7d9195a7SDavid du Colombier 	va[3] = data;
146*7d9195a7SDavid du Colombier 	if(membpt)
147*7d9195a7SDavid du Colombier 		brkchk(addr, Write);
148*7d9195a7SDavid du Colombier }
149*7d9195a7SDavid du Colombier 
150*7d9195a7SDavid du Colombier void
putmem_b(ulong addr,uchar data)151*7d9195a7SDavid du Colombier putmem_b(ulong addr, uchar data)
152*7d9195a7SDavid du Colombier {
153*7d9195a7SDavid du Colombier 	uchar *va;
154*7d9195a7SDavid du Colombier 
155*7d9195a7SDavid du Colombier 	va = vaddr(addr);
156*7d9195a7SDavid du Colombier 	va += addr&(BY2PG-1);
157*7d9195a7SDavid du Colombier 	va[0] = data;
158*7d9195a7SDavid du Colombier 	if(membpt)
159*7d9195a7SDavid du Colombier 		brkchk(addr, Write);
160*7d9195a7SDavid du Colombier }
161*7d9195a7SDavid du Colombier 
162*7d9195a7SDavid du Colombier void
putmem_h(ulong addr,short data)163*7d9195a7SDavid du Colombier putmem_h(ulong addr, short data)
164*7d9195a7SDavid du Colombier {
165*7d9195a7SDavid du Colombier 	uchar *va;
166*7d9195a7SDavid du Colombier 
167*7d9195a7SDavid du Colombier 	if(addr&1) {
168*7d9195a7SDavid du Colombier 		Bprint(bioout, "mem_address_not_aligned [store addr %.8lux]\n", addr);
169*7d9195a7SDavid du Colombier 		longjmp(errjmp, 0);
170*7d9195a7SDavid du Colombier 	}
171*7d9195a7SDavid du Colombier 
172*7d9195a7SDavid du Colombier 	va = vaddr(addr);
173*7d9195a7SDavid du Colombier 	va += addr&(BY2PG-1);
174*7d9195a7SDavid du Colombier 	va[0] = data>>8;
175*7d9195a7SDavid du Colombier 	va[1] = data;
176*7d9195a7SDavid du Colombier 	if(membpt)
177*7d9195a7SDavid du Colombier 		brkchk(addr, Write);
178*7d9195a7SDavid du Colombier }
179*7d9195a7SDavid du Colombier 
180*7d9195a7SDavid du Colombier char *
memio(char * mb,ulong mem,int size,int dir)181*7d9195a7SDavid du Colombier memio(char *mb, ulong mem, int size, int dir)
182*7d9195a7SDavid du Colombier {
183*7d9195a7SDavid du Colombier 	int i;
184*7d9195a7SDavid du Colombier 	char *buf, c;
185*7d9195a7SDavid du Colombier 
186*7d9195a7SDavid du Colombier 	if(size < 0) {
187*7d9195a7SDavid du Colombier 		Bprint(bioout, "memio: invalid size: %d\n", size);
188*7d9195a7SDavid du Colombier 		longjmp(errjmp, 0);
189*7d9195a7SDavid du Colombier 	}
190*7d9195a7SDavid du Colombier 	if(mb == 0)
191*7d9195a7SDavid du Colombier 		mb = emalloc(size);
192*7d9195a7SDavid du Colombier 
193*7d9195a7SDavid du Colombier 	buf = mb;
194*7d9195a7SDavid du Colombier 	switch(dir) {
195*7d9195a7SDavid du Colombier 	default:
196*7d9195a7SDavid du Colombier 		fatal(0, "memio");
197*7d9195a7SDavid du Colombier 	case MemRead:
198*7d9195a7SDavid du Colombier 		while(size--)
199*7d9195a7SDavid du Colombier 			*mb++ = getmem_b(mem++);
200*7d9195a7SDavid du Colombier 		break;
201*7d9195a7SDavid du Colombier 	case MemReadstring:
202*7d9195a7SDavid du Colombier 		for(;;) {
203*7d9195a7SDavid du Colombier 			if(size-- == 0) {
204*7d9195a7SDavid du Colombier 				Bprint(bioout, "memio: user/kernel copy too long for qi\n");
205*7d9195a7SDavid du Colombier 				longjmp(errjmp, 0);
206*7d9195a7SDavid du Colombier 			}
207*7d9195a7SDavid du Colombier 			c = getmem_b(mem++);
208*7d9195a7SDavid du Colombier 			*mb++ = c;
209*7d9195a7SDavid du Colombier 			if(c == '\0')
210*7d9195a7SDavid du Colombier 				break;
211*7d9195a7SDavid du Colombier 		}
212*7d9195a7SDavid du Colombier 		break;
213*7d9195a7SDavid du Colombier 	case MemWrite:
214*7d9195a7SDavid du Colombier 		for(i = 0; i < size; i++)
215*7d9195a7SDavid du Colombier 			putmem_b(mem++, *mb++);
216*7d9195a7SDavid du Colombier 		break;
217*7d9195a7SDavid du Colombier 	}
218*7d9195a7SDavid du Colombier 	return buf;
219*7d9195a7SDavid du Colombier }
220*7d9195a7SDavid du Colombier 
221*7d9195a7SDavid du Colombier void *
vaddr(ulong addr)222*7d9195a7SDavid du Colombier vaddr(ulong addr)
223*7d9195a7SDavid du Colombier {
224*7d9195a7SDavid du Colombier 	Segment *s, *es;
225*7d9195a7SDavid du Colombier 	int off, foff, l, n;
226*7d9195a7SDavid du Colombier 	uchar **p, *a;
227*7d9195a7SDavid du Colombier 
228*7d9195a7SDavid du Colombier 	es = &memory.seg[Nseg];
229*7d9195a7SDavid du Colombier 	for(s = memory.seg; s < es; s++) {
230*7d9195a7SDavid du Colombier 		if(addr >= s->base && addr < s->end) {
231*7d9195a7SDavid du Colombier 			s->refs++;
232*7d9195a7SDavid du Colombier 			off = (addr-s->base)/BY2PG;
233*7d9195a7SDavid du Colombier 			p = &s->table[off];
234*7d9195a7SDavid du Colombier 			if(*p)
235*7d9195a7SDavid du Colombier 				return *p;
236*7d9195a7SDavid du Colombier 			s->rss++;
237*7d9195a7SDavid du Colombier 			switch(s->type) {
238*7d9195a7SDavid du Colombier 			default:
239*7d9195a7SDavid du Colombier 				fatal(0, "vaddr");
240*7d9195a7SDavid du Colombier 			case Text:
241*7d9195a7SDavid du Colombier 				*p = emalloc(BY2PG);
242*7d9195a7SDavid du Colombier 				if(seek(text, s->fileoff+(off*BY2PG), 0) < 0)
243*7d9195a7SDavid du Colombier 					fatal(1, "vaddr text seek");
244*7d9195a7SDavid du Colombier 				if(read(text, *p, BY2PG) < 0)
245*7d9195a7SDavid du Colombier 					fatal(1, "vaddr text read");
246*7d9195a7SDavid du Colombier 				return *p;
247*7d9195a7SDavid du Colombier 			case Data:
248*7d9195a7SDavid du Colombier 				*p = emalloc(BY2PG);
249*7d9195a7SDavid du Colombier 				foff = s->fileoff+(off*BY2PG);
250*7d9195a7SDavid du Colombier 				if(seek(text, foff, 0) < 0)
251*7d9195a7SDavid du Colombier 					fatal(1, "vaddr text seek");
252*7d9195a7SDavid du Colombier 				n = read(text, *p, BY2PG);
253*7d9195a7SDavid du Colombier 				if(n < 0)
254*7d9195a7SDavid du Colombier 					fatal(1, "vaddr text read");
255*7d9195a7SDavid du Colombier 				if(foff + n > s->fileend) {
256*7d9195a7SDavid du Colombier 					l = BY2PG - (s->fileend-foff);
257*7d9195a7SDavid du Colombier 					a = *p+(s->fileend-foff);
258*7d9195a7SDavid du Colombier 					memset(a, 0, l);
259*7d9195a7SDavid du Colombier 				}
260*7d9195a7SDavid du Colombier 				return *p;
261*7d9195a7SDavid du Colombier 			case Bss:
262*7d9195a7SDavid du Colombier 			case Stack:
263*7d9195a7SDavid du Colombier 				*p = emalloc(BY2PG);
264*7d9195a7SDavid du Colombier 				return *p;
265*7d9195a7SDavid du Colombier 			}
266*7d9195a7SDavid du Colombier 		}
267*7d9195a7SDavid du Colombier 	}
268*7d9195a7SDavid du Colombier 	Bprint(bioout, "data_access_MMU_miss [addr 0x%.8lux]\n", addr);
269*7d9195a7SDavid du Colombier 	longjmp(errjmp, 0);
270*7d9195a7SDavid du Colombier 	return 0;		/*to stop compiler whining*/
271*7d9195a7SDavid du Colombier }
272