Exemplo n.º 1
0
static int
sys_get_mac(uint32_t *low, uint32_t *high)
{
	user_mem_assert(curenv, low, sizeof(uint32_t), PTE_P | PTE_U);
	user_mem_assert(curenv, high, sizeof(uint32_t), PTE_P | PTE_U);
	*low = e100[E1000_RAL/sizeof(uint32_t)];
	*high = e100[E1000_RAH/sizeof(uint32_t)] & 0x0000ffff;
	return 0;
}
Exemplo n.º 2
0
// Set envid's trap frame to 'tf'.
// tf is modified to make sure that user environments always run at code
// protection level 3 (CPL 3) with interrupts enabled.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_trapframe(envid_t envid, struct Trapframe *tf)
{
	// LAB 5: Your code here.
	// Remember to check whether the user has supplied us with a good
	// address!
	struct Env *env;
	pte_t *entry;

	user_mem_assert(curenv, tf, sizeof(struct Trapframe), 0);
	if (envid2env(envid, &env, 1) != 0){
		return -E_BAD_ENV;
	}

	entry = pgdir_walk(curenv->env_pgdir, (void *)tf, 0);
	if (entry == NULL){
		return -E_INVAL;
	}

	env->env_tf = *tf;
	// Missing here
	env->env_tf.tf_ds |= 3;
	env->env_tf.tf_es |= 3;
	env->env_tf.tf_ss |= 3;
	env->env_tf.tf_cs |= 3;
	env->env_tf.tf_eflags |= FL_IF;
	env->env_tf.tf_eflags &= ~(FL_IOPL_MASK);
	return 0;
}
Exemplo n.º 3
0
static int
sys_net_rx(void * buf)
{
	int result = 0;
	user_mem_assert(curenv, (const void *)buf, PGSIZE, PTE_U);
	result = pci_receive_packet(buf);
	return result;
}
Exemplo n.º 4
0
static void
sys_cputs(const char *s, size_t len)
{
	// Check that the user has permission to read memory [s, s+len).
	// Destroy the environment if not.
	user_mem_assert(curenv, s, len, 0);
	cprintf("%.*s", len, s);

}
Exemplo n.º 5
0
static int
sys_net_tx(void * buf, size_t size)
{
	//check for user buffer permissions and address
	int result = -1;
	user_mem_assert(curenv, (const void *)buf, size, PTE_U);
	result = pci_transmit_packet(buf ,size);
	return result;
}
Exemplo n.º 6
0
static int
sys_receive_packet(void *va)
{
	int pkt_len = 0;

	user_mem_assert(curenv, va, MAX_ETH_FRAME, PTE_P | PTE_W);
	pkt_len = nic_e100_recv_pkt(va);

	return pkt_len;
}
Exemplo n.º 7
0
Arquivo: syscall.c Projeto: ichaos/jos
// Print a string to the system console.
// The string is exactly 'len' characters long.
// Destroys the environment on memory errors.
static void
sys_cputs(const char *s, size_t len)
{
	// Check that the user has permission to read memory [s, s+len).
	// Destroy the environment if not.
	// LAB 3: Your code here.
        user_mem_assert(curenv, (void *)s, len, PTE_U|PTE_P);
	// Print the string supplied by the user.
	cprintf("%.*s", len, s);
}
static void
sys_cputs(const char *s, size_t len)
{
	// Check that the user has permission to read memory [s, s+len).
	// Destroy the environment if not.

	// LAB 3: Your code here.
        struct Env *e;
	envid2env(sys_getenvid(), &e, 1);
	user_mem_assert(e, s, len, PTE_U);
	// Print the string supplied by the user.
	cprintf("%.*s", len, s);
}
Exemplo n.º 9
0
Arquivo: syscall.c Projeto: gzs715/JOS
// Print a string to the system console.
// The string is exactly 'len' characters long.
// Destroys the environment on memory errors.
static void
sys_cputs(const char *s, size_t len)
{
	// Check that the user has permission to read memory [s, s+len).
	// Destroy the environment if not.
	
	// LAB 3: Your code here.
	//cprintf("curenv env id:%08x,s:%08x,len:%08x\n",curenv->env_id,s,len);
	user_mem_assert(curenv, s, len, 0);

	// Print the string supplied by the user.
	cprintf("%.*s", len, s);
}
Exemplo n.º 10
0
Arquivo: syscall.c Projeto: gzs715/JOS
// Set the page fault upcall for 'envid' by modifying the corresponding struct
// Env's 'env_pgfault_upcall' field.  When 'envid' causes a page fault, the
// kernel will push a fault record onto the exception stack, then branch to
// 'func'.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_pgfault_upcall(envid_t envid, void *func)
{
	// LAB 4: Your code here.
	struct Env *env;
	if(envid2env(envid,&env,1) == -E_BAD_ENV)
		return -E_BAD_ENV;
	env -> env_pgfault_upcall = func;
	//cprintf("env_pgfault_upcall:%08x\n",env->env_pgfault_upcall);
	user_mem_assert(env, (void *)(env->env_pgfault_upcall), 4,0);
	//cprintf("set pgfault up call successfully\n");
	return 0;
	//panic("sys_env_set_pgfault_upcall not implemented");
}
Exemplo n.º 11
0
// Set envid's trap frame to 'tf'.
// tf is modified to make sure that user environments always run at code
// protection level 3 (CPL 3) with interrupts enabled.
static int
sys_env_set_trapframe(envid_t envid, struct Trapframe *tf)
{
	struct Env *e;
	int r;
	if ((r = envid2env(envid, &e, 1)) < 0)
		return r;

	user_mem_assert(e, tf, SIZEOF_STRUCT_TRAPFRAME, 0);
	spin_lock(&e->env_lock);
	e->env_tf = *tf;
	spin_unlock(&e->env_lock);
	return 0;
}
Exemplo n.º 12
0
// Set envid's trap frame to 'tf'.
// tf is modified to make sure that user environments always run at code
// protection level 3 (CPL 3) with interrupts enabled.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_trapframe(envid_t envid, struct Trapframe *tf)
{
	// LAB 5: Your code here.
	// Remember to check whether the user has supplied us with a good
	// address!
    struct Env *e; 
    int ret = envid2env(envid, &e, 1);
    if (ret) return ret;
    user_mem_assert(e, tf, sizeof(struct Trapframe), PTE_U);
    e->env_tf = *tf;
    e->env_tf.tf_eflags = FL_IF|3;
    e->env_tf.tf_cs = GD_UT|3;
    return 0;
//	panic("sys_env_set_trapframe not implemented");
}
Exemplo n.º 13
0
static int
sys_recv_pkt(void *va, size_t *len)
{
	int r;
	user_mem_assert(curenv, va, PGSIZE/2, PTE_W | PTE_P | PTE_U);
	if (!len)
		return -E_INVAL;
	if ((r = receive_packet(va, len)) < 0) {
		curenv->env_e1000_recving = 1;
		curenv->env_status = ENV_NOT_RUNNABLE;
		curenv->env_tf.tf_regs.reg_eax = r;
		sched_yield();
	} else {
		return 0;
	}
}
Exemplo n.º 14
0
// Set the page fault upcall for 'envid' by modifying the corresponding struct
// Env's 'env_pgfault_upcall' field.  When 'envid' causes a page fault, the
// kernel will push a fault record onto the exception stack, then branch to
// 'func'.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_pgfault_upcall(envid_t envid, void *func)
{
	// LAB 4: Your code here.
	struct Env *e;
	
	// Envid valid and caller has perms to access it
	if (envid2env(envid, &e, 1) < 0) {
		return -E_BAD_ENV;
	}

	e->env_pgfault_upcall = func;
	user_mem_assert(e, func, 4, 0);

	return 0;
}
// Set envid's trap frame to 'tf'.
// tf is modified to make sure that user environments always run at code
// protection level 3 (CPL 3) with interrupts enabled.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_trapframe(envid_t envid, struct Trapframe *tf)
{
	// LAB 5: Your code here.
	// Remember to check whether the user has supplied us with a good
	// address!
	//panic("sys_env_set_trapframe not implemented");
        struct Env *newenv;
        int ret;
        if((ret = envid2env(envid, &newenv, 1)) < 0)  
                return ret;
        user_mem_assert(newenv, tf, sizeof(struct Trapframe), PTE_U);
        newenv->env_tf = *tf;
	newenv->env_tf.tf_eflags |= FL_IF;
        newenv->env_tf.tf_cs = GD_UT | 3;	
        return 0;
}
Exemplo n.º 16
0
// Set envid's trap frame to 'tf'.
// tf is modified to make sure that user environments always run at code
// protection level 3 (CPL 3) with interrupts enabled.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_trapframe(envid_t envid, struct Trapframe *tf)
{
	// LAB 5: Your code here.
	// Remember to check whether the user has supplied us with a good
	// address!
	struct Env *env;

	if (envid2env(envid, &env, true) != 0)
		return -E_BAD_ENV;

	user_mem_assert(env, tf, sizeof(struct Trapframe), PTE_W);

	env->env_tf = *tf;
	env->env_tf.tf_eflags |= FL_IF;
	return 0;
}
Exemplo n.º 17
0
// Set the page fault upcall for 'envid' by modifying the corresponding struct
// Env's 'env_pgfault_upcall' field.  When 'envid' causes a page fault, the
// kernel will push a fault record onto the exception stack, then branch to
// 'func'.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_pgfault_upcall(envid_t envid, void *func)
{
	// LAB 4: Your code here.
        int errno;
        struct Env *env;
        
        if ((errno = envid2env(envid, &env, 1)) < 0) {
                dbg_print("env 0x%08x does not exist", envid);
                return errno;
        }

        env->env_pgfault_upcall = func;
        user_mem_assert(env, func, sizeof(func), 0);

        return 0;
	//panic("sys_env_set_pgfault_upcall not implemented");
}
Exemplo n.º 18
0
// Set envid's trap frame to 'tf'.
// tf is modified to make sure that user environments always run at code
// protection level 3 (CPL 3) with interrupts enabled.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_trapframe(envid_t envid, struct Trapframe *tf)
{
	// LAB 4: Your code here.
	// Remember to check whether the user has supplied us with a good
	// address!
	
	struct Env *e;
	int r;
		
	if (( r = envid2env(envid, &e, 1)) < 0)
		return r;
	user_mem_assert(curenv, (const void *)tf, sizeof(struct Trapframe), 0);
	
	tf->tf_eflags |= FL_IF;
	tf->tf_cs |= 3;
	e->env_tf = *tf;
	
	return 0;
}
Exemplo n.º 19
0
// Set envid's trap frame to 'tf'.
// tf is modified to make sure that user environments always run at code
// protection level 3 (CPL 3) with interrupts enabled.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_trapframe(envid_t envid, struct Trapframe *tf)
{
	// LAB 5: Your code here.
	// Remember to check whether the user has supplied us with a good
	// address!
       cprintf("tf value esp-->%x eip  %x",tf->tf_esp,tf->tf_eip);  
    user_mem_assert(curenv,(void *)tf,sizeof(tf),0);
       struct Env *e;  
           if(envid2env(envid,&e,1)<0)
               return -E_BAD_ENV;
         e->env_tf=*tf;
         //e->env_tf.tf_cs=tf->tf_cs|3;
         e->env_tf.tf_eflags|=FL_IF;
         e->env_tf.tf_eflags&=~(FL_IOPL_3);
               
      cprintf("\nHere inside setting trapframe\n");    
     
       return 0;
	//panic("sys_env_set_trapframe not implemented");
}
Exemplo n.º 20
0
//
// Transmit packet data pointed to by pkt to the e1000 network controller.
// If the e1000 has no more space in the transmission buffer, sys_e1000_transmit
// will yield the CPU and try later, much like the loop in ipc_send().
// If after 20 tries the packet cannot be transmitted, return -E_E1000_TXBUF_FULL.
//
// Returns 0 on succes, -E_BAD_ENV if the envid doesn't exist and -E_E1000_TXBUF_FULL
// if after 20 retries the packet still cannot be sent.
//
static int
sys_e1000_transmit(envid_t envid, char *pkt, size_t length)
{
	struct Env *env;

	if (envid2env(envid, &env, 0) != 0)
		return -E_BAD_ENV;

	user_mem_assert(env, pkt, length, PTE_W);

	int num_tries = 20;
	while((e1000_transmit(pkt, length) == -1) && (num_tries > 0)) {
		sys_yield();
		num_tries--;
	}

	if (num_tries == 0)
		return -E_E1000_TXBUF_FULL;

	return 0;
}
Exemplo n.º 21
0
Arquivo: syscall.c Projeto: yahu/JOS
// Print a string to the system console.
// The string is exactly 'len' characters long.
// Destroys the environment on memory errors.
static void
sys_cputs(const char *s, size_t len)
{
	// Check that the user has permission to read memory [s, s+len).
	// Destroy the environment if not.

	// LAB 3: Your code here.
    user_mem_assert(curenv, (void *)s, len, PTE_U | PTE_P | PTE_W);

	pte_t * ptx;
	uint32_t st = ROUNDDOWN((uint32_t) s,PGSIZE);

    while(st < (uint32_t)s + len ){
        ptx=pgdir_walk(curenv->env_pgdir,(void *)st, 0);
        if(!ptx || !(*ptx & PTE_P) || !(*ptx & PTE_U) )
            env_destroy(curenv);
        st+=PGSIZE;
    }

	// Print the string supplied by the user.
	cprintf("%.*s", len, s);
}
Exemplo n.º 22
0
// Set envid's trap frame to 'tf'.
// tf is modified to make sure that user environments always run at code
// protection level 3 (CPL 3) with interrupts enabled.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_trapframe(envid_t envid, struct Trapframe *tf)
{
	// LAB 5: Your code here.
	// Remember to check whether the user has supplied us with a good
	// address!
	
	struct Env *env = NULL;

	int i;

	if((i = envid2env(envid,&env,1)) < 0) return i;

	user_mem_assert(env,tf,sizeof(struct Trapframe), PTE_U);

	tf->tf_cs |= 0x3;
	tf->tf_eflags |= FL_IF;	

	env->env_tf = *tf;	
	return 0;
	//panic("sys_env_set_trapframe not implemented");
}
Exemplo n.º 23
0
Arquivo: syscall.c Projeto: yahu/JOS
// Set the page fault upcall for 'envid' by modifying the corresponding struct
// Env's 'env_pgfault_upcall' field.  When 'envid' causes a page fault, the
// kernel will push a fault record onto the exception stack, then branch to
// 'func'.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_pgfault_upcall(envid_t envid, void *func)
{
	// LAB 4: Your code here.
	struct Env* e;



	if(envid2env(envid,&e,1) < 0)
        return -E_BAD_ENV;

    user_mem_assert(e,(void*)func,sizeof(void *),PTE_U);
        //return -E_BAD_ENV;

    if(curenv != e && e -> env_parent_id != curenv->env_id )
        return -E_BAD_ENV;
    e->env_pgfault_upcall = func;
   // cprintf("in sys_env_set_pgfault_upcall,env %x  set pgfault upcall\n",envid);

    return 0;
	//panic("sys_env_set_pgfault_upcall not implemented");
}
Exemplo n.º 24
0
// Set envid's trap frame to 'tf'.
// tf is modified to make sure that user environments always run at code
// protection level 3 (CPL 3) with interrupts enabled.
//
// Returns 0 on success, < 0 on error.  Errors are:
//	-E_BAD_ENV if environment envid doesn't currently exist,
//		or the caller doesn't have permission to change envid.
static int
sys_env_set_trapframe(envid_t envid, struct Trapframe *tf)
{
	// LAB 5: Your code here.
	// Remember to check whether the user has supplied us with a good
	// address!
	//panic("sys_env_set_trapframe not implemented");
	struct Env* env;
	envid2env(envid,&env,1);
	if(env == NULL)
		return -E_BAD_ENV;
	user_mem_assert(env, tf, sizeof(struct Trapframe), PTE_U);

	
	tf->tf_ds = GD_UD | 3;
	tf->tf_es = GD_UD | 3;
	tf->tf_ss = GD_UD | 3;
	tf->tf_cs = GD_UT | 3;	
	
	tf->tf_eflags |= FL_IF;
	env->env_tf=*tf;	
	return 0;
}
Exemplo n.º 25
0
void
page_fault_handler(struct Trapframe *tf)
{
	uint32_t fault_va;

	// Read processor's CR2 register to find the faulting address
	fault_va = rcr2();

	// Handle kernel-mode page faults.
	
	// LAB 3: Your code here.
	if ((tf->tf_cs & 3) == 0) {
		panic("kernel-mode page fault!\n");
	}

	// We've already handled kernel-mode exceptions, so if we get here,
	// the page fault happened in user mode.

	// Call the environment's page fault upcall, if one exists.  Set up a
	// page fault stack frame on the user exception stack (below
	// UXSTACKTOP), then branch to curenv->env_pgfault_upcall.
	//
	// The page fault upcall might cause another page fault, in which case
	// we branch to the page fault upcall recursively, pushing another
	// page fault stack frame on top of the user exception stack.
	//
	// The trap handler needs one word of scratch space at the top of the
	// trap-time stack in order to return.  In the non-recursive case, we
	// don't have to worry about this because the top of the regular user
	// stack is free.  In the recursive case, this means we have to leave
	// an extra word between the current top of the exception stack and
	// the new stack frame because the exception stack _is_ the trap-time
	// stack.
	//
	// If there's no page fault upcall, the environment didn't allocate a
	// page for its exception stack, or the exception stack overflows,
	// then destroy the environment that caused the fault.
	//
	// Hints:
	//   user_mem_assert() and env_run() are useful here.
	//   To change what the user environment runs, modify 'curenv->env_tf'
	//   (the 'tf' variable points at 'curenv->env_tf').
	
	// LAB 4: Your code here.
	if (curenv->env_pgfault_upcall != NULL){
		struct UTrapframe *utf;
		if (UXSTACKTOP - PGSIZE <= tf->tf_esp && tf->tf_esp < UXSTACKTOP){
			utf = (struct UTrapframe *)(tf->tf_esp - sizeof(struct UTrapframe) - 4);
		} else {
			utf = (struct UTrapframe *)(UXSTACKTOP - sizeof(struct UTrapframe));
		}

		user_mem_assert(curenv, (void *)utf, sizeof(struct UTrapframe), PTE_U | PTE_W);

		utf->utf_eflags = tf->tf_eflags;
		utf->utf_eip = tf->tf_eip;
		utf->utf_err = tf->tf_err;
		utf->utf_esp = tf->tf_esp;
		utf->utf_fault_va = fault_va;
		utf->utf_regs = tf->tf_regs;

		curenv->env_tf.tf_eip = (uint32_t)curenv->env_pgfault_upcall;
		curenv->env_tf.tf_esp = (uint32_t)utf;
		env_run(curenv);
	}

	// Destroy the environment that caused the fault.
	cprintf("[%08x] user fault va %08x ip %08x\n",
		curenv->env_id, fault_va, tf->tf_eip);
	print_trapframe(tf);
	env_destroy(curenv);
}
Exemplo n.º 26
0
void
page_fault_handler(struct Trapframe *tf)
{
	// Read processor's CR2 register to find the faulting address
	int ret;
	uint32_t fault_va = rcr2();
	uint8_t * curr_stack;
	struct UTrapframe curr_frame;

	// Handle kernel-mode page faults.
	//deal with softint in which case error is not pushed to stack
	if(!(tf->tf_cs & 3)) 
	{	
		print_trapframe(tf);
		panic("page fault occurs in kernel mode\n");
	}

	if(!curenv->env_pgfault_upcall)
		goto no_page_fault_handler;
	// We've already handled kernel-mode exceptions, so if we get here,
	// the page fault happened in user mode.

	// Call the environment's page fault upcall, if one exists.  Set up a
	// page fault stack frame on the user exception stack (below
	// UXSTACKTOP), then branch to curenv->env_pgfault_upcall.
	
	// The page fault upcall might cause another page fault, in which case
	// we branch to the page fault upcall recursively, pushing another
	// page fault stack frame on top of the user exception stack.
	// Jie's Note : x86 first dec stack pointer and then store the value

	user_mem_assert(curenv,(void *)(UXSTACKTOP-PGSIZE),PGSIZE,PTE_U|PTE_W|PTE_P);
	
	if(tf->tf_esp < USTACKTOP)
	{
		curr_stack = (uint8_t *)UXSTACKTOP;
	}
	else
	{
		curr_stack = (uint8_t *) tf->tf_esp;
		curr_stack-=sizeof(uint32_t);	
		memset(curr_stack,0,sizeof(uint32_t)); 
	}

	if((uint32_t)curr_stack <= UXSTACKTOP-PGSIZE+sizeof(struct UTrapframe)+sizeof(uint32_t))
		panic("exception stack overflow");
	
	curr_stack-=sizeof(struct UTrapframe);
	
	// The trap handler needs one word of scratch space at the top of the
	// trap-time stack in order to return.  In the non-recursive case, we
	// don't have to worry about this because the top of the regular user
	// stack is free.  In the recursive case, this means we have to leave
	// an extra word between the current top of the exception stack and
	// the new stack frame because the exception stack _is_ the trap-time
	// stack.
	curr_frame.utf_fault_va = fault_va;
	curr_frame.utf_err = tf->tf_err;
	curr_frame.utf_eip = tf->tf_eip;
	curr_frame.utf_esp = tf->tf_esp;
	curr_frame.utf_eflags = tf->tf_eflags;
	memcpy(&(curr_frame.utf_regs),&(tf->tf_regs),sizeof(struct PushRegs));
	memcpy(curr_stack,&curr_frame,sizeof(struct UTrapframe));

	// If there's no page fault upcall, the environment didn't allocate a
	// page for its exception stack or can't write to it, or the exception
	// stack overflows, then destroy the environment that caused the fault.
	// Note that the grade script assumes you will first check for the page
	// fault upcall and print the "user fault va" message below if there is
	// none.  The remaining three checks can be combined into a single test.
	//
	// Hints:
	//   user_mem_assert() and env_run() are useful here.
	//   To change what the user environment runs, modify 'curenv->env_tf'
	//   (the 'tf' variable points at 'curenv->env_tf').
	// LAB 4: Your code here.
	curenv->env_tf.tf_eip = (uintptr_t)curenv->env_pgfault_upcall;
	curenv->env_tf.tf_esp = (uintptr_t)curr_stack;
	env_run(curenv);
	
	// Destroy the environment that caused the fault.
no_page_fault_handler:

	cprintf("[%08x] user fault va %08x ip %08x\n",
		curenv->env_id, fault_va, tf->tf_eip);
	print_trapframe(tf);
	env_destroy(curenv);
}
Exemplo n.º 27
0
Arquivo: trap.c Projeto: chenkexin/jos
void
page_fault_handler(struct Trapframe *tf)
{
	uint32_t fault_va;

	// Read processor's CR2 register to find the faulting address
	fault_va = rcr2();

	// Handle kernel-mode page faults.

	// LAB 3: Your code here.
  	if ((tf->tf_cs&3) == 0)
		panic("Kernel page fault!");

	// We've already handled kernel-mode exceptions, so if we get here,
	// the page fault happened in user mode.

	// Call the environment's page fault upcall, if one exists.  Set up a
	// page fault stack frame on the user exception stack (below
	// UXSTACKTOP), then branch to curenv->env_pgfault_upcall.
	//
	// The page fault upcall might cause another page fault, in which case
	// we branch to the page fault upcall recursively, pushing another
	// page fault stack frame on top of the user exception stack.
	//
	// The trap handler needs one word of scratch space at the top of the
	// trap-time stack in order to return.  In the non-recursive case, we
	// don't have to worry about this because the top of the regular user
	// stack is free.  In the recursive case, this means we have to leave
	// an extra word between the current top of the exception stack and
	// the new stack frame because the exception stack _is_ the trap-time
	// stack.
	//
	// If there's no page fault upcall, the environment didn't allocate a
	// page for its exception stack or can't write to it, or the exception
	// stack overflows, then destroy the environment that caused the fault.
	// Note that the grade script assumes you will first check for the page
	// fault upcall and print the "user fault va" message below if there is
	// none.  The remaining three checks can be combined into a single test.
	//
	// Hints:
	//   user_mem_assert() and env_run() are useful here.
	//   To change what the user environment runs, modify 'curenv->env_tf'
	//   (the 'tf' variable points at 'curenv->env_tf').

	// LAB 4: Your code here.
	if( curenv->env_pgfault_upcall )
	{
		//cprintf("in trap.c: page_fault_handler\n");
		//the curenv->env_pgfault_upcall is set.
	  struct UTrapframe *utf;
		uintptr_t utf_addr;
 		//check if the tf->tf_esp is on the exception stack
		if (UXSTACKTOP-PGSIZE<=tf->tf_esp && tf->tf_esp<=UXSTACKTOP-1)
			utf_addr = tf->tf_esp - sizeof(struct UTrapframe) - 4;
		else 
			utf_addr = UXSTACKTOP - sizeof(struct UTrapframe);
		user_mem_assert(curenv, (void*)utf_addr, 1, PTE_W);
		utf = (struct UTrapframe *) utf_addr;

		utf->utf_fault_va = fault_va;
		utf->utf_err = tf->tf_err;
		utf->utf_regs = tf->tf_regs;
		utf->utf_eip = tf->tf_eip;
		utf->utf_eflags = tf->tf_eflags;
		utf->utf_esp = tf->tf_esp;

//		curenv->env_tf.env_tf
		//set the function running
		curenv->env_tf.tf_eip = (uintptr_t)curenv->env_pgfault_upcall;
		curenv->env_tf.tf_esp = utf_addr;
		env_run(curenv);
	}
	// Destroy the environment that caused the fault.
	cprintf("[%08x] user fault va %08x ip %08x\n",
		curenv->env_id, fault_va, tf->tf_eip);
	print_trapframe(tf);
	env_destroy(curenv);
}
Exemplo n.º 28
0
static int
sys_trans_pkt(void *va, size_t len)
{
	user_mem_assert(curenv, va, len, PTE_P | PTE_U);
	return transmit_packet(va, len);
}
Exemplo n.º 29
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.
	switch(syscallno){
		case SYS_cputs:
			user_mem_assert(curenv, (void *)a1, a2, PTE_U);
			sys_cputs((char *)a1, a2);
			return 0;
			break;
		case SYS_cgetc:
			return sys_cgetc();
			break;
		case SYS_getenvid:
			return sys_getenvid();
			break;
		case SYS_getenv_parent_id:
			return sys_getenv_parent_id(a1);
			break;
		case SYS_env_destroy:
			return sys_env_destroy(a1);
			break;
		case SYS_page_alloc:
			return sys_page_alloc(a1, (void *)a2, a3);
			break;
		case SYS_page_map:
			return sys_page_map(a1, (void *)a2, a3, (void *)a4, a5);
			break;
		case SYS_page_unmap:
			return sys_page_unmap(a1, (void *)a2);
			break;
		case SYS_exofork:
			return sys_exofork();
			break;
		case SYS_env_set_status:
			return sys_env_set_status(a1, a2);
			break;
		case SYS_env_set_trapframe:
			return sys_env_set_trapframe(a1, (struct Trapframe *)a2);
			break;
		case SYS_env_set_pgfault_upcall:
			return sys_env_set_pgfault_upcall(a1, (void *)a2);
			break;
		case SYS_env_get_curdir:
			return sys_env_get_curdir((envid_t)a1, (char *)a2);
			break;
		case SYS_env_set_curdir:
			return sys_env_set_curdir((envid_t)a1, (char *)a2);
			break;
		case SYS_yield:
			sys_yield();
			break;
		case SYS_ipc_try_send:
			return sys_ipc_try_send(a1, a2, (void *)a3, a4);
			break;
		case SYS_ipc_recv:
			return sys_ipc_recv((void *)a1);
			break;
		case SYS_time_msec:
			return sys_time_msec();
			break;
		case SYS_net_send:
			return sys_net_send((void *)a1, a2);
			break;
		case SYS_net_recv:
			return sys_net_recv((void *)a1, a2);
			break;
		case NSYSCALLS:
		default:
			return -E_INVAL;
			break;
	}
	return 0;
}
Exemplo n.º 30
0
void
page_fault_handler(struct Trapframe *tf)
{
	uint32_t fault_va;
	struct PageInfo *pp = NULL;

	// Read processor's CR2 register to find the faulting address
	fault_va = rcr2();

	// Handle kernel-mode page faults.

	// LAB 3: Your code here.
	if ((tf->tf_cs & 3) == 0) {
		panic("page_fault_handler: kernel-mode page fault");
	}

	// We've already handled kernel-mode exceptions, so if we get here,
	// the page fault happened in user mode.

	// Call the environment's page fault upcall, if one exists.  Set up a
	// page fault stack frame on the user exception stack (below
	// UXSTACKTOP), then branch to curenv->env_pgfault_upcall.
	//
	// The page fault upcall might cause another page fault, in which case
	// we branch to the page fault upcall recursively, pushing another
	// page fault stack frame on top of the user exception stack.
	//
	// The trap handler needs one word of scratch space at the top of the
	// trap-time stack in order to return.  In the non-recursive case, we
	// don't have to worry about this because the top of the regular user
	// stack is free.  In the recursive case, this means we have to leave
	// an extra word between the current top of the exception stack and
	// the new stack frame because the exception stack _is_ the trap-time
	// stack.
	//
	// If there's no page fault upcall, the environment didn't allocate a
	// page for its exception stack or can't write to it, or the exception
	// stack overflows, then destroy the environment that caused the fault.
	// Note that the grade script assumes you will first check for the page
	// fault upcall and print the "user fault va" message below if there is
	// none.  The remaining three checks can be combined into a single test.
	//
	// Hints:
	//   user_mem_assert() and env_run() are useful here.
	//   To change what the user environment runs, modify 'curenv->env_tf'
	//   (the 'tf' variable points at 'curenv->env_tf').

	// LAB 4: Your code here.

	// utf is a pointer to the UTrapframe in the user exception stack.
	// If this is the first fault, then the pointer is right below UXSTACKTOP.
	// Otherwise, the pointer is right below tf->tf_esp, with a 32-bit word offset.
	// If UXSTACKTOP-PGSIZE <= tf->tf_esp <= UXSTACKTOP-1, then it is a recursive trap, the latter case.
	struct UTrapframe *utf = (struct UTrapframe *)(
		(((UXSTACKTOP-PGSIZE)<=(tf->tf_esp))&&((tf->tf_esp)<=(UXSTACKTOP-1)))
		?
		((tf->tf_esp)-(sizeof(struct UTrapframe)+sizeof(uint32_t)))
		:
		(UXSTACKTOP-sizeof(struct UTrapframe))
	);

	if (!(curenv->env_pgfault_upcall)) {
		// Destroy the environment that caused the fault.
		cprintf("[%08x] user fault va %08x ip %08x\n",
			curenv->env_id, fault_va, tf->tf_eip);
		print_trapframe(tf);
		env_destroy(curenv);
	}

	// If the environment didn't allocate a
	// page for its exception stack or can't write to it, or the exception
	// stack overflows, then destroy the environment that caused the fault.
	// We can do this with user_mem_assert on the portion of the stack where *utf is stored.
	// This obviously covers the first two cases.
	// It also takes care of the third case because the region below UXSTACKTOP-PGSIZE is unmapped.
	user_mem_assert(curenv, (void *)utf, sizeof(struct UTrapframe), PTE_W|PTE_U|PTE_P);

	utf->utf_fault_va = fault_va;

	// Copy values from the Trapframe to the UTrapframe.
	utf->utf_err = tf->tf_err;
	utf->utf_regs = tf->tf_regs;
	utf->utf_eip = tf->tf_eip;
	utf->utf_eflags = tf->tf_eflags;
	utf->utf_esp = tf->tf_esp;

	// Set the Trapframe to return to env_pgfault_upcall, with an exception stack at utf.
	// NOTE I am not confident that this code is correct.
	// TODO Test that this is correct, and correct it if necessary.
	tf->tf_eip = (uintptr_t)curenv->env_pgfault_upcall;
	tf->tf_esp = (uintptr_t)utf;
}