Esempio n. 1
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 && 0x01 == 0) {
		panic("page_fault in kernel mode, fault address %d\n", fault_va);
	}
	// LAB 3: Your code here.
	
	// We've already handled kernel-mode exceptions, so if we get here,
	// the page fault happened in user mode.

	// 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);
}
Esempio n. 2
0
void syscall(void)
{
	assert(current != NULL);
	struct trapframe *tf = current->tf;
	uint32_t arg[5];
	int num = tf->tf_regs.reg_r[MIPS_REG_V0];
	//num -= T_SYSCALL;
	//kprintf("$ %d %d\n",current->pid, num);
	if (num >= 0 && num < NUM_SYSCALLS) {
		if (syscalls[num] != NULL) {
			arg[0] = tf->tf_regs.reg_r[MIPS_REG_A0];
			arg[1] = tf->tf_regs.reg_r[MIPS_REG_A1];
			arg[2] = tf->tf_regs.reg_r[MIPS_REG_A2];
			arg[3] = tf->tf_regs.reg_r[MIPS_REG_A3];
			arg[4] = tf->tf_regs.reg_r[MIPS_REG_T0];
			tf->tf_regs.reg_r[MIPS_REG_V0] = syscalls[num] (arg);
			return;
		}
	}
	print_trapframe(tf);
	panic("undefined syscall %d, pid = %d, name = %s.\n",
	      num, current->pid, current->name);
}
Esempio n. 3
0
File: trap.c Progetto: kanojs/akaros
static void
unhandled_trap(struct hw_trapframe *state, const char* name)
{
    static spinlock_t screwup_lock = SPINLOCK_INITIALIZER;
    spin_lock(&screwup_lock);

    if(in_kernel(state))
    {
        print_trapframe(state);
        panic("Unhandled trap in kernel!\nTrap type: %s", name);
    }
    else
    {
        char tf_buf[1024];
        format_trapframe(state, tf_buf, sizeof(tf_buf));

        warn("Unhandled trap in user!\nTrap type: %s\n%s", name, tf_buf);
        backtrace();
        spin_unlock(&screwup_lock);

        assert(current);
        proc_destroy(current);
    }
}
Esempio n. 4
0
static void
trap_dispatch(struct Trapframe *tf)
{
	// Handle processor exceptions.
	// LAB 3: Your code here.
	
	int32_t ret;

	switch (tf->tf_trapno){
		case T_PGFLT:{ //14
			page_fault_handler(tf);
			return;
		}
		case T_BRKPT:{ //3 
			breakpoint_handler(tf);
			return;
		}
		case T_DEBUG:{
			breakpoint_handler(tf);
			return;
		}
		case T_SYSCALL:{
			ret = system_call_handler(tf);
			tf->tf_regs.reg_eax = ret;
			return;
		}
		case IRQ_OFFSET+IRQ_TIMER:{
			lapic_eoi();
			time_tick();
			sched_yield();
			return;
		}
		case IRQ_OFFSET+IRQ_KBD:{
			kbd_intr();
			return;
		}
		case IRQ_OFFSET+IRQ_SERIAL:{
			serial_intr();
			return;
		}
		case IRQ_OFFSET+IRQ_E1000:{
			e1000_trap_handler();
			return;
		}
	}	

	// Handle spurious interrupts
	// The hardware sometimes raises these because of noise on the
	// IRQ line or other reasons. We don't care.
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) {
		cprintf("Spurious interrupt on irq 7\n");
		print_trapframe(tf);
		return;
	}

	// Handle clock interrupts. Don't forget to acknowledge the
	// interrupt using lapic_eoi() before calling the scheduler!
	// LAB 4: Your code here.

	// Add time tick increment to clock interrupts.
	// Be careful! In multiprocessors, clock interrupts are
	// triggered on every CPU.
	// LAB 6: Your code here.


	// Handle keyboard and serial interrupts.
	// LAB 5: Your code here.

	// Unexpected trap: The user process or the kernel has a bug.
	print_trapframe(tf);
	if (tf->tf_cs == GD_KT)
	  panic("unhandled trap in kernel");
	else {
		env_destroy(curenv);
		return;
	}
}
Esempio n. 5
0
static void
trap_dispatch(struct trapframe *tf) {
    char c;

    int ret;

	static int counter = 0;
    switch (tf->tf_trapno) {
    case T_PGFLT:  //page fault
        if ((ret = pgfault_handler(tf)) != 0) {
            print_trapframe(tf);
            panic("handle pgfault failed. %e\n", ret);
        }
        break;
    case IRQ_OFFSET + IRQ_TIMER:
#if 0
    LAB3 : If some page replacement algorithm(such as CLOCK PRA) need tick to change the priority of pages, 
    then you can add code here. 
#endif
        /* LAB1 2010011358: STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
		if (++counter == TICK_NUM){
			counter = 0;
			print_ticks();
		}
        break;
    case IRQ_OFFSET + IRQ_COM1:
        c = cons_getc();
        cprintf("serial [%03d] %c\n", c, c);
        break;
    case IRQ_OFFSET + IRQ_KBD:
        c = cons_getc();
        cprintf("kbd [%03d] %c\n", c, c);
        break;
    //LAB1 CHALLENGE 1 : YOUR CODE you should modify below codes.
    case T_SWITCH_TOU:
		asm volatile( "cli;");
		tf->tf_ds =	0x23;
		tf->tf_es =	0x23;
		tf->tf_fs =	0x23;
		tf->tf_gs =	0x23;
		tf->tf_eflags = tf->tf_eflags | 0x200;
		tf->tf_eflags = tf->tf_eflags | 0x3000;
		tf->tf_ss = 0x23;
		tf->tf_cs = 0x1B;
		tf->tf_esp = tf->tf_regs.reg_eax;
		break;
    case T_SWITCH_TOK:
		asm volatile( "cli;");
		tf->tf_ds =	0x10;
		tf->tf_es =	0x10;
		tf->tf_fs =	0x10;
		tf->tf_gs =	0x10;
		tf->tf_eflags = tf->tf_eflags | 0x200;
		tf->tf_eflags = tf->tf_eflags & ~0x3000U | 0x1000U;
		tf->tf_ss = 0x10;
		tf->tf_cs = 0x8;
        break;
    case IRQ_OFFSET + IRQ_IDE1:
    case IRQ_OFFSET + IRQ_IDE2:
        /* do nothing */
        break;
    default:
        // in kernel, it must be a mistake
        if ((tf->tf_cs & 3) == 0) {
            print_trapframe(tf);
            panic("unexpected trap in kernel.\n");
        }
    }
}
Esempio n. 6
0
void
page_fault_handler(struct Trapframe *tf)
{
	u_int fault_va;

	// Read processor's CR2 register to find the faulting address
	fault_va = rcr2();
    
    if(!(tf->tf_cs & 0x3))
    {
        // This happens in kernel mode
        if(page_fault_mode == PFM_NONE) {
            int i;
            u_long ebp = tf->tf_ebp;
            for(i = 0; i < 3; i++) {
                ebp = backtrace_intrap(ebp);
            }
            panic("Aiee, page fault in kernel mode va %08x ip %08x\n", fault_va, tf->tf_eip);
        }
        else
        {
            Pte *pte;
            u_long va = fault_va;
            printf("[%08x] PFM_KILL va %08x ip %08x\n",
                    curenv->env_id, fault_va, tf->tf_eip);
            printf("curenv->env_pgdir[PDX(va)] = %08x\n", curenv->env_pgdir[PDX(va)]);
            pte = KADDR(PTE_ADDR(curenv->env_pgdir[PDX(va)]));
            printf("pte[PTX(va)] = %08x\n", pte[PTX(va)]);
            page_fault_mode = PFM_NONE;
            env_destroy(curenv);
        }
        return;
    }

    if(curenv->env_pgfault_entry)
    {
        u_int newsp;
        struct user_stack_frame *us;
        if(tf->tf_esp > UXSTACKTOP-BY2PG && 
                tf->tf_esp < UXSTACKTOP)
        {
            //Page fault within UXSTACKTOP
            newsp = tf->tf_esp - 8; // Reserve 2 words for eip and eflags
        }
        else
        {
            newsp = UXSTACKTOP;
        }
        if(newsp < UXSTACKTOP-BY2PG)
            goto fail;
        //printf("Trap env[%08x] va %08x ip %08x\n", curenv->env_id, fault_va, tf->tf_eip);
        //print_trapframe(tf);
        //printf("newsp = %08x, tf->tf_esp = %08x\n", newsp, tf->tf_esp);
        us = (struct user_stack_frame *)(newsp - sizeof(struct user_stack_frame));
        us->fault_va = fault_va;
        us->tf_err = tf->tf_err;
        us->esp = tf->tf_esp;
        us->eip = tf->tf_eip;
        us->eflags = tf->tf_eflags;
        tf->tf_esp = newsp;
        tf->tf_eip = curenv->env_pgfault_entry;
        return;
    }
fail:
	// User-mode exception - destroy the environment.
	printf("[%08x] user fault va %08x ip %08x\n",
		curenv->env_id, fault_va, tf->tf_eip);
	print_trapframe(tf);
	env_destroy(curenv);
}
Esempio n. 7
0
static void
trap_dispatch(struct trapframe *tf) {
    char c;

    int ret=0;

    switch (tf->tf_trapno) {
    case T_PGFLT:  //page fault
        if ((ret = pgfault_handler(tf)) != 0) {
            print_trapframe(tf);
            if (current == NULL) {
                panic("handle pgfault failed. ret=%d\n", ret);
            }
            else {
                if (trap_in_kernel(tf)) {
                    panic("handle pgfault failed in kernel mode. ret=%d\n", ret);
                }
                cprintf("killed by kernel.\n");
                panic("handle user mode pgfault failed. ret=%d\n", ret); 
                do_exit(-E_KILLED);
            }
        }
        break;
    case T_SYSCALL:
        syscall();
        break;
    case IRQ_OFFSET + IRQ_TIMER:
#if 0
    LAB3 : If some page replacement algorithm(such as CLOCK PRA) need tick to change the priority of pages,
    then you can add code here. 
#endif
        /* LAB1 2011010312 : STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
        /* LAB5 2011010312 */
        /* you should upate you lab1 code (just add ONE or TWO lines of code):
         *    Every TICK_NUM cycle, you should set current process's current->need_resched = 1
         */
        ticks++;
        if(ticks == TICK_NUM) {
            ticks = 0;
            current->need_resched = 1;
        }
        break;
    case IRQ_OFFSET + IRQ_COM1:
        c = cons_getc();
        cprintf("serial [%03d] %c\n", c, c);
        break;
    case IRQ_OFFSET + IRQ_KBD:
        c = cons_getc();
        cprintf("kbd [%03d] %c\n", c, c);
        break;
    //LAB1 CHALLENGE 1 : YOUR CODE you should modify below codes.
    case T_SWITCH_TOU:
    case T_SWITCH_TOK:
        panic("T_SWITCH_** ??\n");
        break;
    case IRQ_OFFSET + IRQ_IDE1:
    case IRQ_OFFSET + IRQ_IDE2:
        /* do nothing */
        break;
    default:
        print_trapframe(tf);
        if (current != NULL) {
            cprintf("unhandled trap.\n");
            do_exit(-E_KILLED);
        }
        // in kernel, it must be a mistake
        panic("unexpected trap in kernel.\n");

    }
}
Esempio n. 8
0
static void
trap_dispatch(struct trapframe *tf) {
    char c;

    int ret=0;

    switch (tf->tf_trapno) {
    case T_PGFLT:  //page fault
        if ((ret = pgfault_handler(tf)) != 0) {
            print_trapframe(tf);
            if (current == NULL) {
                panic("handle pgfault failed. ret=%d\n", ret);
            }
            else {
                if (trap_in_kernel(tf)) {
                    panic("handle pgfault failed in kernel mode. ret=%d\n", ret);
                }
                cprintf("killed by kernel.\n");
                panic("handle user mode pgfault failed. ret=%d\n", ret); 
                do_exit(-E_KILLED);
            }
        }
        break;
    case T_SYSCALL:
        syscall();
        break;
    case IRQ_OFFSET + IRQ_TIMER:
#if 0
    LAB3 : If some page replacement algorithm(such as CLOCK PRA) need tick to change the priority of pages,
    then you can add code here. 
#endif
        /* LAB1 YOUR CODE : STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
        /* LAB5 YOUR CODE */
        /* you should upate you lab1 code (just add ONE or TWO lines of code):
         *    Every TICK_NUM cycle, you should set current process's current->need_resched = 1
         */
        /* LAB6 YOUR CODE */
        /* IMPORTANT FUNCTIONS:
	     * run_timer_list
	     *----------------------
	     * you should update your lab5 code (just add ONE or TWO lines of code):
         *    Every tick, you should update the system time, iterate the timers, and trigger the timers which are end to call scheduler.
         *    You can use one funcitons to finish all these things.
         */
		ticks ++;
		run_timer_list();

        break;
    case IRQ_OFFSET + IRQ_COM1:
        c = cons_getc();
        cprintf("serial [%03d] %c\n", c, c);
        break;
    case IRQ_OFFSET + IRQ_KBD:
        c = cons_getc();
        cprintf("kbd [%03d] %c\n", c, c);
        break;
    //LAB1 CHALLENGE 1 : 13307130148 you should modify below codes.
    case T_SWITCH_TOU:
		cprintf("To user mode\n");
		if (tf->tf_cs != USER_CS) {
			tfk2u = *tf;
			tfk2u.tf_cs = USER_CS;
			tfk2u.tf_ds = tfk2u.tf_es = tfk2u.tf_ss = USER_DS;
			tfk2u.tf_esp = (uint32_t)tf + sizeof(struct trapframe) - 8;
			tfk2u.tf_eflags |= (3 << 12);
			*((uint32_t *)tf - 1) = (uint32_t)&tfk2u;
		}
		break;
    case T_SWITCH_TOK:
		cprintf("To kernel mode\n");
        //panic("T_SWITCH_** ??\n");
		struct trapframe *tfu2k;
		if (tf->tf_cs != KERNEL_CS) {
			tf->tf_cs = KERNEL_CS;
			tf->tf_ds = tf->tf_es = KERNEL_DS;
			tf->tf_eflags &= ~(3 << 12);
			tfu2k = (struct trapframe*)((uint32_t)tf->tf_esp - sizeof(struct trapframe) + 8);
			memmove(tfu2k, tf, sizeof(struct trapframe)-8);
			*((uint32_t *)tf - 1) = (uint32_t)tfu2k;
		}
        break;
    case IRQ_OFFSET + IRQ_IDE1:
    case IRQ_OFFSET + IRQ_IDE2:
        /* do nothing */
        break;
    default:
        print_trapframe(tf);
        if (current != NULL) {
            cprintf("unhandled trap.\n");
            do_exit(-E_KILLED);
        }
        // in kernel, it must be a mistake
        panic("unexpected trap in kernel.\n");

    }
}
Esempio n. 9
0
File: trap.c Progetto: joe-cai/jos
static void
trap_dispatch(struct Trapframe *tf)
{
    // Handle processor exceptions.
    // LAB 3: Your code here.
    if (tf->tf_trapno == T_BRKPT) {
	print_trapframe(tf);
	// cprintf("Breakpoint!\n");
	while (1)
	    monitor(NULL);
    } else if (tf->tf_trapno == T_PGFLT) {
	page_fault_handler(tf);
	return;
    } else if (tf->tf_trapno == T_SYSCALL) {
	uint32_t syscallno;
	uint32_t a1, a2, a3, a4, a5;
	syscallno = tf->tf_regs.reg_eax;
	a1 = tf->tf_regs.reg_edx;
	a2 = tf->tf_regs.reg_ecx;
	a3 = tf->tf_regs.reg_ebx;
	a4 = tf->tf_regs.reg_edi;
	a5 = tf->tf_regs.reg_esi;
	int32_t ret = syscall(syscallno, a1, a2, a3, a4, a5);
	tf->tf_regs.reg_eax = ret;
	return;
    }

    // Handle spurious interrupts
    // The hardware sometimes raises these because of noise on the
    // IRQ line or other reasons. We don't care.
    if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) {
	cprintf("Spurious interrupt on irq 7\n");
	print_trapframe(tf);
	return;
    }

    // Handle clock interrupts. Don't forget to acknowledge the
    // interrupt using lapic_eoi() before calling the scheduler!
    // LAB 4: Your code here.
    if (tf->tf_trapno == IRQ_OFFSET + IRQ_TIMER) {
	time_tick();
	lapic_eoi(); /* what's that? */
	sched_yield();
    }

    // Handle keyboard and serial interrupts.
    // LAB 5: Your code here.
    if (tf->tf_trapno == IRQ_OFFSET + IRQ_KBD) {
	kbd_intr();
	return;
    }
    if (tf->tf_trapno == IRQ_OFFSET + IRQ_SERIAL) {
	serial_intr();
	return;
    }

    // Unexpected trap: The user process or the kernel has a bug.
    print_trapframe(tf);
    if (tf->tf_cs == GD_KT)
	panic("unhandled trap in kernel");
    else {
	env_destroy(curenv);
	return;
    }
}
Esempio n. 10
0
File: trap.c Progetto: sjyfok/moocos
static void
trap_dispatch(struct trapframe *tf) {
    char c;

    int ret;

    switch (tf->tf_trapno) {
    case T_PGFLT:  //page fault
        if ((ret = pgfault_handler(tf)) != 0) {
            print_trapframe(tf);
            panic("handle pgfault failed. %e\n", ret);
        }
        break;
    case IRQ_OFFSET + IRQ_TIMER:
#if 0
    LAB3 : If some page replacement algorithm(such as CLOCK PRA) need tick to change the priority of pages, 
    then you can add code here. 
#endif
        /* LAB1 YOUR CODE : STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
        ticks ++;
        if (ticks % TICK_NUM == 0)
       		print_ticks();
        break;
    case IRQ_OFFSET + IRQ_COM1:
        c = cons_getc();
        cprintf("serial [%03d] %c\n", c, c);
        break;
    case IRQ_OFFSET + IRQ_KBD:
        c = cons_getc();
        cprintf("kbd [%03d] %c\n", c, c);
        if (c == '0')
        {
        	user2kernel(tf);
        }
        if (c == '3')
        {
			kernel2user(tf);
        }
        print_trapframe(tf);
        break;
    //LAB1 CHALLENGE 1 : YOUR CODE you should modify below codes.
    case T_SWITCH_TOU:
    	kernel2user(tf);
/*    	if (tf->tf_cs != USER_CS)
    	{
    		switchk2u = *tf;
    		switchk2u.tf_cs = USER_CS;
    		switchk2u.tf_ds = switchk2u.tf_es = switchk2u.tf_ss = USER_DS;
    		switchk2u.tf_esp = (uint32_t)tf + sizeof(struct trapframe)-8;

    		switchk2u.tf_eflags |= FL_IOPL_MASK;

    		*((uint32_t *)tf -1) = (uint32_t)&switchk2u;
    	}*/
    	break;
    case T_SWITCH_TOK:
        //panic("T_SWITCH_** ??\n");
        user2kernel(tf);
/*        if (tf->tf_cs != KERNEL_CS)
		{
			tf->tf_cs = KERNEL_CS;
			tf->tf_ds = tf->tf_es = KERNEL_DS;
			tf->tf_eflags &= ~FL_IOPL_MASK;
			switchu2k = (struct trapframe *)(tf->tf_esp - (sizeof(struct trapframe)-8));
			memmove(switchu2k, tf, sizeof(struct trapframe)-8);
			*((uint32_t*)tf-1) = (uint32_t)switchu2k;
		}*/
        break;
    case IRQ_OFFSET + IRQ_IDE1:
    case IRQ_OFFSET + IRQ_IDE2:
        /* do nothing */
        break;
    default:
        // in kernel, it must be a mistake
        if ((tf->tf_cs & 3) == 0) {
            print_trapframe(tf);
            panic("unexpected trap in kernel.\n");
        }
    }
}
Esempio n. 11
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);
}
Esempio n. 12
0
static void
trap_dispatch(struct Trapframe *tf)
{
	// Handle processor exceptions.
	// LAB 3: Your code here.
	switch(tf->tf_trapno) {
	case T_PGFLT:
		page_fault_handler(tf);
		return;
	case T_BRKPT:
	case T_DEBUG:
		monitor(tf);
		return;
	case T_SYSCALL:
		tf->tf_regs.reg_eax = syscall(tf->tf_regs.reg_eax, // syscall #
					tf->tf_regs.reg_edx, // arg1
					tf->tf_regs.reg_ecx, // arg2
					tf->tf_regs.reg_ebx, // arg3
					tf->tf_regs.reg_edi, // arg4
					tf->tf_regs.reg_esi);// arg5
		return;
	}

	// Handle spurious interrupts
	// The hardware sometimes raises these because of noise on the
	// IRQ line or other reasons. We don't care.
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) {
		cprintf("Spurious interrupt on irq 7\n");
		print_trapframe(tf);
		return;
	}

	// Handle clock interrupts. Don't forget to acknowledge the
	// interrupt using lapic_eoi() before calling the scheduler!
	// Add time tick increment to clock interrupts.
	// Be careful! In multiprocessors, clock interrupts are
	// triggered on every CPU.
	// LAB 4: Your code here.
	// LAB 6: Your code here.
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_TIMER) {
		time_tick();
		lapic_eoi();
		sched_yield();
		return;
	}

	// Handle keyboard and serial interrupts.
	// LAB 7: Your code here.
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_SERIAL) {
		serial_intr();
		return;
	}

	if (tf->tf_trapno == IRQ_OFFSET + IRQ_KBD) {
		kbd_intr();
		return;
	}

	// Unexpected trap: The user process or the kernel has a bug.
	print_trapframe(tf);
	if (tf->tf_cs == GD_KT)
		panic("unhandled trap in kernel");
	else {
		env_destroy(curenv);
		return;
	}
}
Esempio n. 13
0
static void
trap_dispatch(struct trapframe *tf) {
    char c;

    int ret=0;

    switch (tf->tf_trapno) {
    case T_PGFLT:  //page fault
        if ((ret = pgfault_handler(tf)) != 0) {
            print_trapframe(tf);
            if (current == NULL) {
                panic("handle pgfault failed. ret=%d\n", ret);
            }
            else {
                if (trap_in_kernel(tf)) {
                    panic("handle pgfault failed in kernel mode. ret=%d\n", ret);
                }
                cprintf("killed by kernel.\n");
                panic("handle user mode pgfault failed. ret=%d\n", ret); 
                do_exit(-E_KILLED);
            }
        }
        break;
    case T_SYSCALL:
        syscall();
        break;
    case IRQ_OFFSET + IRQ_TIMER:
#if 0
    LAB3 : If some page replacement algorithm(such as CLOCK PRA) need tick to change the priority of pages,
    then you can add code here. 
#endif
        /* LAB1 YOUR CODE : STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
        /* LAB5 2014011421 */
        /* you should upate you lab1 code (just add ONE or TWO lines of code):
         *    Every TICK_NUM cycle, you should set current process's current->need_resched = 1
         */
        /* LAB6 2014011421 */
        /* you should upate you lab5 code
         * IMPORTANT FUNCTIONS:
	     * sched_class_proc_tick
         */         
        /* LAB7 2014011421 */
        /* you should upate you lab6 code
         * IMPORTANT FUNCTIONS:
	     * run_timer_list
         */
        ticks++;
        run_timer_list();
        break;
    case IRQ_OFFSET + IRQ_COM1:
        c = cons_getc();
        cprintf("serial [%03d] %c\n", c, c);
        break;
    case IRQ_OFFSET + IRQ_KBD:
        // There are user level shell in LAB8, so we need change COM/KBD interrupt processing.
        c = cons_getc();
        {
          extern void dev_stdin_write(char c);
          dev_stdin_write(c);
        }
        break;
    //LAB1 CHALLENGE 1 : YOUR CODE you should modify below codes.
    case T_SWITCH_TOU:
        if (tf->tf_cs != USER_CS) {
            switchk2u = *tf;
            switchk2u.tf_cs = USER_CS;
            switchk2u.tf_ds = switchk2u.tf_es = switchk2u.tf_ss = USER_DS;
            switchk2u.tf_esp = (uint32_t)tf + sizeof(struct trapframe) - 8;
        
            // set eflags, make sure ucore can use io under user mode.
            // if CPL > IOPL, then cpu will generate a general protection.
            switchk2u.tf_eflags |= FL_IOPL_MASK;
        
            // set temporary stack
            // then iret will jump to the right stack
            *((uint32_t *)tf - 1) = (uint32_t)&switchk2u;
        }
        break;
    case T_SWITCH_TOK:
        if (tf->tf_cs != KERNEL_CS) {
            tf->tf_cs = KERNEL_CS;
            tf->tf_ds = tf->tf_es = KERNEL_DS;
            tf->tf_eflags &= ~FL_IOPL_MASK;
            switchu2k = (struct trapframe *)(tf->tf_esp - (sizeof(struct trapframe) - 8));
            memmove(switchu2k, tf, sizeof(struct trapframe) - 8);
            *((uint32_t *)tf - 1) = (uint32_t)switchu2k;
        }
        break;
    case IRQ_OFFSET + IRQ_IDE1:
    case IRQ_OFFSET + IRQ_IDE2:
        /* do nothing */
        break;
    default:
        print_trapframe(tf);
        if (current != NULL) {
            cprintf("unhandled trap.\n");
            do_exit(-E_KILLED);
        }
        // in kernel, it must be a mistake
        panic("unexpected trap in kernel.\n");

    }
}
Esempio n. 14
0
static void
trap_dispatch(struct trapframe *tf) {
    char c;

    switch (tf->tf_trapno) {
    case IRQ_OFFSET + IRQ_TIMER:
        /* LAB1 YOUR CODE : STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
		ticks++;
		if (ticks >= TICK_NUM)
		{
			print_ticks();
			ticks = 0;
		}
		break;
    case IRQ_OFFSET + IRQ_COM1:
        c = cons_getc();
        cprintf("serial [%03d] %c\n", c, c);
        break;
    case IRQ_OFFSET + IRQ_KBD:
        c = cons_getc();
        cprintf("kbd [%03d] %c\n", c, c);
        break;
    //LAB1 CHALLENGE 1 : YOUR CODE you should modify below codes.
    case T_SWITCH_TOU:
        if (tf->tf_cs != USER_CS)
        {
            k2u = *tf;
            k2u.tf_cs = USER_CS;
            k2u.tf_ds = k2u.tf_es = k2u.tf_ss = USER_DS;
            k2u.tf_esp = (uint32_t)tf + sizeof(struct trapframe) - 8;
            k2u.tf_eflags |= FL_IOPL_MASK;
            *((uint32_t *)tf - 1) = (uint32_t)&k2u;
        }
        break;
    case T_SWITCH_TOK:
        if (tf->tf_cs != KERNEL_CS)
        {
            tf->tf_cs = KERNEL_CS;
            tf->tf_ds = tf->tf_es = KERNEL_DS;
            tf->tf_eflags = tf->tf_eflags & ~FL_IOPL_MASK;
            u2k = *((struct trapframe*)(tf->tf_esp - (sizeof(struct trapframe) - 8)));
            memmove(&u2k, tf, sizeof(struct trapframe) - 8);
            *((uint32_t *)tf - 1) = (uint32_t)&u2k;
         }
        //panic("T_SWITCH_** ??\n");
        break;
    case IRQ_OFFSET + IRQ_IDE1:
    case IRQ_OFFSET + IRQ_IDE2:
        /* do nothing */
        break;
    default:
        // in kernel, it must be a mistake
        if ((tf->tf_cs & 3) == 0) {
            print_trapframe(tf);
            panic("unexpected trap in kernel.\n");
        }
    }
}
Esempio n. 15
0
static void
trap_dispatch(struct Trapframe *tf)
{

	// Handle processor exceptions.
	// LAB 3: Your code here.
//----------------------------------------  Lab3  ------------------------------------------------------------
    if (tf->tf_trapno == T_PGFLT) {
        //cprintf("pagefault!\n");
        page_fault_handler(tf);
        return;
    }
    if (tf->tf_trapno == T_BRKPT) {
        //cprintf("brkpt!\n");
        monitor(tf);
        return;
    }
    if (tf->tf_trapno == T_DEBUG) {
        my_monitor(tf);
        return;
    }
    if (tf->tf_trapno == T_SYSCALL) {
        //cprintf("Syscall!\n");
        tf->tf_regs.reg_eax = syscall(tf->tf_regs.reg_eax, tf->tf_regs.reg_edx, tf->tf_regs.reg_ecx, 
                              tf->tf_regs.reg_ebx, tf->tf_regs.reg_edi, tf->tf_regs.reg_esi);
        if (tf->tf_regs.reg_eax < 0)
            panic("syscall failed: %e\n", tf->tf_regs.reg_eax);
        return;
    }
//----------------------------------------  Lab3  ------------------------------------------------------------

	// Handle spurious interrupts
	// The hardware sometimes raises these because of noise on the
	// IRQ line or other reasons. We don't care.
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) {
		cprintf("Spurious interrupt on irq 7\n");
		print_trapframe(tf);
		return;
	}

	// Handle clock interrupts. Don't forget to acknowledge the
	// interrupt using lapic_eoi() before calling the scheduler!
	// LAB 4: Your code here.
//------------  Lab4  ----------------------------------------------------------------------------------------      
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_TIMER) {
		//	cprintf("clock interrupt!\n");
		lapic_eoi();
		sched_yield();
		return;
	}
//------------  Lab4  ----------------------------------------------------------------------------------------      

	// Unexpected trap: The user process or the kernel has a bug.
	print_trapframe(tf);
	if (tf->tf_cs == GD_KT)
		panic("unhandled trap in kernel");
	else {
		env_destroy(curenv);
		return;
	}
}
Esempio n. 16
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);
}
Esempio n. 17
0
        static void
trap_dispatch(struct Trapframe *tf)
{
        // Handle processor exceptions.
        // LAB 3: Your code here.
        // dec 15,2010 sunus
        switch(tf->tf_trapno)
        {
                case T_PGFLT : 
                        {
                                page_fault_handler(tf);
                                break;
                        }
                case T_DEBUG :
                        cprintf("encounter a breakpoint!\n"); /*fall through*/
                case T_BRKPT :
                        {
                                monitor(tf);
                                break;
                        }
                case T_SYSCALL :
                        {
                                (tf->tf_regs).reg_eax = 
                                        syscall(
                                                        (tf->tf_regs).reg_eax,
                                                        (tf->tf_regs).reg_edx,
                                                        (tf->tf_regs).reg_ecx,
                                                        (tf->tf_regs).reg_ebx,
                                                        (tf->tf_regs).reg_edi,
                                                        (tf->tf_regs).reg_esi);
                                return ;
                        }
                default : ; /* do nothing */
        }

        // Handle clock interrupts.
        // LAB 4: Your code here.

        // JAN 30,2011,SUNUS
        if(tf->tf_trapno == IRQ_OFFSET + IRQ_TIMER)
        {
                sched_yield();
                return;
        }
        // Handle spurious interrupts
        // The hardware sometimes raises these because of noise on the
        // IRQ line or other reasons. We don't care.
        if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) {
                cprintf("Spurious interrupt on irq 7\n");
                print_trapframe(tf);
                return;
        }


        // Unexpected trap: The user process or the kernel has a bug.
        print_trapframe(tf);
        if (tf->tf_cs == GD_KT)
                panic("unhandled trap in kernel");
        else {
                env_destroy(curenv);
                return;
        }
}
static void
trap_dispatch(struct Trapframe *tf)
{
	static int page_to_age = 0;
	int page_to_age_first = page_to_age;
	int num_page_updates = NPAGEUPDATES_FACTOR*NPAGESFREE_LOW_THRESHOLD;
	struct PteChain *pp_refs_chain;
	char page_accessed;

	// Handle processor exceptions.
	// LAB 3: Your code here.
	if (tf->tf_trapno == T_PGFLT) {
		page_fault_handler(tf);
		return;
	}
	else if (tf->tf_trapno == T_BRKPT) {
		monitor(tf);    // breakpoint exceptions invoke the kernel monitor
		return;
	}
	else if (tf->tf_trapno == T_SYSCALL) {
		tf->tf_regs.reg_eax = syscall(tf->tf_regs.reg_eax, tf->tf_regs.reg_edx, tf->tf_regs.reg_ecx, tf->tf_regs.reg_ebx, tf->tf_regs.reg_edi, tf->tf_regs.reg_esi);
		return;
	}

	// Handle spurious interrupts
	// The hardware sometimes raises these because of noise on the
	// IRQ line or other reasons. We don't care.
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) {
		cprintf("Spurious interrupt on irq 7\n");
		print_trapframe(tf);
		return;
	}

	// Handle clock interrupts. Don't forget to acknowledge the
	// interrupt using lapic_eoi() before calling the scheduler!
	// LAB 4: Your code here.
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_TIMER) {
		lapic_eoi();

		// Update the age of some physical pages

		// If we fall below the thresholds, update more pages than usual
		// This is somewhat arbitrary, we can tweak these numbers
		// We also might want to increase the order of magnitude of the number of pages we update per clock tick
		// This will require some testing and profiling
		// There is also no reason why num_page_updates is based on the threshold values, it can be incremented by its own macros
		if (num_free_pages <= NPAGESFREE_LOW_THRESHOLD) {
			num_page_updates += NPAGEUPDATES_FACTOR*NPAGESFREE_HIGH_THRESHOLD;
		}
		if (num_free_pages <= NPAGESFREE_HIGH_THRESHOLD) {
			num_page_updates += NPAGEUPDATES_FACTOR*NPAGESFREE_LOW_THRESHOLD;
		}

		for ( ; num_page_updates >= 0; --num_page_updates) {
			// Find the next page that is currently mapped in user space, by finding one with a nonzero pp_ref
			while (!pages[page_to_age].pp_ref) {
				// If we wrap around to where we started, stop updating page ages
				if ((page_to_age=(page_to_age+1)%npages) == page_to_age_first) {
					goto end_of_page_age_updates;
				}
			}

			// Iterate through all of the user space PTEs that map to this page
			// If any of them have been accessed, increment the age, and then clear the PTE_A bit in all of the PTEs
			page_accessed = 0;
			for (pp_refs_chain = pages[page_to_age].pp_refs_chain; pp_refs_chain; pp_refs_chain = pp_refs_chain->pc_link) {
				if (*pp_refs_chain->pc_pte & PTE_A) {
					page_accessed = 1;
					pages[page_to_age].age += PAGE_AGE_INCREMENT_ON_ACCESS;
					for ( ; pp_refs_chain; pp_refs_chain = pp_refs_chain->pc_link) {
						*(pp_refs_chain->pc_pte) &= ~PTE_A;
					}
					break;
				}
			}
			pages[page_to_age].age = (pages[page_to_age].age > MAX_PAGE_AGE ? MAX_PAGE_AGE : pages[page_to_age].age);
			if (!page_accessed) {
				if (pages[page_to_age].age >= (uint8_t)PAGE_AGE_DECREMENT_ON_CLOCK) {
					pages[page_to_age].age -= (uint8_t)PAGE_AGE_DECREMENT_ON_CLOCK;
				}
				else {
					pages[page_to_age].age = 0;
				}
			}

			// If we wrap around to where we started, stop updating page ages
			if ((page_to_age=(page_to_age+1)%npages) == page_to_age_first) {
				goto end_of_page_age_updates;
			}
		}
		end_of_page_age_updates:
		sched_yield();
	}

	// Handle keyboard and serial interrupts.
	// LAB 5: Your code here.
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_KBD) {
		lapic_eoi();
		kbd_intr();
		return;
	}
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_SERIAL) {
		lapic_eoi();
		serial_intr();
		return;
	}

	// Unexpected trap: The user process or the kernel has a bug.
	print_trapframe(tf);
	if (tf->tf_cs == GD_KT)
		panic("unhandled trap in kernel");
	else {
		env_destroy(curenv);
		return;
	}
}
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;
}
Esempio n. 20
0
/* trap_dispatch - dispatch based on what type of trap occurred */
static void
trap_dispatch(struct trapframe *tf) {
    char c;
    switch (tf->tf_trapno) {
    case IRQ_OFFSET + IRQ_TIMER:
        /* LAB1 YOUR CODE : STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
      ticks++;
      if ((ticks % TICK_NUM) == 0){
        print_ticks();
      }
        break;
    case IRQ_OFFSET + IRQ_COM1:
        c = cons_getc();
        cprintf("serial [%03d] %c\n", c, c);
        break;
    case IRQ_OFFSET + IRQ_KBD:
        c = cons_getc();
        cprintf("kbd [%03d] %c\n", c, c);
        break;
    //LAB1 CHALLENGE 1 : YOUR CODE you should modify below codes.
    case T_SWITCH_TOU:
        asm volatile( "cli;");
        tf->tf_ds =        USER_DS;
        tf->tf_es =        USER_DS;
        tf->tf_fs =        USER_DS;
        tf->tf_gs =        USER_DS;
        tf->tf_eflags = tf->tf_eflags | 0x200;
        tf->tf_eflags = tf->tf_eflags | 0x3000;
        tf->tf_ss = USER_DS;
        tf->tf_cs = USER_CS;
        tf->tf_esp = tf->tf_regs.reg_eax;
        break;        
    case T_SWITCH_TOK:
      //    panic("T_SWITCH_** ??\n");
              asm volatile( "cli;");
                tf->tf_ds =        KERNEL_DS;
                tf->tf_es =        KERNEL_DS;
                tf->tf_fs =        KERNEL_DS;
                tf->tf_gs =        KERNEL_DS;
                tf->tf_eflags = tf->tf_eflags | 0x200;
                tf->tf_eflags = tf->tf_eflags & ~0x3000U | 0x1000U;
                tf->tf_ss = KERNEL_DS;
                tf->tf_cs = KERNEL_CS;
                tf->tf_esp = tf->tf_regs.reg_eax;
                cprintf("%08x\n",tf->tf_esp);
      break;
    case IRQ_OFFSET + IRQ_IDE1:
    case IRQ_OFFSET + IRQ_IDE2:
        /* do nothing */
        break;
    default:
        // in kernel, it must be a mistake
        if ((tf->tf_cs & 3) == 0) {
            print_trapframe(tf);
            panic("unexpected trap in kernel.\n");
        }
    }
}
Esempio n. 21
0
static void
trap_dispatch(struct Trapframe *tf)
{
	int32_t res;
	// Handle processor exceptions.
	// LAB 3: Your code here.

	// Handle spurious interrupts
	// The hardware sometimes raises these because of noise on the
	// IRQ line or other reasons. We don't care.
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) {
		cprintf("Spurious interrupt on irq 7\n");
		print_trapframe(tf);
		return;
	}

	// Handle clock interrupts. Don't forget to acknowledge the
	// interrupt using lapic_eoi() before calling the scheduler!
	// LAB 4: Your code here.

	// Add time tick increment to clock interrupts.
	// Be careful! In multiprocessors, clock interrupts are
	// triggered on every CPU.
	// LAB 6: Your code here.


	// Handle keyboard and serial interrupts.
	// LAB 5: Your code here.

	//if(tf->tf_trapno == 48 && tf->tf_regs.reg_eax==7)
	//{
		//cprintf("trap no = %d at cpu %d env %x\n",tf->tf_trapno,cpunum(),curenv->env_id);		
		//print_trapframe(tf);
	//}
	switch(tf->tf_trapno)
	{
		case IRQ_OFFSET + IRQ_TIMER:
			//cprintf("clock interrupt on irq 7 on cpu %d\n",cpunum());
			//print_trapframe(tf);
			//cprintf("  eip  0x%08x\n", tf->tf_eip);
			//cprintf("  esp  0x%08x\n", tf->tf_esp);
			 lapic_eoi();
			 time_tick();
			 sched_yield();			
			 break;
		case IRQ_OFFSET + IRQ_SERIAL:
			 serial_intr(); break;
		case IRQ_OFFSET + IRQ_KBD:
			 kbd_intr(); break;
		case T_DIVIDE: tf->tf_regs.reg_ecx = 1; break; 
		case T_PGFLT: page_fault_handler(tf); goto err;
		case T_SYSCALL:
			 res = syscall(tf->tf_regs.reg_eax,tf->tf_regs.reg_edx,tf->tf_regs.reg_ecx,tf->tf_regs.reg_ebx,tf->tf_regs.reg_edi,tf->tf_regs.reg_esi); 
			 tf->tf_regs.reg_eax = res; break;
		case T_BRKPT:print_trapframe(tf);monitor(NULL);break;
		default: goto err;
	}
	
	return;
err:
	// Unexpected trap: The user process or the kernel has a bug.
	print_trapframe(tf);
	if (tf->tf_cs == GD_KT)
		panic("unhandled trap in kernel");
	else {
		env_destroy(curenv);
		return;
	}
}
Esempio n. 22
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);
}
Esempio n. 23
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);
}
Esempio n. 24
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);
}
Esempio n. 25
0
static void
trap_dispatch(struct trapframe *tf) {
    char c;

    int ret=0;

    switch (tf->tf_trapno) {
    case T_PGFLT:  //page fault
        if ((ret = pgfault_handler(tf)) != 0) {
            print_trapframe(tf);
            if (current == NULL) {
                panic("handle pgfault failed. ret=%d\n", ret);
            }
            else {
                if (trap_in_kernel(tf)) {
                    panic("handle pgfault failed in kernel mode. ret=%d\n", ret);
                }
                cprintf("killed by kernel.\n");
                panic("handle user mode pgfault failed. ret=%d\n", ret); 
                do_exit(-E_KILLED);
            }
        }
        break;
    case T_SYSCALL:
        syscall();
        break;
    case IRQ_OFFSET + IRQ_TIMER:
#if 0
    LAB3 : If some page replacement algorithm(such as CLOCK PRA) need tick to change the priority of pages,
    then you can add code here. 
#endif
        /* LAB1 2013011365 : STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
        /* LAB5 YOUR CODE */
        /* you should upate you lab1 code (just add ONE or TWO lines of code):
         *    Every TICK_NUM cycle, you should set current process's current->need_resched = 1
         */
        if(++ticks % TICK_NUM == 0) {
			//print_ticks();
			current->need_resched = 1;
		}
        break;
    case IRQ_OFFSET + IRQ_COM1:
        c = cons_getc();
        cprintf("serial [%03d] %c\n", c, c);
        break;
    case IRQ_OFFSET + IRQ_KBD:
        c = cons_getc();
        cprintf("kbd [%03d] %c\n", c, c);
        break;
    //LAB1 CHALLENGE 1 : YOUR CODE you should modify below codes.
    case T_SWITCH_TOU:
    	if(tf->tf_cs != USER_CS) {
			user_stack = *tf;
			user_stack.tf_cs = USER_CS;
			user_stack.tf_ds = USER_DS;
			user_stack.tf_ss = USER_DS;
			user_stack.tf_es = USER_DS;
			user_stack.tf_esp = (uint32_t)tf + sizeof(struct trapframe) - 8;
			user_stack.tf_eflags |= FL_IOPL_MASK;
			*((uint32_t *)tf - 1) = (uint32_t)&user_stack;
		}
		break;
    case T_SWITCH_TOK:
        if(tf->tf_cs != KERNEL_CS) {
			tf->tf_cs = KERNEL_CS;
			tf->tf_ds = KERNEL_DS;
			tf->tf_es = KERNEL_DS;
			tf->tf_eflags &= ~FL_IOPL_MASK;
			struct trapframe* k = (struct trapframe*)(tf->tf_esp - (sizeof(struct trapframe) - 8));
			memmove(k, tf, sizeof(struct trapframe) -8);
			*((uint32_t *)tf - 1) = (uint32_t)k;

		}
		break;
    case IRQ_OFFSET + IRQ_IDE1:
    case IRQ_OFFSET + IRQ_IDE2:
        /* do nothing */
        break;
    default:
        print_trapframe(tf);
        if (current != NULL) {
            cprintf("unhandled trap.\n");
            do_exit(-E_KILLED);
        }
        // in kernel, it must be a mistake
        panic("unexpected trap in kernel.\n");

    }
}
Esempio n. 26
0
File: trap.c Progetto: cky9301/6.828
static void
trap_dispatch(struct Trapframe *tf)
{
	// Handle processor exceptions.
	// LAB 3: Your code here.
        // TODO: chky
        int r;
        switch (tf->tf_trapno) {
          case T_PGFLT:
              page_fault_handler(tf);
              break;
          case T_BRKPT:
              // TODO: lab3 ex6 challenge
              monitor(tf);
              break;
          case T_SYSCALL:
              r = syscall(tf->tf_regs.reg_eax,    // syscallno
                          tf->tf_regs.reg_edx,    // a1
                          tf->tf_regs.reg_ecx,    // a2
                          tf->tf_regs.reg_ebx,    // a3
                          tf->tf_regs.reg_edi,    // a4
                          tf->tf_regs.reg_esi     // a5
                          );
              tf->tf_regs.reg_eax = r;
              return;
          default:
              break;
        }

	// Handle spurious interrupts
	// The hardware sometimes raises these because of noise on the
	// IRQ line or other reasons. We don't care.
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_SPURIOUS) {
		cprintf("Spurious interrupt on irq 7\n");
		print_trapframe(tf);
		return;
	}

	// Handle clock interrupts. Don't forget to acknowledge the
	// interrupt using lapic_eoi() before calling the scheduler!
	// LAB 4: Your code here.
        // TODO: chky
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_TIMER) {
	        lapic_eoi();
                sched_yield();
                return;
	}
        // chky end

	// Handle keyboard and serial interrupts.
	// LAB 5: Your code here.
        // TODO: chky
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_KBD) {
                kbd_intr();
                return;
	}
	
	if (tf->tf_trapno == IRQ_OFFSET + IRQ_SERIAL) {
                serial_intr();
                return;
	}
        // chky end

	// Unexpected trap: The user process or the kernel has a bug.
	print_trapframe(tf);
	if (tf->tf_cs == GD_KT)
		panic("unhandled trap in kernel");
	else {
		env_destroy(curenv);
		return;
	}
}
Esempio n. 27
0
File: trap.c Progetto: 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);
}
Esempio n. 28
0
/* trap_dispatch - dispatch based on what type of trap occurred */
static void trap_dispatch(struct trapframe *tf)
{
	char c;

	int ret;

	//kprintf("Trap [%03d %03d]\n", tf->tf_trapno, tf->tf_trapsubno);

	switch (tf->tf_trapno) {
		// Prefetch Abort service routine
		// Data Abort service routine
	case T_PABT:
	case T_DABT:
		if ((ret = pgfault_handler(tf)) != 0) {
			print_pgfault(tf);
			print_trapframe(tf);
			if (pls_read(current) == NULL) {
				panic("handle pgfault failed. %e\n", ret);
			} else {
				if (trap_in_kernel(tf)) {
					panic
					    ("handle pgfault failed in kernel mode. %e\n",
					     ret);
				}
				killed_by_kernel();
			}
		}
		break;
	case T_SWI:
		syscall();
		break;
		// IRQ Service Routine
		/*        case IRQ_OFFSET + INT_TIMER4:
		   ticks ++;
		   if (ticks % TICK_NUM == 0) {
		   print_ticks();
		   //print_trapframe(tf);
		   }
		   break;
		   case IRQ_OFFSET + INT_UART0:
		   c = cons_getc();
		   kprintf("serial [%03d] %c\n", c, c);
		   break;
		 */
		// SWI Service Routine
#if 0
	case T_SWITCH_TOK:	// a random System call
		kprintf("Random system call\n");
		print_cur_status();
		//print_stackframe();
		break;
#endif
	case T_IRQ:
		__irq_level++;
#if 0
		if (!trap_in_kernel(tf)) {
			uint32_t sp;
			asm volatile ("mov %0, sp":"=r" (sp));
			kprintf("### iRQnotK %08x\n", sp);
		}
#endif
		irq_handler();
		__irq_level--;
		break;
#if 0
	case T_PANIC:
		print_cur_status();
		//print_stackframe();
		break;
#endif
		/* for debugging */
	case T_UNDEF:
		udef_handler(tf);
		break;
	default:
		print_trapframe(tf);
		if (pls_read(current) != NULL) {
			kprintf("unhandled trap.\n");
			do_exit(-E_KILLED);
		}
		panic("unexpected trap in kernel.\n");
	}
Esempio n. 29
0
/* trap_dispatch - dispatch based on what type of trap occurred */
static void
trap_dispatch(struct trapframe *tf) {
    char c;

    switch (tf->tf_trapno) {
    case IRQ_OFFSET + IRQ_TIMER:
        /* LAB1 2012011363 : STEP 3 */
        /* handle the timer interrupt */
        /* (1) After a timer interrupt, you should record this event using a global variable (increase it), such as ticks in kern/driver/clock.c
         * (2) Every TICK_NUM cycle, you can print some info using a funciton, such as print_ticks().
         * (3) Too Simple? Yes, I think so!
         */
        ticks ++;
        if (ticks % TICK_NUM == 0) {
            print_ticks();
        }
        break;
    case IRQ_OFFSET + IRQ_COM1:
        c = cons_getc();
        cprintf("serial [%03d] %c\n", c, c);
        break;
    case IRQ_OFFSET + IRQ_KBD:
        c = cons_getc();
        cprintf("kbd [%03d] %c\n", c, c);
        break;
    //LAB1 CHALLENGE 1 : 2012011363 you should modify below codes.
    case T_SWITCH_TOU:
        if (tf->tf_cs != USER_CS) {
            switchk2u = *tf;
            switchk2u.tf_cs = USER_CS;
            switchk2u.tf_ds = switchk2u.tf_es = switchk2u.tf_ss = USER_DS;
            switchk2u.tf_esp = (uint32_t)tf + sizeof(struct trapframe) - 8;
		
            // set eflags, make sure ucore can use io under user mode.
            // if CPL > IOPL, then cpu will generate a general protection.
            switchk2u.tf_eflags |= FL_IOPL_MASK;
		
            // set temporary stack
            // then iret will jump to the right stack
            *((uint32_t *)tf - 1) = (uint32_t)&switchk2u;
        }
        break;
    case T_SWITCH_TOK:
        if (tf->tf_cs != KERNEL_CS) {
            tf->tf_cs = KERNEL_CS;
            tf->tf_ds = tf->tf_es = KERNEL_DS;
            tf->tf_eflags &= ~FL_IOPL_MASK;
            switchu2k = (struct trapframe *)(tf->tf_esp - (sizeof(struct trapframe) - 8));
            memmove(switchu2k, tf, sizeof(struct trapframe) - 8);
            *((uint32_t *)tf - 1) = (uint32_t)switchu2k;
        }
        break;
    case IRQ_OFFSET + IRQ_IDE1:
    case IRQ_OFFSET + IRQ_IDE2:
        /* do nothing */
        break;
    default:
        // in kernel, it must be a mistake
        if ((tf->tf_cs & 3) == 0) {
            print_trapframe(tf);
            panic("unexpected trap in kernel.\n");
        }
    }
}
Esempio n. 30
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);
}