⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mm.cc

📁 南京航空航天大学开发的一个类Unix和Linux的操作系统,好不好看看就知道了,
💻 CC
字号:
#include <lib/root.h>#include <lib/errno.h>#include <lib/limits.h>#include <lib/string.h>#include <lib/gcc.h>#include <kern/sched.h>#include <mm/allocpage.h>#include <asm/pgtbl.h>#include <fs/inode.h>#include "mm.h"#undef debug#define debug(...)#define __try curr->mm->onfault = (vaddr_t) &&onfault#define __final \	curr->mm->onfault = 0; \	return 0; \onfault: /* here must be reachable */ \	curr->mm->onfault = 0; \	return EFAULT/* verify read */ int verr(void * area, int size){	if (!size)		return EFAULT;	__try;	for (void * end = pageup(area + size); area < end; area += PAGESIZE) {		if (!uspace(area))			goto onfault; /* goto make onfault reachable */		char tmp;		asm volatile ("movb %1,%0":"=r"(tmp):"m"(*(char*)area));	}	__final;}/* verify write */int verw(void * area, int size){	if (!size)		return EFAULT;	__try;	for (void * end = pageup(area + size); area < end; area += PAGESIZE) {		if (!uspace(area))			goto onfault; /* goto make onfault reachable */		char tmp;		asm volatile ("movb %1,%0":"=r"(tmp):"m"(*(char*)area));		asm volatile ("movb %1,%0":"=m"(*(char*)area):"r"(tmp));	}	__final;}/* verify read string */int verrstr(const char * str){	__try;	for (; *str; str++) {		if (!uspace(str))			goto onfault;		char tmp;		asm volatile ("movb %1,%0":"=r"(tmp):"m"(*str));	}	__final;}/* verify read path */int verrpath(const char * path){	if (verrstr(path))		return EFAULT;	return (strlen(path) <= PATHMAX) ? 0 : ENAMETOOLONG;}/* verify read null terminated vector */static int verrvec(char ** vec){	__try;	for (; *vec; vec++) {		if (!uspace(vec))			goto onfault;		void * tmp;		asm volatile ("movl %1,%0":"=r"(tmp):"m"(*vec));	}	__final;}/*	 curr->startstack = sp & 0xfffff000; * sp:	 argc *	 argv : IBCS need not this field *	 envp : IBCS need not this field * argv: argv[0..argc-1] *       0 * envp: envp[0..envc-1] *       0 * sp:   argv[0][0] argv[0][1] ... 0; argv[1][0] argv[1][1] ... 0 *       envp[0][0] envp[0][1] ... 0; envp[0][0] envp[0][1] ... 0 */static vaddr_t createargv(ustack_t * ustack){	char * str = (char*) (ustack->vbase() + pagemod(ustack->sp));	ulong * sp = (ulong*) rounddown2((ulong)str, sizeof(ulong));	int argc = ustack->argc;	int envc = ustack->envc;	sp -= envc + 1;	char ** envp = (char**) sp;	sp -= argc + 1;	char ** argv = (char**) sp;#ifdef AOUT	*--sp = (ulong) envp;	*--sp = (ulong) argv;#endif	*--sp = (ulong) argc;	while (argc-- > 0) {		*argv++ = str;		str = str + strlen(str) + 1;	}	*argv = NULL;	while (envc-- > 0) {		*envp++ = str;		str = str + strlen(str) + 1;	}	*envp = NULL;	allege((vaddr_t)str == USEREND);	return (vaddr_t) sp;}int ustack_t::pushkstr(char * str){	char * c;	/* the trailing zero is also pushed onto stack */	for (c = str + strlen(str); c >= str; c--) {		if (!pagemod(sp)) {			if (--base < 0)				return E2BIG;			page[base] = (char*) allocpage(AUSER);			if (!page[base])				return ENOMEM;			sp = page[base] + PAGESIZE;		}		*--sp = *c;	}	return 0;}int ustack_t::pushustr(char * str){	int e;	if (e = verrstr(str))		return e;	return pushkstr(str);}int ustack_t::pushuvec(char ** vec){	int e;	char ** str;	if (e = verrvec(vec))		return e;	for (str = vec; *str; str++)		/* nothing */;	for (str--; str >= vec; str--) {		if (e = pushustr(*str))			return e;	}	return 0;}int mm_t::initustack(ustack_t * ustack, vaddr_t * initsp){	int i = ustack->base, e;	vaddr_t vaddr = ustack->vbase(); 	for (; vaddr < USEREND; vaddr += PAGESIZE, i++) {		if (e = mapto(vaddr, vtop(ustack->page[i]), PROTRW))			return e;	}	*initsp = createargv(ustack);	return anonmap(*initsp, USEREND, PROTRW, MAPPRIVATE|MAPFIXED);}void mm_t::dump(){	seg_t * s;	printf("start-end offset-inode prot\n");	foreach (s, segq) {		const char * prot = (s->prot & PROTW) ? "write" : "read";		printf("%08lx-%08lx %08lx-%08lx %s\n", 		s->start, s->end, s->offset, s->inode, prot);	}}seg_t * mm_t::findustack(){	if (segq.count() < 4) { 		warn("bad mm layout\n");		dump();		return NULL;	}	seg_t * seg = segq.tail();	if (seg && (seg->prot & PROTW))		return seg;	warn("user stack segment not found\n");	return NULL;}/* code data bss stack */seg_t * mm_t::findbss(){	if (segq.count() < 4) { 		warn("bad mm layout\n");		dump();		return NULL;	}	seg_t * seg = segq.at(2); 	if (seg && seg->prot & PROTW)		return seg;	warn("user bss segment not found\n");	return NULL;}/* look up the first segment which satifies vaddr < seg->end, NULL if none */seg_t * mm_t::findseg(vaddr_t vaddr){	seg_t * seg;	foreach (seg, segq)		if (vaddr < seg->end)			return seg;	return NULL;}seg_t * mm_t::contain(vaddr_t vaddr){	seg_t * seg;	return ((seg = findseg(vaddr)) && (seg->start <= vaddr)) ? seg : NULL;}int mm_t::mapto(ulong vaddr, paddr_t paddr, int prot){	pte_t * pte = pgtbl->getpte(vaddr);	if (!pte)		return ENOMEM;	assert(pte->none());	prot = (prot & PROTW) ? (PTEU | PTEW | PTEP) : (PTEU | PTEP);	pte->mapto(paddr, prot); 	return 0;}void mm_t::pagefault(regs_t * regs, vaddr_t vaddr, int u, int w, int p){	seg_t * seg;	if (!(seg = findseg(vaddr)))		goto bad;	if (vaddr < seg->start) {		if (findustack() != seg)			goto bad;		/* accessing the stack below %esp is always a bug.		   The "+ 32" is there due to some instructions (like		   pusha) doing pre-decrement on the stack and that		   doesn't show up until later.. */		if (vaddr + 32 < regs->esp)			goto bad;		/* grow the user stack */		seg->start = pagedown(vaddr);	}	/* now the segment contain the vaddr */	assert(!p || w);	if (w && !(seg->prot & PROTW))		goto bad;	/* good area */	p ? seg->wppage(vaddr, u) : seg->nopage(vaddr, u);	return;bad:	if (u) {		debug("user fault:(eip=%08lx,cr2=%08lx,u=%d,w=%d,p=%d)\n",			regs->eip, vaddr, u, w, p);		curr->post(SIGSEGV);		return;	}	if (uspace(vaddr) && onfault) {		regs->eip = onfault; /* throw the exception */		return;	}	panic("unhandled page fault(eip=%08lx,cr2=%08lx,u=%d,w=%d,p=%d)", 	regs->eip, vaddr, u, w, p);}/* we don't consider overlap currently */int mm_t::insertseg(seg_t * neu){	if ((neu->start > neu->end) || (neu->end > USEREND))		return EINVAL;	segq.insertlt(neu);	return 0;}static inline void clear(vaddr_t from, vaddr_t to){	memset((void*)from, 0, to - from);}/* We need to explicitly zero any fractional pages   after the data section (i.e. bss).  This would   contain the junk from the file that should not   be in memory */void mm_t::clearfrag(vaddr_t from, vaddr_t to){	assert(from < to);	seg_t * s = findseg(from);	assert(s);	s->nopage(from, 0);	pte_t * pte = pgtbl->probe(from);	pte->setw();	flushone(from);	memset((void*)from, 0, to - from);	if (!(s->prot & PROTW)) {		pte->clrw();		flushone(from);	}}/* size == 0 is acceptable, an empty segment will be created in this case */int mm_t::mmap(vaddr_t from, vaddr_t to, int prot, int flags, 	inode_t * inode, ulong offset){	int e;	seg_t * x;	assert(from <= to);	assert(flags & MAPFIXED);	if (inode && (pagemod(from) != pagemod(offset))) {		warn("from:(%lx) offset(%x) is not suitable for demand"		      "paging\n", from, offset);		return EINVAL;	}	x = new seg_t();	x->next = x->prev = NULL;	x->mm = this;	x->start = pagedown(from);	x->end = pageup(to);/* the segment must be writebale while clear the fractional page */	x->prot = prot;	x->flags = flags;	x->inode = inode;	x->offset = pagedown(offset);	if (e = insertseg(x)) {		delete x;		return e;	}	if (inode)		inode->hold();	return 0;}static int copypte(pgtbl_t * x, pgtbl_t * y, vaddr_t from, vaddr_t to){	int e;	copypgtbl_t copy;	if (e = copy.fromto(x, y, from, to))		return e;	while (copy.more()) {		pte_t * src = copy.cursrcpte();		pte_t * dst = copy.curdstpte();		*dst = *src;		if (src->none())			goto next;		if (src->tstw()) {			src->clrw();			dst->clrw();			flushone(copy.cursor());		}		dupphys(src->paddr());	next:	if (e = copy.next())			return e;	}	return 0;}void mm_t::unmapuspace(){	seg_t * seg;	foreachsafe (seg, segq)		delete seg;}mm_t::~mm_t(){	unmapuspace();	allege(*(ulong*)kstack == KSTACKMAGIC);	freepage(kstack);	delete pgtbl;}void mm_t::init(){	onfault = 0;	pgtbl = new pgtbl_t();	pgtbl->sharekpgtbl();	kstack = (char*)allocpage(AKERN);	*(ulong*)kstack = KSTACKMAGIC;}mm_t::mm_t(){	init();}#include "idletaskcode.h"/* init idle task's mm */mm_t::mm_t(vaddr_t * esp, vaddr_t * eip){	init();	anonmap(IDLETASKSTART, IDLETASKEND, PROTRWX, MAPFIXED|MAPPRIVATE);	char * page = (char *)allocpage(AKERN);	memcpy(page, idletaskcode, sizeof(idletaskcode));	mapto(IDLETASKSTART, vtop(page), PROTRWX);	*esp = IDLETASKSTART + PAGESIZE;	*eip = IDLETASKSTART;}int mm_t::clone(mm_t ** result){	int e;	mm_t * y = new mm_t();	*result = NULL;	seg_t * seg, * segy;	pgtbl_t * pgtbly = y->pgtbl;	foreach (seg, segq) {		segy = new seg_t();		segy->next = segy->prev = NULL;		segy->mm = y;		segy->start = seg->start;		segy->end = seg->end;		segy->prot = seg->prot;		segy->flags = seg->flags;		if (segy->inode = seg->inode)			segy->inode->hold();		segy->offset = seg->offset;  		if (e = copypte(pgtbl, pgtbly, seg->start, seg->end))			return e;		y->segq.enqtail(segy);	}	*result = y;	return 0;}int seg_t::clone(seg_t ** result){	seg_t * x = new seg_t();	*result = x;	x->next = x->prev = NULL;	return 0;}void seg_t::nopage(vaddr_t vaddr, int u){	assert(between(start,vaddr,end));	void * page = allocpage(AUSER);	if (!page) {		outofmem(u);		return;	}	if (mm->mapto(vaddr, vtop(page), prot) == ENOMEM) {		freepage(page);		outofmem(u);		return;	}	if (!inode) {		memset(page, 0, PAGESIZE);		return;	}	inode->read(offset + pagedown(vaddr) - start, page, PAGESIZE);	debug("nopage vaddr:%x mapto paddr:%x--no\n", vaddr, vtop(page));}void seg_t::wppage(vaddr_t vaddr, int u){	pte_t * pte = mm->pgtbl->probe(vaddr);	assert(pte);	page_t * our = patopage(pte->paddr());	assert(our->refcnt>0);	if (our->refcnt == 1) {		pte->setw();		flushone(vaddr);		return;	}	void * my = allocpage(AUSER);	if (!my) {		outofmem(u);		return;	}	pte->clear();	flushone(vaddr);	pte->mapto(vtop(my), PTEU | PTEW | PTEP);	memcpy(my, our->data(), PAGESIZE);	our->refcnt--;}seg_t::~seg_t(){	unlink();	unmap(start, end);	if (inode) inode->lose(), inode = NULL;}extern int sig;void seg_t::unmap(vaddr_t from, vaddr_t to){	vaddr_t cursor;	pte_t * pte;	foreachpte2 (cursor, pte, mm->pgtbl, from, to) {		if (pte->tstp()) {			freephys(pte->paddr());			pte->clear();			flushone(cursor);		}	}//	mm->pgtbl->freetree(from, to);}vaddr_t mm_t::brk(vaddr_t ebss){	ebss = pageup(ebss);	seg_t * bss = findbss();	if (!bss)		return NULL;	if (ebss < bss->start)		return bss->end;	if (ebss < bss->end) {		bss->unmap(pageup(ebss), pageup(bss->end));		bss->end = ebss;		return bss->end;	}	bss->end = min(ebss, pagedown(bss->next->start));	return bss->end;}asmlinkage vaddr_t sysbrk(vaddr_t ebss){	return curr->mm->brk(ebss);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -