294 lines · 4.6 KB · C
RawDownload
/*  * This file is part of the UCB release of Plan 9. It is subject to the license * terms in the LICENSE file found in the top-level directory of this * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No * part of the UCB release of Plan 9, including this file, may be copied, * modified, propagated, or distributed except according to the terms contained * in the LICENSE file. */ #include <u.h>#include <libc.h>#include <bio.h>#include <mach.h>#include "arm.h" extern ulong	textbase; ulongifetch(ulong addr){	uchar *va; 	if(addr&3) {		Bprint(bioout, "Address error (I-fetch) vaddr %.8lux\n", addr);		longjmp(errjmp, 0);	} 	if(icache.on)		updateicache(addr);	iprof[(addr-textbase)/PROFGRAN]++; 	va = vaddr(addr);	va += addr&(BY2PG-1); 	return va[3]<<24 | va[2]<<16 | va[1]<<8 | va[0];} ulonggetmem_4(ulong addr){	ulong val;	int i; 	val = 0;	for(i = 0; i < 4; i++)		val = (val>>8) | (getmem_b(addr++)<<24);	return val;} ulonggetmem_2(ulong addr){	ulong val;	int i; 	val = 0;	for(i = 0; i < 2; i++)		val = (val>>8) | (getmem_b(addr++)<<16);	return val;} ulonggetmem_w(ulong addr){	uchar *va;	ulong w; 	if(addr&3) {		w = getmem_w(addr & ~3);		while(addr & 3) {			w = (w>>8) | (w<<24);			addr--;		}		return w;	}	if(membpt)		brkchk(addr, Read); 	va = vaddr(addr);	va += addr&(BY2PG-1); 	return va[3]<<24 | va[2]<<16 | va[1]<<8 | va[0];} ushortgetmem_h(ulong addr){	uchar *va;	ulong w; 	if(addr&1) {		w = getmem_h(addr & ~1);		while(addr & 1) {			w = (w>>8) | (w<<8);			addr--;		}		return w;	}	if(membpt)		brkchk(addr, Read); 	va = vaddr(addr);	va += addr&(BY2PG-1); 	return va[1]<<8 | va[0];} uchargetmem_b(ulong addr){	uchar *va; 	if(membpt)		brkchk(addr, Read); 	va = vaddr(addr);	va += addr&(BY2PG-1);	return va[0];} uvlonggetmem_v(ulong addr){	return ((uvlong)getmem_w(addr+4) << 32) | getmem_w(addr);} voidputmem_h(ulong addr, ushort data){	uchar *va; 	if(addr&1) {		Bprint(bioout, "Address error (Store) vaddr %.8lux\n", addr);		longjmp(errjmp, 0);	} 	va = vaddr(addr);	va += addr&(BY2PG-1); 	va[1] = data>>8;	va[0] = data;	if(membpt)		brkchk(addr, Write);} voidputmem_w(ulong addr, ulong data){	uchar *va; 	if(addr&3) {		Bprint(bioout, "Address error (Store) vaddr %.8lux\n", addr);		longjmp(errjmp, 0);	} 	va = vaddr(addr);	va += addr&(BY2PG-1); 	va[3] = data>>24;	va[2] = data>>16;	va[1] = data>>8;	va[0] = data;	if(membpt)		brkchk(addr, Write);} voidputmem_b(ulong addr, uchar data){	uchar *va; 	va = vaddr(addr);	va += addr&(BY2PG-1);	va[0] = data;	if(membpt)		brkchk(addr, Write);} voidputmem_v(ulong addr, uvlong data){	putmem_w(addr, data);	/* two stages, to catch brkchk */	putmem_w(addr+4, data>>32);} char *memio(char *mb, ulong mem, int size, int dir){	int i;	char *buf, c; 	if(mb == 0)		mb = emalloc(size); 	buf = mb;	switch(dir) {	default:		fatal(0, "memio");	case MemRead:		while(size--)			*mb++ = getmem_b(mem++);		break;	case MemReadstring:		for(;;) {			if(size-- == 0) {				Bprint(bioout, "memio: user/kernel copy too long for arm\n");				longjmp(errjmp, 0);			}			c = getmem_b(mem++);			*mb++ = c;			if(c == '\0')				break;		}		break;	case MemWrite:		for(i = 0; i < size; i++)			putmem_b(mem++, *mb++);		break;	}	return buf;} voiddotlb(ulong vaddr){	ulong *l, *e; 	vaddr &= ~(BY2PG-1); 	e = &tlb.tlbent[tlb.tlbsize];	for(l = tlb.tlbent; l < e; l++)		if(*l == vaddr) {			tlb.hit++;			return;		} 	tlb.miss++;	tlb.tlbent[lnrand(tlb.tlbsize)] = vaddr;} void *vaddr(ulong addr){	Segment *s, *es;	int off, foff, l, n;	uchar **p, *a; 	if(tlb.on)		dotlb(addr); 	es = &memory.seg[Nseg];	for(s = memory.seg; s < es; s++) {		if(addr >= s->base && addr < s->end) {			s->refs++;			off = (addr-s->base)/BY2PG;			p = &s->table[off];			if(*p)				return *p;			s->rss++;			switch(s->type) {			default:				fatal(0, "vaddr");			case Text:				*p = emalloc(BY2PG);				if(seek(text, s->fileoff+(off*BY2PG), 0) < 0)					fatal(1, "vaddr text seek");				if(read(text, *p, BY2PG) < 0)					fatal(1, "vaddr text read");				return *p;			case Data:				*p = emalloc(BY2PG);				foff = s->fileoff+(off*BY2PG);				if(seek(text, foff, 0) < 0)					fatal(1, "vaddr text seek");				n = read(text, *p, BY2PG);				if(n < 0)					fatal(1, "vaddr text read");				if(foff + n > s->fileend) {					l = BY2PG - (s->fileend-foff);					a = *p+(s->fileend-foff);					memset(a, 0, l);				}				return *p;			case Bss:			case Stack:				*p = emalloc(BY2PG);				return *p;			}		}	}	Bprint(bioout, "User TLB miss vaddr 0x%.8lux\n", addr);	longjmp(errjmp, 0);	return 0;		/*to stop compiler whining*/}