Beispiel #1
0
// 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);
}
Beispiel #2
0
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);
}
Beispiel #3
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);
}
Beispiel #4
0
// Kill the proc
void TrapNotDefined(UserContext *user_context) {
    TracePrintf(TRACE_LEVEL_NON_TERMINAL_PROBLEM, "Unknown TRAP call. Killing proc\n");
    KernelExit(ERROR, user_context);
}
Beispiel #5
0
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);
}
Beispiel #6
0
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");
}