/* use software emulated X86 pgfault */ static void handle_tlbmiss(struct trapframe* tf, int write) { #if 0 if(!trap_in_kernel(tf)){ print_trapframe(tf); while(1); } #endif static int entercnt = 0; entercnt ++; //kprintf("## enter handle_tlbmiss %d times\n", entercnt); int in_kernel = trap_in_kernel(tf); assert(current_pgdir != NULL); //print_trapframe(tf); uint32_t badaddr = tf->tf_vaddr; int ret = 0; pte_t *pte = get_pte(current_pgdir, tf->tf_vaddr, 0); if(pte==NULL || ptep_invalid(pte)){ //PTE miss, pgfault //panic("unimpl"); //TODO //tlb will not be refill in do_pgfault, //so a vmm pgfault will trigger 2 exception //permission check in tlb miss ret = pgfault_handler(tf, badaddr, get_error_code(write, pte)); }else{ //tlb miss only, reload it /* refill two slot */ /* check permission */ if(in_kernel){ tlb_refill(badaddr, pte); //kprintf("## refill K\n"); return; }else{ if(!ptep_u_read(pte)){ ret = -1; goto exit; } if(write && !ptep_u_write(pte)){ ret = -2; goto exit; } //kprintf("## refill U %d %08x\n", write, badaddr); tlb_refill(badaddr, pte); return ; } } exit: if(ret){ print_trapframe(tf); if(in_kernel){ panic("unhandled pgfault"); }else{ do_exit(-E_KILLED); } } return ; }
/* * General trap (exception) handling function for mips. * This is called by the assembly-language exception handler once * the trapframe has been set up. */ void mips_trap(struct trapframe *tf) {//kprintf("mips_trap:epc=0x%x cause=%x badvaddr=0x%08x\n", tf->tf_epc, (tf->tf_cause >> 2) & 0x1F, tf->tf_vaddr); // dispatch based on what type of trap occurred // used for previous projects if (current == NULL) { trap_dispatch(tf); } else { // keep a trapframe chain in stack struct trapframe *otf = current->tf; current->tf = tf; bool in_kernel = trap_in_kernel(tf); trap_dispatch(tf); current->tf = otf; if (!in_kernel) { if (current->flags & PF_EXITING) { do_exit(-E_KILLED); } if (current->need_resched) { schedule(); } } } }
// forkret -- the first kernel entry point of a new thread/process // NOTE: the addr of forkret is setted in copy_thread function // after switch_to, the current proc will execute here. void forkret(void) { if (!trap_in_kernel(current->tf)) { kern_leave(); } forkrets(current->tf); }
/* * * trap - handles or dispatches an exception/interrupt. if and when trap() returns, * the code in kern/trap/trapentry.S restores the old CPU state saved in the * trapframe and then uses the iret instruction to return from the exception. * */ void trap(struct trapframe *tf) { // dispatch based on what type of trap occurred // used for previous projects if (current == NULL) { trap_dispatch(tf); } else { // keep a trapframe chain in stack struct trapframe *otf = current->tf; current->tf = tf; bool in_kernel = trap_in_kernel(tf); trap_dispatch(tf); current->tf = otf; if (!in_kernel) { if (current->flags & PF_EXITING) { do_exit(-E_KILLED); } if (current->need_resched) { schedule(); } } } }
void print_trapframe(struct trapframe *tf) { cprintf("trapframe at %p\n", tf); print_regs(&tf->tf_regs); cprintf(" ds 0x----%04x\n", tf->tf_ds); cprintf(" es 0x----%04x\n", tf->tf_es); cprintf(" fs 0x----%04x\n", tf->tf_fs); cprintf(" gs 0x----%04x\n", tf->tf_gs); cprintf(" trap 0x%08x %s\n", tf->tf_trapno, trapname(tf->tf_trapno)); cprintf(" err 0x%08x\n", tf->tf_err); cprintf(" eip 0x%08x\n", tf->tf_eip); cprintf(" cs 0x----%04x\n", tf->tf_cs); cprintf(" flag 0x%08x ", tf->tf_eflags); int i, j; for (i = 0, j = 1; i < sizeof(IA32flags) / sizeof(IA32flags[0]); i ++, j <<= 1) { if ((tf->tf_eflags & j) && IA32flags[i] != NULL) { cprintf("%s,", IA32flags[i]); } } cprintf("IOPL=%d\n", (tf->tf_eflags & FL_IOPL_MASK) >> 12); if (!trap_in_kernel(tf)) { cprintf(" esp 0x%08x\n", tf->tf_esp); cprintf(" ss 0x----%04x\n", tf->tf_ss); } }
static void trap_dispatch(struct trapframe *tf) { char c; int ret; switch (tf->tf_trapno) { case T_DEBUG: case T_BRKPT: debug_monitor(tf); break; case T_PGFLT: if ((ret = pgfault_handler(tf)) != 0) { print_trapframe(tf); if (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); } cprintf("killed by kernel.\n"); do_exit(-E_KILLED); } } break; case T_SYSCALL: syscall(); break; case IRQ_OFFSET + IRQ_TIMER: ticks ++; assert(current != NULL); run_timer_list(); break; case IRQ_OFFSET + IRQ_COM1: case IRQ_OFFSET + IRQ_KBD: if ((c = cons_getc()) == 13) { debug_monitor(tf); } else { cprintf("%s [%03d] %c\n", (tf->tf_trapno != IRQ_OFFSET + IRQ_KBD) ? "serial" : "kbd", c, c); } 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); } panic("unexpected trap in kernel.\n"); } }
static int udef_handler(struct trapframe *tf) { // print_trapframe(tf); uint32_t inst = *(uint32_t *) (tf->tf_epc - 4); if (inst == KGDB_BP_INSTR) { return kgdb_trap(tf); } else { print_trapframe(tf); if (trap_in_kernel(tf)) { panic("undefined instruction\n"); } else { killed_by_kernel(); } } return 0; }
void print_trapframe(struct trapframe *tf) { PRINT_HEX("trapframe at ", tf); print_regs(&tf->tf_regs); PRINT_HEX(" $ra\t: ", tf->tf_ra); PRINT_HEX(" BadVA\t: ", tf->tf_vaddr); PRINT_HEX(" Status\t: ", tf->tf_status); PRINT_HEX(" Cause\t: ", tf->tf_cause); PRINT_HEX(" EPC\t: ", tf->tf_epc); if (!trap_in_kernel(tf)) { kprintf("Trap in usermode: "); } else { kprintf("Trap in kernel: "); } kprintf(trapname(GET_CAUSE_EXCODE(tf->tf_cause))); kputchar('\n'); }
static void trap_dispatch(struct trapframe *tf) { int code = GET_CAUSE_EXCODE(tf->tf_cause); switch(code){ case EX_IRQ: interrupt_handler(tf); break; case EX_TLBL: handle_tlbmiss(tf, 0); break; case EX_TLBS: handle_tlbmiss(tf, 1); break; case EX_RI: print_trapframe(tf); kprintf("inst not include, I will use software to implement\n"); tf->tf_epc += 4; //panic("hey man! Do NOT use that insn!"); break; case EX_SYS: //print_trapframe(tf); tf->tf_epc += 4; syscall(); break; /* alignment error or access kernel * address space in user mode */ case EX_ADEL: case EX_ADES: if(trap_in_kernel(tf)){ print_trapframe(tf); panic("Alignment Error"); }else{ print_trapframe(tf); do_exit(-E_KILLED); } break; default: print_trapframe(tf); panic("Unhandled Exception"); } }
// do syscall sigreturn, reset the user stack and eip int do_sigreturn() { struct mm_struct *mm = current->mm; if (!current) return -E_INVAL; struct sighand_struct *sighand = current->signal_info.sighand; if (!sighand) return -E_INVAL; struct sigframe *kframe = kmalloc(sizeof(struct sigframe)); if (!kframe) return -E_NO_MEM; struct sigframe *frame = (struct sigframe *)(current->tf->tf_esp); lock_mm(mm); { if (!copy_from_user (mm, kframe, frame, sizeof(struct sigframe), 0)) { unlock_mm(mm); kfree(kframe); return -E_INVAL; } } unlock_mm(mm); /* check the trapframe */ if (trap_in_kernel(&kframe->tf)) { do_exit(-E_KILLED); return -E_INVAL; } lock_sig(sighand); current->signal_info.blocked = kframe->old_blocked; sig_recalc_pending(current); unlock_sig(sighand); *(current->tf) = kframe->tf; kfree(kframe); return 0; }
void trap(struct trapframe *tf) { // used for previous projects if (pls_read(current) == NULL) { trap_dispatch(tf); } else { // keep a trapframe chain in stack struct trapframe *otf = pls_read(current)->tf; pls_read(current)->tf = tf; bool in_kernel = trap_in_kernel(tf); trap_dispatch(tf); pls_read(current)->tf = otf; if (!in_kernel) { may_killed(); if (pls_read(current)->need_resched) { schedule(); } } } }
void print_trapframe(struct trapframe *tf) { PRINT_HEX("trapframe at ", tf); print_regs(&tf->tf_regs); PRINT_HEX(" $ra\t: ", tf->tf_ra); PRINT_HEX(" BadVA\t: ", tf->tf_vaddr); PRINT_HEX(" Status\t: ", tf->tf_status); PRINT_HEX(" Cause\t: ", tf->tf_cause); PRINT_HEX(" EPC\t: ", tf->tf_epc); if (!trap_in_kernel(tf)) { kprintf("Trap in usermode: "); }else{ kprintf("Trap in kernel: "); } kprintf(trapname(GET_CAUSE_EXCODE(tf->tf_cause))); kputchar('\n'); // /* int i; for (i = 0; i < 20; ++i) { int *addr = (int*)(tf->tf_epc + i * 4); kprintf("0x%08x=0x%08x\n", addr, *addr); } // */ }
static void trap_dispatch(struct trapframe *tf) { #ifdef DEBUG_PRINT_SYSCALL_NUM static const char * const syscallnames[] = { [SYS_exit] "sys_exit", [SYS_fork] "sys_fork", [SYS_wait] "sys_wait", [SYS_exec] "sys_exec", [SYS_clone] "sys_clone", [SYS_yield] "sys_yield", [SYS_kill] "sys_kill", [SYS_sleep] "sys_sleep", [SYS_gettime] "sys_gettime", [SYS_getpid] "sys_getpid", [SYS_brk] "sys_brk", [SYS_mmap] "sys_mmap", [SYS_munmap] "sys_munmap", [SYS_shmem] "sys_shmem", [SYS_putc] "sys_putc", [SYS_pgdir] "sys_pgdir", [SYS_sem_init] "sys_sem_init", [SYS_sem_post] "sys_sem_post", [SYS_sem_wait] "sys_sem_wait", [SYS_sem_free] "sys_sem_free", [SYS_sem_get_value] "sys_sem_get_value", [SYS_event_send] "sys_event_send", [SYS_event_recv] "sys_event_recv", [SYS_mbox_init] "sys_mbox_init", [SYS_mbox_send] "sys_mbox_send", [SYS_mbox_recv] "sys_mbox_recv", [SYS_mbox_free] "sys_mbox_free", [SYS_mbox_info] "sys_mbox_info", [SYS_open] "sys_open", [SYS_close] "sys_close", [SYS_read] "sys_read", [SYS_write] "sys_write", [SYS_seek] "sys_seek", [SYS_fstat] "sys_fstat", [SYS_fsync] "sys_fsync", [SYS_chdir] "sys_chdir", [SYS_getcwd] "sys_getcwd", [SYS_mkdir] "sys_mkdir", [SYS_link] "sys_link", [SYS_rename] "sys_rename", [SYS_unlink] "sys_unlink", [SYS_getdirentry] "sys_getdirentry", [SYS_dup] "sys_dup", [SYS_pipe] "sys_pipe", [SYS_mkfifo] "sys_mkfifo", [SYS_modify_ldt] "sys_modify_ldt", [SYS_gettimeofday] "sys_gettimeofday", [SYS_exit_group] "sys_exit_group", }; #endif char c; int ret; switch (tf->tf_trapno) { case T_DEBUG: case T_BRKPT: debug_monitor(tf); break; case T_PGFLT: if ((ret = pgfault_handler(tf)) != 0) { print_trapframe(tf); if (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); } cprintf("killed by kernel.\n"); do_exit(-E_KILLED); } } break; case T_SYSCALL: #ifdef DEBUG_PRINT_SYSCALL_NUM if (tf->tf_regs.reg_eax != SYS_write && tf->tf_regs.reg_eax != SYS_read && tf->tf_regs.reg_eax != SYS_putc) cprintf("Syscall [%d] (%s) detected!\n", tf->tf_regs.reg_eax, syscallnames[tf->tf_regs.reg_eax]); #endif syscall(); break; case IRQ_OFFSET + IRQ_TIMER: ticks ++; assert(current != NULL); run_timer_list(); break; case IRQ_OFFSET + IRQ_COM1: case IRQ_OFFSET + IRQ_KBD: if ((c = cons_getc()) == 13) { debug_monitor(tf); } else { extern void dev_stdin_write(char c); dev_stdin_write(c); } break; case IRQ_OFFSET + IRQ_IDE1: case IRQ_OFFSET + IRQ_IDE2: /* do nothing */ break; default: print_trapframe(tf); if (current != NULL) { cprintf("unhandled trap %d.\n", tf->tf_trapno); do_exit(-E_KILLED); } panic("unexpected trap in kernel.\n"); } }
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"); } }
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"); } }
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"); } }
/* 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"); }
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"); } }
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! */ ticks++; if(ticks % TICK_NUM ==0) { // print_ticks(); /* 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 */ 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. */ 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: 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"); } }