// C-Level interrupt/exception handler. NOTE: We are running on the stack // of the thread that was interrupted! void irq_handle_exception(int code, uint32 errcode) { int handled = 0; // Nested exception? if (inside_int) { irq_handler hnd = irq_handlers[EXC_DOUBLE_FAULT]; if (hnd != NULL) hnd(EXC_DOUBLE_FAULT, irq_srt_addr); else irq_dump_regs(code, errcode); thd_pslist(dbgio_printf); process_print_list(dbgio_printf); panic("double fault"); } inside_int = 1; // If there's a global handler, call it if (irq_hnd_global) { irq_hnd_global(code, irq_srt_addr); handled = 1; } // If there's a handler, call it { irq_handler hnd = irq_handlers[code]; if (hnd != NULL) { hnd(code, irq_srt_addr); handled = 1; } } // Did it get handled? if (!handled) { irq_handler hnd = irq_handlers[EXC_UNHANDLED_EXC]; if (hnd != NULL) hnd(code, irq_srt_addr); else irq_dump_regs(code, errcode); panic("unhandled IRQ/Exception"); } inside_int = 0; }
static void syscall_handler (struct intr_frame *f) { int32_t* esp = (int32_t*)f->esp; /* Any parameters passed to syscall will be above ESP, see illustration below. Number of arguments each syscall expects is in argc[] array above. syscall number is pointed to by ESP. -------------------------------------- PHYS_BASE ................. <param> <param> ESP ---> <syscall_number> -------------------------------------- */ // verify esp pointer is ok, first parameter: current thread if(esp == NULL || verify_fix_length(esp, sizeof(esp)) == false){ sys_exit(-1); } // esp adress belongs to thread if(pagedir_get_page(thread_current()->pagedir, esp) == NULL){ sys_exit(-1); } // ok syscall nr int32_t syscall_nr = *esp; if(syscall_nr < 0 || syscall_nr >= SYS_NUMBER_OF_CALLS){ sys_exit(-1); } // Make sure our data is not overwriting PHYS_BASE. int expected_args = argc[syscall_nr]; unsigned long highest_addr = esp + (expected_args * sizeof(int)); if(highest_addr >= PHYS_BASE){ sys_exit(-1); } if(pagedir_get_page(thread_current()->pagedir, highest_addr) == NULL){ sys_exit(-1); } /* int i = 1; for(; i <= expected_args; i++){ if(verify_fix_length(&esp[i], sizeof(int) ) == false){ sys_exit(-1); } } */ DEBUG_SYSCALL("# SYSCALL received = %s\n", get_system_call_name(syscall_nr)); switch (syscall_nr) { case SYS_HALT: power_off(); break; case SYS_EXEC: { f->eax = SYS_EXEC_handler(esp); } break; case SYS_WAIT: { int child_pid = *(esp + 1); f->eax = process_wait (child_pid); break; } case SYS_EXIT: { if(is_kernel_vaddr(pg_round_up((void*)esp[1]) )){ sys_exit(-1); } int exit_status = *(esp + 1); process_exit(exit_status); thread_exit(); break; } case SYS_PLIST: process_print_list(); break; case SYS_CREATE: { bool success = false; char *name = (char*)*(esp + 1); if(name == NULL){ sys_exit(-1); } unsigned initial_size = *(esp + 2); if(verify_fix_length(esp[1], initial_size) == false){ sys_exit(-1); } if(verify_variable_length(esp[1]) == false){ sys_exit(-1); } success = filesys_create(name, initial_size); if(success) { DEBUG_SYSCALL("#SYS_CREATE - File with name: %s created. \n", name); } else { DEBUG_SYSCALL("#SYS_CREATE - filesys_create failed: file named \'%s\' already exists or internal memory allocation failed \n", name); } f->eax = success; break; } case SYS_OPEN: { char *name = (char*)*(esp + 1); if(name == NULL){ sys_exit(-1); } if(verify_variable_length(esp[1]) == false){ sys_exit(-1); } struct file *file; file = filesys_open(name); int retVal = -1; if(file != NULL) { DEBUG_SYSCALL("# SYS_OPEN - File with name: '%s' created. \n", name); int fd = flist_add_file(file); retVal = fd; } else { DEBUG_SYSCALL("# SYS_OPEN - filesys_open failed: no file named \'%s\' exists or internal memory allocation failed \n", name); retVal = -1; } f->eax = retVal; break; } case SYS_READ: { int retVal = SYS_READ_handler(esp); f->eax = retVal; break; } case SYS_CLOSE: { int retVal = SYS_CLOSE_handler(esp); f->eax = retVal; break; } case SYS_REMOVE: { int retVal = SYS_REMOVE_handler(esp); f->eax = retVal; break; } case SYS_WRITE: { int retVal = SYS_WRITE_handler(esp); f->eax = retVal; break; } case SYS_SEEK: { f->eax = SYS_SEEK_handler(esp); break; } case SYS_TELL: f->eax = SYS_TELL_handler(esp); break; case SYS_FILESIZE: f->eax = SYS_FILESIZE_handler(esp); break; default: { DEBUG_SYSCALL ("Executed an unknown system call (nr: %i)!\n", syscall_nr); DEBUG_SYSCALL ("Stack top + 0: %d\n", esp[0]); DEBUG_SYSCALL ("Stack top + 1: %d\n", esp[1]); thread_exit (); } } }