17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <mach.h>
57dd7cddfSDavid du Colombier #include "arm.h"
67dd7cddfSDavid du Colombier
77dd7cddfSDavid du Colombier extern ulong textbase;
87dd7cddfSDavid du Colombier
97dd7cddfSDavid du Colombier ulong
ifetch(ulong addr)107dd7cddfSDavid du Colombier ifetch(ulong addr)
117dd7cddfSDavid du Colombier {
127dd7cddfSDavid du Colombier uchar *va;
137dd7cddfSDavid du Colombier
147dd7cddfSDavid du Colombier if(addr&3) {
157dd7cddfSDavid du Colombier Bprint(bioout, "Address error (I-fetch) vaddr %.8lux\n", addr);
167dd7cddfSDavid du Colombier longjmp(errjmp, 0);
177dd7cddfSDavid du Colombier }
187dd7cddfSDavid du Colombier
197dd7cddfSDavid du Colombier if(icache.on)
207dd7cddfSDavid du Colombier updateicache(addr);
217dd7cddfSDavid du Colombier iprof[(addr-textbase)/PROFGRAN]++;
227dd7cddfSDavid du Colombier
237dd7cddfSDavid du Colombier va = vaddr(addr);
247dd7cddfSDavid du Colombier va += addr&(BY2PG-1);
257dd7cddfSDavid du Colombier
267dd7cddfSDavid du Colombier return va[3]<<24 | va[2]<<16 | va[1]<<8 | va[0];
277dd7cddfSDavid du Colombier }
287dd7cddfSDavid du Colombier
297dd7cddfSDavid du Colombier ulong
getmem_4(ulong addr)307dd7cddfSDavid du Colombier getmem_4(ulong addr)
317dd7cddfSDavid du Colombier {
327dd7cddfSDavid du Colombier ulong val;
337dd7cddfSDavid du Colombier int i;
347dd7cddfSDavid du Colombier
357dd7cddfSDavid du Colombier val = 0;
367dd7cddfSDavid du Colombier for(i = 0; i < 4; i++)
377dd7cddfSDavid du Colombier val = (val>>8) | (getmem_b(addr++)<<24);
387dd7cddfSDavid du Colombier return val;
397dd7cddfSDavid du Colombier }
407dd7cddfSDavid du Colombier
417dd7cddfSDavid du Colombier ulong
getmem_2(ulong addr)427dd7cddfSDavid du Colombier getmem_2(ulong addr)
437dd7cddfSDavid du Colombier {
447dd7cddfSDavid du Colombier ulong val;
457dd7cddfSDavid du Colombier int i;
467dd7cddfSDavid du Colombier
477dd7cddfSDavid du Colombier val = 0;
487dd7cddfSDavid du Colombier for(i = 0; i < 2; i++)
497dd7cddfSDavid du Colombier val = (val>>8) | (getmem_b(addr++)<<16);
507dd7cddfSDavid du Colombier return val;
517dd7cddfSDavid du Colombier }
527dd7cddfSDavid du Colombier
537dd7cddfSDavid du Colombier ulong
getmem_w(ulong addr)547dd7cddfSDavid du Colombier getmem_w(ulong addr)
557dd7cddfSDavid du Colombier {
567dd7cddfSDavid du Colombier uchar *va;
577dd7cddfSDavid du Colombier ulong w;
587dd7cddfSDavid du Colombier
597dd7cddfSDavid du Colombier if(addr&3) {
607dd7cddfSDavid du Colombier w = getmem_w(addr & ~3);
617dd7cddfSDavid du Colombier while(addr & 3) {
627dd7cddfSDavid du Colombier w = (w>>8) | (w<<24);
637dd7cddfSDavid du Colombier addr--;
647dd7cddfSDavid du Colombier }
657dd7cddfSDavid du Colombier return w;
667dd7cddfSDavid du Colombier }
677dd7cddfSDavid du Colombier if(membpt)
687dd7cddfSDavid du Colombier brkchk(addr, Read);
697dd7cddfSDavid du Colombier
707dd7cddfSDavid du Colombier va = vaddr(addr);
717dd7cddfSDavid du Colombier va += addr&(BY2PG-1);
727dd7cddfSDavid du Colombier
737dd7cddfSDavid du Colombier return va[3]<<24 | va[2]<<16 | va[1]<<8 | va[0];
747dd7cddfSDavid du Colombier }
757dd7cddfSDavid du Colombier
7659cc4ca5SDavid du Colombier ushort
getmem_h(ulong addr)7759cc4ca5SDavid du Colombier getmem_h(ulong addr)
7859cc4ca5SDavid du Colombier {
7959cc4ca5SDavid du Colombier uchar *va;
8059cc4ca5SDavid du Colombier ulong w;
8159cc4ca5SDavid du Colombier
8259cc4ca5SDavid du Colombier if(addr&1) {
8359cc4ca5SDavid du Colombier w = getmem_h(addr & ~1);
8459cc4ca5SDavid du Colombier while(addr & 1) {
8559cc4ca5SDavid du Colombier w = (w>>8) | (w<<8);
8659cc4ca5SDavid du Colombier addr--;
8759cc4ca5SDavid du Colombier }
8859cc4ca5SDavid du Colombier return w;
8959cc4ca5SDavid du Colombier }
9059cc4ca5SDavid du Colombier if(membpt)
9159cc4ca5SDavid du Colombier brkchk(addr, Read);
9259cc4ca5SDavid du Colombier
9359cc4ca5SDavid du Colombier va = vaddr(addr);
9459cc4ca5SDavid du Colombier va += addr&(BY2PG-1);
9559cc4ca5SDavid du Colombier
9659cc4ca5SDavid du Colombier return va[1]<<8 | va[0];
9759cc4ca5SDavid du Colombier }
9859cc4ca5SDavid du Colombier
997dd7cddfSDavid du Colombier uchar
getmem_b(ulong addr)1007dd7cddfSDavid du Colombier getmem_b(ulong addr)
1017dd7cddfSDavid du Colombier {
1027dd7cddfSDavid du Colombier uchar *va;
1037dd7cddfSDavid du Colombier
1047dd7cddfSDavid du Colombier if(membpt)
1057dd7cddfSDavid du Colombier brkchk(addr, Read);
1067dd7cddfSDavid du Colombier
1077dd7cddfSDavid du Colombier va = vaddr(addr);
1087dd7cddfSDavid du Colombier va += addr&(BY2PG-1);
1097dd7cddfSDavid du Colombier return va[0];
1107dd7cddfSDavid du Colombier }
1117dd7cddfSDavid du Colombier
112*51480713SDavid du Colombier uvlong
getmem_v(ulong addr)113*51480713SDavid du Colombier getmem_v(ulong addr)
114*51480713SDavid du Colombier {
115*51480713SDavid du Colombier return ((uvlong)getmem_w(addr+4) << 32) | getmem_w(addr);
116*51480713SDavid du Colombier }
117*51480713SDavid du Colombier
1187dd7cddfSDavid du Colombier void
putmem_h(ulong addr,ushort data)11959cc4ca5SDavid du Colombier putmem_h(ulong addr, ushort data)
12059cc4ca5SDavid du Colombier {
12159cc4ca5SDavid du Colombier uchar *va;
12259cc4ca5SDavid du Colombier
12359cc4ca5SDavid du Colombier if(addr&1) {
12459cc4ca5SDavid du Colombier Bprint(bioout, "Address error (Store) vaddr %.8lux\n", addr);
12559cc4ca5SDavid du Colombier longjmp(errjmp, 0);
12659cc4ca5SDavid du Colombier }
12759cc4ca5SDavid du Colombier
12859cc4ca5SDavid du Colombier va = vaddr(addr);
12959cc4ca5SDavid du Colombier va += addr&(BY2PG-1);
13059cc4ca5SDavid du Colombier
13159cc4ca5SDavid du Colombier va[1] = data>>8;
13259cc4ca5SDavid du Colombier va[0] = data;
13359cc4ca5SDavid du Colombier if(membpt)
13459cc4ca5SDavid du Colombier brkchk(addr, Write);
13559cc4ca5SDavid du Colombier }
13659cc4ca5SDavid du Colombier
13759cc4ca5SDavid du Colombier void
putmem_w(ulong addr,ulong data)1387dd7cddfSDavid du Colombier putmem_w(ulong addr, ulong data)
1397dd7cddfSDavid du Colombier {
1407dd7cddfSDavid du Colombier uchar *va;
1417dd7cddfSDavid du Colombier
1427dd7cddfSDavid du Colombier if(addr&3) {
1437dd7cddfSDavid du Colombier Bprint(bioout, "Address error (Store) vaddr %.8lux\n", addr);
1447dd7cddfSDavid du Colombier longjmp(errjmp, 0);
1457dd7cddfSDavid du Colombier }
1467dd7cddfSDavid du Colombier
1477dd7cddfSDavid du Colombier va = vaddr(addr);
1487dd7cddfSDavid du Colombier va += addr&(BY2PG-1);
1497dd7cddfSDavid du Colombier
1507dd7cddfSDavid du Colombier va[3] = data>>24;
1517dd7cddfSDavid du Colombier va[2] = data>>16;
1527dd7cddfSDavid du Colombier va[1] = data>>8;
1537dd7cddfSDavid du Colombier va[0] = data;
1547dd7cddfSDavid du Colombier if(membpt)
1557dd7cddfSDavid du Colombier brkchk(addr, Write);
1567dd7cddfSDavid du Colombier }
15759cc4ca5SDavid du Colombier
1587dd7cddfSDavid du Colombier void
putmem_b(ulong addr,uchar data)1597dd7cddfSDavid du Colombier putmem_b(ulong addr, uchar data)
1607dd7cddfSDavid du Colombier {
1617dd7cddfSDavid du Colombier uchar *va;
1627dd7cddfSDavid du Colombier
1637dd7cddfSDavid du Colombier va = vaddr(addr);
1647dd7cddfSDavid du Colombier va += addr&(BY2PG-1);
1657dd7cddfSDavid du Colombier va[0] = data;
1667dd7cddfSDavid du Colombier if(membpt)
1677dd7cddfSDavid du Colombier brkchk(addr, Write);
1687dd7cddfSDavid du Colombier }
1697dd7cddfSDavid du Colombier
170*51480713SDavid du Colombier void
putmem_v(ulong addr,uvlong data)171*51480713SDavid du Colombier putmem_v(ulong addr, uvlong data)
172*51480713SDavid du Colombier {
173*51480713SDavid du Colombier putmem_w(addr, data); /* two stages, to catch brkchk */
174*51480713SDavid du Colombier putmem_w(addr+4, data>>32);
175*51480713SDavid du Colombier }
176*51480713SDavid du Colombier
1777dd7cddfSDavid du Colombier char *
memio(char * mb,ulong mem,int size,int dir)1787dd7cddfSDavid du Colombier memio(char *mb, ulong mem, int size, int dir)
1797dd7cddfSDavid du Colombier {
1807dd7cddfSDavid du Colombier int i;
1817dd7cddfSDavid du Colombier char *buf, c;
1827dd7cddfSDavid du Colombier
1837dd7cddfSDavid du Colombier if(mb == 0)
1847dd7cddfSDavid du Colombier mb = emalloc(size);
1857dd7cddfSDavid du Colombier
1867dd7cddfSDavid du Colombier buf = mb;
1877dd7cddfSDavid du Colombier switch(dir) {
1887dd7cddfSDavid du Colombier default:
1897dd7cddfSDavid du Colombier fatal(0, "memio");
1907dd7cddfSDavid du Colombier case MemRead:
1917dd7cddfSDavid du Colombier while(size--)
1927dd7cddfSDavid du Colombier *mb++ = getmem_b(mem++);
1937dd7cddfSDavid du Colombier break;
1947dd7cddfSDavid du Colombier case MemReadstring:
1957dd7cddfSDavid du Colombier for(;;) {
1967dd7cddfSDavid du Colombier if(size-- == 0) {
1977dd7cddfSDavid du Colombier Bprint(bioout, "memio: user/kernel copy too long for arm\n");
1987dd7cddfSDavid du Colombier longjmp(errjmp, 0);
1997dd7cddfSDavid du Colombier }
2007dd7cddfSDavid du Colombier c = getmem_b(mem++);
2017dd7cddfSDavid du Colombier *mb++ = c;
2027dd7cddfSDavid du Colombier if(c == '\0')
2037dd7cddfSDavid du Colombier break;
2047dd7cddfSDavid du Colombier }
2057dd7cddfSDavid du Colombier break;
2067dd7cddfSDavid du Colombier case MemWrite:
2077dd7cddfSDavid du Colombier for(i = 0; i < size; i++)
2087dd7cddfSDavid du Colombier putmem_b(mem++, *mb++);
2097dd7cddfSDavid du Colombier break;
2107dd7cddfSDavid du Colombier }
2117dd7cddfSDavid du Colombier return buf;
2127dd7cddfSDavid du Colombier }
2137dd7cddfSDavid du Colombier
2147dd7cddfSDavid du Colombier void
dotlb(ulong vaddr)2157dd7cddfSDavid du Colombier dotlb(ulong vaddr)
2167dd7cddfSDavid du Colombier {
2177dd7cddfSDavid du Colombier ulong *l, *e;
2187dd7cddfSDavid du Colombier
2197dd7cddfSDavid du Colombier vaddr &= ~(BY2PG-1);
2207dd7cddfSDavid du Colombier
2217dd7cddfSDavid du Colombier e = &tlb.tlbent[tlb.tlbsize];
2227dd7cddfSDavid du Colombier for(l = tlb.tlbent; l < e; l++)
2237dd7cddfSDavid du Colombier if(*l == vaddr) {
2247dd7cddfSDavid du Colombier tlb.hit++;
2257dd7cddfSDavid du Colombier return;
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier
2287dd7cddfSDavid du Colombier tlb.miss++;
2297dd7cddfSDavid du Colombier tlb.tlbent[lnrand(tlb.tlbsize)] = vaddr;
2307dd7cddfSDavid du Colombier }
2317dd7cddfSDavid du Colombier
2327dd7cddfSDavid du Colombier void *
vaddr(ulong addr)2337dd7cddfSDavid du Colombier vaddr(ulong addr)
2347dd7cddfSDavid du Colombier {
2357dd7cddfSDavid du Colombier Segment *s, *es;
2367dd7cddfSDavid du Colombier int off, foff, l, n;
2377dd7cddfSDavid du Colombier uchar **p, *a;
2387dd7cddfSDavid du Colombier
2397dd7cddfSDavid du Colombier if(tlb.on)
2407dd7cddfSDavid du Colombier dotlb(addr);
2417dd7cddfSDavid du Colombier
2427dd7cddfSDavid du Colombier es = &memory.seg[Nseg];
2437dd7cddfSDavid du Colombier for(s = memory.seg; s < es; s++) {
2447dd7cddfSDavid du Colombier if(addr >= s->base && addr < s->end) {
2457dd7cddfSDavid du Colombier s->refs++;
2467dd7cddfSDavid du Colombier off = (addr-s->base)/BY2PG;
2477dd7cddfSDavid du Colombier p = &s->table[off];
2487dd7cddfSDavid du Colombier if(*p)
2497dd7cddfSDavid du Colombier return *p;
2507dd7cddfSDavid du Colombier s->rss++;
2517dd7cddfSDavid du Colombier switch(s->type) {
2527dd7cddfSDavid du Colombier default:
2537dd7cddfSDavid du Colombier fatal(0, "vaddr");
2547dd7cddfSDavid du Colombier case Text:
2557dd7cddfSDavid du Colombier *p = emalloc(BY2PG);
2567dd7cddfSDavid du Colombier if(seek(text, s->fileoff+(off*BY2PG), 0) < 0)
2577dd7cddfSDavid du Colombier fatal(1, "vaddr text seek");
2587dd7cddfSDavid du Colombier if(read(text, *p, BY2PG) < 0)
2597dd7cddfSDavid du Colombier fatal(1, "vaddr text read");
2607dd7cddfSDavid du Colombier return *p;
2617dd7cddfSDavid du Colombier case Data:
2627dd7cddfSDavid du Colombier *p = emalloc(BY2PG);
2637dd7cddfSDavid du Colombier foff = s->fileoff+(off*BY2PG);
2647dd7cddfSDavid du Colombier if(seek(text, foff, 0) < 0)
2657dd7cddfSDavid du Colombier fatal(1, "vaddr text seek");
2667dd7cddfSDavid du Colombier n = read(text, *p, BY2PG);
2677dd7cddfSDavid du Colombier if(n < 0)
2687dd7cddfSDavid du Colombier fatal(1, "vaddr text read");
2697dd7cddfSDavid du Colombier if(foff + n > s->fileend) {
2707dd7cddfSDavid du Colombier l = BY2PG - (s->fileend-foff);
2717dd7cddfSDavid du Colombier a = *p+(s->fileend-foff);
2727dd7cddfSDavid du Colombier memset(a, 0, l);
2737dd7cddfSDavid du Colombier }
2747dd7cddfSDavid du Colombier return *p;
2757dd7cddfSDavid du Colombier case Bss:
2767dd7cddfSDavid du Colombier case Stack:
2777dd7cddfSDavid du Colombier *p = emalloc(BY2PG);
2787dd7cddfSDavid du Colombier return *p;
2797dd7cddfSDavid du Colombier }
2807dd7cddfSDavid du Colombier }
2817dd7cddfSDavid du Colombier }
2827dd7cddfSDavid du Colombier Bprint(bioout, "User TLB miss vaddr 0x%.8lux\n", addr);
2837dd7cddfSDavid du Colombier longjmp(errjmp, 0);
2847dd7cddfSDavid du Colombier return 0; /*to stop compiler whining*/
2857dd7cddfSDavid du Colombier }
286