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