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