📄 fault.c
字号:
#pragma warning(default:4035) // Turn warning back on
_inline void ClearOneSlot (DWORD dwVMBase)
{
memset (&g_pPageDir->PTE[dwVMBase >> 22], 0, 32);
}
void ClearSlots (BOOL fNeedFlush)
{
DWORD dwSlotRst;
if (dwSlotRst = gdwSlotTouched & ~CurAKey) {
int i;
for (i = 1; dwSlotRst; i ++) {
if (dwSlotRst & (1 << i)) {
dwSlotRst &= ~(1 << i);
ClearOneSlot (ProcArray[i].dwVMBase);
}
}
fNeedFlush = TRUE;
gdwSlotTouched &= CurAKey;
}
if (gfObjStoreTouched && !(pFileSysProc->aky & CurAKey)) {
DWORD dwBits = g_ObjStoreSlotBits;
int i;
for (i = 0; dwBits; i ++) {
if (dwBits & (1 << i)) {
dwBits &= ~(1 << i);
ClearOneSlot ((FIRST_MAPPER_SLOT + i) << VA_SECTION);
}
}
fNeedFlush = TRUE;
gfObjStoreTouched = FALSE;
}
if (fNeedFlush) {
OEMCacheRangeFlush (0, 0, CACHE_SYNC_FLUSH_TLB);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
SetCPUASID(
PTHREAD pth
)
{
if (!InSysCall ()) {
KCall ((FARPROC) SetCPUASID, pth);
} else {
BOOL fNeedFlush = (pCurProc != pth->pProc);
if (fNeedFlush) {
DWORD dwPDE = SHARED_BASE_ADDRESS >> 22;
int i;
if (IsCeLogStatus(CELOGSTATUS_ENABLED_GENERAL)) {
CeLogThreadMigrate(pth->pProc->hProc, 0);
}
memcpy (&g_pPageDir->PTE[0], &pth->pProc->pPTBL[0], 32);
// make shared section read-only
for (i = 0; i < PDES_PER_SLOT; i ++) {
g_pPageDir->PTE[dwPDE+i] &= ~PG_WRITE_MASK;
}
}
ClearSlots (fNeedFlush);
pCurProc = pth->pProc;
hCurProc = pCurProc->hProc;
SectionTable[0] = pCurProc->procnum? SectionTable[pCurProc->procnum+1] : &NKSection;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
LPVOID MDValidateKVA (DWORD dwAddr)
{
DWORD dwPageDir;
PPAGETABLE pPageTable;
//
// Find entry in 1st level page dir
//
if ((dwPageDir = g_pPageDir->PTE[VA_TO_PD_IDX (dwAddr)]) != 0) {
if ((dwPageDir & (PG_LARGE_PAGE_MASK|PG_VALID_MASK)) == (PG_LARGE_PAGE_MASK|PG_VALID_MASK)) {
return (LPVOID) dwAddr;
} else {
pPageTable = (PPAGETABLE)PHYS_TO_LIN(dwPageDir & PG_PHYS_ADDR_MASK);
if (pPageTable->PTE[(dwAddr>>VA_PAGE)&0x3FF] & PG_VALID_MASK)
return (LPVOID) dwAddr;
}
}
return 0;
}
//------------------------------------------------------------------------------
//
// Function:
// CommonFault
//
// Description:
// CommonFault is jumped to by the specific fault handlers for unhandled
// exceptions which are then dispatched to the C routine HandleException.
//
// At entry:
// ESP points to stack frame containing PUSHAD, ERROR CODE, EIP, CS,
// EFLAGS, (and optionally Old ESP, Old SS). Normally this is the
// last part of the thread structure, the saved context. In the case
// of a nested exception the context has been saved on the ring 0
// stack. We will create a fake thread structure on the stack to hold
// the captured context. The remaining segment registers are added by
// this routine.
//
// ECX is the faulting address which is passed to HandleException
//
// ESI is the exception id which is passed to HandleException
//
// Return:
// CommonFault jumps to Reschedule or resumes execution based on the return
// value of HandleException.
//
//------------------------------------------------------------------------------
Naked
CommonFault()
{
_asm {
cld
mov eax, KGDT_R3_DATA
mov ds, ax
mov es, ax
dec [KData].cNest
jnz short cf20 // nested fault
mov esp, offset KData-4
mov edi, PtrCurThd
cf10: sti
push ecx
push esi
push edi
call HandleException
add esp, 3*4
test eax, eax
jnz short NoReschedule
jmp Reschedule
NoReschedule:
jmp RunThread
// Nested exception. Create a fake thread structure on the stack
cf20: push ds
push es
push fs
push gs
sub esp, THREAD_CONTEXT_OFFSET
mov edi, esp // (edi) = ptr to fake thread struct
jmp short cf10
}
}
//------------------------------------------------------------------------------
//
// Do a reschedule.
//
// (edi) = ptr to current thread or 0 to force a context reload
//
//------------------------------------------------------------------------------
Naked
Reschedule()
{
__asm {
rsd10:
sti
cmp word ptr ([KData].bResched), 1
jne short rsd11
mov word ptr ([KData].bResched), 0
call NextThread
rsd11:
cmp dword ptr ([KData].dwKCRes), 1
jne short rsd12
mov dword ptr ([KData].dwKCRes), 0
call KCNextThread
cmp dword ptr ([KData].dwKCRes), 1
je short rsd10
rsd12:
mov eax, [RunList.pth]
test eax, eax
jz short rsd50 // nothing to run
cmp eax, edi
jne short rsd20
jmp RunThread // redispatch the same thread
// Switch to a new thread's process context.
// Switching to a new thread. Update current process and address space
// information. Edit the ring0 stack pointer in the TSS to point to the
// new thread's register save area.
//
// (eax) = ptr to thread structure
rsd20: mov edi, eax // Save thread pointer
mov esi, (THREAD)[eax].hTh // (esi) = thread handle
push edi
call SetCPUASID // Sets hCurProc for us!
pop ecx // Clean up stack
mov hCurThd, esi // set the current thread handle
mov PtrCurThd, edi // and the current thread pointer
mov ecx, [edi].tlsPtr // (ecx) = thread local storage ptr
mov [KData].lpvTls, ecx // set TLS pointer
cmp edi, g_CurFPUOwner
jne SetTSBit
clts
jmp MuckWithFSBase
SetTSBit:
mov eax, CR0
test eax, TS_MASK
jnz MuckWithFSBase
or eax, TS_MASK
mov CR0, eax
MuckWithFSBase:
mov edx, offset g_aGlobalDescriptorTable+KGDT_PCR
sub ecx, FS_LIMIT+1 // (ecx) = ptr to NK_PCR base
mov word ptr [edx+2], cx // set low word of FS base
shr ecx, 16
mov byte ptr [edx+4], cl // set third byte of FS base
mov byte ptr [edx+7], ch // set high byte of FS base
push fs
pop fs
lea ecx, [edi].ctx.TcxSs+4 // (ecx) = ptr to end of context save area
mov [MainTSS].Esp0, ecx
jmp RunThread // Run thread pointed to by edi
// No threads ready to run. Call OEMIdle to shutdown the cpu.
rsd50: cli
cmp word ptr ([KData].bResched), 1
je short DoReschedule
call OEMIdle
mov byte ptr ([KData].bResched), 1
jmp Reschedule
DoReschedule:
sti
jmp Reschedule
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Naked
CommonIntDispatch()
{
_asm {
cld
mov eax, KGDT_R3_DATA
mov ds, ax
mov es, ax
dec [KData].cNest
jnz short cid20 // nested fault
mov esp, offset KData-4
mov edi, PtrCurThd
cid10:
#ifdef NKPROF
push esi // save ESI
mov eax, 80000000h // mark as ISR entry
push eax // Arg 0, cNest + SYSINTR_xxx
call CeLogInterrupt
pop eax // cleanup the stack from the call
pop esi // restore ESI
#endif // NKPROF
sti
call esi
mov ecx, dword ptr [pfnOEMIntrOccurs] // (ecx) = pfnOEMIntrOccurs
push eax // push argument == SYSINTR returned
call ecx // call pfnOEMintrOccurs
pop ecx // dummy pop
cli
#ifdef NKPROF
push eax // Save original SYSINTR return value.
bswap eax // Reverse endian
mov ah, [KData].cNest // Nesting level (0 = no nesting, -1 = nested once)
neg ah // Nesting level (0 = no nesting, 1 = nested once)
bswap eax // Reverse endian
push eax // Arg 0, cNest + SYSINTR_xxx
call CeLogInterrupt
pop eax // cleanup the stack from the call
pop eax // restore original SYSINTR value
#endif // NKPROF
test eax, eax
jz short RunThread // SYSINTR_NOP: nothing more to do
#ifdef NKPROF
cmp eax, SYSINTR_PROFILE
jne short cid13
call ProfilerHit
jmp RunThread // Continue on our merry way...
cid13:
#endif // NKPROF
cmp eax, SYSINTR_RESCHED
je short cid15
lea ecx, [eax-SYSINTR_DEVICES]
cmp ecx, SYSINTR_MAX_DEVICES
jae short cid15 // force a reschedule for good measure
// A device interrupt has been signaled. Set the appropriate bit in the pending
// events mask and set the reschedule flag. The device event will be signaled
// by the scheduler.
mov eax, 1 // (eax) = 1
cmp ecx, 32 // ISR# >= 32?
jae cid18 // take care of ISR# >= 32 if true
// ISR# < 32
shl eax, cl // (eax) = 1 << ISR#
or [KData].aPend1, eax // update PendEvent1
cid15: or [KData].bResched, 1 // must reschedule
jmp RunThread
// ISR# >= 32
cid18: sub cl, 32 // ISR# -= 32
shl eax, cl // (eax) = 1 << (ISR#-32)
or [KData].aPend2, eax // update PendEvent2
or [KData].bResched, 1 // must reschedule
jmp RunThread
// Nested exception. Create a fake thread structure on the stack
cid20: push ds
push es
push fs
push gs
sub esp, THREAD_CONTEXT_OFFSET
mov edi, esp // (edi) = ptr to fake thread struct
#ifdef NKPROF
mov dword ptr (pthFakeStruct), edi
#endif
jmp short cid10
}
}
//------------------------------------------------------------------------------
//
// Continue thread execution.
//
// (edi) = ptr to Thread structure
//
//------------------------------------------------------------------------------
Naked
RunThread()
{
_asm {
cli
cmp word ptr ([KData].bResched), 1
jne short NotReschedule
jmp Reschedule
NotReschedule:
inc [KData].cNest
lea esp, [edi].ctx.TcxGs
pop gs
pop fs
pop es
pop ds
popad
add esp, 4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -