]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/5i/mem.c
git/branch: somewhere in the syncing, the fix for junk files was lost
[plan9front.git] / sys / src / cmd / 5i / mem.c
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
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
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
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
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
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
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
113 getmem_v(ulong addr)
114 {
115         return ((uvlong)getmem_w(addr+4) << 32) | getmem_w(addr);
116 }
117
118 void
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
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
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
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 *
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
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 *
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 }