xref: /plan9/sys/src/cmd/5i/mem.c (revision 514807136a8518a9c368e175000825c6e1429f43)
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