/* 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! */ 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: 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: // in kernel, it must be a mistake if ((tf->tf_cs & 3) == 0) { print_trapframe(tf); panic("unexpected trap in kernel.\n"); } } }
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); 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: // in kernel, it must be a mistake if ((tf->tf_cs & 3) == 0) { print_trapframe(tf); 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; switch (tf->tf_trapno) { case IRQ_OFFSET + IRQ_TIMER: /* LAB1 2012012139 : 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 : 2012012139 you should modify below codes. case T_SWITCH_TOU: tf->tf_cs = USER_CS; tf->tf_ds = USER_DS; tf->tf_es = USER_DS; tf->tf_ss = USER_DS; // 改变IO输出所需要的权限,使得用户可以写 tf->tf_eflags |= 0x3000; break; case T_SWITCH_TOK: tf->tf_cs = KERNEL_CS; tf->tf_ds = KERNEL_DS; tf->tf_es = KERNEL_DS; // tf->tf_ss = KERNEL_DS; // 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"); } } }
/* 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: 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; case T_SWITCH_TOU: if (tf->tf_cs != USER_CS) { tf->tf_cs = USER_CS; tf->tf_ds = tf->tf_es = USER_DS; tf->tf_ss = USER_DS; // set eflags, make sure ucore can use io under user mode. // if CPL > IOPL, then cpu will generate a general protection. tf->tf_rflags |= FL_IOPL_MASK; } 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_ss = KERNEL_DS; tf->tf_rflags &= ~FL_IOPL_MASK; } break; default: // in kernel, it must be a mistake if ((tf->tf_cs & 3) == 0) { print_trapframe(tf); 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; 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: case T_SWITCH_TOK: 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"); } } }
/* 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"); } } }
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"); } } }
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 */ /* LAB6 YOUR CODE */ /* you should upate you lab5 code * IMPORTANT FUNCTIONS: * sched_class_proc_tick */ /* LAB7 YOUR CODE */ /* you should upate you lab6 code * IMPORTANT FUNCTIONS: * run_timer_list */ break; case IRQ_OFFSET + IRQ_COM1: 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"); } }
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 2010012193 : 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 2010012193 */ /* 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 2010012193 */ /* 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. */ if (!(++ticks % TICK_NUM)) { print_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 : 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; 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 2011011384 : 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 % 100 == 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 : 2011011384 you should modify below codes. case T_SWITCH_TOU: //The idea is iret pops EFLAGS, EIP, CS to CPU registers //So we push to the stack these registers we want and then directly jump to iret tf->tf_gs = USER_DS; tf->tf_fs = USER_DS; tf->tf_es = USER_DS; tf->tf_ds = USER_DS; tf->tf_ss = USER_DS; tf->tf_cs = USER_CS; //we also have to set IOPL, else cprintf will cause general protection fault //tf->tf_esp doesn't matter here because it will be reset by %ebp in switch_to_user tf->tf_eflags |= FL_IOPL_MASK; break; case T_SWITCH_TOK: tf->tf_gs = KERNEL_DS; tf->tf_fs = KERNEL_DS; tf->tf_es = KERNEL_DS; tf->tf_ds = KERNEL_DS; tf->tf_ss = KERNEL_DS; tf->tf_cs = KERNEL_CS; //we also have to set IOPL, else cprintf will cause general protection fault //tf->tf_esp doesn't matter here because it will be reset by %ebp in switch_to_user tf->tf_eflags &= ~FL_IOPL_MASK; 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"); } } }