xref: /plan9/sys/src/cmd/qi/mem.c (revision 7d9195a7bc3493d7fc3e1166ef25bf446be66b1a)
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