📄 fault.c
字号:
iretd
cli
hlt
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Naked
PageFault()
{
_asm {
pushad
mov ebx, OFFSET KData
mov edi, cr2
test edi, edi
jns short pf05
// Address > 2GB, kmode only
mov esi, [esp+32]
and esi, 1
jnz short pf50 // prevelige vialoation, get out now
mov ecx, edi
shr ecx, VA_SECTION
cmp ecx, SECURE_SECTION
jne short pf50 // get out if not secure section
pf05:
dec [ebx].cNest // count kernel reentrancy level
mov esi, esp // (esi) = original stack pointer
jnz short pf10
lea esp, [ebx-4] // switch to kernel stack (&KData-4)
// Process a page fault for the "user" address space (0 to 0x7FFFFFFF)
//
// (edi) = Faulting address
// (ebx) = ptr to KData
// (esi) = Original ESP
pf10: cld // Need to do this since the page fault could have come from anywhere!
cmp dword ptr ([KData].dwInDebugger), 0 // see if debugger active
jne short pf20 // if so, skip turning on of interrupts
sti // enable interrupts
pf20: push [esi+32]
push edi
call LoadPageTable
cli
test eax, eax
jz short pf40 // page not found in the Virtual memory tree
cmp word ptr ([KData].bResched), 1
je short pf60 // must reschedule now
inc [ebx].cNest // back out of kernel one level
mov esp, esi // restore stack pointer
popad
add esp, 4
iretd
// This one was not a good one! Jump to common fault handler
//
// (edi) = faulting address
pf40: inc [ebx].cNest // back out of kernel one level
mov esp, esi // restore stack pointer
pf50: mov ecx, edi // (ecx) = fault effective address
mov esi, 0Eh
jmp CommonFault
// The reschedule flag was set and we are at the first nest level into the kernel
// so we must reschedule now.
pf60: mov edi, PtrCurThd // (edi) = ptr to current THREAD
jmp Reschedule
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Naked
GeneralFault()
{
_asm {
pushad
xor ecx, ecx // (ecx) = 0 (fault effective address)
mov esi, 13
jmp CommonFault
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Naked
InvalidOpcode(void)
{
__asm {
push eax
pushad
mov esi, 6
xor ecx, ecx // (ecx) = 0 (fault effective address)
jmp CommonFault
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Naked
ZeroDivide(void)
{
__asm {
push eax
pushad
xor esi, esi // (esi) = 0 (divide by zero fault)
xor ecx, ecx // (ecx) = 0 (fault effective address)
jmp CommonFault
}
}
const BYTE PosTable[256] = {
0,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
8,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
7,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,
6,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1,5,1,2,1,3,1,2,1,4,1,2,1,3,1,2,1
};
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void __declspec(naked)
GetHighPos(
DWORD foo
)
{
_asm {
mov ecx, dword ptr [esp + 4]
push ebx
lea ebx, PosTable
mov dl, 0xff
xor eax, eax
mov al, cl
xlatb
test al, al
jne res
shr ecx, 8
add dl, 8
mov al, cl
xlatb
test al, al
jne res
shr ecx, 8
add dl, 8
mov al, cl
xlatb
test al, al
jne res
shr ecx, 8
add dl, 8
mov al, cl
xlatb
test al, al
jne res
mov al, 9
res:
add al, dl
pop ebx
ret
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Naked
Int1Fault(void)
{
__asm {
push eax // Save orig EAX as fake error code
cmp word ptr [esp + 6], 0FFFFh // Is it an API call fault?
je skip_debug // Yes - handle page fault first
mov eax, [esp + 4] // (eax) = faulting EIP
and dword ptr [esp + 12], not 0100h // Clear TF if set
test byte ptr [esp + 8], 3 // Are we trying to SS ring 0?
jz skip_debug // Yes - get out quick
mov eax, dword ptr [esp] // Restore original EAX
pushad
mov esi, 1
xor ecx, ecx // (ecx) = 0 (fault effective address)
jmp CommonFault
skip_debug:
pop eax
iretd
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Naked
Int2Fault(void)
{
__asm {
push eax // Fake error code
pushad
mov esi, 2
xor ecx, ecx // (ecx) = 0 (fault effective address)
jmp CommonFault
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Naked
Int3Fault(void)
{
__asm {
dec dword ptr [esp] // Back up EIP
push eax // Fake error code
pushad
mov esi, 3
xor ecx, ecx // (ecx) = 0 (fault effective address)
jmp CommonFault
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
InvalidateRange(
PVOID pvAddr,
ULONG ulSize
)
{
// just flush TLB
KCall ((FARPROC) OEMCacheRangeFlush, 0, 0, CACHE_SYNC_FLUSH_TLB);
}
static DWORD addrPagesForPT;
#define IsSystemStarted() (VAcs.hCrit)
static BOOL AllocPagesForPT (DWORD cbPages)
{
if (IsSystemStarted ()) {
return HoldPages (cbPages, FALSE);
}
// called from OEMInit - special handling
addrPagesForPT = pTOC->ulRAMFree + MemForPT;
MemForPT += cbPages * PAGE_SIZE;
return TRUE;
}
static DWORD GetNextPageForPT (void)
{
DWORD dwPhys;
if (IsSystemStarted ()) {
return GetHeldPage ();
}
// called from OEMInit - special handling
dwPhys = LIN_TO_PHYS (addrPagesForPT);
addrPagesForPT += PAGE_SIZE;
return dwPhys;
}
#define PG_KERNEL_RW (PG_WRITE_MASK | PG_VALID_MASK | PG_ACCESSED_MASK | PG_DIRTY_MASK)
#define FIRST_STATIC_PDE (0xC40 >> 2) // VA 0xC4000000, in 4M chunks
#define STATIC_PDE_LIMIT (0xE00 >> 2) // VA 0xE0000000, in 4M chunks
#define LARGE_PAGE_SUPPORT_DETECTED (KData.dwCpuCap & CPUID_PSE)
const int dw4M = 4 * 1024 * 1024;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
DWORD
FindFreePDE(
DWORD dwNumPDE // Number of consecutive 4MB sections needed
)
{
DWORD pdeStart, pdeWalk;
DWORD dwNumFound;
for (pdeStart = FIRST_STATIC_PDE; (pdeStart + dwNumPDE - 1) < STATIC_PDE_LIMIT; pdeStart++) {
dwNumFound = 0;
if (!g_pPageDir->PTE[pdeStart]) {
//
// This is a potential starting point. See if enough consecutive
// blocks are available.
//
dwNumFound = 1;
for (pdeWalk = pdeStart + 1; pdeWalk < pdeStart + dwNumPDE; pdeWalk++) {
if (g_pPageDir->PTE[pdeWalk]) {
break;
} else {
dwNumFound++;
}
}
if (dwNumFound == dwNumPDE) {
return pdeStart;
}
}
}
// none found
return 0;
}
DWORD FindExistingMapping (DWORD dw4MPhysBase, DWORD dwNumPDE)
{
DWORD pdeStart, pdeWalk, dwPDE;
DWORD dwNumFound;
PPAGETABLE pPageTable;
DEBUGCHK (!(dw4MPhysBase & (dw4M - 1))); // must be 4M aligned
// loop through the page directory until we find an unused entry or existing mapping
for (pdeStart = FIRST_STATIC_PDE; g_pPageDir->PTE[pdeStart] && ((pdeStart + dwNumPDE - 1) < STATIC_PDE_LIMIT); pdeStart++) {
// find the consective PDE entries that satisfy the request
for (dwNumFound = 0, pdeWalk = pdeStart; dwNumFound < dwNumPDE; dwNumFound ++, pdeWalk ++) {
if (LARGE_PAGE_SUPPORT_DETECTED) {
// large page, physical base is in the entry itself
dwPDE = g_pPageDir->PTE[pdeWalk] & PG_PHYS_ADDR_MASK;
} else {
// 4K page tables, first entry in the pagetable is the 4M aligned address
pPageTable = (PPAGETABLE) Phys2Virt (g_pPageDir->PTE[pdeWalk] & PG_PHYS_ADDR_MASK);
DEBUGCHK (pPageTable);
dwPDE = pPageTable->PTE[0] & PG_PHYS_ADDR_MASK;
}
if (dwPDE != dw4MPhysBase + dwNumFound * dw4M) {
break;
}
}
if (dwNumFound == dwNumPDE) {
return pdeStart;
}
}
// not found
return 0;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPVOID
NKCreateStaticMapping(
DWORD dwPhysBase,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -