/* 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"); } } }
/* getchar - reads a single non-zero character from stdin */ int getchar(void) { int c; while ((c = cons_getc()) == 0) /* do nothing */; return c; }
static int serial_int_handler(int irq, void * data) { extern void dev_stdin_write(char c); char c = cons_getc(); dev_stdin_write(c); return 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 T_DEBUG: case T_BRKPT: debug_monitor(tf); break; case IRQ_OFFSET + IRQ_TIMER: ticks ++; if (ticks % TICK_NUM == 0) { cprintf("%d ticks\n",TICK_NUM); } 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; default: // in kernel, it must be a mistake if ((tf->tf_cs & 3) == 0) { print_trapframe(tf); panic("unexpected trap in kernel.\n"); } } }
// Synchronize the root process's console special files // with the actual console I/O device. bool cons_io(void) { int num_io = 0; // Get output file fileinode *fi = &files->fi[FILEINO_CONSOUT]; int c; // spinlock_acquire(&cons_lock); while(cons_out_pos < fi->size) { c = ((char*)FILEDATA(FILEINO_CONSOUT))[cons_out_pos]; cons_putc(c); num_io++; cons_out_pos++; } // spinlock_release(&cons_lock); // Input file fi = &files->fi[FILEINO_CONSIN]; // Read from console while(fi->size <= FILE_MAXSIZE && (c = cons_getc())) { // And appened to CONSIN ((char*)FILEDATA(FILEINO_CONSIN))[fi->size++] = c; num_io++; } return num_io; }
void irq_handler(){ uint32_t pending = inw(VIC_VBASE+INTERRUPT_STATUS); uint32_t irq = 0; while(pending > 0){ irq = inw(VIC_VBASE+INTERRUPT_NUMBER); if(actions[irq].handler){ (*actions[irq].handler)(irq, actions[irq].opaque); }else{ pic_disable(irq); } pending = inw(VIC_VBASE+INTERRUPT_STATUS); } #if 0 if(status & (1<<TIMER0_IRQ)){ //kprintf("@"); ticks++; //assert(pls_read(current) != NULL); run_timer_list(); clock_clear(); } if( status & (1<<UART_IRQ) ){ //if ((c = cons_getc()) == 13) { // debug_monitor(tf); //} //else { extern void dev_stdin_write(char c); char c = cons_getc(); dev_stdin_write(c); //} //kprintf("#"); serial_clear(); } #endif }
/* 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"); } } }
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"); } }
/* 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"); } } }
void serial_int_handler(void *opaque) { unsigned char id = inb(COM1+COM_IIR); if(id & 0x01) return ; //int c = serial_proc_data(); int c = cons_getc(c); extern void dev_stdin_write(char c); dev_stdin_write(c); }
void arch_init() { pci_init(); #ifdef __CONFIG_ENABLE_MPTABLES__ mptables_parse(); ioapic_init(); // MUST BE AFTER PCI/ISA INIT! // TODO: move these back to regular init. requires fixing the // __CONFIG_NETWORKING__ inits to not need multiple cores running. #endif // this returns when all other cores are done and ready to receive IPIs #ifdef __CONFIG_SINGLE_CORE__ smp_percpu_init(); #else smp_boot(); #endif proc_init(); /* EXPERIMENTAL NETWORK FUNCTIONALITY * To enable, define __CONFIG_NETWORKING__ in your Makelocal * If enabled, will load the rl8168 driver (if device exists) * and will a boot into userland matrix, so remote syscalls can be performed. * If in simulation, will do some debugging information with the ne2k device * * Note: If you use this, you should also define the mac address of the * teathered machine via USER_MAC_ADDRESS in Makelocal. * * Additionally, you should have a look at the syscall server in the tools directory */ #ifdef __CONFIG_NETWORKING__ #ifdef __CONFIG_SINGLE_CORE__ warn("You currently can't have networking if you boot into single core mode!!\n"); #else rl8168_init(); ne2k_init(); e1000_init(); #endif // __CONFIG_SINGLE_CORE__ #endif // __CONFIG_NETWORKING__ perfmon_init(); #ifdef __CONFIG_MONITOR_ON_INT__ /* Handler to read a char from the interrupt source and call the monitor. * Need to read the character so the device will send another interrupt. * Note this will read from both the serial and the keyboard, and throw away * the result. We condition, since we don't want to trigger on a keyboard * up interrupt */ void mon_int(struct trapframe *tf, void *data) { // Enable interrupts here so that we can receive // other interrupts (e.g. from the NIC) enable_irq(); if (cons_getc()) monitor(0); }
// Read a character from the system console. // Returns the character. static int sys_cgetc(void) { int c; // The cons_getc() primitive doesn't wait for a character, // but the sys_cgetc() system call does. while ((c = cons_getc()) == 0) /* do nothing */; return c; }
// Read a character from the system console. // Returns the character. static int sys_cgetc(void) { int c; /* The cons_getc() primitive doesn't wait for a character, But we do. * TODO: Make kernel interruptable later * Now just a makeshift, without kernel being interruptable, Ether * device refuses to function properly. */ while ((c = cons_getc()) == 0); /* { */ /* assert(curenv->env_status == ENV_RUNNING); */ /* spin_lock(&curenv->env_lock); */ /* curenv->env_status = ENV_RUNNABLE; */ /* spin_unlock(&curenv->env_lock); */ /* sched_yield();/\* This enables daemons to get CPU cycles when */ /* * sh is running. */ /* *\/ */ /* } */ return c; }
// Read a character from the system console without blocking. // Returns the character, or 0 if there is no input waiting. static int sys_cgetc(void) { return cons_getc(); }
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"); } }
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) { #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 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; int int_num; switch ((tf->tf_Cause & 0x0000007c) >> 2) { case EXC_TLBL: case EXC_TLBS: if ((ret = tlb_miss_handler(tf)) != 0) { print_trapframe(tf); panic("handle TLB Miss failed. %e\n", ret); } break; case EXC_SYS: syscall(); break; case EXC_INT: //switch ((tf->tf_Cause & tf->tf_Status & 0x0000ff00) >> 8) { int_num = (tf->tf_Cause & tf->tf_Status & 0x0000ff00) >> 8; //case (1 << IRQ_TIMER): if (int_num & (1 << 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 2011011278 : 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(); current -> need_resched = 1; } /* LAB5 2011011278 */ /* 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 2011011278 */ /* 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(); clock_intr(); //break; } else if (int_num & ((1 << IRQ_KBD) | (1 << IRQ_COM1))) //case (1 << IRQ_KBD): //case (1 << IRQ_COM1): // There are user level shell in LAB8, so we need change COM/KBD interrupt processing. { // cprintf("serial [%03d] %c\n", c, c); extern void dev_stdin_write(char c); while ((c = cons_getc()) != 0) dev_stdin_write(c); } //break; else if (int_num & (1 << IRQ_ETH)) //case (1 << IRQ_ETH): ethernet_intr(); //break; //default: else { print_trapframe(tf); panic("unknown int.\n"); } break; case EXC_RI: if ((ret = ri_handler(tf)) != 0) { print_trapframe(tf); if (current != NULL) do_exit(-E_KILLED); panic("unexpected RI in kernel.\n"); } break; //LAB1 CHALLENGE 1 : 2011011278 you should modify below codes. 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"); } }
static void trap_dispatch(struct trapframe *tf) { char c; int ret; switch ((tf->tf_Cause & 0x0000007c) >> 2) { case EXC_TLBL: case EXC_TLBS: if ((ret = tlb_miss_handler(tf)) != 0) { print_trapframe(tf); panic("handle TLB Miss failed. %e\n", ret); } break; case EXC_SYS: syscall(); break; case EXC_INT: switch ((tf->tf_Cause & tf->tf_Status & 0x0000ff00) >> 8) { case (1 << 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 2011011278 : 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(); current -> need_resched = 1; } /* LAB5 2011011278 */ /* 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 */ clock_intr(); break; case (1 << IRQ_COM1): c = cons_getc(); cprintf("serial [%03d] %c\n", c, c); break; default: print_trapframe(tf); panic("unknown int.\n"); } break; //LAB1 CHALLENGE 1 : 2011011278 you should modify below codes. 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; 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 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"); } } }