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