Beispiel #1
1
// Challenge!
int
sfork(void)
{
	int r;
	pde_t *pde;
	pte_t *pte;
	unsigned i;
	uint32_t addr;
	envid_t envid;
	envid = sys_exofork();//创建子环境
	if(envid < 0)
		panic("sys_exofork: %e", envid);
	if(envid==0)//子环境中
	{
		env = &envs[ENVX(sys_getenvid())];
		return 0;
	}
	else{//父环境中,注意:这里需要设置父环境的缺页异常栈,还需要设置子环境的缺页异常栈,
	//父子环境的页异常栈不共享?具体原因还得思考
		env = &envs[ENVX(sys_getenvid())];
		set_pgfault_handler(pgfault);//设置缺页异常处理函数,这里设置了父环境的缺页异常栈
		for(i=0;i<(unsigned)VPN(UTOP);i++)//重映射writable or copy-to-write的页面
		{
			addr=i*PGSIZE;
			pde =(pde_t*) &vpd[VPD(addr)];
			if(*pde&PTE_P)//这里只处理有物理页面映射的页表项
			{
				pte=(pte_t*)&vpt[VPN(addr)];
			}
			else    continue;
			if((i==(unsigned)VPN(USTACKTOP-PGSIZE))||(i==(unsigned)VPN(PFTEMP)))
								//特殊处理,用户层普通栈
			{	
				if((r=duppage(envid,i))<0)
					return r;
				continue;
			}
			if((r=sduppage(envid,i))<0)
				return r;
		}
		if((r=sys_page_alloc(envid,(void*)(UXSTACKTOP-PGSIZE),PTE_W|PTE_U|PTE_P))<0)
                        return r;//设置子环境的缺页异常栈
		if((r=sys_env_set_pgfault_upcall(envid,(void*)_pgfault_upcall))<0)
			return r;//设置子环境的缺页异常处理入口点
		if((r=sys_env_set_status(envid,ENV_RUNNABLE))<0)
			return r;//设置子环境的状态为可运行
		return envid;
	}
	//panic("sfork not implemented");
	//return -E_INVAL;
}
Beispiel #2
0
//
// User-level fork with copy-on-write.
// Set up our page fault handler appropriately.
// Create a child.
// Copy our address space and page fault handler setup to the child.
// Then mark the child as runnable and return.
//
// Returns: child's envid to the parent, 0 to the child, < 0 on error.
// It is also OK to panic on error.
//
// Hint:
//   Use uvpd, uvpt, and duppage.
//   Remember to fix "thisenv" in the child process.
//   Neither user exception stack should ever be marked copy-on-write,
//   so you must allocate a new page for the child's user exception stack.
//
envid_t
fork(void)
{
	// LAB 4: Your code here.
	set_pgfault_handler(pgfault);
	envid_t childid = sys_exofork();
	if(childid < 0)
		panic("Fork Failed\n");
	if(childid == 0) {
		thisenv = &envs[ENVX(sys_getenvid())];
		return 0;
	}

	int i, j;
	for(i = 0; i < PDX(UTOP); i++) {
		if (!(uvpd[i] & PTE_P)) continue;
		for(j = 0; (j < 1024) && (i*NPDENTRIES + j < PGNUM(UXSTACKTOP - PGSIZE)); j++ ) {
			if(!uvpt[i*NPDENTRIES + j] & PTE_P) continue;
			if(duppage(childid, i*NPDENTRIES + j) < 0)
				panic("dup page failed");
		}
	}
	if ((sys_page_alloc(childid, (void *)(UXSTACKTOP - PGSIZE), PTE_U | PTE_P | PTE_W)) < 0) {
          panic("Allocation of page for Exception stack cups!\n");
        }

        if ((sys_env_set_pgfault_upcall(childid, thisenv->env_pgfault_upcall)) < 0) {
          panic("Unable to set child process' upcall");
        }

	 // Copy own uxstack to temp page
        memmove((void *)(UXSTACKTOP - PGSIZE), PFTEMP, PGSIZE);
	int r;
        // Unmap temp page
        if (sys_page_unmap(sys_getenvid(), PFTEMP) < 0) {
                return -1;
        }        

        if ((r = sys_env_set_pgfault_upcall(childid, thisenv->env_pgfault_upcall)) < 0)
                panic("sys_env_set_pgfault_upcall: error %e\n", r);

        if ((r = sys_env_set_status(childid, ENV_RUNNABLE)) < 0) {
                cprintf("sys_env_set_status: error %e\n", r);
                return -1;
        }


	return childid;
	panic("fork not implemented");
}
Beispiel #3
0
//
// User-level fork with copy-on-write.
// Set up our page fault handler appropriately.
// Create a child.
// Copy our address space and page fault handler setup to the child.
// Then mark the child as runnable and return.
//
// Returns: child's envid to the parent, 0 to the child, < 0 on error.
// It is also OK to panic on error.
//
// Hint:
//   Use uvpd, uvpt, and duppage.
//   Remember to fix "thisenv" in the child process.
//   Neither user exception stack should ever be marked copy-on-write,
//   so you must allocate a new page for the child's user exception stack.
//
envid_t
fork(void)
{
  extern void _pgfault_upcall();
  // LAB 4: Your code here.
  set_pgfault_handler(pgfault);

  envid_t envid = sys_exofork();
  if (envid == 0) {
    thisenv = &envs[ENVX(sys_getenvid())];
    return 0;
  }
  if (envid < 0) {
    panic("sys_exofork failed: %e", envid);
  }

  uint32_t addr;
  for (addr = 0; addr < USTACKTOP; addr += PGSIZE) {
    if ((uvpd[PDX(addr)] & PTE_P) && (uvpt[PGNUM(addr)] & PTE_P) && (uvpt[PGNUM(addr)] & PTE_U)) {
      duppage(envid, PGNUM(addr));
    }
  }
  int alloc_err = sys_page_alloc(envid, (void *)(UXSTACKTOP-PGSIZE), PTE_U|PTE_W|PTE_P);
  if (alloc_err) {
    panic("sys_page_alloc failed with error: %e", alloc_err);
  }
  sys_env_set_pgfault_upcall(envid, _pgfault_upcall);
  int set_status_err = sys_env_set_status(envid, ENV_RUNNABLE);
  if (set_status_err) {
    panic("sys_env_set_status");
  }
  return envid;
}
Beispiel #4
0
//
// User-level fork with copy-on-write.
// Set up our page fault handler appropriately.
// Create a child.
// Copy our address space and page fault handler setup to the child.
// Then mark the child as runnable and return.
//
// Returns: child's envid to the parent, 0 to the child, < 0 on error.
// It is also OK to panic on error.
//
// Hint:
//   Use uvpd, uvpt, and duppage.
//   Remember to fix "thisenv" in the child process.
//   Neither user exception stack should ever be marked copy-on-write,
//   so you must allocate a new page for the child's user exception stack.
//
envid_t
fork(void)
{
	// LAB 4: Your code here.
	set_pgfault_handler (pgfault);
	envid_t envid;
	uint32_t addr;
	int r;
	envid = sys_exofork();
	if (envid < 0)
		panic("sys_exofork: %e", envid);
	// We’re the child
	if (envid == 0) {
		env = &envs[ENVX(sys_getenvid())];
		return 0;
	}
	// We’re the parent.
	for (addr = UTEXT; addr < UXSTACKTOP - PGSIZE; addr += PGSIZE) {
	if ((vpd[VPD(addr)] & PTE_P) > 0 && (vpt[VPN(addr)] & PTE_P) > 0 && (vpt[
		VPN(addr)] & PTE_U) > 0)
		duppage (envid, VPN(addr));
	}

	if ((r = sys_page_alloc (envid, (void *)(UXSTACKTOP - PGSIZE), PTE_U|PTE_W|PTE_P)) < 0)
		panic ("fork: page allocation failed : %e", r);
	extern void _pgfault_upcall (void);
	sys_env_set_pgfault_upcall (envid, _pgfault_upcall);
	// Start the child environment running
	if ((r = sys_env_set_status(envid, ENV_RUNNABLE)) < 0)
		panic("fork: set child env status failed : %e", r);
	return envid;
	//panic("fork not implemented");
}
Beispiel #5
0
//
// Set the page fault handler function.
// If there isn't one yet, _pgfault_handler will be 0.
// The first time we register a handler, we need to
// allocate an exception stack (one page of memory with its top
// at UXSTACKTOP), and tell the kernel to call the assembly-language
// _pgfault_upcall routine when a page fault occurs.
//
void
set_pgfault_handler(void (*handler)(struct UTrapframe *utf))
{
	int r;
    int re;
    envid_t envid = sys_getenvid();

	if (_pgfault_handler == 0) {
		// First time through!
		// LAB 4: Your code here.

		sys_env_set_pgfault_upcall(envid, _pgfault_upcall);
		re = sys_page_alloc(envid, (void *)(UXSTACKTOP - PGSIZE),PTE_U | PTE_P |PTE_W);
        if( re < 0){
            cprintf("process %x,sys_page_alloc fail\n",envid);
            sys_env_destroy(envid);
        }

		//panic("set_pgfault_handler not implemented");
	}

	// Save handler pointer for assembly to call.

	_pgfault_handler = handler;
	//cprintf("_pgfault_handler = %x\n",(uint32_t)_pgfault_handler);
}
Beispiel #6
0
void
umain(int, char **)
{
	sys_page_alloc(0, (void*) (UXSTACKTOP - PGSIZE), PTE_P|PTE_U|PTE_W);
	sys_env_set_pgfault_upcall(0, (void*) 0xDeadBeef);
	*(int*)0 = 0;
}
Beispiel #7
0
//
// User-level fork with copy-on-write.
// Set up our page fault handler appropriately.
// Create a child.
// Copy our address space and page fault handler setup to the child.
// Then mark the child as runnable and return.
//
// Returns: child's envid to the parent, 0 to the child, < 0 on error.
// It is also OK to panic on error.
//
// Hint:
//   Use vpd, vpt, and duppage.
//   Remember to fix "thisenv" in the child process.
//   Neither user exception stack should ever be marked copy-on-write,
//   so you must allocate a new page for the child's user exception stack.
//
envid_t
fork(void)
{
	// LAB 4: Your code here.
	//panic("fork not implemented");
	extern void _pgfault_upcall(void);
	set_pgfault_handler(pgfault);
	envid_t id = sys_exofork();
	int r;
	if (id < 0)
		panic("exofork: child");
	if (id == 0)
	{
		thisenv = envs + ENVX(sys_getenvid());
		return 0;
	}
//	cprintf("fork id: %x",id);
	if ((r=sys_page_alloc(id, (void*)(UXSTACKTOP-PGSIZE), PTE_U | PTE_W | PTE_P))<0)
		return r;
	int i;
	for (i=0;i<UTOP-PGSIZE;i+=PGSIZE)
		if ((vpd[PDX(i)] & PTE_P) && (vpt[PGNUM(i)] & PTE_P))
		{
//			cprintf("i:%x ",i);
			if ((r=duppage(id,PGNUM(i)))<0)
				return r;
		}
	if ((r=sys_env_set_pgfault_upcall(id,(void*)_pgfault_upcall))<0)
		return r;
	if ((r=sys_env_set_status(id, ENV_RUNNABLE))<0)
		return r;
	return id;
}
//
// User-level fork with copy-on-write.
// Set up our page fault handler appropriately.
// Create a child.
// Copy our address space and page fault handler setup to the child.
// Then mark the child as runnable and return.
//
// Returns: child's envid to the parent, 0 to the child, < 0 on error.
// It is also OK to panic on error.
//
// Hint:
//   Use uvpd, uvpt, and duppage.
//   Remember to fix "thisenv" in the child process.
//   Neither user exception stack should ever be marked copy-on-write,
//   so you must allocate a new page for the child's user exception stack.
//
envid_t
fork(void)
{
    // LAB 4: Your code here.
    //panic("fork not implemented");
    void *addr;
    set_pgfault_handler(pgfault);
    envid_t forkid = sys_exofork();
    if (forkid < 0)
        panic("sys_exofork: %e", forkid);
    if(forkid == 0) {
        thisenv = &envs[ENVX(sys_getenvid())];
        return 0;
    }
    for (addr = (uint8_t*) UTEXT; addr < (void *) USTACKTOP; addr += PGSIZE)
        if( (uvpd[PDX(addr)] & PTE_P) && (uvpt[PGNUM(addr)] & PTE_P) )
            duppage(forkid, PGNUM(addr));
    if (sys_page_alloc(forkid, (void *)(UXSTACKTOP-PGSIZE), PTE_U|PTE_W|PTE_P) < 0)
        panic("user stack alloc failure\n");
    extern void _pgfault_upcall();
    if(sys_env_set_pgfault_upcall(forkid, _pgfault_upcall) < 0)
        panic("set pgfault upcall fails %d\n", forkid);
    if(sys_env_set_status(forkid, ENV_RUNNABLE) < 0)
        panic("set %d runnable fails\n", forkid);
    return forkid;
}
Beispiel #9
0
//
// Set the page fault handler function.
// If there isn't one yet, _pgfault_handler will be 0.
// The first time we register a handler, we need to
// allocate an exception stack (one page of memory with its top
// at UXSTACKTOP), and tell the kernel to call the assembly-language
// _pgfault_upcall routine when a page fault occurs.
//
void
set_pgfault_handler(void (*handler)(struct UTrapframe *utf))
{
	int r;

	//cprintf("inside page fault handler, _pgfault_handler = %0x\n", _pgfault_handler);
	if (_pgfault_handler == 0) {
		// First time through!
		// LAB 4: Your code here.
		envid_t envid = sys_getenvid();
		r = sys_page_alloc(envid, (void*) (UXSTACKTOP - PGSIZE), PTE_P|PTE_U|PTE_W);
		r = sys_page_alloc(envid, (void*) (UXSTACKTOP - 2*PGSIZE), PTE_P|PTE_U|PTE_W);
		if(r < 0)
			panic("page_alloc: %e", r);
		//cprintf("setting the upcall\n");
		r = sys_env_set_pgfault_upcall(envid, _pgfault_upcall);
		//cprintf("set the upcall with result = %d\n", r);
		if(r < 0)
			panic("pgfault_upcall: %e", r);
		//panic("set_pgfault_handler not implemented");
	}

	// Save handler pointer for assembly to call.
	_pgfault_handler = handler;
}
Beispiel #10
0
//
// User-level fork with copy-on-write.
// Set up our page fault handler appropriately.
// Create a child.
// Copy our address space and page fault handler setup to the child.
// Then mark the child as runnable and return.
//
// Returns: child's envid to the parent, 0 to the child, < 0 on error.
// It is also OK to panic on error.
//
// Hint:
//   Use vpd, vpt, and duppage.
//   Remember to fix "thisenv" in the child process.
//   Neither user exception stack should ever be marked copy-on-write,
//   so you must allocate a new page for the child's user exception stack.
//
    envid_t
fork(void)
{
    // LAB 4: Your code here.
    envid_t envid;
        uint64_t addr;
        uint32_t err;
        extern unsigned char end[];
        int r;

        set_pgfault_handler(pgfault);
        envid = sys_exofork();

        if (envid < 0)
                panic("sys_exofork: %e", envid);
        if (envid == 0) {
                // We're the child.
                // The copied value of the global variable 'thisenv'
                // is no longer valid (it refers to the parent!).
                // Fix it and return 0.

                thisenv = &envs[ENVX(sys_getenvid())];
                return 0;
        }

        //Allocate exception stack for the child
        if ((err = sys_page_alloc(envid, (void *) (UXSTACKTOP - PGSIZE), PTE_P|PTE_U|PTE_W)) < 0)
                panic("Error in sys_page_alloc: %e", err);

        // We're the parent.
        // Map our entire address space into the child.
        for (addr = UTEXT; addr < USTACKTOP-PGSIZE; addr += PGSIZE) {
               if((vpml4e[VPML4E(addr)] & PTE_P) && (vpde[VPDPE(addr)] & PTE_P)
                        && (vpd[VPD(addr)] & PTE_P) && (vpt[VPN(addr)] & PTE_P)) {
                       duppage(envid, VPN(addr));
                }
        }

        //Allocate a new stack for the child and copy the contents of parent on to it.
        addr = USTACKTOP-PGSIZE;
	if ((r = sys_page_alloc(0, (void *)PFTEMP, PTE_P|PTE_U|PTE_W)) < 0)
                panic("sys_page_alloc failed: %e\n", r);
        memcpy(PFTEMP, (void *) ROUNDDOWN(addr, PGSIZE), PGSIZE);
        void *vaTemp = (void *) ROUNDDOWN(addr, PGSIZE);
        if ((r = sys_page_map(0, (void *)PFTEMP, envid, vaTemp, PTE_P|PTE_U|PTE_W)) < 0)
                panic("sys_page_map failed: %e\n", r);
        if ((r = sys_page_unmap(0, (void *)PFTEMP)) < 0)
                panic("sys_page_unmap failed: %e\n", r);

        //Set child's page fault handler
        if ((err = sys_env_set_pgfault_upcall(envid, _pgfault_upcall) < 0))
                panic("Error in sys_env_set_pgfault_upcall: %e",err);

        //Set the child ready to run
        if ((err = sys_env_set_status(envid, ENV_RUNNABLE)) < 0)
                panic("sys_env_set_status: %e", err);

        return envid;
    panic("fork not implemented");
}
Beispiel #11
0
//
// Set the page fault handler function.
// If there isn't one yet, _pgfault_handler will be 0.
// The first time we register a handler, we need to
// allocate an exception stack (one page of memory with its top
// at UXSTACKTOP), and tell the kernel to call the assembly-language
// _pgfault_upcall routine when a page fault occurs.
//
void
set_pgfault_handler(void (*handler)(struct UTrapframe *utf))
{
	int r;

	if (_pgfault_handler == 0) {
		// First time through!
		// LAB 4: Your code here.
		void *offset=(void *)(UXSTACKTOP-PGSIZE);
//		envid_t envid=sys_getenvid();
//		cprintf("set_pgfault_handler\n");
		r=sys_page_alloc(0,(void *)(UXSTACKTOP-PGSIZE),PTE_P|PTE_U|PTE_W);
//		cprintf("page alloc successfull\n");
		if(r<0)
		{
			panic("not enough memory to allocate page");
		}
//		cprintf("setting page upcall\n");
		sys_env_set_pgfault_upcall(0,_pgfault_upcall);
		//panic("set_pgfault_handler not implemented");
	}

	// Save handler pointer for assembly to call.
	_pgfault_handler = handler;
}
// Dispatches to the correct kernel function, passing the arguments.
int64_t
syscall(uint64_t syscallno, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5)
{
	// Call the function corresponding to the 'syscallno' parameter.
	// Return any appropriate return value.
	// LAB 3: Your code here.
//	panic("syscall not implemented");

	switch (syscallno) {

	case SYS_cputs:
			sys_cputs((const char *)a1, (size_t)a2);
			return 0;
	case SYS_cgetc:
			return sys_cgetc();
        case SYS_getenvid:
			return sys_getenvid();
        case SYS_env_destroy:
			return sys_env_destroy(a1);
	case SYS_yield:
			sys_yield();
			return 0;			
	case SYS_page_alloc:
        		return sys_page_alloc((envid_t)a1, (void *)a2,(int)a3);
	case SYS_page_map:
			return sys_page_map((envid_t)a1, (void *)a2, (envid_t)a3, (void *)a4, (int)a5);        
	case SYS_page_unmap:
			return sys_page_unmap((envid_t)a1, (void *)a2);        
	case SYS_exofork:
			return sys_exofork();        
	case SYS_env_set_status:
			return sys_env_set_status((envid_t)a1, a2);	
	case SYS_env_set_pgfault_upcall:
			return sys_env_set_pgfault_upcall((envid_t)a1,(void *)a2);		
	case SYS_ipc_try_send:
			return sys_ipc_try_send((envid_t)a1, (uint32_t)a2, (void *)a3, a4);
	case SYS_ipc_recv:
			return sys_ipc_recv((void *)a1);	
	case SYS_env_set_trapframe:
			return sys_env_set_trapframe((envid_t)a1, (struct Trapframe *)a2);
	case SYS_time_msec:
			return sys_time_msec();
	case SYS_packet_transmit:
			return sys_packet_transmit((char*)a1,(size_t)a2);
	case SYS_packet_receive:
                        return sys_packet_receive((char *)a1);
	//lab 7 code from here
	case SYS_insmod:
			return sys_insmod((char *)a1, (char *)a2,(char *)a3);
	case SYS_rmmod:
			return sys_rmmod((char *)a1);
	case SYS_lsmod:
			return sys_lsmod();
	case SYS_depmod:
			return sys_depmod((char *)a1);
	//lab7 code ends here
	default:
		return -E_NO_SYS;
	}
}
Beispiel #13
0
//
// Set the page fault handler function.
// If there isn't one yet, _pgfault_handler will be 0.
// The first time we register a handler, we need to
// allocate an exception stack (one page of memory with its top
// at UXSTACKTOP), and tell the kernel to call the assembly-language
// _pgfault_upcall routine when a page fault occurs.
//
void
set_pgfault_handler(void (*handler)(struct UTrapframe *utf))
{
	int r;

	if (_pgfault_handler == 0) {
		// First time through!	
		// LAB 4: Your code here.

		//int sys_page_alloc(envid_t envid, void *va, int perm)
		r = sys_page_alloc(0, (void*)(UXSTACKTOP - PGSIZE), PTE_U | PTE_W | PTE_P);
		if (r < 0) {
			panic("sys_page_alloc error : %e\n", r);
		}

		// how to know envid, put 0, envid2env will help us to get curenv in syscall
		r = sys_env_set_pgfault_upcall(0, _pgfault_upcall);		
		if (r < 0) {
			panic("sys_env_set_pgfault_upcall error : %e\n", r);
		}
	}

	// Save handler pointer for assembly to call.
	_pgfault_handler = handler;
}
Beispiel #14
0
//
// Set the page fault handler function.
// If there isn't one yet, _pgfault_handler will be 0.
// The first time we register a handler, we need to
// allocate an exception stack (one page of memory with its top
// at UXSTACKTOP), and tell the kernel to call the assembly-language
// _pgfault_upcall routine when a page fault occurs.
//
void
set_pgfault_handler(void (*handler)(struct UTrapframe *utf))
{
	int r;

	if (_pgfault_handler == 0) {
		// First time through!
		// code for lab 4 -M.G
        //	panic("set_pgfault_handler not implemented");

        envid_t cur_envid = sys_getenvid();
        uintptr_t ux_stack_top = UXSTACKTOP - PGSIZE;
        
        if (sys_page_alloc(cur_envid, (void *)ux_stack_top, PTE_P | PTE_U | PTE_W) < 0)
        {        
            panic("ERROR: Cannot allocate memory for exception stack!!");
        }
        
        if (sys_env_set_pgfault_upcall(cur_envid, _pgfault_upcall) < 0)
        {
            panic("ERROR: Cannot set pagefault handler!!");
        }
	}

	// Save handler pointer for assembly to call.
	_pgfault_handler = handler;
}
Beispiel #15
0
//
// User-level fork with copy-on-write.
// Set up our page fault handler appropriately.
// Create a child.
// Copy our address space and page fault handler setup to the child.
// Then mark the child as runnable and return.
//
// Returns: child's envid to the parent, 0 to the child, < 0 on error.
// It is also OK to panic on error.
//
// Hint:
//   Use uvpd, uvpt, and duppage.
//   Remember to fix "thisenv" in the child process.
//   Neither user exception stack should ever be marked copy-on-write,
//   so you must allocate a new page for the child's user exception stack.
//
envid_t
fork(void)
{
	// LAB 4: Your code here.
    set_pgfault_handler(pgfault);
    int r, childid;
    childid = sys_exofork();
    if (childid <0)
            panic("exofork error in fork()!\n");
    else if (childid ==0)
    {
            thisenv = &envs[ENVX(sys_getenvid())];
            return 0;
    } else
    {
        int addr;
        for (addr = UTEXT; addr<UXSTACKTOP-PGSIZE; addr+=PGSIZE)
        {
                int pn = PGNUM(addr);
                if (((uvpd[PDX(addr)] & PTE_P) >0) &&
                    ((uvpt[pn] & PTE_P) >0) &&
                    ((uvpt[pn] & PTE_U) > 0))
                        duppage(childid, pn);
        }
        extern void _pgfault_upcall();
        sys_page_alloc(childid, (void*) (UXSTACKTOP - PGSIZE),  PTE_U|PTE_W|PTE_P);
        sys_env_set_pgfault_upcall(childid, _pgfault_upcall);
        sys_env_set_status(childid, ENV_RUNNABLE);
        return childid;
    }
}
Beispiel #16
0
//
// Set the page fault handler function.
// If there isn't one yet, _pgfault_handler will be 0.
// The first time we register a handler, we need to 
// allocate an exception stack (one page of memory with its top
// at UXSTACKTOP), and tell the kernel to call the assembly-language
// _pgfault_upcall routine when a page fault occurs.
//
void
set_pgfault_handler(void (*handler)(struct UTrapframe *utf))
{
	int r;

     //cprintf("Env %x called setpgflt handler cur value of pgflt handler %x\n",sys_getenvid(),_pgfault_handler);

    if (_pgfault_handler == 0) 
    {
         // First time through!
         // LAB 4: Your code here.

         //First allocate a page to map to UXSTACKTOP
        if ((r = sys_page_alloc(0, (void*)(UXSTACKTOP - PGSIZE), PTE_P|PTE_U|PTE_W)) < 0)
            panic("sys_page_alloc: %e", r);
 
        //cprintf("Registering the handler %x\n",handler);
        //Register the handler with kernel
        sys_env_set_pgfault_upcall(0,_pgfault_upcall);
    }

   // Save handler pointer for assembly to call.
    _pgfault_handler = handler;

}
Beispiel #17
0
//
// Set the page fault handler function.
// If there isn't one yet, _pgfault_handler will be 0.
// The first time we register a handler, we need to
// allocate an exception stack (one page of memory with its top
// at UXSTACKTOP), and tell the kernel to call the assembly-language
// _pgfault_upcall routine when a page fault occurs.
//
void
set_pgfault_handler(void (*handler)(struct UTrapframe *utf))
{
	int r;

	if (_pgfault_handler == 0) {
		r = sys_page_alloc(sys_getenvid(), (void*)(UXSTACKTOP - PGSIZE), PTE_W | PTE_U | PTE_P);

		if(r)
		{
			panic("pgfault.c:40: Error %e when allocating User Exception Stack\n", r);
		} 	
	}

	// Save handler pointer for assembly to call.
	_pgfault_handler = handler;

	/*
	* We register with the kernel the assembly routine to return to execution.
	*/
	r = sys_env_set_pgfault_upcall(sys_getenvid(), _pgfault_upcall);
	
	if(r)
	{
		panic("pgfault.c:55: Error %e when setting the pgfault upcall\n", r);
	} 	
}
Beispiel #18
0
// Dispatches to the correct kernel function, passing the arguments.
int32_t
syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5)
{
	// Call the function corresponding to the 'syscallno' parameter.
	// Return any appropriate return value.
	// LAB 3: Your code here.
        curenv->env_syscalls++;
        switch(syscallno){
        case SYS_cputs:
                sys_cputs((char *)a1, (size_t)a2);break;
        case SYS_cgetc:
                sys_cgetc();break;
        case SYS_getenvid:
                return sys_getenvid();
        case SYS_env_destroy:
                return sys_env_destroy((envid_t)a1);
        case SYS_dump_env:
                sys_dump_env();break;
        case SYS_page_alloc:
                return sys_page_alloc((envid_t)a1, (void *)a2, (int)a3);
        case SYS_page_map: {
                return sys_page_map((envid_t)a1, (void *)a2,
                                    (envid_t)a3, (void *)a4, (int)a5);
        }
        case SYS_page_unmap:
                return sys_page_unmap((envid_t)a1, (void *)a2);
        case SYS_exofork:
                return sys_exofork();
        case SYS_env_set_status:
                return sys_env_set_status((envid_t)a1,(int)a2);
        case SYS_env_set_trapframe:
                return sys_env_set_trapframe((envid_t)a1,
                                             (struct Trapframe *)a2);
        case SYS_env_set_pgfault_upcall:
                return sys_env_set_pgfault_upcall((envid_t)a1, (void *)a2);
        case SYS_yield:
                sys_yield();break;//new add syscall for lab4;
        case SYS_ipc_try_send:
                return sys_ipc_try_send((envid_t)a1, (uint32_t)a2,
                                        (void *)a3, (unsigned)a4);
        case SYS_ipc_recv:
                return sys_ipc_recv((void *)a1);
        case SYS_ide_read:
                sys_ide_read((uint32_t)a1, (void *)a2, (size_t)a3);
                break;
        case SYS_ide_write:
                sys_ide_write((uint32_t)a1, (void *)a2, (size_t)a3);
                break;
        case SYS_time_msec:
                return sys_time_msec();
        case NSYSCALLS:
                break;
        default:
                return -E_INVAL;
        }
        return 0;

	//panic("syscall not implemented");
}
Beispiel #19
0
//
// User-level fork with copy-on-write.
// Set up our page fault handler appropriately.
// Create a child.
// Copy our address space and page fault handler setup to the child.
// Then mark the child as runnable and return.
//
// Returns: child's envid to the parent, 0 to the child, < 0 on error.
// It is also OK to panic on error.
//
// Hint:
//   Use vpd, vpt, and duppage.
//   Remember to fix "thisenv" in the child process.
//   Neither user exception stack should ever be marked copy-on-write,
//   so you must allocate a new page for the child's user exception stack.
//
envid_t
fork(void)
{
	// LAB 4: Your code here.
	int r;
	envid_t envid;
	set_pgfault_handler(pgfault);
	if((envid = sys_exofork())<0)
		panic("sys_exofork error: %e\n",envid);

	if(envid == 0){
		thisenv = &envs[ENVX(sys_getenvid())];
		return 0;
	}	
	


	uint32_t vaddr;
	extern unsigned char end[];

	for (vaddr = 0 ; vaddr < UTOP; vaddr += PGSIZE ){
		//Check sequentially
		if ((vpml4e[VPML4E(vaddr)] & PTE_P ) && (vpde[VPDPE(vaddr)] & PTE_P ) && (vpd[VPD(vaddr)] & PTE_P ) 
				&& (vpt[VPN(vaddr)] & PTE_P)){ //Order is imp...
			if ((vaddr != (UXSTACKTOP - PGSIZE)) && (vaddr != (USTACKTOP - PGSIZE))){
				duppage(envid, (uint64_t)vaddr / PGSIZE);
			}
		}	
	}


	if ((r = sys_page_alloc(envid,(void*)(USTACKTOP - PGSIZE), PTE_U | PTE_W | PTE_P ))<0){
		panic("error from sys_page_alloc: %e\n", r);

	}
	else 
	{
		if ((r = sys_page_alloc(0, PFTEMP, PTE_U|PTE_W|PTE_P)) < 0)
	        panic("error from sys_page_alloc: %e", r);

		memmove(PFTEMP, (void *)(USTACKTOP - PGSIZE), PGSIZE);

		if ((r = sys_page_map(0,PFTEMP, envid, (void *)(USTACKTOP - PGSIZE) , PTE_U|PTE_W|PTE_P)) < 0)
	        panic("error from sys_page_map: %e", r);
	}

	if((r = sys_page_alloc(envid,(void*)(UXSTACKTOP - PGSIZE), PTE_U | PTE_W | PTE_P ))<0)	
		panic("error from sys_page_alloc : %e\n",r);

	if((r=sys_env_set_pgfault_upcall(envid, thisenv->env_pgfault_upcall))!=0)
		panic("error from sys_env_set_pgfault_upcall : %e\n",r);

	if((r = sys_env_set_status(envid, ENV_RUNNABLE))<0)
		panic("error from sys_env_set_status : %e\n",r);
	
	return envid;

}
Beispiel #20
0
// Dispatches to the correct kernel function, passing the arguments.
int32_t
syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5)
{
	// Call the function corresponding to the 'syscallno' parameter.
	// Return any appropriate return value.
	// LAB 3: Your code here.
    /* lj */
    int ret = 0;
    switch(syscallno) {
        case SYS_cputs:
            sys_cputs((const char *)a1, a2);
        break;
        case SYS_cgetc:
            ret = sys_cgetc();
        break;
        case SYS_getenvid:
            ret = sys_getenvid();
        break;
        case SYS_env_destroy:
            ret = sys_env_destroy(a1);
        break;
        case SYS_yield:
            sys_yield();
        break;
        case SYS_exofork:
            ret = sys_exofork();
        break;
        case SYS_env_set_status:
            ret = sys_env_set_status((envid_t)a1, a2);
        break;
        case SYS_page_alloc:
            ret = sys_page_alloc((envid_t)a1, (void *)a2, a3);
        break;
        case SYS_page_map:
            ret = sys_page_map((envid_t)a1, (void *)a2, (envid_t)a3, (void *)a4, a5);
        break;
        case SYS_page_unmap:
            ret = sys_page_unmap((envid_t)a1, (void *)a2);
        break;
        case SYS_env_set_pgfault_upcall:
            ret = sys_env_set_pgfault_upcall((envid_t)a1, (void *)a2);
        break;
        case SYS_ipc_try_send:
            ret = sys_ipc_try_send((envid_t)a1, a2, (void *)a3, a4);
        break;
        case SYS_ipc_recv:
            ret = sys_ipc_recv((void *)a1);
        break;
        default:
            ret = -E_INVAL;
        break;
    }

    //panic("syscall not implemented");
    //cprintf("%d return to user %d\n", syscallno, ret);
    return ret;
}
Beispiel #21
0
// Dispatches to the correct kernel function, passing the arguments.
int32_t
syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5)
{
	// Call the function corresponding to the 'syscallno' parameter.
	// Return any appropriate return value.
	// LAB 3: Your code here.
	int32_t ret = -E_INVAL;
	switch(syscallno) {
		case SYS_cputs:
			sys_cputs((char *)a1, a2);
			break;
		case SYS_cgetc:
			ret = sys_cgetc();
			break;
		case SYS_getenvid:
			ret = sys_getenvid();
			break;
		case SYS_env_destroy:
			ret = sys_env_destroy(a1);
			break;
		case SYS_yield:
			sys_yield();
			ret = 0;
			break;
		case SYS_map_kernel_page:
			ret = sys_map_kernel_page((void *)a1, (void *)a2);
			break;
		case SYS_sbrk:
			ret = sys_sbrk(a1);
			break;
		case SYS_exofork:
			ret = sys_exofork();
			break;
		case SYS_env_set_status:
			ret = sys_env_set_status(a1,a2);
			break;
		case SYS_page_alloc:
			ret = sys_page_alloc(a1,(void*)a2,a3);
			break;
		case SYS_page_map:
			ret = sys_page_map(a1,(void*)a2,a3,(void*)a4,a5);
			break;
		case SYS_page_unmap:
			ret = sys_page_unmap(a1,(void*)a2);
			break;
		case SYS_env_set_pgfault_upcall:
			ret = sys_env_set_pgfault_upcall(a1,(void*)a2);
			break;
		case SYS_ipc_try_send:
			ret = sys_ipc_try_send(a1,a2,(void*)a3,a4);
			break;
		case SYS_ipc_recv:
			ret = sys_ipc_recv((void*)a1);
	}
	return ret;
//	panic("syscall not implemented");
}
Beispiel #22
0
//
// User-level fork with copy-on-write.
// Set up our page fault handler appropriately.
// Create a child.
// Copy our address space and page fault handler setup to the child.
// Then mark the child as runnable and return.
//
// Returns: child's envid to the parent, 0 to the child, < 0 on error.
// It is also OK to panic on error.
//
// Hint:
//   Use vpd, vpt, and duppage.
//   Remember to fix "env" in the child process.
//   Neither user exception stack should ever be marked copy-on-write,
//   so you must allocate a new page for the child's user exception stack.
//
envid_t
fork(void)
{
	// LAB 4: Your code here.
	//cprintf("In environment %04x\n", sys_getenvid());
	set_pgfault_handler(pgfault);
	envid_t envid;
	int r;
	envid = sys_exofork();
	if(envid < 0)
		panic("sys_exofork: %e", envid);	
	else if(envid == 0)
	{
		env = &envs[ENVX(sys_getenvid())];
		//cprintf("I am the child %04x %04x\n", sys_getenvid(), env->env_id);
		return 0;
	}
	
	//cprintf("In the parent process %04x\n", sys_getenvid());
	if((r = sys_page_alloc(envid, (void *)(UXSTACKTOP - PGSIZE), PTE_W | PTE_U | PTE_P))<0)
		panic("sys_page_alloc: %e", r);
	if((r = sys_env_set_pgfault_upcall(envid, env->env_pgfault_upcall))<0)
		panic("sys_env_set_pgfault_upcall: %e", r);
	
	uint32_t va;
	for(va = UTEXT; va < UTOP; va += PGSIZE)
		if(va == UXSTACKTOP - PGSIZE) 
		{
			if((r = sys_page_alloc(envid, (void *)(UXSTACKTOP - PGSIZE), PTE_P | PTE_W | PTE_U))<0)
				panic("sys_page_alloc: %e", r);
		}
		else if((vpd[VPN(va)/NPTENTRIES] & PTE_P) && (vpt[VPN(va)] & PTE_P))
			duppage(envid, va>>PGSHIFT);

	//cprintf("Done with the copying in environment %04x\n", env->env_id);
	if((r = sys_env_set_pgfault_upcall(envid, env->env_pgfault_upcall))<0)
		panic("sys_env_set_pgfault_upcall: %e", r);

	if((r = sys_env_set_status(envid, ENV_RUNNABLE))<0)
		panic("sys_env_status: %e", r);

	// Returning the child's envid to the parent
	return envid;
}
Beispiel #23
0
//
// User-level fork with copy-on-write.
// Set up our page fault handler appropriately.
// Create a child.
// Copy our address space and page fault handler setup to the child.
// Then mark the child as runnable and return.
//
// Returns: child's envid to the parent, 0 to the child, < 0 on error.
// It is also OK to panic on error.
//
// Hint:
//   Use vpd, vpt, and duppage.
//   Remember to fix "env" and the user exception stack in the child process.
//   Neither user exception stack should ever be marked copy-on-write,
//   so you must allocate a new page for the child's user exception stack.
//
envid_t
fork(void)
{
	// LAB 4: Your code here.
	
	// Assembly language pgfault entrypoint defined in lib/pgfaultentry.S.
	extern void _pgfault_upcall(void);
	
	envid_t chenvid;	
	void *addr;
	void *addr2;
	unsigned pn;	
	pte_t pte, pde;
	int count, r, entries;

	set_pgfault_handler(pgfault);

	if ( (chenvid = sys_exofork()) < 0)
		panic("fork() - no free env!");
	else if (chenvid == 0){					//we are in child - ren
		env = &envs[ENVX(sys_getenvid())];	
		return 0;
	     }
	
	//we are in parent - ren

	//copy mappings - ren
	entries = NPDENTRIES;
	for(addr = 0; entries--; addr+=NPTENTRIES*PGSIZE){	//walk through page directory - ren
		pde = vpd[PDX(addr)];
		if (pde & PTE_P) {				
								//walk through page table - ren
			for(addr2 = addr, count = NPTENTRIES; ((uintptr_t)addr2 < (uintptr_t)UTOP - PGSIZE) && (count);
							       addr2+=PGSIZE, count--){	
				pte = vpt[VPN(addr2)];
				if (pte & PTE_P){
					duppage(chenvid, (uintptr_t)addr2/PGSIZE);				
				}
			}
			if (count)			
				break;				//reached exception stack - ren				
		}	
	}
	
	if( (r = sys_page_alloc(chenvid, (void *) UXSTACKTOP-PGSIZE, PTE_U | PTE_P | PTE_W)) < 0)
			panic("fork() - could not allocate exception stack for the child!");	

	if( (r = sys_env_set_pgfault_upcall(chenvid, (void *) _pgfault_upcall)) < 0)
			panic("fork() - could not set page fault entrypoint for the child!");

	if( (r = sys_env_set_status(chenvid, ENV_RUNNABLE)) < 0)
			panic("fork() - could not set child ENV_RUNNABLE!");

	return chenvid;
}		
Beispiel #24
0
Datei: fork.c Projekt: HVNT/6.828
envid_t
fork(void)
{
    // LAB 4: Your code here.
    // seanyliu
    int r;
    int pdidx = 0;
    int peidx = 0;
    envid_t childid;
    set_pgfault_handler(pgfault);

    // create child environment
    childid = sys_exofork();
    if (childid < 0) {
        panic("fork: failed to create child %d", childid);
    }
    if (childid == 0) {
        env = &envs[ENVX(sys_getenvid())];
        return 0;
    }

    // loop through pg dir, avoid user exception stack (which is immediately below UTOP
    for (pdidx = 0; pdidx < PDX(UTOP); pdidx++) {
        // check if the pg is present
        if (!(vpd[pdidx] & PTE_P)) continue;

        // loop through pg table entries
        for (peidx = 0; (peidx < NPTENTRIES) && (pdidx*NPDENTRIES+peidx < (UXSTACKTOP - PGSIZE)/PGSIZE); peidx++) {
            if (vpt[pdidx * NPTENTRIES + peidx] & PTE_P) {
                if ((r = duppage(childid, pdidx * NPTENTRIES + peidx)) < 0) {
                    panic("fork: duppage failed: %d", r);
                }
            }
        }
    }

    // allocate fresh page in the child for exception stack.
    if ((r = sys_page_alloc(childid, (void *)(UXSTACKTOP - PGSIZE), PTE_U | PTE_P | PTE_W)) < 0) {
        panic("fork: %d", r);
    }

    // parent sets the user page fault entrypoint for the child to look like its own.
    if ((r = sys_env_set_pgfault_upcall(childid, env->env_pgfault_upcall)) < 0) {
        panic("fork: %d", r);
    }

    // parent marks child runnable
    if ((r = sys_env_set_status(childid, ENV_RUNNABLE)) < 0) {
        panic("fork: %d", r);
    }

    return childid;

    //panic("fork not implemented");
}
Beispiel #25
0
//
// User-level fork with copy-on-write.
// Set up our page fault handler appropriately.
// Create a child.
// Copy our address space and page fault handler setup to the child.
// Then mark the child as runnable and return.
//
// Returns: child's envid to the parent, 0 to the child, < 0 on error.
// It is also OK to panic on error.
//
// Hint:
//   Use uvpd, uvpt, and duppage.
//   Remember to fix "thisenv" in the child process.
//   Neither user exception stack should ever be marked copy-on-write,
//   so you must allocate a new page for the child's user exception stack.
//
envid_t
fork(void)
{
	// LAB 4: Your code here.

	//panic("fork not implemented");
	envid_t envid=-1;
	pte_t ptentry=0, ptable=0, page_num=0;
	pde_t pdentry=0;
	uintptr_t addr=0;
	int pdindex = 0, pte_perm=0, pte_loop=0;
	int r=-1;
	//cprintf("\nin fork envid:%x\n", thisenv->env_id);
	set_pgfault_handler(pgfault);
	if((envid=sys_exofork())<0)
		panic("\nCannot create a child process:%e\n",envid);
	//cprintf("\nenvid of newly created child:%x\n",envid);
	if (envid == 0) {
		// We're the child.
		// The copied value of the global variable 'thisenv'
		// is no longer valid (it refers to the parent!).
		// Fix it and return 0.
		thisenv = &envs[ENVX(sys_getenvid())];
		//set_pgfault_handler(pgfault);
		return 0;
	}
	//Incrementing by PGSIZE in loop because 1 page of pgsize corresponds to 1 page taable entry
	//Incrementing the address by 4MB because uvpd has no entry means 1 uvpd->4 MB region so need to skip it.
	while(addr<(UXSTACKTOP-PGSIZE))
	{
		//cprintf("parent address:%x",addr);
		if(uvpd[PDX(addr)] & PTE_P)
		{
			if(uvpt[PGNUM(addr)] & PTE_P)
			{
				//cprintf("\ncalling duppgae for address %x\n",addr);
				duppage(envid, PGNUM(addr));
			}
			addr += PGSIZE;
		}
		else
		{
			addr = addr + PTSIZE;
		}
	}

	if ((r = sys_page_alloc(envid,(void *)UXSTACKTOP-PGSIZE, PTE_P|PTE_U|PTE_W)) < 0)
		panic("sys_page_alloc: %e", r);
	if ((r = sys_env_set_pgfault_upcall(envid, _pgfault_upcall)) < 0)
		panic("pagefault upcall setup error: %e", r);
	sys_env_set_status(envid, ENV_RUNNABLE);
	//cprintf("\n fork exiting - envid:%x\n",thisenv->env_id);
	return envid;

}
Beispiel #26
0
// Dispatches to the correct kernel function, passing the arguments.
int32_t
syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5)
{
	// Call the function corresponding to the 'syscallno' parameter.
	// Return any appropriate return value.
	// LAB 3: Your code here.
	int32_t r =0;
	switch(syscallno){
		case SYS_cputs:
			sys_cputs((const char*)a1,(size_t)a2);
			break;
		case SYS_cgetc:
			r = sys_cgetc();
			break;
		case SYS_getenvid:
			r = sys_getenvid();
			break;
		case SYS_env_destroy:
			r = sys_env_destroy((envid_t)a1);
			break;
		case SYS_yield:
			sys_yield();
			r =0;
			break;
		case SYS_exofork:
			r = sys_exofork();
			break;
		case SYS_env_set_status:
			r = sys_env_set_status((envid_t)a1,(int)a2);
			break;
		case SYS_page_alloc:
			r = sys_page_alloc((envid_t)a1 ,(void *)a2, (int)a3);
			break;
		case SYS_page_map:
			r = sys_page_map((envid_t)a1, (void *)a2, (envid_t)a3, (void *)a4, (int)a5);
			break;
		case SYS_page_unmap:
			r = sys_page_unmap((envid_t)a1,(void *)a2);
			break;
		case SYS_env_set_pgfault_upcall:
			r = sys_env_set_pgfault_upcall((envid_t)a1, (void *)a2);
			break;
		case SYS_ipc_try_send:
			r = sys_ipc_try_send((envid_t)a1, (uint32_t)a2, (void *)a3, (unsigned int)a4);
			break;
		case SYS_ipc_recv:
			r = sys_ipc_recv((void *)a1);
			break;
		default:
			r = -E_INVAL;
	}
	return r;
	panic("syscall not implemented");
}
Beispiel #27
0
// Dispatches to the correct kernel function, passing the arguments.
int32_t
syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5)
{
	// Call the function corresponding to the 'syscallno' parameter.
	// Return any appropriate return value.
	// LAB 3: Your code here.
	switch (syscallno){
		case SYS_getenvid:
			return sys_getenvid();
		case SYS_cputs:
			sys_cputs((const char*)a1, a2);
			return 0;
		case SYS_cgetc:
			return sys_cgetc();
		case SYS_env_destroy:
			return sys_env_destroy(a1);
		case SYS_map_kernel_page:
			return sys_map_kernel_page((void*)a1, (void*)a2);
		case SYS_sbrk:
			return sys_sbrk(a1);
		case SYS_yield:
			sys_yield();
			return 0;
		case SYS_exofork:
			return sys_exofork();
		case SYS_env_set_status:
			return sys_env_set_status((envid_t)a1, (int)a2);
		case SYS_page_alloc:
			return sys_page_alloc((envid_t)a1, (void *)a2, 
						(int)a3);
		case SYS_page_map:
			return sys_page_map((envid_t)*((uint32_t*)a1),
					(void*)*((uint32_t*)a1+1), 
					(envid_t)*((uint32_t*)a1+2), 
					(void*)*((uint32_t*)a1+3), 
					(int)*((uint32_t*)a1+4));
		case SYS_page_unmap:
			return sys_page_unmap((envid_t)a1, (void*)a2);
		case SYS_env_set_priority:
			return sys_env_set_priority((envid_t)a1, (int) a2);
		case SYS_env_set_pgfault_upcall:
			return sys_env_set_pgfault_upcall((envid_t)a1,
						 (void*)a2);
		case SYS_ipc_recv:
			return sys_ipc_recv((void*)a1);
		case SYS_ipc_try_send:
			return sys_ipc_try_send((envid_t)a1, a2, 
						(void*)a3, (int)a4);
		default:
			return -E_INVAL;
	}
}
Beispiel #28
0
// Dispatches to the correct kernel function, passing the arguments.
int32_t
syscall(uint32_t syscallno, uint32_t a1, uint32_t a2, uint32_t a3, uint32_t a4, uint32_t a5)
{
	// Call the function corresponding to the 'syscallno' parameter.
	// Return any appropriate return value.
	// LAB 3: Your code here.

//	panic("syscall not implemented");

	switch (syscallno) {
	case SYS_cputs:
		sys_cputs((char *)a1, a2);
		break;
	case SYS_cgetc:
		return sys_cgetc();
	case SYS_env_destroy:
		return sys_env_destroy(a1);
	case SYS_getenvid:
		return sys_getenvid();
	case SYS_yield:
		sys_yield();
		break;
	case SYS_page_alloc:
		return sys_page_alloc(a1, (void *)a2, a3);
	case SYS_page_map:
		return sys_page_map(a1, (void *)a2, a3, (void *)a4, a5);
	case SYS_page_unmap:
		return sys_page_unmap(a1, (void *)a2);
	case SYS_env_set_status:
		return sys_env_set_status(a1, a2);
	case SYS_exofork:
		return sys_exofork();
	case SYS_env_set_pgfault_upcall:
		return sys_env_set_pgfault_upcall(a1, (void *)a2);
	case SYS_ipc_try_send:
		return sys_ipc_try_send(a1, a2, (void*)a3, a4);
	case SYS_ipc_recv:
		return sys_ipc_recv((void*)a1);
	case SYS_env_set_trapframe:
		return sys_env_set_trapframe(a1, (struct Trapframe *)a2);
	case SYS_time_msec:
		return sys_time_msec();
	case SYS_trans_pkt:
		return sys_trans_pkt((void*)a1, a2);
	case SYS_recv_pkt:
		return sys_recv_pkt((void *)a1, (size_t *)a2);
	default:
		return -E_INVAL;
	}

	return 0;
}
Beispiel #29
0
//
// User-level fork with copy-on-write.
// Set up our page fault handler appropriately.
// Create a child.
// Copy our address space and page fault handler setup to the child.
// Then mark the child as runnable and return.
//
// Returns: child's envid to the parent, 0 to the child, < 0 on error.
// It is also OK to panic on error.
//
// Hint:
//   Use uvpd, uvpt, and duppage.
//   Remember to fix "thisenv" in the child process.
//   Neither user exception stack should ever be marked copy-on-write,
//   so you must allocate a new page for the child's user exception stack.
//
envid_t
fork(void)
{
    // Step 1: install user mode pgfault handler.
    set_pgfault_handler(pgfault);

    // Step 2: create child environment.
    envid_t envid = sys_exofork();
    if (envid < 0) {
        panic("fork: cannot create child env");
    }
    else if (envid == 0) {
        // child environment.
        thisenv = &envs[ENVX(sys_getenvid())];
        return 0;
    }

    // Step 3: duplicate pages.
    int ipd;
    for (ipd = 0; ipd < PDX(UTOP); ipd++) {
        // No page table yet.
        if (!(uvpd[ipd] & PTE_P))
            continue;

        int ipt;
        for (ipt = 0; ipt < NPTENTRIES; ipt++) {
            unsigned pn = (ipd << 10) | ipt;
            if (pn != PGNUM(UXSTACKTOP - PGSIZE)) {
                duppage(envid, pn);
            }
        }
    }

    // allocate a new page for child to hold the exception stack.
    if (sys_page_alloc(envid, (void *)(UXSTACKTOP - PGSIZE), PTE_W | PTE_U | PTE_P)) {
        panic("fork: no phys mem for xstk");
    }

    // Step 4: set user page fault entry for child.
    if (sys_env_set_pgfault_upcall(envid, thisenv->env_pgfault_upcall)) {
        panic("fork: cannot set pgfault upcall");
    }

    // Step 5: set child status to ENV_RUNNABLE.
    if (sys_env_set_status(envid, ENV_RUNNABLE)) {
        panic("fork: cannot set env status");
    }

    return envid;

}
Beispiel #30
0
// Dispatches to the correct kernel function, passing the arguments.
	int64_t
syscall(uint64_t syscallno, uint64_t a1, uint64_t a2, uint64_t a3, uint64_t a4, uint64_t a5)
{
	// Call the function corresponding to the 'syscallno' parameter.
	// Return any appropriate return value.
	// LAB 3: Your code here.
	uint64_t retval = 0;

	switch (syscallno) {
		case SYS_cputs:
			sys_cputs((char *) a1, (size_t) a2);
			return retval;
		case SYS_cgetc:
			return (int64_t) sys_cgetc();
		case SYS_getenvid:
			return (int64_t) sys_getenvid();
		case SYS_env_destroy:
			return (int64_t) sys_env_destroy((envid_t) a1);
		case SYS_yield:
			sys_yield();
			return retval;
		case SYS_exofork:
			return (int64_t)sys_exofork();
		case SYS_page_alloc:
			return (int64_t)sys_page_alloc((envid_t)a1, (void *)a2, (int)a3);
		case SYS_page_map:
			return (int64_t)sys_page_map((envid_t)a1, (void *)a2, (envid_t)a3, (void *)a4, (int)a5);
		case SYS_page_unmap:
			return (int64_t)sys_page_unmap((envid_t)a1, (void *)a2);
		case SYS_env_set_status:
			return (int64_t)sys_env_set_status((envid_t)a1, (int)a2);
		case SYS_env_set_pgfault_upcall:
			return (int64_t)sys_env_set_pgfault_upcall((envid_t)a1, (void *)a2);
		case SYS_ipc_try_send:
			return (int64_t) sys_ipc_try_send((envid_t) a1, (uint32_t) a2, (void *) a3, (unsigned) a4);
		case SYS_ipc_recv:
			return (int64_t)sys_ipc_recv((void*)a1);
		case SYS_env_set_trapframe:
			return sys_env_set_trapframe((envid_t)a1, (struct Trapframe*)a2);
		case SYS_time_msec:
			return sys_time_msec();
		case SYS_net_try_send:
			return sys_net_try_send((char *) a1, (int) a2);
		case SYS_net_try_receive:
			return sys_net_try_receive((char *) a1, (int *) a2);
		default:
			return -E_INVAL;
	}

	panic("syscall not implemented");
}