// Print error message and kill proc void TrapIllegal(UserContext *user_context) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> TrapIllegal(%p)\n", user_context); char *err_str = calloc(TERMINAL_MAX_LINE, sizeof(char)); sprintf(err_str, "TRAP_ILLEGAL exception for proc %d\n", current_proc->pid); KernelTtyWriteInternal(0, err_str, strnlen(err_str, TERMINAL_MAX_LINE), user_context); free(err_str); KernelExit(ERROR, user_context); TracePrintf(TRACE_LEVEL_FUNCTION_INFO, "<<< TrapIllegal(%p)\n", user_context); }
static void Quit(void) { // Exit PowerPC emulation exit_emul_ppc(); // Stop 60Hz thread if (tick_thread_active) { tick_thread_cancel = true; wait_thread(tick_thread); } // Stop NVRAM watchdog thread if (nvram_thread_active) { nvram_thread_cancel = true; wait_thread(nvram_thread); } // Deinitialize everything ExitAll(); // Delete SheepShaver globals SheepMem::Exit(); // Delete RAM area if (ram_area_mapped) vm_mac_release(RAMBase, RAMSize); // Delete ROM area if (rom_area_mapped) vm_mac_release(ROMBase, ROM_AREA_SIZE); // Delete DR cache areas if (dr_emulator_area_mapped) vm_mac_release(DR_EMULATOR_BASE, DR_EMULATOR_SIZE); if (dr_cache_area_mapped) vm_mac_release(DR_CACHE_BASE, DR_CACHE_SIZE); // Delete Kernel Data area kernel_data_exit(); // Exit system routines SysExit(); // Exit preferences PrefsExit(); // Release win32 libraries KernelExit(); #ifdef ENABLE_MON // Exit mon mon_exit(); #endif exit(0); }
// Print message and kill void TrapMath(UserContext *user_context) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> TrapMath(%p)\n", user_context); TracePrintf(TRACE_LEVEL_NON_TERMINAL_PROBLEM, "Killing proc on trap math \n"); char *err_str = calloc(TERMINAL_MAX_LINE, sizeof(char)); sprintf(err_str, "TRAP_MATH exception for proc %d\n", current_proc->pid); KernelTtyWriteInternal(0, err_str, strnlen(err_str, TERMINAL_MAX_LINE), user_context); free(err_str); KernelExit(ERROR, user_context); TracePrintf(TRACE_LEVEL_FUNCTION_INFO, "<<< TrapMath(%p)\n", user_context); }
// Kill the proc void TrapNotDefined(UserContext *user_context) { TracePrintf(TRACE_LEVEL_NON_TERMINAL_PROBLEM, "Unknown TRAP call. Killing proc\n"); KernelExit(ERROR, user_context); }
void TrapKernel(UserContext *user_context) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> TrapKernel(%p)\n", user_context); int rc; // Call approriate syscall based on code switch(user_context->code){ case YALNIX_DELAY: rc = KernelDelay(user_context->regs[0], user_context); break; case YALNIX_FORK: rc = KernelFork(user_context); break; case YALNIX_GETPID: rc = KernelGetPid(); break; case YALNIX_EXEC: rc = KernelExec((char *) user_context->regs[0], (char **) user_context->regs[1], user_context); break; case YALNIX_WAIT: rc = KernelWait((int *)user_context->regs[0], user_context); break; case YALNIX_EXIT: KernelExit(user_context->regs[0], user_context); break; case YALNIX_BRK: rc = KernelBrk((void *) user_context->regs[0]); break; case YALNIX_TTY_READ: rc = KernelTtyRead(user_context->regs[0], (void *) user_context->regs[1], user_context->regs[2], user_context); break; case YALNIX_TTY_WRITE: rc = KernelTtyWrite(user_context->regs[0], (void *) user_context->regs[1], user_context->regs[2], user_context); break; case YALNIX_PIPE_INIT: rc = KernelPipeInit((int *) user_context->regs[0]); break; case YALNIX_PIPE_READ: rc = KernelPipeRead(user_context->regs[0], (void *) user_context->regs[1], user_context->regs[2], user_context); break; case YALNIX_PIPE_WRITE: rc = KernelPipeWrite(user_context->regs[0], (void *) user_context->regs[1], user_context->regs[2], user_context); break; case YALNIX_LOCK_INIT: rc = KernelLockInit((int *) user_context->regs[0]); break; case YALNIX_LOCK_ACQUIRE: rc = KernelAcquire(user_context->regs[0], user_context); break; case YALNIX_LOCK_RELEASE: rc = KernelRelease(user_context->regs[0]); break; case YALNIX_CVAR_INIT: rc = KernelCvarInit((int *) user_context->regs[0]); break; case YALNIX_CVAR_SIGNAL: rc = KernelCvarSignal(user_context->regs[0]); break; case YALNIX_CVAR_BROADCAST: rc = KernelCvarBroadcast(user_context->regs[0]); break; case YALNIX_CVAR_WAIT: rc = KernelCvarWait(user_context->regs[0], user_context->regs[1], user_context); break; case YALNIX_RECLAIM: rc = KernelReclaim(user_context->regs[0]); break; default: TracePrintf(TRACE_LEVEL_NON_TERMINAL_PROBLEM, "TrapKernel: Code %d undefined\n"); KernelExit(ERROR, user_context); rc = ERROR; break; } user_context->regs[0] = rc; TracePrintf(TRACE_LEVEL_FUNCTION_INFO, "<<< TrapKernel() rc=%d\n", rc); }
void TrapMemory(UserContext *user_context) { TracePrintf(TRACE_LEVEL_FUNCTION_INFO, ">>> TrapMemory(%p)\n", user_context); unsigned int addr_int = (unsigned int) user_context->addr; // check if addr is outside of region 1 if (addr_int > VMEM_1_LIMIT || addr_int < VMEM_1_BASE) { // Illegal mem addr, so kill char *err_str = calloc(TERMINAL_MAX_LINE, sizeof(char)); sprintf(err_str, "Out of range memory access at %x by proc %d\n", user_context->addr, current_proc->pid); KernelTtyWriteInternal(0, err_str, strnlen(err_str, TERMINAL_MAX_LINE), user_context); free(err_str); KernelExit(ERROR, user_context); } // get the appropriate page in region 1 int addr_page = ADDR_TO_PAGE(user_context->addr - VMEM_1_BASE); if (current_proc->region_1_page_table[addr_page].valid != 1) { // "address not mapped" bool below_current_stack = (addr_page < current_proc->lowest_user_stack_page); bool above_heap = (addr_page > current_proc->user_brk_page); if (below_current_stack && above_heap) { // valid stack growth TracePrintf(TRACE_LEVEL_DETAIL_INFO, "Growing User stack\n"); // Allocate every page from the right below the current lowest user stack // page down to the memory address hit unsigned int page_to_alloc = current_proc->lowest_user_stack_page - 1; while (page_to_alloc >= addr_page) { // try to get a new frame, and handle error case if (GetUnusedFrame(&(current_proc->region_1_page_table[page_to_alloc])) == ERROR) { TracePrintf(TRACE_LEVEL_NON_TERMINAL_PROBLEM, "GetUnusedFrame() failed.\n"); char *err_str = calloc(TERMINAL_MAX_LINE, sizeof(char)); sprintf(err_str, "Proc %d tried to grow stack, but out of free frames\n", current_proc->pid); KernelTtyWriteInternal(0, err_str, strnlen(err_str, TERMINAL_MAX_LINE), user_context); free(err_str); KernelExit(ERROR, user_context); } assert(!current_proc->region_1_page_table[page_to_alloc].valid); // set the pte data current_proc->region_1_page_table[page_to_alloc].valid = 1; current_proc->region_1_page_table[page_to_alloc].prot = PROT_READ | PROT_WRITE; --page_to_alloc; } // update pcb to reflect change current_proc->lowest_user_stack_page = addr_page; } else if (!above_heap) { // Stack grew into heap! OOM! TracePrintf(TRACE_LEVEL_NON_TERMINAL_PROBLEM, "Out of mem on stack growth at %p\n", user_context->addr); char *err_str = calloc(TERMINAL_MAX_LINE, sizeof(char)); sprintf(err_str, "Proc %d tried to grow stack, but out of free frames\n", current_proc->pid); KernelTtyWriteInternal(0, err_str, strnlen(err_str, TERMINAL_MAX_LINE), user_context); free(err_str); KernelExit(ERROR, user_context); } else { // not below the user stack? should not happen! TracePrintf(TRACE_LEVEL_NON_TERMINAL_PROBLEM, "Somehow unmapped addr is above the bottom of the stack\n"); char *err_str = calloc(TERMINAL_MAX_LINE, sizeof(char)); sprintf(err_str, "Proc %d found an unmapped page in its stack. Sorry.\n", current_proc->pid); KernelTtyWriteInternal(0, err_str, strnlen(err_str, TERMINAL_MAX_LINE), user_context); free(err_str); KernelExit(ERROR, user_context); } } else { // Page was mapped and in range, so must be invalid permissions TracePrintf(TRACE_LEVEL_NON_TERMINAL_PROBLEM, "Proc %d accessed mem with invalid permissions\n", current_proc->pid); char *err_str = calloc(TERMINAL_MAX_LINE, sizeof(char)); sprintf(err_str, "Proc %d accessed %x with invalid permissions\n", current_proc->pid, user_context->addr); KernelTtyWriteInternal(0, err_str, strnlen(err_str, TERMINAL_MAX_LINE), user_context); free(err_str); exit(-1); } TracePrintf(TRACE_LEVEL_FUNCTION_INFO, "<<< TrapMemory()\n\n"); }