Ejemplo n.º 1
0
void
trap(struct Trapframe *tf)
{
    //struct Trapframe *tf = &tf_;
	// The environment may have set DF and some versions
	// of GCC rely on DF being clear
	asm volatile("cld" ::: "cc");

	// Check that interrupts are disabled.  If this assertion
	// fails, DO NOT be tempted to fix it by inserting a "cli" in
	// the interrupt path.
	assert(!(read_eflags() & FL_IF));

	cprintf("Incoming TRAP frame at %p\n", tf);

	if ((tf->tf_cs & 3) == 3) {
		// Trapped from user mode.
		assert(curenv);

		// Copy trap frame (which is currently on the stack)
		// into 'curenv->env_tf', so that running the environment
		// will restart at the trap point.
		curenv->env_tf = *tf;
		// The trapframe on the stack should be ignored from here on.
		tf = &curenv->env_tf;
	}

	// Record that tf is the last real trapframe so
	// print_trapframe can print some additional information.
	last_tf = tf;

	// Dispatch based on what type of trap occurred
	trap_dispatch(tf);

	// Return to the current environment, which should be running.
	assert(curenv && curenv->env_status == ENV_RUNNING);
	env_run(curenv);
}
Ejemplo n.º 2
0
void
trap(struct Trapframe *tf)
{
	// The environment may have set DF and some versions
	// of GCC rely on DF being clear
	asm volatile("cld" ::: "cc");

	// Check that interrupts are disabled.  If this assertion
	// fails, DO NOT be tempted to fix it by inserting a "cli" in
	// the interrupt path.
	// Debug info
	// if (tf->tf_trapno != 48 && tf->tf_trapno != 32 && tf->tf_trapno != 14) cprintf("Trapno %d\n", tf->tf_trapno);
	assert(!(read_eflags() & FL_IF));

	// cprintf("Incoming TRAP frame at %p\n", tf);

	if ((tf->tf_cs & 3) == 3) {
		// Trapped from user mode.
		// Copy trap frame (which is currently on the stack)
		// into 'curenv->env_tf', so that running the environment
		// will restart at the trap point.
		assert(curenv);
		curenv->env_tf = *tf;
		// The trapframe on the stack should be ignored from here on.
		tf = &curenv->env_tf;
	}
	
	// Dispatch based on what type of trap occurred
	trap_dispatch(tf);

	// If we made it to this point, then no other environment was
	// scheduled, so we should return to the current environment
	// if doing so makes sense.
	if (curenv && curenv->env_status == ENV_RUNNABLE)
		env_run(curenv);
	else
		sched_yield();
}
Ejemplo n.º 3
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.
        //cprintf("SUNUS : tf eip = %08x\n",tf->tf_eip);
        //sunus_dbg(0,3,page_fault_handler);
        if((tf->tf_cs & 0x3) != 0x3)
                panic("page_fault_handler @ %08x\n",fault_va);
        // 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.
        // JAN,10,SUNUS
        if(curenv->env_pgfault_upcall)
        {
                struct UTrapframe utf;
                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_eip = tf->tf_eip;
                utf.utf_eflags = tf->tf_eflags;
                utf.utf_esp = tf->tf_esp;
                if(tf->tf_esp >= (UXSTACKTOP - PGSIZE) && tf->tf_esp <= UXSTACKTOP) /* check if it's in another PGFLT */
                {
                        //LINE 277-279
                        tf->tf_esp -= 4;
                        user_mem_assert(curenv, (const void *)(tf->tf_esp - sizeof(utf) - 4), sizeof(utf), PTE_W|PTE_U);// -4 is the extra 32bit
                }
                else
                {
                        tf->tf_esp = UXSTACKTOP;
                        user_mem_assert(curenv, (const void *)(tf->tf_esp - sizeof(utf)), sizeof(utf), PTE_W|PTE_U);
                }
                tf->tf_esp -= sizeof(utf);
                if(tf->tf_esp < (UXSTACKTOP - PGSIZE))
                {
                        cprintf("tf->tf_esp < UXSTACKTOP - PGSIZE!\n");
                        env_destroy(curenv);
                        return;
                }
                memmove((void *)(tf->tf_esp), &utf, sizeof(struct UTrapframe));
                tf->tf_eip = (uintptr_t)curenv->env_pgfault_upcall;
                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);
}
Ejemplo n.º 4
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.
	if ((tf->tf_cs & 3) != 3) {
		panic("Page fault in kernel mode.\n");
	}
	// LAB 3: Your code here.

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

	uint32_t* user_stack;

	if (tf->tf_esp >= UXSTACKTOP - PGSIZE && tf->tf_esp <= UXSTACKTOP - 1) {
		if (tf->tf_esp - sizeof(struct UTrapframe) < UXSTACKTOP - PGSIZE) {
			cprintf("Crossing User Stack boundaries.\n");
		}
		tf->tf_esp = tf->tf_esp - 4;
		lcr3(PADDR(curenv->env_pgdir));
		*((uint32_t*)tf->tf_esp) = 0;
		lcr3(PADDR(kern_pgdir));

		user_stack = (uint32_t*)tf->tf_esp;
		tf->tf_esp = tf->tf_esp + 4;
	   	user_stack -= 13;	
		user_mem_assert(curenv, (void*)user_stack, 
						sizeof(struct UTrapframe) + 4, PTE_U | PTE_P);
	} else {
		user_stack = (uint32_t*)(UXSTACKTOP);
	   	user_stack -= 13;	
		user_mem_assert(curenv, (void*)user_stack, sizeof(struct UTrapframe),
						PTE_U | PTE_P);
	}
	
	uint32_t user_stack_start = (uint32_t)user_stack;
	lcr3(PADDR(curenv->env_pgdir));
	*((uint32_t*)user_stack) = fault_va;
	user_stack++;
	*((uint32_t*)user_stack) = tf->tf_err;
	user_stack++;
	*((uint32_t*)user_stack) = tf->tf_regs.reg_edi;
	user_stack++;
	*((uint32_t*)user_stack) = tf->tf_regs.reg_esi;
	user_stack++;
	*((uint32_t*)user_stack) = tf->tf_regs.reg_ebp;
	user_stack++;
	*((uint32_t*)user_stack) = tf->tf_esp;
	user_stack++;
	*((uint32_t*)user_stack) = tf->tf_regs.reg_ebx;
	user_stack++;
	*((uint32_t*)user_stack) = tf->tf_regs.reg_edx;
	user_stack++;
	*((uint32_t*)user_stack) = tf->tf_regs.reg_ecx;
	user_stack++;
	*((uint32_t*)user_stack) = tf->tf_regs.reg_eax;
	user_stack++;
	*((uint32_t*)user_stack) = tf->tf_eip;
	user_stack++;
	*((uint32_t*)user_stack) = tf->tf_eflags;
	user_stack++;
	*((uint32_t*)user_stack) = tf->tf_esp;
	lcr3(PADDR(kern_pgdir));

	curenv->env_tf.tf_eip = (uint32_t)(curenv->env_pgfault_upcall);
	curenv->env_tf.tf_esp = (uint32_t)(user_stack_start); 
	env_run(curenv);
}
Ejemplo n.º 5
0
void
page_fault_handler(struct Trapframe *tf)
{
	uint64_t fault_va;
    	uintptr_t stktop;
        uint64_t arr[20];

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

	// Handle kernel-mode page faults.

	// Ashish
	if ((tf->tf_cs & 0x03) == 0)
		panic("ERROR: Page fault occurred in kernel mode : Fault va=%x\n",fault_va);

	// 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').

	// Ashish
       	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_rip);
               print_trapframe(tf);
               env_destroy(curenv);
       	}
       	user_mem_assert(curenv, (void*)UXSTACKTOP-1, 1, PTE_P|PTE_W|PTE_U);
	if (tf->tf_rsp-sizeof(arr)-8 >= UXSTACKTOP) {
               cprintf("Exception stack overflow for env:\n", curenv->env_id);
               print_trapframe(tf);
               env_destroy(curenv);
	}

	//Store the trapframe
       	memcpy(&(curenv->env_tf), tf, sizeof(struct Trapframe));

	//Assign stacktop appropriately. In non-recursive case, stack top is UXSTACKTOP-sizeof(UTrapframe)
	//In recursive case, stack top will point to tf->tf_rsp-sizeof(UTrapframe)-8. Note that 8 is scratch space.
       	if (tf->tf_rsp < UXSTACKTOP && tf->tf_rsp > UXSTACKTOP - PGSIZE)
       		stktop = tf->tf_rsp-sizeof(arr)-8;
       	else
		stktop = UXSTACKTOP-sizeof(arr);

	//Prepare reverse-UTrapframe
	arr[0]=fault_va;
	arr[1]=tf->tf_err;
	arr[2]=tf->tf_regs.reg_r15;
	arr[3]=tf->tf_regs.reg_r14;
	arr[4]=tf->tf_regs.reg_r13;
	arr[5]=tf->tf_regs.reg_r12;
	arr[6]=tf->tf_regs.reg_r11;
	arr[7]=tf->tf_regs.reg_r10;
	arr[8]=tf->tf_regs.reg_r9;
	arr[9]=tf->tf_regs.reg_r8;
	arr[10]=tf->tf_regs.reg_rsi;
	arr[11]=tf->tf_regs.reg_rdi;
	arr[12]=tf->tf_regs.reg_rbp;
	arr[13]=tf->tf_regs.reg_rdx;
	arr[14]=tf->tf_regs.reg_rcx;
	arr[15]=tf->tf_regs.reg_rbx;
	arr[16]=tf->tf_regs.reg_rax;
	arr[17]=tf->tf_rip;
	arr[18]=tf->tf_eflags;
	arr[19]=tf->tf_rsp;

	//Copy these values on the stack.
	memcpy((void*)(stktop), (void*)arr, sizeof(arr));
	tf->tf_rsp =  stktop;

	//Force the env to execute _pgfault_upcall from pgfault.S
        curenv->env_tf.tf_rip = (uintptr_t)curenv->env_pgfault_upcall;
        env_run(curenv);
}
Ejemplo n.º 6
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 & 0x3) == 0) {
        print_trapframe(tf);
		panic("page fault in kernel space");
    }

	// 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 no pgfault_upcall, fall to destruction.
    // If page faults take place in the region [USTACKTOP, UXSTACKTOP - PGSIZE),
    // it means the exception stack is exhausted.

    if (curenv->env_pgfault_upcall &&
        (tf->tf_esp < USTACKTOP ||
         tf->tf_esp >= UXSTACKTOP - PGSIZE)) {

        // Determine the starting address of the stack frame.
        uint32_t xtop;
        if (tf->tf_esp >= UXSTACKTOP - PGSIZE &&
            tf->tf_esp < UXSTACKTOP)
            xtop = tf->tf_esp - sizeof(struct UTrapframe) - 4/* a required empty word */;
        else
            xtop = UXSTACKTOP - sizeof(struct UTrapframe);
        
        // Check perms
        user_mem_assert(curenv, (void *)xtop, UXSTACKTOP - xtop, PTE_W | PTE_U);

        // Push the struct UTrapframe onto the stack.
        struct UTrapframe *utf = (struct UTrapframe *)xtop;
        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;
        
        // Run current env with user-page fault handler.
        tf->tf_eip = (uint32_t)curenv->env_pgfault_upcall;
        tf->tf_esp = xtop;
        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);
}
Ejemplo n.º 7
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);
}
Ejemplo n.º 8
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);
}
Ejemplo n.º 9
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 == GD_KT) {
		print_trapframe(tf);
		panic("kernel page fault va %08x ip %08x env %x\n",
		      fault_va, tf->tf_eip, curenv->env_id);
	}

	// 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) {
		goto destroy;
	}

	// Check that exception stack is allocated
	user_mem_assert(curenv, (void *)(UXSTACKTOP - 4), 4, 0);

	uintptr_t exstack;
	struct UTrapframe *utf;
	
	// Figure out top where trapframe should end, leaving 1 word scratch space
	if (tf->tf_esp >= UXSTACKTOP-PGSIZE && tf->tf_esp <= UXSTACKTOP-1) {
		exstack = tf->tf_esp - 4; // recursive
	}
	else {
		exstack = UXSTACKTOP; // non-recursive
	}

	// Check if enough space to copy trapframe
	if ((exstack - sizeof(struct UTrapframe)) < UXSTACKTOP-PGSIZE) {
		goto destroy;
	}

	// Set up UTrapframe on exception stack
	utf = (struct UTrapframe *) (exstack - sizeof(struct UTrapframe));
	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;
	// Fix trapframe to return to user handler
	tf->tf_esp = (uintptr_t) utf;
	tf->tf_eip = (uintptr_t) curenv->env_pgfault_upcall;
	env_run(curenv);

	panic("Unreachable code!\n");
	
	destroy:
	// 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);
}
Ejemplo n.º 10
0
void
page_fault_handler(struct Trapframe *tf)
{
	uint64_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 & 0x3)) {
		print_trapframe(tf);
        panic("unhandled trap in kernel");
    }
	
	// 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').
	
	if (curenv->env_pgfault_upcall) {
		struct UTrapframe *utexp;
		if (tf->tf_rsp <= UXSTACKTOP-1 && tf->tf_rsp >= UXSTACKTOP-PGSIZE) {
			utexp = (struct UTrapframe*) (tf->tf_rsp - sizeof(struct UTrapframe) - 8);
		}
		else {
			utexp = (struct UTrapframe*)(UXSTACKTOP - sizeof(struct UTrapframe));
		}
		//storing that 64 bit thingy.(this was tough!, I'm weak with bits ;) )
		//(time frame) to be stored...but how does it get pushed into the stack...you assign it to uxstacktop
		//thats brilliant. Thank you! thank you...wait a minute...see if it overflows!
		user_mem_assert(curenv, (void*)utexp, sizeof(struct UTrapframe), PTE_W|PTE_U);
		utexp->utf_fault_va = fault_va;
		utexp->utf_err = tf->tf_err;
		utexp->utf_regs = tf->tf_regs;
		utexp->utf_rip = tf->tf_rip;
		utexp->utf_eflags = tf->tf_eflags;
		utexp->utf_rsp = tf->tf_rsp;
		//How do i run the upcall...set the rip...thats nice...thank you exercise 10 :)
		tf->tf_rip = (uint64_t)curenv->env_pgfault_upcall;
		tf->tf_rsp = (uint64_t)utexp;
		env_run(curenv);
	}
	// LAB 4: Your code here.

	// Destroy the environment that caused the fault.
	cprintf("[%08x] user fault va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_rip);
	print_trapframe(tf);
	env_destroy(curenv);
}
Ejemplo n.º 11
0
void
page_fault_handler(struct Trapframe *tf)
{
	uint64_t fault_va;

	// Read processor's CR2 register to find the faulting address
	fault_va = rcr2();
	struct UTrapframe *utf;
	struct PageInfo *pp;

	// Handle kernel-mode page faults.
	
	// LAB 3: Your code here.
	if((tf->tf_cs & 3) == 0)
	{
		cprintf("fault_va is [%x]",fault_va);
		print_trapframe(tf);
		panic("Page fault hapened in kernel mode");
	}

	// 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.
	
	/*check if user env has registered a pg fault upcall.*/
		//cprintf("hello1");
	//cprintf("hello2");
    if(curenv->env_pgfault_upcall){
		//user_mem_assert(curenv,(const void *)curenv->env_pgfault_upcall,8,PTE_P|PTE_U);
		user_mem_assert(curenv,(const void *)UXSTACKTOP-PGSIZE,PGSIZE, PTE_W | PTE_U | PTE_P);
		/*If user mem assert returns , then the address is valid for the env*/	
		if(!(tf->tf_rsp < UXSTACKTOP && tf->tf_rsp > UXSTACKTOP-PGSIZE)){
			/*1st Page Fault*/
			utf = (struct UTrapframe *)(UXSTACKTOP - sizeof(struct UTrapframe));
		}else{
			if(tf->tf_rsp - sizeof(struct UTrapframe) - 8 < (UXSTACKTOP-PGSIZE)){
				env_destroy(curenv);
			}
			else
			{
				utf = (struct UTrapframe *)(tf->tf_rsp - sizeof(struct UTrapframe) - 8);
			}
			/*Nested Page Fault*/
			
		}
		/*Populate the Utrapframe*/
		//user_mem_assert(curenv,(const void *)utf,sizeof(struct UTrapframe),PTE_W|PTE_U);
		utf->utf_eflags = tf->tf_eflags;
		utf->utf_err = tf->tf_err;
		utf->utf_fault_va = fault_va;
		utf->utf_regs = tf->tf_regs;
		utf->utf_rip = tf->tf_rip;
		utf->utf_rsp = tf->tf_rsp;
		tf->tf_rip = (uint64_t)curenv->env_pgfault_upcall;
		tf->tf_rsp = (uint64_t)utf;
		

		
		env_run(curenv);
	
    }else{
		// Destroy the environment that caused the fault.
		cprintf("[%08x] user fault va %08x ip %08x\n",
			curenv->env_id, fault_va, tf->tf_rip);
		print_trapframe(tf);
		env_destroy(curenv);
    }
}
Ejemplo n.º 12
0
// interrupt and trap handlers
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.
	// previlage level = 0
	if ((tf->tf_cs & 3) == 0){
		panic("kernel page fault");
	}
	// LAB 3: Your code here.

	// 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.
	// Now we are in kernel mode
	if (curenv->env_pgfault_upcall != NULL){
		struct UTrapframe *utf;

		// Check tf_esp is in UXSTACK
		// -4, scratch space to save eip return address
		if (tf->tf_esp >= UXSTACKTOP - PGSIZE && tf->tf_esp < UXSTACKTOP){
			utf = (struct UTrapframe *)(tf->tf_esp - sizeof(struct UTrapframe) - 4);
		} else {
			utf = (struct UTrapframe *)(UXSTACKTOP - sizeof(struct UTrapframe));
		}

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

		// dump Trapframe info to UTrapframe
		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;

		// set eip to env_pgfault_upcall
		curenv->env_tf.tf_eip = (uint32_t)curenv->env_pgfault_upcall;
		curenv->env_tf.tf_esp = (uint32_t)utf;

		// Debug info
		// cprintf("Dispatch to user-mode page fault handler: fault_va %08x\n", fault_va);
		// if (fault_va >= USTACKTOP - PGSIZE && fault_va < USTACKTOP) cprintf("pgfautl on stack\n");
		env_run(curenv);
	} else {
		cprintf("ERROR: %x env_pgfault_upcall is NULL\n", curenv->env_id);
	}

	// 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);
}
Ejemplo n.º 13
0
// Choose a user environment to run and run it.
void
sched_yield(void)
{
	// Implement simple round-robin scheduling.
	// Search through 'envs' for a runnable environment,
	// in circular fashion starting after the previously running env,
	// and switch to the first such environment found.
	// It's OK to choose the previously running env if no other env
	// is runnable.
	// But never choose envs[0], the idle environment,
	// unless NOTHING else is runnable.

	// LAB 4: Your code here.
#if LAB4A_SCHED_PRI
	int cur_index=0, next_index=0, priority_index=0,selected_index=0;
	int  priority_selected = 0 ;

	if(NULL != curenv){
		cur_index = ENVX(curenv->env_id);
	}

	next_index = (cur_index + 1)%NENV;

	for(;next_index != cur_index; next_index=(next_index+1)%NENV){
		if((envs[next_index].env_status == ENV_RUNNABLE) && (next_index != 0)){

			if(next_index & 0x01){
				priority_index = next_index;
				priority_selected = 1;
			}else{
				if(selected_index == 0)
				{
					selected_index=next_index;

				}
			}
			//          env_run(&envs[next_index]);
		}
	}
	if(priority_selected){
		env_run(&envs[priority_index]);
	}else{
		env_run(&envs[selected_index]);
	}
#else
	struct Env *penv, *pstart;
	int i = 0;

	if ((curenv == NULL) || (curenv == &envs[NENV - 1])) {
		// Skip envs[0]
		pstart = &envs[1];
	}
	else {
		pstart = curenv + 1;
	}
	penv = pstart;
	while (1) {
		++i;
		if ((penv == pstart) && (i > 1)) {
			// We've come back to start full-circle, time to break out
			break;
		}

		if (penv->env_status == ENV_RUNNABLE) {
			env_run(penv);
			break;
		}

		if (penv == &envs[NENV - 1]) {
			// Skip envs[0]
			penv = &envs[1];
		}
		else {
			++penv;
		}
	}
#endif

	// Run the special idle environment when nothing else is runnable.
	if (envs[0].env_status == ENV_RUNNABLE)
		env_run(&envs[0]);
	else {
		cprintf("Destroyed all environments - nothing more to do!\n");
		while (1)
			monitor(NULL);
	}
}
Ejemplo n.º 14
0
void 
sched_fair_yield(void)
{
	//Increment real_tick_used of global clock
        global_clock.real_tick++;
	
	int i, env_index = 1024;
	struct Env *e = NULL;
	
	//Find index in envs of curenv
	for(i = 0; i < NENV; i++)
	{
		e = &envs[i];
		if(e == curenv)
		{
			env_index = i;
			break;
		}
	}
	
	//Decrementing timeslice for current process as it has run once
	if(env_index > -1 && env_index < 1024)		// for scenarios when there is no current environment
		envs[env_index].env_se.timeslice--;

//	cprintf("Entering sched_fair_yield envID : %d , timeslice_remaining %d \n", env_index, envs[env_index].env_se.timeslice);

	i = env_index;
	
	if(envs[i].env_se.timeslice == 0)	
	{
	
		//Current process has finished one timeslice, so increment vruntime and reset timeslice	
	  	 if(env_index > -1 && env_index < 1024)
	   	{
			envs[i].env_se.vruntime++;
		
			// Reset the timeslice on the basis of priority
			envs[i].env_se.timeslice = MIN_TIMESLICE * (envs[i].env_se.priority - MIN_PRIORITY + 1);		
	   	}
	}	//Terminated this loop here
	   
	
	int flag = 0, k = 1;
	
	// variables to find the process to be scheduled next on the basis of  vruntime and timeslices left
	uint64_t min_vruntime = 0;
	int timesleft = 0;
		
		
	env_index = -1;			//setting env_index to -1, remains -1 if there is no env to be scheduled
	i = 1;				//CHECK THIS LINE LATER
	
	while(i > 0 && i < NENV)
	{
		if(i == NENV -1)
			i = 1;
		if(envs[i].env_status == ENV_RUNNABLE)// && envs[i].env_se.timeslice > 0)
		{
			//cprintf("i: %d\n",i);	
			if(flag == 0)
			{
				min_vruntime = envs[i].env_se.vruntime;
				env_index = i;
				timesleft = envs[i].env_se.timeslice;
				flag = 1;
			}
			else if(envs[i].env_se.vruntime < min_vruntime)
			{
				env_index = i;
				min_vruntime = envs[i].env_se.timeslice;
				timesleft = envs[i].env_se.timeslice;
			} 
			else if(envs[i].env_se.vruntime == min_vruntime && envs[i].env_se.timeslice > timesleft)
			{
				env_index = i;
				timesleft = envs[i].env_se.timeslice;
			}
		}
		k++;
		if(k == NENV)
			break;
		i++;
	}
	
	

	//Check if global clock has to be incremented
	if(global_clock.global_tick == min_vruntime)  	// Change comparison operaor from <= to ==
	{
		global_clock_increment();
	}

	cprintf("******* CF Scheduler Selected Process ENV-ID  [%08x] VRUNTIME: %llu  TIMESLICE-LEFT: %llu ********\n",envs[env_index].env_id,envs[env_index].env_se.vruntime,envs[env_index].env_se.timeslice);	
	if(env_index > 0)
		env_run(&envs[env_index]);
	else if(envs[0].env_status == ENV_RUNNABLE)
		env_run(&envs[0]);
	else
	{
		cprintf("Destroyed all environments - nothing more to do");
		while(1)
			monitor(NULL);
	}
	
}
Ejemplo n.º 15
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 == 0x8) 
		panic("page_fault_handler: page fault in kernel mode va %08x ip %08x", fault_va,  tf->tf_eip);

	// 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) {
		user_mem_assert(curenv, (void *)(UXSTACKTOP-4), 4, 0);
		struct UTrapframe utf;

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

		//If in a recursive pgfault call
		if (tf->tf_esp >= UXSTACKTOP-PGSIZE && tf->tf_esp < UXSTACKTOP)
			tf->tf_esp -= 4;
		else
			tf->tf_esp = UXSTACKTOP;
		
		tf->tf_esp -= sizeof(struct UTrapframe);

		//Stack overflow
		if (tf->tf_esp < UXSTACKTOP-PGSIZE) {
			cprintf("[%08x] user exception stack overflowed: va %08x ip %08x esp %08x\n",	curenv->env_id, fault_va, tf->tf_eip, tf->tf_esp);
			print_trapframe(tf);
			env_destroy(curenv);
			return;
		}

		*(struct UTrapframe *) tf->tf_esp = utf;

		tf->tf_eip = (unsigned int) curenv->env_pgfault_upcall;
		env_run(curenv);
		cprintf("[DEBUG] should not reach here!\n");
	}

	// 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);
}
Ejemplo n.º 16
0
// Choose a user environment to run and run it.
void
sched_yield(void)
{
	// Implement simple round-robin scheduling.
	// Search through 'envs' for a runnable environment,
	// in circular fashion starting after the previously running env,
	// and switch to the first such environment found.
	// It's OK to choose the previously running env if no other env
	// is runnable.
	// But never choose envs[0], the idle environment,
	// unless NOTHING else is runnable.

	// LAB 4: Your code here.
#ifndef SCHED_PRIORITY
	/*
	struct Env *env_current;
	int count;

	if(curenv != NULL)
	{
		env_current=curenv;
	}
	else
	{
		env_current=envs;
	}

	for(count=0; count<NENV; count++)
	{
		env_current++;

		if(envs+NENV <= env_current)
		{
			env_current=envs+1;
		}
		else
		{
			if(env_current->env_status==ENV_RUNNABLE)
			{
				env_run(env_current);
			}
		}
	}*/

	uint32_t env_idx , n ;
		// if curenv's time slice has used up
	if (curenv) {
		env_idx = curenv - envs + 1 ;
	} else {
		// there's no env running
		env_idx = 1 ;
	}
			
	for (n = 0; n < NENV - 1 ; ++n) {
		if (envs[env_idx].env_status == ENV_RUNNABLE) {
			env_run(&envs[env_idx]) ;
			return ;
		}
		++env_idx ;
		if (env_idx == NENV) {
			env_idx = 1 ;
		}
	}
#endif

#ifdef SCHED_PRIORITY
	struct Env *env_current;
	struct Env *env_max;
	uint32_t max_priority;
	int count;

	env_current=envs;
	env_max=envs;

	max_priority=0;
	for(count=0; count<NENV; count++)
	{
		env_current++;

		if(env_current->env_status != ENV_RUNNABLE)
		{
			continue;
		}

		if(env_current->env_priority > max_priority)
		{
			max_priority=env_current->env_priority;
			env_max=env_current;
		}
	}

	if(env_max != envs)
	{
		env_run(env_max);
	}
#endif
			
	// Run the special idle environment when nothing else is runnable.
	if (envs[0].env_status == ENV_RUNNABLE)
		env_run(&envs[0]);
	else {
		cprintf("Destroyed all environments - nothing more to do!\n");
		while (1)
			monitor(NULL);
	}
	
	// Run the special idle environment when nothing else is runnable.
	if (envs[0].env_status == ENV_RUNNABLE)
		env_run(&envs[0]);
	else {
		cprintf("Destroyed all environments - nothing more to do!\n");
		while (1)
			monitor(NULL);
	}
}
Ejemplo n.º 17
0
static void runAddingAutoPhaser(LADSPA_Handle instance, unsigned long sample_count) {
	AutoPhaser *plugin_data = (AutoPhaser *)instance;
	LADSPA_Data run_adding_gain = plugin_data->run_adding_gain;

	/* Attack time (s) (float value) */
	const LADSPA_Data attack_p = *(plugin_data->attack_p);

	/* Decay time (s) (float value) */
	const LADSPA_Data decay_p = *(plugin_data->decay_p);

	/* Modulation depth (float value) */
	const LADSPA_Data depth_p = *(plugin_data->depth_p);

	/* Feedback (float value) */
	const LADSPA_Data fb = *(plugin_data->fb);

	/* Spread (octaves) (float value) */
	const LADSPA_Data spread = *(plugin_data->spread);

	/* Input (array of floats of length sample_count) */
	const LADSPA_Data * const input = plugin_data->input;

	/* Output (array of floats of length sample_count) */
	LADSPA_Data * const output = plugin_data->output;
	allpass * ap = plugin_data->ap;
	envelope * env = plugin_data->env;
	float sample_rate = plugin_data->sample_rate;
	float ym1 = plugin_data->ym1;

#line 114 "phasers_1217.xml"
	unsigned long pos;
	float y, d, ofs;
	float attack = attack_p;
	float decay = decay_p;
	const float depth = depth_p * 0.5f;

	if (attack < 0.01f) {
	  attack = 0.01f;
	}
	if (decay < 0.01f) {
	  decay = 0.01f;
	}
	env_set_attack(env, attack * sample_rate * 0.25f);
	env_set_release(env, decay * sample_rate * 0.25f);


	for (pos = 0; pos < sample_count; pos++) {
	  if (pos % 4 == 0) {
	    d = env_run(env, input[pos]) * depth;
	    ap_set_delay(ap, d);
	    ofs = spread * 0.01562f;
	    ap_set_delay(ap+1, d+ofs);
	    ofs *= 2.0f;
	    ap_set_delay(ap+2, d+ofs);
	    ofs *= 2.0f;
	    ap_set_delay(ap+3, d+ofs);
	    ofs *= 2.0f;
	    ap_set_delay(ap+4, d+ofs);
	    ofs *= 2.0f;
	    ap_set_delay(ap+5, d+ofs);
	  }

	  //Run allpass filters in series
	  y = ap_run(ap, input[pos] + ym1 * fb);
	  y = ap_run(ap+1, y);
	  y = ap_run(ap+2, y);
	  y = ap_run(ap+3, y);
	  y = ap_run(ap+4, y);
	  y = ap_run(ap+5, y);

	  buffer_write(output[pos], y);
	  ym1 = y;
	}

	plugin_data->ym1 = ym1;
}
Ejemplo n.º 18
0
void
trap(struct Trapframe *tf)
{

	// The environment may have set DF and some versions
	// of GCC rely on DF being clear		
	asm volatile("cld" ::: "cc");

	// Halt the CPU if some other CPU has called panic()
	extern char *panicstr;
	if (panicstr)
		asm volatile("hlt");

	// Re-acqurie the big kernel lock if we were halted in
	// sched_yield()
	//if(tf->tf_eip >= KERNBASE && tf->tf_trapno >= IRQ_OFFSET)
	//	lock_kernel();
	
	if (xchg(&thiscpu->cpu_status, CPU_STARTED) == CPU_HALTED)
		lock_kernel();
	// Check that interrupts are disabled.  If this assertion
	// fails, DO NOT be tempted to fix it by inserting a "cli" in
	// the interrupt path.
	assert(!(read_eflags() & FL_IF));

	if ((tf->tf_cs & 3) == 3) {
		// Trapped from user mode.
		// Acquire the big kernel lock before doing any
		// serious kernel work.
		// LAB 4: Your code here.
		lock_kernel();
		assert(curenv);

		// Garbage collect if current enviroment is a zombie
		if (curenv->env_status == ENV_DYING) {
			env_free(curenv);
			curenv = NULL;
			sched_yield();
		}

		// Copy trap frame (which is currently on the stack)
		// into 'curenv->env_tf', so that running the environment
		// will restart at the trap point.
		curenv->env_tf = *tf;
		// The trapframe on the stack should be ignored from here on.
		tf = &curenv->env_tf;
	}

	// Record that tf is the last real trapframe so
	// print_trapframe can print some additional information.
	last_tf = tf;

	// Dispatch based on what type of trap occurred
	trap_dispatch(tf);

	// If we made it to this point, then no other environment was
	// scheduled, so we should return to the current environment
	// if doing so makes sense.
	thiscpu->cpu_ts.ts_esp0 = KSTACKTOP-cpunum()*(KSTKSIZE+KSTKGAP);
	thiscpu->cpu_ts.ts_ss0 = GD_KD;
	thiscpu->cpu_ts.ts_eflags = 0;
	
	if (curenv && curenv->env_status == ENV_RUNNING)
		env_run(curenv);
	else
		sched_yield();
}
Ejemplo n.º 19
0
void
page_fault_handler(struct Trapframe *tf)
{
	struct UTrapframe *utfp;
	uint32_t fault_va;
	void *handler = NULL;
	int i;

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

	// If the low two bits of tf_cs are 0, the current privilage level
	//  is 0, or kernel mode.  Panic!!!
	if((tf->tf_cs&0x3) == 0)
		panic("page fault in kernel mode");

	// 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').

	// Try to find an appropriate page fault handler.  First search through
	//  the environment's region handlers, and if fault_va is contained in
	//  any of them, use the associated handler.
	for(i = 0; i < MAXHANDLERS; i++) {
		if(curenv->env_pgfault_handlers[i].erh_handler != NULL &&
		   fault_va >= curenv->env_pgfault_handlers[i].erh_minaddr &&
		   fault_va < curenv->env_pgfault_handlers[i].erh_maxaddr) {
			handler = curenv->env_pgfault_handlers[i].erh_handler;
			break;
		}
	}

	// If there is no appropriate region handler, use env_pgfault_global
	if(handler == NULL) handler = curenv->env_pgfault_global;

	// Check if a user-installed handler exists
	if(handler != NULL) {
		// If tf is on the exception stack, push a word onto the stack,
		//  otherwise set up UXSTACKTOP as the user exception stack.
		//  'utfp' is used to more easily push values to the user stack.
		if(tf->tf_esp < UXSTACKTOP && tf->tf_esp >= UXSTACKTOP-PGSIZE) {
			// Creates space for a new UTrapframe plus one extra word
			utfp = ((struct UTrapframe *)(tf->tf_esp-4))-1;
		} else {
			// Creates space for a new UTrapframe
			utfp = ((struct UTrapframe *)UXSTACKTOP)-1;
		}

		// Check that utfp exists and is writable
		user_mem_assert(curenv, utfp, sizeof(struct UTrapframe), PTE_W);

		// If the stack isn't overflown, press on!
		if((int)utfp >= UXSTACKTOP-PGSIZE) {
			// Push values onto the stack
			utfp->utf_esp = tf->tf_esp;
			utfp->utf_eflags = tf->tf_eflags;
			utfp->utf_eip = tf->tf_eip;
			utfp->utf_regs = tf->tf_regs;
			utfp->utf_err = tf->tf_err;
			utfp->utf_fault_va = fault_va;

			// Now return to the user-defined handler, switching
			//  to the newly created stack
			tf->tf_eip = (int)curenv->env_pgfault_upcall;

			// There should be one more word on the stack to store
			//  the handler pointer to use.  This allows for multiple
			//  handlers to be registered simultaneously.
			tf->tf_esp = (int)utfp-4;
			*((void **)tf->tf_esp) = handler;
			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);
}
Ejemplo n.º 20
0
Archivo: trap.c Proyecto: 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);
}
Ejemplo n.º 21
0
void
page_fault_handler(struct Trapframe *tf)
{
	uint64_t fault_va;

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

	// Handle kernel-mode page faults.
//	cprintf("entering page fault\n");
	// LAB 3: Your code here.
	if((tf->tf_cs & 3) == 0)
	{
		panic("pagefault occurs in kernel mode");
	}
	// 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.
	struct UTrapframe *new_utrap;
	if((curenv->env_pgfault_upcall)!=NULL)
	{
        
	int perm=PTE_P|PTE_U|PTE_W;
	 if((tf->tf_rsp>=UXSTACKTOP-PGSIZE)&&(tf->tf_rsp<=UXSTACKTOP-1))
	{
		cprintf("case 1\n");
                new_utrap=(struct UTrapframe *)(tf->tf_rsp-sizeof(struct UTrapframe)-8);
        }
	else
                new_utrap=(struct UTrapframe *)(UXSTACKTOP-sizeof(struct UTrapframe));
		
	// Destroy the environment that caused the fault.
//	cprintf("check user mem envid=%08x\n",curenv->env_id);
	user_mem_assert(curenv,(void *)new_utrap,sizeof(struct UTrapframe),perm);
	//memmove((void *)recurs,(void *)&new_utrap,sizeof(new_utrap));
//	cprintf("user mem ok utf_fault_va=%08x\n",fault_va);
	new_utrap->utf_fault_va=fault_va;
        new_utrap->utf_err=tf->tf_err;
        new_utrap->utf_regs=tf->tf_regs;
        new_utrap->utf_rip=tf->tf_rip;
        new_utrap->utf_rsp=tf->tf_rsp;
        new_utrap->utf_eflags=tf->tf_eflags;
	tf->tf_rip=(uint64_t)curenv->env_pgfault_upcall;
	tf->tf_rsp=(uint64_t)new_utrap;
	env_run(curenv);
	}
//	  	cprintf("check page fault 2\n");
		cprintf("[%08x] user fault va %08x ip %08x\n",
                curenv->env_id, fault_va, tf->tf_rip);
                print_trapframe(tf);
                env_destroy(curenv);
}		
Ejemplo n.º 22
0
Archivo: sched.c Proyecto: ajsbu/cse506
// Choose a user environment to run and run it.
void
sched_yield(void)
{
	struct Env *idle;
	int i;

	// Implement simple round-robin scheduling.
	//
	// Search through 'envs' for an ENV_RUNNABLE environment in
	// circular fashion starting just after the env this CPU was
	// last running.  Switch to the first such environment found.
	//
	// If no envs are runnable, but the environment previously
	// running on this CPU is still ENV_RUNNING, it's okay to
	// choose that environment.
	//
	// Never choose an environment that's currently running on
	// another CPU (env_status == ENV_RUNNING) and never choose an
	// idle environment (env_type == ENV_TYPE_IDLE).  If there are
	// no runnable environments, simply drop through to the code
	// below to switch to this CPU's idle environment.

	// LAB 4: Your code here.

	if(thiscpu->cpu_env) {
		i = thiscpu->cpu_env-envs;
	} else {
		i = 1;
	}

	int k = i+1;
	int j = 1;
	for (j = 1; j<NENV; j++) {
		if ((envs[k].env_status == ENV_RUNNABLE) && (envs[k].env_type != ENV_TYPE_IDLE)) {
			env_run(&envs[k]);
		}

		k++;
		if (k==NENV) {
			k = 0;
		}
	}

	if (thiscpu->cpu_env) {
		if (j==NENV && thiscpu->cpu_env->env_status == ENV_RUNNING) {
			env_run(thiscpu->cpu_env);
		}
	}


	// For debugging and testing purposes, if there are no
	// runnable environments other than the idle environments,
	// drop into the kernel monitor.

        // For debugging and testing purposes, if there are no
        // runnable environments other than the idle environments,
        // drop into the kernel monitor.
        for (i = 0; i < NENV; i++) {
	        if (envs[i].env_type != ENV_TYPE_IDLE &&
                    (envs[i].env_status == ENV_RUNNABLE ||
                     envs[i].env_status == ENV_RUNNING))
                     break;
        }

        if (i == NENV) {
                cprintf("No more runnable environments!\n");
                while (1)
                        monitor(NULL);
        }

        // Run this CPU's idle environment when nothing else is runnable.
        idle = &envs[cpunum()];
        if (!(idle->env_status == ENV_RUNNABLE || idle->env_status == ENV_RUNNING))
                panic("CPU %d: No idle environment!", cpunum());
        env_run(idle);

}
Ejemplo n.º 23
0
void
page_fault_handler(struct Trapframe *tf)
{
	uint32_t fault_va;
	void *va;
	int rc;
	struct UTrapframe utf;

	// 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 & 0x3) == RPL_K) {
		panic("Oops! Page fault in kernel: %p", fault_va);
	}

	// 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 != NULL) {
		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;

		// NOTE: since PF happened in user mode, CR3 should already have the
		// corres. env's PD loaded, hence no need to do explicit lcr3().
		if ( ((UXSTACKTOP - PGSIZE) <= tf->tf_esp)
				&& (tf->tf_esp < UXSTACKTOP) ) {
			va = (void *) (tf->tf_esp - sizeof(utf) - 4);
			//clog("wp1: va = %p, fault_va = %p, err = 0x%x, esp = %p, eip = %p",
			//		va, fault_va, tf->tf_err, tf->tf_esp, tf->tf_eip);
			user_mem_assert(curenv, va, sizeof(utf) + 4, PTE_W | PTE_U);

			//lcr3(curenv->env_cr3);
			memset(va + sizeof(utf), 0, 4);
		}
		else {
			va = (void *) (UXSTACKTOP - sizeof(utf));
			//clog("wp2: va = %p, fault_va = %p, err = 0x%x, esp = %p, eip = %p",
			//		va, fault_va, tf->tf_err, tf->tf_esp, tf->tf_eip);
			user_mem_assert(curenv, va, sizeof(utf), PTE_W | PTE_U);

			//lcr3(curenv->env_cr3);
		}
		memmove(va, &utf, sizeof(utf));

		tf->tf_esp = (uintptr_t) va;
		tf->tf_eip = (uintptr_t) curenv->env_pgfault_upcall;
		env_run(curenv);
	}

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