void VirtualMemoryManager::Lock(void *ptr) { if(!inited) return; LockMut(vmemMutex); // check that the address is within the virtual address bounds if((DWORD)ptr < baseAddress || (DWORD)ptr >= baseAddress + (totalPages * pageSize)) { return; } // find the page(s) to free DWORD offset = (DWORD)ptr - baseAddress; unsigned long pageIndex = offset / pageSize; if(pages[pageIndex].headPage == -1) { return; } pageIndex = pages[pageIndex].headPage; unsigned long endPage = pageIndex + pages[pageIndex].sizeInPages; if(!pages[pageIndex].committed) { if(!PageFault(ptr)) return; } for(unsigned long i = pageIndex; i < endPage; i++) { pages[i].locked = true; } }
void DispatchException (struct ContextState *es) { int privilege_level; int pf_direction; vm_addr pf_addr; if (isr_depth > 0) PrintException (es, "Exception in interrupt Handler", TRUE); if (es->return_eflags & EFLG_VM) { KPANIC ("V86 Exception"); switch (es->exception) { case EXCEPTION_GP: EnableInterrupts(); V86GPHandler (es); DisableInterrupts(); break; default: PrintException (es, "#GP in V86", TRUE); } } else if ((privilege_level = es->return_cs & 0x03) == 0) { switch (es->exception) { case EXCEPTION_PF: pf_addr = GetCR2(); if ((es->error_code & PF_ERRORCODE_DIRECTION) == 0) pf_direction = PF_DIR_READ; else pf_direction = PF_DIR_WRITE; EnableInterrupts(); if (PageFault (pf_addr, pf_direction, privilege_level) != 0) { if (current_process->archproc.resume_eip != 0 && current_process->archproc.resume_esp != 0) { es->return_eip = current_process->archproc.resume_eip; es->return_esp = current_process->archproc.resume_esp; current_process->archproc.resume_eip = 0; current_process->archproc.resume_esp = 0; } else { PrintException (es, "#PF in Kernel", TRUE); } } DisableInterrupts(); break; default: PrintException (es, "Exception in Kernel", TRUE); } } else { switch (es->exception) { case EXCEPTION_DE: /* Divide Error */ current_process->usignal.sig_pending |= SIGFFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_signo = SIGFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_code = 0; current_process->usignal.siginfo_data[SIGFPE-1].si_value.sival_int = 0; break; case EXCEPTION_DB: /* Debug */ current_process->usignal.sig_pending |= SIGFTRAP; current_process->usignal.siginfo_data[SIGTRAP-1].si_signo = SIGTRAP; current_process->usignal.siginfo_data[SIGTRAP-1].si_code = 0; current_process->usignal.siginfo_data[SIGTRAP-1].si_value.sival_int = 0; break; case EXCEPTION_NMI: /* Non-Maskable Interupt */ break; case EXCEPTION_BP: /* Breakpoint */ current_process->usignal.sig_pending |= SIGFTRAP; current_process->usignal.siginfo_data[SIGTRAP-1].si_signo = SIGTRAP; current_process->usignal.siginfo_data[SIGTRAP-1].si_code = 0; current_process->usignal.siginfo_data[SIGTRAP-1].si_value.sival_int = 0; break; case EXCEPTION_OF: /* Overflow */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; case EXCEPTION_BR: /* Boundary-Range Exceeded */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; case EXCEPTION_UD: /* Undefined-Opcode */ current_process->usignal.sig_pending |= SIGFILL; current_process->usignal.siginfo_data[SIGILL-1].si_signo = SIGILL; current_process->usignal.siginfo_data[SIGILL-1].si_code = 0; current_process->usignal.siginfo_data[SIGILL-1].si_value.sival_int = 0; break; case EXCEPTION_NM: /* Device-Not Available */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; case EXCEPTION_DF: /* Double-Fault */ KPANIC ("DF"); break; case EXCEPTION_CSO: /* Reserved : Coprocessor Segment Overrun */ current_process->usignal.sig_pending |= SIGFFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_signo = SIGFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_code = 0; current_process->usignal.siginfo_data[SIGFPE-1].si_value.sival_int = 0; break; case EXCEPTION_TS: /* Invalid TSS */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; case EXCEPTION_NP: /* Segment / Not Present */ current_process->usignal.sig_pending |= SIGFBUS; current_process->usignal.siginfo_data[SIGBUS-1].si_signo = SIGBUS; current_process->usignal.siginfo_data[SIGBUS-1].si_code = 0; current_process->usignal.siginfo_data[SIGBUS-1].si_value.sival_int = 0; break; case EXCEPTION_SS: /* Stack Segment */ current_process->usignal.sig_pending |= SIGFBUS; current_process->usignal.siginfo_data[SIGBUS-1].si_signo = SIGBUS; current_process->usignal.siginfo_data[SIGBUS-1].si_code = 0; current_process->usignal.siginfo_data[SIGBUS-1].si_value.sival_int = 0; break; case EXCEPTION_GP: /* General Protection */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; case EXCEPTION_PF: pf_addr = GetCR2(); if ((es->error_code & PF_ERRORCODE_DIRECTION) == 0) pf_direction = PF_DIR_READ; else pf_direction = PF_DIR_WRITE; EnableInterrupts(); if (PageFault (pf_addr, pf_direction, privilege_level) != 0) { current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; PrintException (es, "Page Fault in PL3", FALSE); } DisableInterrupts(); break; case EXCEPTION_RESV: /* Reserved */ break; case EXCEPTION_MF: /* Math Fault */ current_process->usignal.sig_pending |= SIGFFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_signo = SIGFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_code = 0; current_process->usignal.siginfo_data[SIGFPE-1].si_value.sival_int = 0; break; case EXCEPTION_AC: /* Alignment Check */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; case EXCEPTION_MC: /* Machine Check */ break; case EXCEPTION_XF: /* Extended Math Fault */ current_process->usignal.sig_pending |= SIGFFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_signo = SIGFPE; current_process->usignal.siginfo_data[SIGFPE-1].si_code = 0; current_process->usignal.siginfo_data[SIGFPE-1].si_value.sival_int = 0; break; default: /* Unknown Exception */ current_process->usignal.sig_pending |= SIGFSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_signo = SIGSEGV; current_process->usignal.siginfo_data[SIGSEGV-1].si_code = 0; current_process->usignal.siginfo_data[SIGSEGV-1].si_value.sival_int = 0; break; } } }