📄 fault.c
字号:
mov [edx].tlsPtr, ecx // update thread's tlsPtr
mov [KData].lpvTls, ecx // set KData's TLS pointer
// update fs
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 // cause fs to reload
jmp short CBRtnCommon
/////////////////////////////////////////////////////////////////////////////////////////
// callbacks
// CALLER MUST BE IN KMODE
DoPerformCallback:
sti // interrupt okay now
// setup OBJCALLSTRUCT
mov edx, fs:[0] // replace EFLAGS with linkage
mov [esp], edx // replace EFLAGS with linkage
sub esp, 12 // room for mode, prevSP, and method
push esp // arg1 == ptr to OBJCALLSTRUCT
lea ecx, [esp+20] // (ecx) = original SP
mov [esp+8], ecx // pobs->prevSP = original SP
call PerformCallBackExt // argument to PerformCallBackExt is (excpLink, ra, pcbi, pmode)
// eax == function to call
mov ecx, [esp+12] // (ecx) = mode
add esp, 20 // remove args we pushed
cmp dword ptr [esp-12], 0 // use same stack?
je short CBCommon
// need to change stack
mov edx, PtrCurThd // (edx) == pCurThread
mov ecx, [edx].tlsNonSecure // (ecx) == TLSPTR of the non-secure stack
mov [edx].tlsPtr, ecx // update thread's tlsPtr
mov [KData].lpvTls, ecx // set KData's TLS pointer
// update fs
// (ecx) == pCurThread->tlsPtr
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
// make sure fs got updated
push fs
pop fs // cause fs to reload
// save current ESP in callstack structure
mov ecx, [esp-12] // (ecx) == new SP
xchg ecx, esp // switch stack
push dword ptr [ecx+32]
push dword ptr [ecx+28]
push dword ptr [ecx+24]
push dword ptr [ecx+20]
push dword ptr [ecx+16]
push dword ptr [ecx+12]
push dword ptr [ecx+8]
push dword ptr [ecx+4]
sub esp, 4 // room for return address
mov ecx, [ecx-8] // reload mode
CBCommon:
// (eax) == function to call
// (ecx) == mode
// mark PSL boundary
mov dword ptr fs:[0], -2
// save registers for exception handling
mov edx, PtrCurThd // (eax) = ptr to THREAD struct
mov edx, [edx].pcstkTop // (eax) = ptr to CALLSTACK struct
mov [edx].ExEsp, esp // .\ v
mov [edx].ExEbp, ebp // ..\ v
mov [edx].ExEbx, ebx // ...> save registers for possible exception recovery
mov [edx].ExEsi, esi // ../
mov [edx].ExEdi, edi // ./
// (ecx) == mode
cmp ecx, KERNEL_MODE
je short CBInKMode
// setup return address to trap back
mov dword ptr [esp], SYSCALL_RETURN
// setup far-return stack
mov edx, esp
push KGDT_R3_DATA | 3 // SS of ring 3
push edx // target ESP
push KGDT_R3_CODE | 3 // CS of ring 3
push eax // function to call
// return to user code
retf
CBInKMode:
pop edx // get rid of return address
call eax // call the function directly
CBRtnCommon:
// (eax) == return value for callback
push eax // save return value
sub esp, 4 // room for linkage
push esp // arg0 == pLinkage
call CallbackReturn
// (eax) == return address
mov ecx, eax // (ecx) == return address
mov eax, [esp+4]
mov fs:[0], eax // restore exception linkage
mov eax, [esp+8] // restore return value
add esp, 12 // remove the stuffs we pushed onto
push ecx // push return address onto stack
ret // return to caller of PerformCallback in KMODE
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
int __declspec(naked)
KCall(
PKFN pfn,
...
)
{
__asm {
push ebp
mov ebp, esp
push ebx
mov eax, 12[ebp] // (eax) = arg0
mov edx, 16[ebp] // (edx) = arg1
mov ecx, 20[ebp] // (ecx) = arg2
mov ebx, 8[ebp] // (ebx) = function address
cmp [KData].cNest, 1
jne short kcl50 // Already in non-preemtible state
int KCALL_INT // trap to ring0 for non-preemtible stuff
pop ebx
pop ebp // restore original EBP
ret
kcl50: push ecx // push Arg2
push edx // push Arg1
push eax // push Arg0
call ebx // invoke function
add esp, 3*4 // remove args from stack
pop ebx
pop ebp // restore original EBP
ret
}
}
#pragma warning(default:4035 4733) // Turn warning back on
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Naked
Int22KCallHandler(void)
{
__asm {
push eax // fake Error Code
pushad
mov esi, esp // save ptr to register save area
mov esp, offset KData-4 // switch to kernel stack
dec [KData].cNest
sti
push ecx // push Arg2
push edx // push Arg1
push eax // push Arg0
call ebx // invoke non-preemtible function
mov [esi+7*4], eax // save return value into PUSHAD frame
mov ecx, OFFSET KData
xor edi, edi // force Reschedule to reload the thread's state
cli
cmp word ptr ([ecx].bResched), 1
jne short NotReschedule
jmp Reschedule
NotReschedule:
cmp dword ptr ([ecx].dwKCRes), 1
jne short NotResched2
jmp Reschedule
NotResched2:
mov esp, esi
inc [ecx].cNest
popad
add esp, 4 // throw away the error code
iretd
}
}
//------------------------------------------------------------------------------
// rdmsr - C wrapper for the assembly call. Must be in RING 0 to make this call!
// Assumes that the rdmsr instruction is supported on this CPU; you must check
// using the CPUID instruction before calling this function.
//------------------------------------------------------------------------------
static void rdmsr(
DWORD dwAddr, // Address of MSR being read
DWORD *lpdwValHigh, // Receives upper 32 bits of value, can be NULL
DWORD *lpdwValLow // Receives lower 32 bits of value, can be NULL
)
{
DWORD dwValHigh, dwValLow;
_asm {
;// RDMSR: address read from ECX, data returned in EDX:EAX
mov ecx, dwAddr
rdmsr
mov dwValHigh, edx
mov dwValLow, eax
}
if (lpdwValHigh) {
*lpdwValHigh = dwValHigh;
}
if (lpdwValLow) {
*lpdwValLow = dwValLow;
}
}
//------------------------------------------------------------------------------
// NKrdmsr - C wrapper for the rdmsr assembly call. Handles getting into
// ring 0 but does not check whether MSRs are supported or whether the
// particular MSR address being read from is supported.
//------------------------------------------------------------------------------
BOOL
NKrdmsr(
DWORD dwAddr, // Address of MSR being read
DWORD *lpdwValHigh, // Receives upper 32 bits of value, can be NULL
DWORD *lpdwValLow // Receives lower 32 bits of value, can be NULL
)
{
if (InSysCall()) {
rdmsr(dwAddr, lpdwValHigh, lpdwValLow);
} else {
KCall((PKFN)rdmsr, dwAddr, lpdwValHigh, lpdwValLow);
}
return TRUE;
}
//------------------------------------------------------------------------------
// wrmsr - C wrapper for the assembly call. Must be in RING 0 to make this call!
// Assumes that the wrmsr instruction is supported on this CPU; you must check
// using the CPUID instruction before calling this function.
//------------------------------------------------------------------------------
static void wrmsr(
DWORD dwAddr, // Address of MSR being written
DWORD dwValHigh, // Upper 32 bits of value being written
DWORD dwValLow // Lower 32 bits of value being written
)
{
_asm {
;// WRMSR: address read from ECX, data read from EDX:EAX
mov ecx, dwAddr
mov edx, dwValHigh
mov eax, dwValLow
wrmsr
}
}
//------------------------------------------------------------------------------
// NKwrmsr - C wrapper for the wrmsr assembly call. Handles getting into
// ring 0 but does not check whether MSRs are supported or whether the
// particular MSR address being written to is supported.
//------------------------------------------------------------------------------
BOOL
NKwrmsr(
DWORD dwAddr, // Address of MSR being written
DWORD dwValHigh, // Upper 32 bits of value being written
DWORD dwValLow // Lower 32 bits of value being written
)
{
if (InSysCall()) {
wrmsr(dwAddr, dwValHigh, dwValLow);
} else {
KCall((PKFN)wrmsr, dwAddr, dwValHigh, dwValLow);
}
return TRUE;
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
InitializePageTables(void)
{
InitIDTEntry(SYSCALL_INT, KGDT_R1_CODE | 1, Int20SyscallHandler(), RING3_INT_GATE);
InitIDTEntry(KCALL_INT, KGDT_R0_CODE, Int22KCallHandler, RING1_INT_GATE);
NKDbgPrintfW (L"g_pPageDir = %8.8lx\n", g_pPageDir);
}
///////////////////////////// FLOATING POINT UNIT CODE /////////////////////////////////
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
InitializeEmx87(void)
{
// Fast FP save/restore instructions are not available when emulating FP
KCALLPROFON(70);
ProcessorFeatures &= ~CPUID_FXSR;
_asm {
mov eax, cr0
or eax, MP_MASK or EM_MASK
and eax, NOT (TS_MASK or NE_MASK)
mov cr0, eax
}
KCALLPROFOFF(70);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void
InitNPXHPHandler(
LPVOID NPXNPHandler
)
{
KCALLPROFON(71);
if(pTOC->ulKernelFlags & KFLAG_NOTALLKMODE)
{
InitIDTEntry(0x07, KGDT_R3_CODE, NPXNPHandler, RING3_TRAP_GATE);
}
else
{
InitIDTEntry(0x07, KGDT_R1_CODE, NPXNPHandler, RING1_TRAP_GATE);
}
KCALLPROFOFF(71);
}
BOOL __declspec(naked) NKIsSysIntrValid (DWORD idInt)
{
_asm {
mov eax, [esp+4] // (eax) = idInt
sub eax, SYSINTR_DEVICES // (eax) = idInt - SYSINTR_DEVICES
jb NKIRetFalse // return FALSE if < SYSINTR_DEVICES
cmp eax, SYSINTR_MAX_DEVICES // (eax) >= SYSINTR_MAX_DEVICES?
jae NKIRetFalse // return FALSE if >= SYSINTR_MAX_DEVICES
//; idInt is valid, return IntrEvents[idInt-SYSINTR_DEVICES]
mov eax, dword ptr KData.alpeIntrEvents[eax*4]
ret
NKIRetFalse:
xor eax, eax // return FALSE
ret
}
}
//------------------------------------------------------------------------------
//----------------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -