- Fix critical bugs in exception handling: Unwinding was completely broken, using the wrong SEH protector to detect collided unwinding. The correct protector itself also had a broken check.

- Fix architectural bug in the entire TrapFrame<->Context conversion system and Ring Privilege Transitions (Inter-ring and intra-ring) which was lacking proper sanitation and validation of segments, flags and debug registers. Among other things, IOPL is now respected, CS is not KGDT_R0_CODE | RPL_MASK anymore, and the GPF code is now properly being called. This completely fixes exception handling being totally broken and crashing firefox installer, mirc, and other applications.
- Rewrite the page fault handler base code in assembly instead of relying on a broken C routine. Detect VDM, V8086, detecting expected/normal fault in ExpInterlockedPopEntrySList and faults in the system handler code. Rewrite MmAccessFault to be the main function that calls out to other sub-fault functions, and use the same prototype as NT.
- Fix the KGDT boot table to have proper granularity and big flags, and extend it to 256 entries.
- Create proper thread context in RtlInitializeContext and cleanup Rtl Thread routines.
- Remove all int3 and breakpoints from trap handlers, and replace them with a much better "UNHANDLED_PATH" macro which freezes the system, beeps, and displays a message with the line of code that's unhandled. This is to clearly tell the user that something is unhandled, instead of nesting infinite exceptions due to the int3.
- Fix a bug in INT_PROLOG.
- Sanitize EFLAGS and Code Segments in KeContextToTrapFrame and KeTrapFrameToContext.
- Implement KiUpdateDr7 and KiRecordDr7 as well as DR_MASK and other DR-validation macros and functions to protect against DR-vulnerabilites as well as to properly account for each active hardware breakpoint in a per-thread fashion by using the dispatcher header.
- Allow CR0_EM when running in a VDM.
- Fix FPU/NPX Register handling in KeContextToTrapFrame and KeTrapFrameToContext, and also speed it up by manual copying instead of a memory move.
- Properly give IOPL 3 to user-mode threads if they requested it.
- Detect GPF during GPF.
- Detect pagefault with a trap-frame spread over two or more pages and nested.
- Properly sanitize and set correct trap frame in KiInitailizeUserApc.
- Return STATUS_ACCESS_VIOLATION during page faults instead of STATUS_UNSUCESSFUL. 
- Fix assert in VdmSwapContext, as well as Code Selector check which was broken.
- Fix delayed object deletion (ObDeferDeleteObject) and the Ob Repear Routine and list.
- Update Kernel Fun.
- BUGBUG: Temporaily hack VMWare to detection to always detect VMWare.

svn path=/trunk/; revision=25238
This commit is contained in:
Alex Ionescu 2006-12-29 18:49:00 +00:00
parent 32b82baa21
commit c0a3750d26
28 changed files with 943 additions and 545 deletions

View file

@ -68,7 +68,7 @@ LONG CALLBACK VectoredExceptionHandler(PEXCEPTION_POINTERS ExceptionInfo)
return EXCEPTION_CONTINUE_EXECUTION;
}
static BOOL
BOOL
DetectVMware(int *Version)
{
int magic, ver;
@ -1010,7 +1010,7 @@ WinMain(HINSTANCE hInstance,
{
PVOID ExceptionHandler;
int Version;
//int Version;
WCHAR *lc;
hAppInstance = hInstance;
@ -1024,9 +1024,9 @@ WinMain(HINSTANCE hInstance,
return 1;
}
if(!DetectVMware(&Version))
//if(!DetectVMware(&Version))
{
return 1;
//return 1;
}
/* unregister the handler */

View file

@ -67,6 +67,7 @@ NtAcceptConnectPort@24
NtAccessCheck@32
NtAccessCheckAndAuditAlarm@44
NtAddAtom@12
NtAddBootEntry@8
NtAdjustGroupsToken@24
NtAdjustPrivilegesToken@24
NtAlertResumeThread@8

View file

@ -169,6 +169,7 @@ Author:
#define KPCR_STALL_SCALE_FACTOR 0x4C
#define KPCR_SET_MEMBER 0x48
#define KPCR_NUMBER 0x51
#define KPCR_VDM_ALERT 0x54
#define KPCR_PRCB_DATA 0x120
#define KPCR_CURRENT_THREAD 0x124
#define KPCR_PRCB_NEXT_THREAD 0x128
@ -473,9 +474,13 @@ Author:
#endif
//
// DR7 Values
// DR6 and 7 Masks
//
#define DR6_LEGAL 0xE00F
#define DR7_LEGAL 0xFFFF0155
#define DR7_ACTIVE 0x55
#define DR7_RESERVED_MASK 0xDC00
#define DR7_OVERRIDE_MASK 0xF0000
//
// Usermode callout frame definitions
@ -491,6 +496,10 @@ Author:
//
#ifdef __ASM__
#define STATUS_ACCESS_VIOLATION 0xC0000005
#define STATUS_IN_PAGE_ERROR 0xC0000006
#define STATUS_GUARD_PAGE_VIOLATION 0x80000001
#define STATUS_STACK_OVERFLOW 0xC00000FD
#define KI_EXCEPTION_ACCESS_VIOLATION 0x10000004
#define STATUS_INVALID_SYSTEM_SERVICE 0xC000001C
#define STATUS_NO_CALLBACK_ACTIVE 0xC0000258
#define STATUS_CALLBACK_POP_STACK 0xC0000423

View file

@ -1893,9 +1893,9 @@ RtlCreateUserThread(
IN HANDLE ProcessHandle,
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN BOOLEAN CreateSuspended,
IN LONG StackZeroBits,
IN ULONG StackReserve,
IN ULONG StackCommit,
IN ULONG StackZeroBits,
IN SIZE_T StackReserve,
IN SIZE_T StackCommit,
IN PTHREAD_START_ROUTINE StartAddress,
IN PVOID Parameter,
IN OUT PHANDLE ThreadHandle,

View file

@ -134,7 +134,7 @@ _RtlpExecuteHandlerForException@20:
.globl _RtlpExecuteHandlerForUnwind@20
_RtlpExecuteHandlerForUnwind@20:
/* Copy the routine in EDX */
mov edx, offset _RtlpExceptionProtector
mov edx, offset _RtlpUnwindProtector
.endfunc
.func RtlpExecuteHandler@20
@ -243,7 +243,7 @@ _RtlpUnwindProtector:
/* Put the exception record in ECX and check the Flags */
mov ecx, [esp+4]
test dword ptr [ecx+EXCEPTION_RECORD_EXCEPTION_FLAGS], EXCEPTION_UNWINDING + EXCEPTION_EXIT_UNWIND
jnz .return
jz .return
/* Save the frame in ECX and Context in EDX */
mov ecx, [esp+8]

View file

@ -10,30 +10,9 @@
/* INCLUDES *****************************************************************/
#include <rtl.h>
#define NDEBUG
#include <debug.h>
/* PRIVATE FUNCTIONS *********************************************************/
VOID
NTAPI
RtlpGetStackLimits(PULONG_PTR StackBase,
PULONG_PTR StackLimit);
PEXCEPTION_REGISTRATION_RECORD
NTAPI
RtlpGetExceptionList(VOID);
VOID
NTAPI
RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList);
typedef struct _DISPATCHER_CONTEXT
{
PEXCEPTION_REGISTRATION_RECORD RegistrationPointer;
} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;
/* PUBLIC FUNCTIONS **********************************************************/
/*
@ -100,7 +79,6 @@ RtlDispatchException(IN PEXCEPTION_RECORD ExceptionRecord,
sizeof(*RegistrationFrame));
/* Call the handler */
DPRINT1("Calling handler: %p\n", RegistrationFrame->Handler);
Disposition = RtlpExecuteHandlerForException(ExceptionRecord,
RegistrationFrame,
Context,
@ -192,7 +170,7 @@ RtlUnwind(IN PVOID TargetFrame OPTIONAL,
IN PVOID ReturnValue)
{
PEXCEPTION_REGISTRATION_RECORD RegistrationFrame, OldFrame;
DISPATCHER_CONTEXT DispatcherContext;
DISPATCHER_CONTEXT DispatcherContext;
EXCEPTION_RECORD ExceptionRecord2, ExceptionRecord3;
EXCEPTION_DISPOSITION Disposition;
ULONG_PTR StackLow, StackHigh;
@ -306,7 +284,7 @@ RtlUnwind(IN PVOID TargetFrame OPTIONAL,
&DispatcherContext,
RegistrationFrame->
Handler);
switch (Disposition)
switch(Disposition)
{
/* Continue searching */
case ExceptionContinueSearch:

View file

@ -16,6 +16,24 @@ extern VOID FASTCALL CHECK_PAGED_CODE_RTL(char *file, int line);
#define PAGED_CODE_RTL()
#endif
VOID
NTAPI
RtlpGetStackLimits(PULONG_PTR StackBase,
PULONG_PTR StackLimit);
PEXCEPTION_REGISTRATION_RECORD
NTAPI
RtlpGetExceptionList(VOID);
VOID
NTAPI
RtlpSetExceptionList(PEXCEPTION_REGISTRATION_RECORD NewExceptionList);
typedef struct _DISPATCHER_CONTEXT
{
PEXCEPTION_REGISTRATION_RECORD RegistrationPointer;
} DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT;
/* These provide support for sharing code between User and Kernel RTL */
PVOID
NTAPI
@ -112,7 +130,7 @@ RtlpCaptureContext(OUT PCONTEXT ContextRecord);
NTSTATUS
NTAPI
DebugService(IN ULONG Service,
IN PCVOID Buffer,
IN const void* Buffer,
IN ULONG Length,
IN PVOID Argument1,
IN PVOID Argument2);

View file

@ -3,7 +3,7 @@
* PROJECT: ReactOS system libraries
* PURPOSE: Rtl user thread functions
* FILE: lib/rtl/thread.c
* PROGRAMERS:
* PROGRAMERS:
* Alex Ionescu (alex@relsoft.net)
* Eric Kohl
* KJK::Hyperion
@ -21,60 +21,54 @@
NTSTATUS
NTAPI
RtlpCreateUserStack(HANDLE hProcess,
ULONG StackReserve,
ULONG StackCommit,
ULONG StackZeroBits,
PINITIAL_TEB InitialTeb)
RtlpCreateUserStack(IN HANDLE hProcess,
IN SIZE_T StackReserve OPTIONAL,
IN SIZE_T StackCommit OPTIONAL,
IN ULONG StackZeroBits OPTIONAL,
OUT PINITIAL_TEB InitialTeb)
{
NTSTATUS Status;
SYSTEM_BASIC_INFORMATION SystemBasicInfo;
PIMAGE_NT_HEADERS Headers;
ULONG_PTR Stack = 0;
BOOLEAN UseGuard = FALSE;
DPRINT("RtlpCreateUserStack\n");
ULONG Dummy, GuardPageSize;
/* Get some memory information */
Status = NtQuerySystemInformation(SystemBasicInformation,
Status = ZwQuerySystemInformation(SystemBasicInformation,
&SystemBasicInfo,
sizeof(SYSTEM_BASIC_INFORMATION),
NULL);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failure to query system info\n");
return Status;
}
if (!NT_SUCCESS(Status)) return Status;
/* Use the Image Settings if we are dealing with the current Process */
if (hProcess == NtCurrentProcess())
{
/* Get the Image Headers */
Headers = RtlImageNtHeader(NtCurrentPeb()->ImageBaseAddress);
DPRINT("Headers: %p\n", Headers);
/* If we didn't get the parameters, find them ourselves */
StackReserve = (StackReserve) ?
StackReserve : Headers->OptionalHeader.SizeOfStackReserve;
StackCommit = (StackCommit) ?
StackCommit : Headers->OptionalHeader.SizeOfStackCommit;
if (!StackReserve) StackReserve = Headers->OptionalHeader.
SizeOfStackReserve;
if (!StackCommit) StackCommit = Headers->OptionalHeader.
SizeOfStackCommit;
}
else
{
/* Use the System Settings if needed */
StackReserve = (StackReserve) ? StackReserve :
SystemBasicInfo.AllocationGranularity;
StackCommit = (StackCommit) ? StackCommit : SystemBasicInfo.PageSize;
if (!StackReserve) StackReserve = SystemBasicInfo.AllocationGranularity;
if (!StackCommit) StackCommit = SystemBasicInfo.PageSize;
}
/* Align everything to Page Size */
StackReserve = ROUND_UP(StackReserve, SystemBasicInfo.AllocationGranularity);
StackCommit = ROUND_UP(StackCommit, SystemBasicInfo.PageSize);
#if 1 // FIXME: Remove once Guard Page support is here
// FIXME: Remove once Guard Page support is here
#if 1
StackCommit = StackReserve;
#endif
DPRINT("StackReserve: %lx, StackCommit: %lx\n", StackReserve, StackCommit);
/* Reserve memory for the stack */
Status = ZwAllocateVirtualMemory(hProcess,
(PVOID*)&Stack,
@ -82,33 +76,26 @@ RtlpCreateUserStack(HANDLE hProcess,
&StackReserve,
MEM_RESERVE,
PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failure to reserve stack\n");
return Status;
}
if (!NT_SUCCESS(Status)) return Status;
/* Now set up some basic Initial TEB Parameters */
InitialTeb->PreviousStackBase = NULL;
InitialTeb->PreviousStackLimit = NULL;
InitialTeb->AllocatedStackBase = (PVOID)Stack;
InitialTeb->StackBase = (PVOID)(Stack + StackReserve);
/* Update the Stack Position */
Stack += StackReserve - StackCommit;
/* Check if we will need a guard page */
if (StackReserve > StackCommit)
{
/* Remove a page to set as guard page */
Stack -= SystemBasicInfo.PageSize;
StackCommit += SystemBasicInfo.PageSize;
UseGuard = TRUE;
}
DPRINT("AllocatedBase: %p, StackBase: %p, Stack: %lx, StackCommit: %lx\n",
InitialTeb->AllocatedStackBase, InitialTeb->StackBase, Stack,
StackCommit);
/* Allocate memory for the stack */
Status = ZwAllocateVirtualMemory(hProcess,
(PVOID*)&Stack,
@ -116,75 +103,68 @@ RtlpCreateUserStack(HANDLE hProcess,
&StackCommit,
MEM_COMMIT,
PAGE_READWRITE);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failure to allocate stack\n");
return Status;
}
if (!NT_SUCCESS(Status)) return Status;
/* Now set the current Stack Limit */
InitialTeb->StackLimit = (PVOID)Stack;
DPRINT("StackLimit: %lx\n", Stack);
/* Create a guard page */
if (UseGuard)
{
ULONG GuardPageSize = SystemBasicInfo.PageSize;
ULONG Dummy;
/* Attempt maximum space possible */
/* Attempt maximum space possible */
GuardPageSize = SystemBasicInfo.PageSize;
Status = ZwProtectVirtualMemory(hProcess,
(PVOID*)&Stack,
&GuardPageSize,
PAGE_GUARD | PAGE_READWRITE,
&Dummy);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failure to create guard page\n");
return Status;
}
if (!NT_SUCCESS(Status)) return Status;
/* Update the Stack Limit keeping in mind the Guard Page */
InitialTeb->StackLimit = (PVOID)((ULONG_PTR)InitialTeb->StackLimit -
GuardPageSize);
DPRINT1("StackLimit: %lx\n", Stack);
}
/* We are done! */
return Status;
return STATUS_SUCCESS;
}
NTSTATUS
NTAPI
RtlpFreeUserStack(HANDLE hProcess,
PINITIAL_TEB InitialTeb)
RtlpFreeUserStack(IN HANDLE Process,
IN PINITIAL_TEB InitialTeb)
{
ULONG Dummy = 0;
NTSTATUS Status;
/* Free the Stack */
return ZwFreeVirtualMemory(hProcess,
&InitialTeb->AllocatedStackBase,
&Dummy,
MEM_RELEASE);
Status = ZwFreeVirtualMemory(Process,
&InitialTeb->AllocatedStackBase,
&Dummy,
MEM_RELEASE);
/* Clear the initial TEB */
RtlZeroMemory(InitialTeb, sizeof(INITIAL_TEB));
return Status;
}
/* FUNCTIONS ***************************************************************/
/*
@implemented
*/
NTSTATUS
NTAPI
RtlCreateUserThread(HANDLE ProcessHandle,
PSECURITY_DESCRIPTOR SecurityDescriptor,
BOOLEAN CreateSuspended,
LONG StackZeroBits,
ULONG StackReserve,
ULONG StackCommit,
PTHREAD_START_ROUTINE StartAddress,
PVOID Parameter,
PHANDLE ThreadHandle,
PCLIENT_ID ClientId)
NTSTATUS
NTAPI
RtlCreateUserThread(IN HANDLE ProcessHandle,
IN PSECURITY_DESCRIPTOR SecurityDescriptor OPTIONAL,
IN BOOLEAN CreateSuspended,
IN ULONG StackZeroBits OPTIONAL,
IN SIZE_T StackReserve OPTIONAL,
IN SIZE_T StackCommit OPTIONAL,
IN PTHREAD_START_ROUTINE StartAddress,
IN PVOID Parameter OPTIONAL,
OUT PHANDLE ThreadHandle OPTIONAL,
OUT PCLIENT_ID ClientId OPTIONAL)
{
NTSTATUS Status;
HANDLE Handle;
@ -192,37 +172,27 @@ RtlCreateUserThread(HANDLE ProcessHandle,
INITIAL_TEB InitialTeb;
OBJECT_ATTRIBUTES ObjectAttributes;
CONTEXT Context;
DPRINT("RtlCreateUserThread: (hProcess: %p, Suspended: %d,"
"ZeroBits: %lx, StackReserve: %lx, StackCommit: %lx,"
"StartAddress: %p, Parameter: %p)\n", ProcessHandle,
CreateSuspended, StackZeroBits, StackReserve, StackCommit,
StartAddress, Parameter);
/* First, we'll create the Stack */
Status = RtlpCreateUserStack(ProcessHandle,
StackReserve,
StackCommit,
StackZeroBits,
&InitialTeb);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failure to create User Stack\n");
return Status;
}
if (!NT_SUCCESS(Status)) return Status;
/* Next, we'll set up the Initial Context */
RtlInitializeContext(ProcessHandle,
&Context,
Parameter,
StartAddress,
InitialTeb.StackBase);
/* We are now ready to create the Kernel Thread Object */
InitializeObjectAttributes(&ObjectAttributes,
NULL,
0,
NULL,
InitializeObjectAttributes(&ObjectAttributes,
NULL,
0,
NULL,
SecurityDescriptor);
Status = ZwCreateThread(&Handle,
THREAD_ALL_ACCESS,
@ -234,18 +204,16 @@ RtlCreateUserThread(HANDLE ProcessHandle,
CreateSuspended);
if (!NT_SUCCESS(Status))
{
DPRINT1("Failure to create Thread\n");
/* Free the stack */
RtlpFreeUserStack(ProcessHandle, &InitialTeb);
}
else
{
DPRINT("Thread created: %p\n", Handle);
/* Return thread data */
if (ThreadHandle) *ThreadHandle = Handle;
if (ClientId) *ClientId = ThreadCid;
}
/* Return success or the previous failure */
return Status;
}
@ -262,10 +230,7 @@ RtlInitializeContext(IN HANDLE ProcessHandle,
IN PTHREAD_START_ROUTINE ThreadStartAddress,
IN PINITIAL_TEB InitialTeb)
{
DPRINT("RtlInitializeContext: (hProcess: %p, ThreadContext: %p, Teb: %p\n",
ProcessHandle, ThreadContext, InitialTeb);
/*
/*
* Set the Initial Registers
* This is based on NT's default values -- crazy apps might expect this...
*/
@ -276,27 +241,27 @@ RtlInitializeContext(IN HANDLE ProcessHandle,
ThreadContext->Edx = 3;
ThreadContext->Esi = 4;
ThreadContext->Edi = 5;
/* Set the Selectors */
ThreadContext->SegGs = 0;
ThreadContext->SegFs = KGDT_R3_TEB | RPL_MASK;
ThreadContext->SegEs = KGDT_R3_DATA | RPL_MASK;
ThreadContext->SegDs = KGDT_R3_DATA | RPL_MASK;
ThreadContext->SegCs = KGDT_R3_CODE | RPL_MASK;
ThreadContext->SegSs = KGDT_R3_DATA | RPL_MASK;
ThreadContext->SegFs = KGDT_R3_TEB;
ThreadContext->SegEs = KGDT_R3_DATA;
ThreadContext->SegDs = KGDT_R3_DATA;
ThreadContext->SegSs = KGDT_R3_DATA;
ThreadContext->SegCs = KGDT_R3_CODE;
/* Enable Interrupts */
ThreadContext->EFlags = 0x200; /*X86_EFLAGS_IF */
ThreadContext->EFlags = EFLAGS_INTERRUPT_MASK;
/* Settings passed */
ThreadContext->Eip = (ULONG)ThreadStartAddress;
ThreadContext->Esp = (ULONG)InitialTeb;
/* Only the basic Context is initialized */
ThreadContext->ContextFlags = CONTEXT_CONTROL |
CONTEXT_INTEGER |
ThreadContext->ContextFlags = CONTEXT_CONTROL |
CONTEXT_INTEGER |
CONTEXT_SEGMENTS;
/* Set up ESP to the right value */
ThreadContext->Esp -= sizeof(PVOID);
ZwWriteVirtualMemory(ProcessHandle,
@ -304,7 +269,7 @@ RtlInitializeContext(IN HANDLE ProcessHandle,
(PVOID)&ThreadStartParam,
sizeof(PVOID),
NULL);
/* Push it down one more notch for RETEIP */
ThreadContext->Esp -= sizeof(PVOID);
}
@ -312,13 +277,13 @@ RtlInitializeContext(IN HANDLE ProcessHandle,
/*
* @implemented
*/
VOID
NTAPI
VOID
NTAPI
RtlExitUserThread(NTSTATUS Status)
{
/* Call the Loader and tell him to notify the DLLs */
LdrShutdownThread();
/* Shut us down */
NtCurrentTeb()->FreeStackOnTermination = TRUE;
NtTerminateThread(NtCurrentThread(), Status);
@ -327,8 +292,8 @@ RtlExitUserThread(NTSTATUS Status)
/*
@implemented
*/
VOID
NTAPI
VOID
NTAPI
RtlFreeUserThreadStack(HANDLE ProcessHandle,
HANDLE ThreadHandle)
{
@ -336,19 +301,15 @@ RtlFreeUserThreadStack(HANDLE ProcessHandle,
THREAD_BASIC_INFORMATION ThreadBasicInfo;
ULONG Dummy, Size = 0;
PVOID StackLocation;
/* Query the Basic Info */
Status = NtQueryInformationThread(ThreadHandle,
ThreadBasicInformation,
&ThreadBasicInfo,
sizeof(THREAD_BASIC_INFORMATION),
NULL);
if (!NT_SUCCESS(Status) || !ThreadBasicInfo.TebBaseAddress)
{
DPRINT1("Could not query info, or TEB is NULL\n");
return;
}
if (!NT_SUCCESS(Status) || !ThreadBasicInfo.TebBaseAddress) return;
/* Get the deallocation stack */
Status = NtReadVirtualMemory(ProcessHandle,
&((PTEB)ThreadBasicInfo.TebBaseAddress)->
@ -356,12 +317,8 @@ RtlFreeUserThreadStack(HANDLE ProcessHandle,
&StackLocation,
sizeof(PVOID),
&Dummy);
if (!NT_SUCCESS(Status) || !StackLocation)
{
DPRINT1("Could not read Deallocation Base\n");
return;
}
if (!NT_SUCCESS(Status) || !StackLocation) return;
/* Free it */
NtFreeVirtualMemory(ProcessHandle, &StackLocation, &Size, MEM_RELEASE);
}

View file

@ -10,31 +10,32 @@
//
//
// Ob:
// - Fix bug related to Deferred Loading (don't requeue active work item).
// - Add Directory Lock.
// - Strengthen code with debug checks and assertions.
// - Fix FIXMEs/commented out code.
//
// Ex:
// - Fixup existing code that talks to Ke.
// - Implement Generic Callback mechanism.
// - Use pushlocks for handle implementation.
//
// Lpc:
// - Figure out why NTLPC-processes won't die anymore.
//
// Ke1:
// - Implement KiInitMachineDependent.
// - Implement Privileged Instruction Handler in Umode GPF.
//
// Fstub:
// - Implement IoAssignDriveLetters using mount manager support.
//
// Ke:
// - Figure out why the DPC stack doesn't really work.
// - Fix SEH/Page Fault + Exceptions!? Weird exception bugs!
// Hal:
// - Use APC and DPC Interrupt Dispatchers.
// - CMOS Initialization and CMOS Spinlock.
//
// Ke2:
// - New optimized table-based tick-hashed timer implementation.
// - New Thread Scheduler based on 2003.
// - Implement KiCallbackReturn, KiGetTickCount, KiRaiseAssertion.
//
// Hal:
// - New IRQL Implementation.
// - CMOS Initialization and CMOS Spinlock.
// - Report resource usage to kernel (HalReportResourceUsage).
//
// Lpc:
// - Activate new NTLPC and delete old implementation.
// - Figure out why LPC-processes won't die anymore.
//
// Ex:
// - Implement Generic Callback mechanism.
// - Use pushlocks for handle implementation.
//
// Kd:
// - Implement KD Kernel Debugging and WinDBG support.
@ -45,3 +46,30 @@
//
///////////////////////////////////////////////////////////////////////////////
// REACTOS GUIDANCE PLAN
// ________________________________________________________________________________________________________
// / \
// | OB, PS, LPC, DBGK, IO => Almost entirely fixed interaction with Ke/Ex. | |
// | SE => Not looked at. Interaction with Ps/Io is minimal and currently hacked away. Preserve. |J|
// | EX => Needs re-visiting (in trunk). Do callbacks/push locks for interaction with Ps. |A|
// | KD/KDBG => Laptop has special version of ROS without these components. Commit in branch. |N|
// | INIT => Boot sequence still needs work in terms of interaction with Ke and CPU features. | |
// | || || || || || || || || || || || || |F|
// | \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ |E|
// | HAL => Needs APC/DPC/IRQL implementation fixed ASAP in terms of interaction with Ke. |B|
// | FSTUB => Needs IoAssignDriveLetters fixed ASAP but not critical to Ke/Ex. Interacts with Io. | |
// | || || || || || || || || || || || || |M|
// | \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ |A|
// | CM => TOTAL REWRITE. |R|
// | || || || || || || || || || || || || | |
// | || || || || || || || || || || || || |A|
// | \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ |P|
// | KE => Timer Rewrite + Thread Scheduler Rewrite. |R|
// | || || || || || || || || || || || || |I|
// | || || || || || || || || || || || || |L|
// | || || || || || || || || || || || || | |
// | \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ \/ |M|
// | MM => TOTAL REWRITE. |A|
// | |Y|
// \________________________________________________________________________________________________________/
//

View file

@ -381,6 +381,9 @@
*/
.global @ExInterlockedPopEntrySList@8
.global @InterlockedPopEntrySList@4
.global _ExpInterlockedPopEntrySListResume@0
.global _ExpInterlockedPopEntrySListFault@0
.global _ExpInterlockedPopEntrySListEnd@0
@ExInterlockedPopEntrySList@8:
@InterlockedPopEntrySList@4:
@ -392,10 +395,10 @@
mov ebp, ecx
/* Get sequence number and link pointer */
_ExpInterlockedPopEntrySListResume@0:
mov edx, [ebp+4]
mov eax, [ebp]
1:
/* Check if the list is empty */
or eax, eax
jz 2f
@ -404,9 +407,11 @@
lea ecx, [edx-1]
/* Get next pointer and do the exchange */
_ExpInterlockedPopEntrySListFault@0:
mov ebx, [eax]
_ExpInterlockedPopEntrySListEnd@0:
LOCK cmpxchg8b [ebp]
jnz 1b
jnz _ExpInterlockedPopEntrySListResume@0
/* Restore registers and return */
2:

View file

@ -65,6 +65,30 @@
#define RELEASE_SPINLOCK(x)
#endif
//
// @name UNHANDLED_PATH
//
// This macro TODO
//
// @param None
//
// @remark None.
//
.macro UNHANDLED_PATH
/* Get EIP */
call $+5
pop eax
/* Print debug message */
push eax
push offset _UnhandledMsg
call _DbgPrint
add esp, 8
/* Loop indefinitely */
jmp $
.endm
//
// @name IDT
//
@ -182,7 +206,6 @@ _KiUnexpectedInterrupt&Number:
push offset V86DebugMsg
call _DbgPrint
add esp, 8
int 3
jmp $
.endm
@ -511,7 +534,7 @@ _KiUnexpectedInterrupt&Number:
/* Check if this was kernel mode */
1:
cmp dword ptr [esp+KTRAP_FRAME_CS], KGDT_R0_CODE
cmp word ptr [esp+KTRAP_FRAME_CS], KGDT_R0_CODE
jz 1f
/* Set segments */
@ -947,7 +970,7 @@ PendingUserApc:
/* Assert the saved exception list */
or edx, edx
jnz 1f
int 3
UNHANDLED_PATH
1:
#endif
@ -962,7 +985,7 @@ PendingUserApc:
/* Assert the saved previous mode */
cmp ecx, -1
jnz 1f
int 3
UNHANDLED_PATH
1:
#endif
@ -976,7 +999,7 @@ PendingUserApc:
mov ecx, [esp+KTRAP_FRAME_PREVIOUS_MODE]
cmp ecx, -1
jz 1f
int 3
UNHANDLED_PATH
1:
#endif
.endif
@ -1111,7 +1134,7 @@ FastExit:
add dword ptr [esp+KTRAP_FRAME_DEBUGARGMARK], 0xBADB0D00
6:
int 3
UNHANDLED_PATH
jmp 5b
#endif

View file

@ -41,12 +41,8 @@
#define X86_EXT_FEATURE_SSE3 0x00000001 /* SSE3 extension present */
#define X86_EXT_FEATURE_3DNOW 0x40000000 /* 3DNOW! extension present */
#define DR7_ACTIVE 0x00000055 /* If any of these bits are set, a Dr is active */
#define FRAME_EDITED 0xFFF8
#define WE_DO_NOT_SPEAK_ABOUT_THE_V86_HACK 1
#ifndef __ASM__
extern ULONG Ke386CacheAlignment;

View file

@ -130,6 +130,8 @@ extern PVOID KeUserApcDispatcher;
extern PVOID KeUserCallbackDispatcher;
extern PVOID KeUserExceptionDispatcher;
extern PVOID KeRaiseUserExceptionDispatcher;
extern UCHAR KiDebugRegisterTrapOffsets[9];
extern UCHAR KiDebugRegisterContextOffsets[9];
/* MACROS *************************************************************************/

View file

@ -6,6 +6,86 @@
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
*/
//
// Thread Dispatcher Header DebugActive Mask
//
#define DR_MASK(x) 1 << x
#define DR_ACTIVE_MASK 0x10
#define DR_REG_MASK 0x4F
//
// Sanitizes a selector
//
FORCEINLINE
ULONG
Ke386SanitizeSeg(IN ULONG Cs,
IN KPROCESSOR_MODE Mode)
{
//
// Check if we're in kernel-mode, and force CPL 0 if so.
// Otherwise, force CPL 3.
//
return ((Mode == KernelMode) ?
(Cs & (0xFFFF & ~RPL_MASK)) :
(RPL_MASK | (Cs & 0xFFFF)));
}
//
// Sanitizes EFLAGS
//
FORCEINLINE
ULONG
Ke386SanitizeFlags(IN ULONG Eflags,
IN KPROCESSOR_MODE Mode)
{
//
// Check if we're in kernel-mode, and sanitize EFLAGS if so.
// Otherwise, also force interrupt mask on.
//
return ((Mode == KernelMode) ?
(Eflags & (EFLAGS_USER_SANITIZE | EFLAGS_INTERRUPT_MASK)) :
(EFLAGS_INTERRUPT_MASK | (Eflags & EFLAGS_USER_SANITIZE)));
}
//
// Gets a DR register from a CONTEXT structure
//
FORCEINLINE
PVOID
KiDrFromContext(IN ULONG Dr,
IN PCONTEXT Context)
{
return *(PVOID*)((ULONG_PTR)Context + KiDebugRegisterContextOffsets[Dr]);
}
//
// Gets a DR register from a KTRAP_FRAME structure
//
FORCEINLINE
PVOID*
KiDrFromTrapFrame(IN ULONG Dr,
IN PKTRAP_FRAME TrapFrame)
{
return (PVOID*)((ULONG_PTR)TrapFrame + KiDebugRegisterTrapOffsets[Dr]);
}
//
//
//
FORCEINLINE
PVOID
Ke386SanitizeDr(IN PVOID DrAddress,
IN KPROCESSOR_MODE Mode)
{
//
// Check if we're in kernel-mode, and return the address directly if so.
// Otherwise, make sure it's not inside the kernel-mode address space.
// If it is, then clear the address.
//
return ((Mode == KernelMode) ? DrAddress :
(DrAddress <= MM_HIGHEST_USER_ADDRESS) ? DrAddress : 0);
}
//
// Enters a Guarded Region
//

View file

@ -686,17 +686,10 @@ MmPageFault(
NTSTATUS
NTAPI
MmAccessFault(
KPROCESSOR_MODE Mode,
ULONG_PTR Address,
BOOLEAN FromMdl
);
NTSTATUS
NTAPI
MmNotPresentFault(
KPROCESSOR_MODE Mode,
ULONG_PTR Address,
BOOLEAN FromMdl
IN BOOLEAN StoreInstruction,
IN PVOID Address,
IN KPROCESSOR_MODE Mode,
IN PVOID TrapInformation
);
/* anonmem.c *****************************************************************/

View file

@ -188,9 +188,10 @@ ObQueryDeviceMapInformation(
// Object Lifetime Functions
//
VOID
FASTCALL
NTAPI
ObpDeleteObject(
IN PVOID Object
IN PVOID Object,
IN BOOLEAN CalledFromWorkerThread
);
LONG

View file

@ -29,17 +29,17 @@ UCHAR KiDoubleFaultTSS[KTSS_IO_MAPS];
/* The TSS to use for NMI Fault Traps (INT 0x2) */
UCHAR KiNMITSS[KTSS_IO_MAPS];
/* The Boot GDT (FIXME: should have more entries */
KGDTENTRY KiBootGdt[12] =
/* The Boot GDT */
KGDTENTRY KiBootGdt[256] =
{
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_NULL */
{0xffff, 0x0000, {{0x00, 0x9a, 0xcf, 0x00}}}, /* KGDT_R0_CODE */
{0xffff, 0x0000, {{0x00, 0x92, 0xcf, 0x00}}}, /* KGDT_R0_DATA */
{0xffff, 0x0000, {{0x00, 0xfa, 0xcf, 0x00}}}, /* KGDT_R3_CODE */
{0xffff, 0x0000, {{0x00, 0xf2, 0xcf, 0x00}}}, /* KGDT_R3_DATA*/
{0xffff, 0x0000, {{0x00, 0x9b, 0xcf, 0x00}}}, /* KGDT_R0_CODE */
{0xffff, 0x0000, {{0x00, 0x93, 0xcf, 0x00}}}, /* KGDT_R0_DATA */
{0xffff, 0x0000, {{0x00, 0xfb, 0xcf, 0x00}}}, /* KGDT_R3_CODE */
{0xffff, 0x0000, {{0x00, 0xf3, 0xcf, 0x00}}}, /* KGDT_R3_DATA*/
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_TSS */
{0x0fff, 0x0000, {{0x00, 0x92, 0x00, 0xff}}}, /* KGDT_R0_PCR */
{0x0fff, 0x0000, {{0x00, 0xf2, 0x00, 0x00}}}, /* KGDT_R3_TEB */
{0x0fff, 0x0000, {{0x00, 0x93, 0xc0, 0xff}}}, /* KGDT_R0_PCR */
{0x0fff, 0x0000, {{0x00, 0xf3, 0x40, 0x00}}}, /* KGDT_R3_TEB */
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_UNUSED */
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_LDT */
{0x0000, 0x0000, {{0x00, 0x00, 0x00, 0x00}}}, /* KGDT_DF_TSS */

View file

@ -14,6 +14,36 @@
#define NDEBUG
#include <debug.h>
/* GLOBALS *******************************************************************/
/* DR Registers in the CONTEXT structure */
UCHAR KiDebugRegisterContextOffsets[9] =
{
FIELD_OFFSET(CONTEXT, Dr0),
FIELD_OFFSET(CONTEXT, Dr1),
FIELD_OFFSET(CONTEXT, Dr2),
FIELD_OFFSET(CONTEXT, Dr3),
0,
0,
FIELD_OFFSET(CONTEXT, Dr6),
FIELD_OFFSET(CONTEXT, Dr7),
0,
};
/* DR Registers in the KTRAP_FRAME structure */
UCHAR KiDebugRegisterTrapOffsets[9] =
{
FIELD_OFFSET(KTRAP_FRAME, Dr0),
FIELD_OFFSET(KTRAP_FRAME, Dr1),
FIELD_OFFSET(KTRAP_FRAME, Dr2),
FIELD_OFFSET(KTRAP_FRAME, Dr3),
0,
0,
FIELD_OFFSET(KTRAP_FRAME, Dr6),
FIELD_OFFSET(KTRAP_FRAME, Dr7),
0,
};
/* FUNCTIONS *****************************************************************/
_SEH_DEFINE_LOCALS(KiCopyInfo)
@ -53,6 +83,101 @@ KeInitExceptions(VOID)
}
}
ULONG
FASTCALL
KiUpdateDr7(IN ULONG Dr7)
{
ULONG DebugMask = KeGetCurrentThread()->DispatcherHeader.DebugActive;
/* Check if debugging is enabled */
if (DebugMask & DR_ACTIVE_MASK)
{
/* Sanity checks */
ASSERT((DebugMask & DR_REG_MASK) != 0);
ASSERT((Dr7 & ~DR7_RESERVED_MASK) == DR7_OVERRIDE_MASK);
return 0;
}
/* Return DR7 itself */
return Dr7;
}
BOOLEAN
FASTCALL
KiRecordDr7(OUT PULONG Dr7Ptr,
OUT PULONG DrMask)
{
ULONG NewMask, Mask;
UCHAR Result;
/* Check if the caller gave us a mask */
if (!DrMask)
{
/* He didn't use the one from the thread */
Mask = KeGetCurrentThread()->DispatcherHeader.DebugActive;
}
else
{
/* He did, read it */
Mask = *DrMask;
}
/* Sanity check */
ASSERT((*Dr7Ptr & DR7_RESERVED_MASK) == 0);
/* Check if DR7 is empty */
NewMask = Mask;
if (!(*Dr7Ptr))
{
/* Assume failure */
Result = FALSE;
/* Check the DR mask */
NewMask &= 0x7F;
if (NewMask & DR_REG_MASK)
{
/* Set the active mask */
NewMask |= DR_ACTIVE_MASK;
/* Set DR7 override */
*DrMask = DR7_OVERRIDE_MASK;
}
else
{
/* Sanity check */
ASSERT(NewMask == 0);
}
}
else
{
/* Check if we have a mask or not */
Result = NewMask ? TRUE: FALSE;
/* Update the mask to disable debugging */
NewMask &= ~DR_ACTIVE_MASK;
NewMask |= 0x80;
}
/* Check if caller wants the new mask */
if (DrMask)
{
/* Update it */
*DrMask = NewMask;
}
else
{
/* Check if the mask changed */
if (Mask != NewMask)
{
/* Update it */
KeGetCurrentThread()->DispatcherHeader.DebugActive = NewMask;
}
}
/* Return the result */
return Result;
}
ULONG
NTAPI
KiEspFromTrapFrame(IN PKTRAP_FRAME TrapFrame)
@ -192,6 +317,8 @@ KeContextToTrapFrame(IN PCONTEXT Context,
ULONG i;
BOOLEAN V86Switch = FALSE;
KIRQL OldIrql = APC_LEVEL;
ULONG DrMask = 0;
PVOID SafeDr;
/* Do this at APC_LEVEL */
if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
@ -207,8 +334,8 @@ KeContextToTrapFrame(IN PCONTEXT Context,
V86Switch = TRUE;
}
/* Copy EFLAGS. FIXME: Needs to be sanitized */
TrapFrame->EFlags = Context->EFlags;
/* Copy EFLAGS and sanitize them*/
TrapFrame->EFlags = Ke386SanitizeFlags(Context->EFlags, PreviousMode);
/* Copy EBP and EIP */
TrapFrame->Ebp = Context->Ebp;
@ -222,14 +349,14 @@ KeContextToTrapFrame(IN PCONTEXT Context,
}
else
{
/* We weren't in V86, so sanitize the CS (FIXME!) */
TrapFrame->SegCs = Context->SegCs;
/* We weren't in V86, so sanitize the CS */
TrapFrame->SegCs = Ke386SanitizeSeg(Context->SegCs, PreviousMode);
/* Don't let it under 8, that's invalid */
if ((PreviousMode != KernelMode) && (TrapFrame->SegCs < 8))
{
/* Force it to User CS */
TrapFrame->SegCs = (KGDT_R3_CODE | RPL_MASK);
TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
}
}
@ -261,7 +388,7 @@ KeContextToTrapFrame(IN PCONTEXT Context,
/* Check if we were in V86 Mode */
if (TrapFrame->EFlags & EFLAGS_V86_MASK)
{
/* Copy the V86 Segments directlry */
/* Copy the V86 Segments directly */
TrapFrame->V86Ds = Context->SegDs;
TrapFrame->V86Es = Context->SegEs;
TrapFrame->V86Fs = Context->SegFs;
@ -272,12 +399,12 @@ KeContextToTrapFrame(IN PCONTEXT Context,
/* For kernel mode, write the standard values */
TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegFs = Context->SegFs;
TrapFrame->SegFs = Ke386SanitizeSeg(Context->SegFs, PreviousMode);
TrapFrame->SegGs = 0;
}
else
{
/* For user mode, return the values directlry */
/* For user mode, return the values directly */
TrapFrame->SegDs = Context->SegDs;
TrapFrame->SegEs = Context->SegEs;
TrapFrame->SegFs = Context->SegFs;
@ -320,7 +447,13 @@ KeContextToTrapFrame(IN PCONTEXT Context,
/* Mask out any invalid flags */
FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS);
/* FIXME: Check if this is a VDM app */
/* Check if this is a VDM app */
if (PsGetCurrentProcess()->VdmObjects)
{
/* Allow the EM flag */
FxSaveArea->Cr0NpxState |= Context->FloatSave.Cr0NpxState &
(CR0_EM | CR0_MP);
}
}
}
@ -373,16 +506,40 @@ KeContextToTrapFrame(IN PCONTEXT Context,
}
else
{
/* Just dump the Fn state in */
RtlCopyMemory(&FxSaveArea->U.FnArea,
&Context->FloatSave,
sizeof(FNSAVE_FORMAT));
/* Copy the structure */
FxSaveArea->U.FnArea.ControlWord = Context->FloatSave.
ControlWord;
FxSaveArea->U.FnArea.StatusWord = Context->FloatSave.
StatusWord;
FxSaveArea->U.FnArea.TagWord = Context->FloatSave.TagWord;
FxSaveArea->U.FnArea.ErrorOffset = Context->FloatSave.
ErrorOffset;
FxSaveArea->U.FnArea.ErrorSelector = Context->FloatSave.
ErrorSelector;
FxSaveArea->U.FnArea.DataOffset = Context->FloatSave.
DataOffset;
FxSaveArea->U.FnArea.DataSelector = Context->FloatSave.
DataSelector;
/* Loop registers */
for (i = 0; i < SIZE_OF_80387_REGISTERS; i++)
{
/* Copy registers */
FxSaveArea->U.FnArea.RegisterArea[i] =
Context->FloatSave.RegisterArea[i];
}
}
/* Mask out any invalid flags */
FxSaveArea->Cr0NpxState &= ~(CR0_EM | CR0_MP | CR0_TS);
/* FIXME: Check if this is a VDM app */
/* Check if this is a VDM app */
if (PsGetCurrentProcess()->VdmObjects)
{
/* Allow the EM flag */
FxSaveArea->Cr0NpxState |= Context->FloatSave.Cr0NpxState &
(CR0_EM | CR0_MP);
}
}
else
{
@ -394,23 +551,38 @@ KeContextToTrapFrame(IN PCONTEXT Context,
/* Handle the Debug Registers */
if ((ContextFlags & CONTEXT_DEBUG_REGISTERS) == CONTEXT_DEBUG_REGISTERS)
{
/* FIXME: All these should be sanitized */
TrapFrame->Dr0 = Context->Dr0;
TrapFrame->Dr1 = Context->Dr1;
TrapFrame->Dr2 = Context->Dr2;
TrapFrame->Dr3 = Context->Dr3;
TrapFrame->Dr6 = Context->Dr6;
TrapFrame->Dr7 = Context->Dr7;
/* Loop DR registers */
for (i = 0; i < 4; i++)
{
/* Sanitize the context DR Address */
SafeDr = Ke386SanitizeDr(KiDrFromContext(i, Context), PreviousMode);
/* Check if usermode */
/* Save it in the trap frame */
*KiDrFromTrapFrame(i, TrapFrame) = SafeDr;
/* Check if this DR address is active and add it in the DR mask */
if (SafeDr) DrMask |= DR_MASK(i);
}
/* Now save and sanitize DR6 */
TrapFrame->Dr6 = Context->Dr6 & DR6_LEGAL;
if (TrapFrame->Dr6) DrMask |= DR_MASK(6);
/* Save and sanitize DR7 */
TrapFrame->Dr7 = Context->Dr7 & DR7_LEGAL;
KiRecordDr7(&TrapFrame->Dr7, &DrMask);
/* If we're in user-mode */
if (PreviousMode != KernelMode)
{
/* Set the Debug Flag */
KeGetCurrentThread()->DispatcherHeader.DebugActive =
(Context->Dr7 & DR7_ACTIVE) ? TRUE: FALSE;
/* FIXME: Save the mask */
//KeGetCurrentThread()->DispatcherHeader.DebugActive = DrMask;
}
}
/* Check if thread has IOPL and force it enabled if so */
if (KeGetCurrentThread()->Iopl) TrapFrame->EFlags |= 0x3000;
/* Restore IRQL */
if (OldIrql < APC_LEVEL) KeLowerIrql(OldIrql);
}
@ -429,6 +601,7 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
} FloatSaveBuffer;
FLOATING_SAVE_AREA *FloatSaveArea;
KIRQL OldIrql = APC_LEVEL;
ULONG i;
/* Do this at APC_LEVEL */
if (KeGetCurrentIrql() < APC_LEVEL) KeRaiseIrql(APC_LEVEL, &OldIrql);
@ -550,10 +723,23 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
KiFlushNPXState(NULL);
}
/* Copy into the Context */
RtlCopyMemory(&Context->FloatSave,
FloatSaveArea,
sizeof(FNSAVE_FORMAT));
/* Copy structure */
Context->FloatSave.ControlWord = FloatSaveArea->ControlWord;
Context->FloatSave.StatusWord = FloatSaveArea->StatusWord;
Context->FloatSave.TagWord = FloatSaveArea->TagWord;
Context->FloatSave.ErrorOffset = FloatSaveArea->ErrorOffset;
Context->FloatSave.ErrorSelector = FloatSaveArea->ErrorSelector;
Context->FloatSave.DataOffset = FloatSaveArea->DataOffset;
Context->FloatSave.DataSelector = FloatSaveArea->DataSelector;
Context->FloatSave.Cr0NpxState = FxSaveArea->Cr0NpxState;
/* Loop registers */
for (i = 0; i < SIZE_OF_80387_REGISTERS; i++)
{
/* Copy them */
Context->FloatSave.RegisterArea[i] =
FloatSaveArea->RegisterArea[i];
}
}
else
{
@ -566,24 +752,26 @@ KeTrapFrameToContext(IN PKTRAP_FRAME TrapFrame,
if ((Context->ContextFlags & CONTEXT_DEBUG_REGISTERS) ==
CONTEXT_DEBUG_REGISTERS)
{
/* Copy the debug registers */
Context->Dr0 = TrapFrame->Dr0;
Context->Dr1 = TrapFrame->Dr1;
Context->Dr2 = TrapFrame->Dr2;
Context->Dr3 = TrapFrame->Dr3;
Context->Dr6 = TrapFrame->Dr6;
/* For user-mode, only set DR7 if a debugger is active */
if (((TrapFrame->SegCs & MODE_MASK) ||
(TrapFrame->EFlags & EFLAGS_V86_MASK)) &&
(KeGetCurrentThread()->DispatcherHeader.DebugActive))
/* Make sure DR7 is valid */
if (TrapFrame->Dr7 & ~DR7_RESERVED_MASK)
{
/* Copy it over */
Context->Dr7 = TrapFrame->Dr7;
/* Copy the debug registers */
Context->Dr0 = TrapFrame->Dr0;
Context->Dr1 = TrapFrame->Dr1;
Context->Dr2 = TrapFrame->Dr2;
Context->Dr3 = TrapFrame->Dr3;
Context->Dr6 = TrapFrame->Dr6;
/* Update DR7 */
//Context->Dr7 = KiUpdateDr7(TrapFrame->Dr7);
}
else
{
/* Clear it */
/* Otherwise clear DR registers */
Context->Dr0 =
Context->Dr1 =
Context->Dr3 =
Context->Dr6 =
Context->Dr7 = 0;
}
}
@ -757,13 +945,13 @@ DispatchToUser:
KiEspToTrapFrame(TrapFrame, NewStack - 2 * sizeof(ULONG_PTR));
/* Force correct segments */
TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegFs = KGDT_R3_TEB | RPL_MASK;
TrapFrame->SegCs = Ke386SanitizeSeg(KGDT_R3_CODE, PreviousMode);
TrapFrame->SegDs = Ke386SanitizeSeg(KGDT_R3_DATA, PreviousMode);
TrapFrame->SegEs = Ke386SanitizeSeg(KGDT_R3_DATA, PreviousMode);
TrapFrame->SegFs = Ke386SanitizeSeg(KGDT_R3_TEB, PreviousMode);
TrapFrame->SegGs = 0;
/* Set EIP to the User-mode Dispathcer */
/* Set EIP to the User-mode Dispatcher */
TrapFrame->Eip = (ULONG)KeUserExceptionDispatcher;
_SEH_LEAVE;
}

View file

@ -87,13 +87,17 @@ _KiUnexpectedEntrySize:
_UnexpectedMsg:
.asciz "\n\x7\x7!!! Unexpected Interrupt %02lx !!!\n"
_UnhandledMsg:
.asciz "\n\x7\x7!!! Unhandled or Unexpected Code at line: %lx!!!\n"
/* SOFTWARE INTERRUPT SERVICES ***********************************************/
.text
_KiGetTickCount:
_KiCallbackReturn:
_KiRaiseAssertion:
int 3
/* FIXME: TODO */
UNHANDLED_PATH
.func KiSystemService
Dr_kss: DR_TRAP_FIXUP
@ -144,6 +148,7 @@ SharedCode:
/* Check if we should flush the User Batch */
xor ebx, ebx
ReadBatch:
or ebx, [ecx+TEB_GDI_BATCH_COUNT]
jz NotWin32K
@ -432,8 +437,8 @@ V86_Exit:
iret
AbiosExit:
/* Not yet supported */
int 3
/* FIXME: TODO */
UNHANDLED_PATH
.func KiDebugService
Dr_kids: DR_TRAP_FIXUP
@ -672,6 +677,13 @@ _DispatchTwoParam:
/* HARDWARE TRAP HANDLERS ****************************************************/
.func KiFixupFrame
_KiFixupFrame:
/* TODO: Routine to fixup a KTRAP_FRAME when faulting from a syscall. */
UNHANDLED_PATH
.endfunc
.func KiTrap0
Dr_kit0: DR_TRAP_FIXUP
V86_kit0: V86_TRAP_FIXUP
@ -710,7 +722,8 @@ VdmCheck:
/* We don't support this yet! */
V86Int0:
int 3
/* FIXME: TODO */
UNHANDLED_PATH
.endfunc
.func KiTrap1
@ -754,7 +767,7 @@ V86Int1:
jz EnableInterrupts
/* We don't support VDM! */
int 3
UNHANDLED_PATH
.endfunc
.globl _KiTrap2
@ -813,7 +826,7 @@ V86Int3:
jz EnableInterrupts3
/* We don't support VDM! */
int 3
UNHANDLED_PATH
.endfunc
.func KiTrap4
@ -855,7 +868,7 @@ VdmCheck4:
/* We don't support this yet! */
V86Int4:
int 3
UNHANDLED_PATH
.endfunc
.func KiTrap5
@ -901,7 +914,7 @@ VdmCheck5:
/* We don't support this yet! */
V86Int5:
int 3
UNHANDLED_PATH
.endfunc
.func KiTrap6
@ -917,8 +930,7 @@ _KiTrap6:
V86_TRAP_PROLOG kit6
/* Not yet supported (Invalid OPCODE from V86) */
int 3
jmp $
UNHANDLED_PATH
NotV86UD:
/* Push error code */
@ -993,8 +1005,7 @@ LockCrash:
IsVdmOpcode:
/* Unhandled yet */
int 3
jmp $
UNHANDLED_PATH
/* Return to caller */
jmp _Kei386EoiHelper@0
@ -1302,8 +1313,7 @@ V86Npx:
jz HandleUserNpx
/* V86 NPX not handled */
int 3
jmp $
UNHANDLED_PATH
EmulationEnabled:
/* Did this come from kernel-mode? */
@ -1456,7 +1466,7 @@ RaiseIrql:
jnz NoReflect
/* FIXME: TODO */
int 3
UNHANDLED_PATH
NoReflect:
@ -1485,9 +1495,21 @@ NotV86:
test dword ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jnz UserModeGpf
/* FIXME: Check for GPF during GPF */
/* Check if we have a VDM alert */
cmp dword ptr fs:[KPCR_VDM_ALERT], 0
jnz VdmAlertGpf
/* Check for GPF during GPF */
mov eax, [ebp+KTRAP_FRAME_EIP]
cmp eax, offset CheckPrivilegedInstruction
jbe KmodeGpf
cmp eax, offset CheckPrivilegedInstruction2
/* FIXME: TODO */
UNHANDLED_PATH
/* Get the opcode and trap frame */
KmodeGpf:
mov eax, [ebp+KTRAP_FRAME_EIP]
mov eax, [eax]
mov edx, [ebp+KTRAP_FRAME_EBP]
@ -1573,8 +1595,7 @@ TrapCopy:
MsrCheck:
/* FIXME: Handle RDMSR/WRMSR */
int 3
jmp $
UNHANDLED_PATH
NotIretGpf:
@ -1606,7 +1627,6 @@ SegPopGpf:
lea eax, [ebp+KTRAP_FRAME_ESP]
cmp edx, eax
jz HandleSegPop
int 3
/* Handle segment POP fault by setting it to 0 */
HandleSegPop:
@ -1620,26 +1640,239 @@ ExitGpfTrap:
UserModeGpf:
/* FIXME: Unhandled */
int 3
jmp $
/* If the previous mode was kernel, raise a fatal exception */
mov eax, 13
test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jz _KiSystemFatalException
/* Get the process and check which CS this came from */
mov ebx, fs:[KPCR_CURRENT_THREAD]
mov ebx, [ebx+KTHREAD_APCSTATE_PROCESS]
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
jz CheckVdmGpf
/* Check if this is a VDM */
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jnz DispatchV86Gpf
/* Enable interrupts and check if we have an error code */
sti
cmp word ptr [ebp+KTRAP_FRAME_ERROR_CODE], 0
jnz SetException
jmp CheckPrivilegedInstruction
HandleSegPop2:
/* Update EIP (will be updated below again) */
add dword ptr [ebp+KTRAP_FRAME_EIP], 1
HandleBop4:
/* Clear the segment, update EIP and ESP */
mov dword ptr [edx], 0
add dword ptr [ebp+KTRAP_FRAME_EIP], 1
add dword ptr [ebp+KTRAP_FRAME_ESP], 4
jmp _Kei386EoiHelper@0
CheckVdmGpf:
/* Check if this is a VDM */
cmp dword ptr [ebx+EPROCESS_VDM_OBJECTS], 0
jz CheckPrivilegedInstruction
/* Check what kind of instruction this is */
mov eax, [ebp+KTRAP_FRAME_EIP]
mov eax, [eax]
/* FIXME: Check for BOP4 */
/* Check if this is POP FS */
mov edx, ebp
add edx, KTRAP_FRAME_FS
cmp ax, 0xA10F
jz HandleSegPop2
/* Check if this is POP GS */
add edx, KTRAP_FRAME_GS - KTRAP_FRAME_FS
cmp ax, 0xA90F
jz HandleSegPop2
CheckPrivilegedInstruction:
/* FIXME */
UNHANDLED_PATH
CheckPrivilegedInstruction2:
/* FIXME */
UNHANDLED_PATH
SetException:
/* FIXME */
UNHANDLED_PATH
DispatchV86Gpf:
/* FIXME */
UNHANDLED_PATH
.endfunc
.func KiTrap14
Dr_kit14: DR_TRAP_FIXUP
V86_kit14: V86_TRAP_FIXUP
_KiTrap14:
/* Enter trap */
TRAP_PROLOG kit14
/* Call the C exception handler */
push 14
push ebp
call _KiPageFaultHandler
add esp, 8
/* Check if we have a VDM alert */
cmp dword ptr fs:[KPCR_VDM_ALERT], 0
jnz VdmAlertGpf
/* Return to caller */
/* Get the current thread */
mov edi, fs:[KPCR_CURRENT_THREAD]
/* Get the stack address of the frame */
lea eax, [esp+KTRAP_FRAME_LENGTH+NPX_FRAME_LENGTH]
sub eax, [edi+KTHREAD_INITIAL_STACK]
jz NoFixUp
/* This isn't the base frame, check if it's the second */
cmp eax, -KTRAP_FRAME_EFLAGS
jb NoFixUp
/* Check if we have a TEB */
mov eax, fs:[KPCR_TEB]
or eax, eax
jle NoFixUp
/* Fixup the frame */
call _KiFixupFrame
/* Save CR2 */
NoFixUp:
mov edi, cr2
/* ROS HACK: Sometimes we get called with INTS DISABLED! WTF? */
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
je HandlePf
/* Enable interrupts and check if we got here with interrupts disabled */
sti
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_INTERRUPT_MASK
jz IllegalState
HandlePf:
/* Send trap frame and check if this is kernel-mode or usermode */
push ebp
mov eax, [ebp+KTRAP_FRAME_CS]
and eax, MODE_MASK
push eax
/* Send faulting address and check if this is read or write */
push edi
mov eax, [ebp+KTRAP_FRAME_ERROR_CODE]
and eax, 1
push eax
/* Call the access fault handler */
call _MmAccessFault@16
test eax, eax
jl AccessFail
/* Access fault handled, return to caller */
jmp _Kei386EoiHelper@0
AccessFail:
/* First check if this is a fault in the S-LIST functions */
mov ecx, offset _ExpInterlockedPopEntrySListFault@0
cmp [ebp+KTRAP_FRAME_EIP], ecx
jz SlistFault
/* Check if this is a fault in the syscall handler */
mov ecx, offset CopyParams
cmp [ebp+KTRAP_FRAME_EIP], ecx
jz SysCallCopyFault
mov ecx, offset ReadBatch
cmp [ebp+KTRAP_FRAME_EIP], ecx
jnz CheckVdmPf
/* FIXME: TODO */
UNHANDLED_PATH
jmp _Kei386EoiHelper@0
SysCallCopyFault:
/* FIXME: TODO */
UNHANDLED_PATH
jmp _Kei386EoiHelper@0
/* Check if the fault occured in a V86 mode */
CheckVdmPf:
mov ecx, [ebp+KTRAP_FRAME_ERROR_CODE]
and ecx, 1
shr ecx, 1
test dword ptr [ebp+KTRAP_FRAME_EFLAGS], EFLAGS_V86_MASK
jnz VdmPF
/* Check if the fault occured in a VDM */
mov esi, fs:[KPCR_CURRENT_THREAD]
mov esi, [esi+KTHREAD_APCSTATE_PROCESS]
cmp dword ptr [esi+EPROCESS_VDM_OBJECTS], 0
jz CheckStatus
/* Check if we this was in kernel-mode */
test byte ptr [ebp+KTRAP_FRAME_CS], MODE_MASK
jz CheckStatus
cmp word ptr [ebp+KTRAP_FRAME_CS], KGDT_R3_CODE + RPL_MASK
jz CheckStatus
VdmPF:
/* FIXME: TODO */
UNHANDLED_PATH
/* Save EIP and check what kind of status failure we got */
CheckStatus:
mov esi, [ebp+KTRAP_FRAME_EIP]
cmp eax, STATUS_ACCESS_VIOLATION
je AccessViol
cmp eax, STATUS_GUARD_PAGE_VIOLATION
je SpecialCode
cmp eax, STATUS_STACK_OVERFLOW
je SpecialCode
/* Setup an in-page exception to dispatch */
mov edx, ecx
mov ebx, esi
mov esi, edi
mov ecx, 3
mov edi, eax
mov eax, STATUS_IN_PAGE_ERROR
call _CommonDispatchException
AccessViol:
/* Use more proper status code */
mov eax, KI_EXCEPTION_ACCESS_VIOLATION
SpecialCode:
/* Setup a normal page fault exception */
mov ebx, esi
mov edx, ecx
mov esi, edi
jmp _DispatchTwoParam
SlistFault:
/* FIXME: TODO */
UNHANDLED_PATH
IllegalState:
/* This is completely illegal, bugcheck the system */
push ebp
push esi
push ecx
push eax
push edi
push IRQL_NOT_LESS_OR_EQUAL
call _KeBugCheckWithTf@24
VdmAlertGpf:
/* FIXME: NOT SUPPORTED */
UNHANDLED_PATH
.endfunc
.func KiTrap0F
@ -1752,8 +1985,7 @@ _Ki16BitStackException:
add esp, [eax+KTHREAD_INITIAL_STACK]
/* Switch to good stack segment */
/* TODO */
int 3
UNHANDLED_PATH
.endfunc
/* UNEXPECTED INTERRUPT HANDLERS **********************************************/
@ -1867,7 +2099,7 @@ CheckQuantum:
jz Return
/* FIXME: Schedule new thread */
int 3
UNHANDLED_PATH
Return:
/* All done */
@ -1904,7 +2136,7 @@ _KiInterruptTemplateDispatch:
_KiChainedDispatch2ndLvl@0:
/* Not yet supported */
int 3
UNHANDLED_PATH
.endfunc
.func KiChainedDispatch@0

View file

@ -71,7 +71,7 @@ KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
_SEH_DECLARE_LOCALS(KiCopyInfo);
/* Don't deliver APCs in V86 mode */
if (TrapFrame->EFlags & X86_EFLAGS_VM) return;
if (TrapFrame->EFlags & EFLAGS_V86_MASK) return;
/* Save the full context */
Context.ContextFlags = CONTEXT_FULL | CONTEXT_DEBUG_REGISTERS;
@ -102,22 +102,19 @@ KiInitializeUserApc(IN PKEXCEPTION_FRAME ExceptionFrame,
TrapFrame->HardwareEsp = Stack;
/* Setup Ring 3 state */
TrapFrame->SegCs = KGDT_R3_CODE | RPL_MASK;
TrapFrame->HardwareSegSs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegDs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegEs = KGDT_R3_DATA | RPL_MASK;
TrapFrame->SegCs = Ke386SanitizeSeg(KGDT_R3_CODE, UserMode);
TrapFrame->HardwareSegSs = Ke386SanitizeSeg(KGDT_R3_DATA, UserMode);
TrapFrame->SegDs = Ke386SanitizeSeg(KGDT_R3_DATA, UserMode);
TrapFrame->SegEs = Ke386SanitizeSeg(KGDT_R3_DATA, UserMode);
TrapFrame->SegFs = Ke386SanitizeSeg(KGDT_R3_TEB, UserMode);
TrapFrame->SegGs = 0;
TrapFrame->ErrCode = 0;
/* Sanitize EFLAGS */
TrapFrame->EFlags = Context.EFlags & EFLAGS_USER_SANITIZE;
TrapFrame->EFlags |= EFLAGS_INTERRUPT_MASK;
TrapFrame->EFlags = Ke386SanitizeFlags(Context.EFlags, UserMode);
/* Check if user-mode has IO privileges */
if (KeGetCurrentThread()->Iopl)
{
/* Enable them*/
TrapFrame->EFlags |= (0x3000);
}
/* Check if thread has IOPL and force it enabled if so */
if (KeGetCurrentThread()->Iopl) TrapFrame->EFlags |= 0x3000;
/* Setup the stack */
*(PULONG_PTR)(Stack + 0 * sizeof(ULONG_PTR)) = (ULONG_PTR)NormalRoutine;

View file

@ -1,17 +0,0 @@
.globl @MmSafeReadPtr@4
.globl _MmSafeReadPtrStart
.globl _MmSafeReadPtrEnd
/*****************************************************************************/
/*
* PVOID FASTCALL MmSafeReadPtr(PVOID Source)
*/
@MmSafeReadPtr@4:
_MmSafeReadPtrStart:
/*
* If we incur a pagefault, eax will be set NULL
*/
movl (%ecx),%eax
_MmSafeReadPtrEnd:
ret

View file

@ -1,135 +0,0 @@
/* $Id$
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/i386/pfault.c
* PURPOSE: Paging file functions
*
* PROGRAMMERS: David Welch (welch@mcmail.com)
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#define NDEBUG
#include <internal/debug.h>
/* EXTERNS *******************************************************************/
extern VOID MmSafeReadPtrStart(VOID);
extern VOID MmSafeReadPtrEnd(VOID);
extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address);
extern ULONG KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2);
extern BOOLEAN Ke386NoExecute;
/* FUNCTIONS *****************************************************************/
ULONG KiPageFaultHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
{
ULONG_PTR cr2;
NTSTATUS Status;
KPROCESSOR_MODE Mode;
EXCEPTION_RECORD Er;
ASSERT(ExceptionNr == 14);
/* get the faulting address */
cr2 = __readcr2();
Tf->DbgArgPointer = cr2;
/* it's safe to enable interrupts after cr2 has been saved */
if (Tf->EFlags & (X86_EFLAGS_VM|X86_EFLAGS_IF))
{
_enable();
}
if (cr2 >= (ULONG_PTR)MmSystemRangeStart)
{
/* check for an invalid page directory in kernel mode */
if (!(Tf->ErrCode & 0x5) && Mmi386MakeKernelPageTableGlobal((PVOID)cr2))
{
return 0;
}
/* check for non executable memory in kernel mode */
if (Ke386NoExecute && Tf->ErrCode & 0x10)
{
KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY, 0, 0, 0, 0, Tf);
}
}
Mode = Tf->ErrCode & 0x4 ? UserMode : KernelMode;
/* handle the fault */
if (Tf->ErrCode & 0x1)
{
Status = MmAccessFault(Mode, cr2, FALSE);
}
else
{
Status = MmNotPresentFault(Mode, cr2, FALSE);
}
/* handle the return for v86 mode */
if (Tf->EFlags & X86_EFLAGS_VM)
{
if (!NT_SUCCESS(Status))
{
/* FIXME: This should use ->VdmObjects */
if(!PsGetCurrentProcess()->Pcb.Unused)
{
*((PKV86M_TRAP_FRAME)Tf)->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
}
return 1;
}
return 0;
}
if (Mode == KernelMode)
{
if (!NT_SUCCESS(Status))
{
if (Tf->Eip >= (ULONG_PTR)MmSafeReadPtrStart &&
Tf->Eip < (ULONG_PTR)MmSafeReadPtrEnd)
{
Tf->Eip = (ULONG_PTR)MmSafeReadPtrEnd;
Tf->Eax = 0;
return 0;
}
}
}
else
{
if (KeGetCurrentThread()->ApcState.UserApcPending)
{
KIRQL oldIrql;
KeRaiseIrql(APC_LEVEL, &oldIrql);
KiDeliverApc(UserMode, NULL, NULL);
KeLowerIrql(oldIrql);
}
}
if (NT_SUCCESS(Status))
{
return 0;
}
Er.ExceptionCode = STATUS_ACCESS_VIOLATION;
Er.ExceptionFlags = 0;
Er.ExceptionRecord = NULL;
Er.ExceptionAddress = (PVOID)Tf->Eip;
Er.NumberParameters = 2;
Er.ExceptionInformation[0] = Tf->ErrCode & 0x1;
Er.ExceptionInformation[1] = (ULONG)cr2;
/* FIXME: Which exceptions are noncontinuable? */
Er.ExceptionFlags = 0;
KiDispatchException(&Er, 0, Tf, Mode, TRUE);
return 0;
}

View file

@ -433,7 +433,7 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
if (!MmIsPagePresent(NULL, Address))
{
Status = MmNotPresentFault(Mode, (ULONG_PTR)Address, TRUE);
Status = MmAccessFault(FALSE, Address, Mode, NULL);
if (!NT_SUCCESS(Status))
{
for (j = 0; j < i; j++)
@ -457,7 +457,7 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
if ((Operation == IoWriteAccess || Operation == IoModifyAccess) &&
(!(MmGetPageProtect(NULL, (PVOID)Address) & PAGE_READWRITE)))
{
Status = MmAccessFault(Mode, (ULONG_PTR)Address, TRUE);
Status = MmAccessFault(TRUE, Address, Mode, NULL);
if (!NT_SUCCESS(Status))
{
for (j = 0; j < i; j++)

View file

@ -75,9 +75,9 @@ BOOLEAN STDCALL MmIsAddressValid(PVOID VirtualAddress)
NTSTATUS
NTAPI
MmAccessFault(KPROCESSOR_MODE Mode,
ULONG_PTR Address,
BOOLEAN FromMdl)
MmpAccessFault(KPROCESSOR_MODE Mode,
ULONG_PTR Address,
BOOLEAN FromMdl)
{
PMADDRESS_SPACE AddressSpace;
MEMORY_AREA* MemoryArea;
@ -109,7 +109,7 @@ MmAccessFault(KPROCESSOR_MODE Mode,
{
DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode, Address);
DbgPrint("%s:%d\n",__FILE__,__LINE__);
return(STATUS_UNSUCCESSFUL);
return(STATUS_ACCESS_VIOLATION);
}
AddressSpace = MmGetKernelAddressSpace();
}
@ -131,13 +131,13 @@ MmAccessFault(KPROCESSOR_MODE Mode,
{
MmUnlockAddressSpace(AddressSpace);
}
return (STATUS_UNSUCCESSFUL);
return (STATUS_ACCESS_VIOLATION);
}
switch (MemoryArea->Type)
{
case MEMORY_AREA_SYSTEM:
Status = STATUS_UNSUCCESSFUL;
Status = STATUS_ACCESS_VIOLATION;
break;
case MEMORY_AREA_PAGED_POOL:
@ -152,15 +152,15 @@ MmAccessFault(KPROCESSOR_MODE Mode,
break;
case MEMORY_AREA_VIRTUAL_MEMORY:
Status = STATUS_UNSUCCESSFUL;
Status = STATUS_ACCESS_VIOLATION;
break;
case MEMORY_AREA_SHARED_DATA:
Status = STATUS_UNSUCCESSFUL;
Status = STATUS_ACCESS_VIOLATION;
break;
default:
Status = STATUS_UNSUCCESSFUL;
Status = STATUS_ACCESS_VIOLATION;
break;
}
}
@ -174,32 +174,6 @@ MmAccessFault(KPROCESSOR_MODE Mode,
return(Status);
}
NTSTATUS
NTAPI
MmCommitPagedPoolAddress(PVOID Address, BOOLEAN Locked)
{
NTSTATUS Status;
PFN_TYPE AllocatedPage;
Status = MmRequestPageMemoryConsumer(MC_PPOOL, FALSE, &AllocatedPage);
if (!NT_SUCCESS(Status))
{
MmUnlockAddressSpace(MmGetKernelAddressSpace());
Status = MmRequestPageMemoryConsumer(MC_PPOOL, TRUE, &AllocatedPage);
MmLockAddressSpace(MmGetKernelAddressSpace());
}
Status =
MmCreateVirtualMapping(NULL,
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READWRITE,
&AllocatedPage,
1);
if (Locked)
{
MmLockPage(AllocatedPage);
}
return(Status);
}
NTSTATUS
NTAPI
MmNotPresentFault(KPROCESSOR_MODE Mode,
@ -227,7 +201,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
DPRINT("No current process\n");
if (Address < (ULONG_PTR)MmSystemRangeStart)
{
return(STATUS_UNSUCCESSFUL);
return(STATUS_ACCESS_VIOLATION);
}
}
@ -242,7 +216,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
if (Mode != KernelMode)
{
CPRINT("Address: %x\n", Address);
return(STATUS_UNSUCCESSFUL);
return(STATUS_ACCESS_VIOLATION);
}
AddressSpace = MmGetKernelAddressSpace();
}
@ -268,7 +242,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
{
MmUnlockAddressSpace(AddressSpace);
}
return (STATUS_UNSUCCESSFUL);
return (STATUS_ACCESS_VIOLATION);
}
switch (MemoryArea->Type)
@ -280,7 +254,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
}
case MEMORY_AREA_SYSTEM:
Status = STATUS_UNSUCCESSFUL;
Status = STATUS_ACCESS_VIOLATION;
break;
case MEMORY_AREA_SECTION_VIEW:
@ -309,7 +283,7 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
break;
default:
Status = STATUS_UNSUCCESSFUL;
Status = STATUS_ACCESS_VIOLATION;
break;
}
}
@ -323,6 +297,67 @@ MmNotPresentFault(KPROCESSOR_MODE Mode,
return(Status);
}
extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address);
NTSTATUS
NTAPI
MmAccessFault(IN BOOLEAN StoreInstruction,
IN PVOID Address,
IN KPROCESSOR_MODE Mode,
IN PVOID TrapInformation)
{
/* Cute little hack for ROS */
if ((ULONG_PTR)Address >= (ULONG_PTR)MmSystemRangeStart)
{
/* Check for an invalid page directory in kernel mode */
if (Mmi386MakeKernelPageTableGlobal(Address))
{
/* All is well with the world */
return STATUS_SUCCESS;
}
}
/* Keep same old ReactOS Behaviour */
if (StoreInstruction)
{
/* Call access fault */
return MmpAccessFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE);
}
else
{
/* Call not present */
return MmNotPresentFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE);
}
}
NTSTATUS
NTAPI
MmCommitPagedPoolAddress(PVOID Address, BOOLEAN Locked)
{
NTSTATUS Status;
PFN_TYPE AllocatedPage;
Status = MmRequestPageMemoryConsumer(MC_PPOOL, FALSE, &AllocatedPage);
if (!NT_SUCCESS(Status))
{
MmUnlockAddressSpace(MmGetKernelAddressSpace());
Status = MmRequestPageMemoryConsumer(MC_PPOOL, TRUE, &AllocatedPage);
MmLockAddressSpace(MmGetKernelAddressSpace());
}
Status =
MmCreateVirtualMapping(NULL,
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READWRITE,
&AllocatedPage,
1);
if (Locked)
{
MmLockPage(AllocatedPage);
}
return(Status);
}
/* Miscellanea functions: they may fit somewhere else */
/*

View file

@ -257,9 +257,7 @@
<directory name="mm">
<if property="ARCH" value="i386">
<directory name="i386">
<file>memsafe.s</file>
<file>page.c</file>
<file>pfault.c</file>
</directory>
</if>
<file>anonmem.c</file>

View file

@ -134,8 +134,9 @@ ObpDeallocateObject(IN PVOID Object)
}
VOID
FASTCALL
ObpDeleteObject(IN PVOID Object)
NTAPI
ObpDeleteObject(IN PVOID Object,
IN BOOLEAN CalledFromWorkerThread)
{
POBJECT_HEADER Header;
POBJECT_TYPE ObjectType;
@ -203,12 +204,15 @@ VOID
NTAPI
ObpReapObject(IN PVOID Parameter)
{
POBJECT_HEADER ReapObject;
POBJECT_HEADER ReapObject = (PVOID)1;
PVOID NextObject;
/* Start reaping */
while ((ReapObject = InterlockedExchangePointer(&ObpReaperList, NULL)))
do
{
/* Get the reap object */
ReapObject = InterlockedExchangePointer(&ObpReaperList, ReapObject);
/* Start deletion loop */
do
{
@ -216,12 +220,13 @@ ObpReapObject(IN PVOID Parameter)
NextObject = ReapObject->NextToFree;
/* Delete the object */
ObpDeleteObject(&ReapObject->Body);
ObpDeleteObject(&ReapObject->Body, TRUE);
/* Move to the next one */
ReapObject = NextObject;
} while (NextObject);
}
} while ((NextObject) && (NextObject != (PVOID)1));
} while ((ObpReaperList != (PVOID)1) ||
(InterlockedCompareExchange((PLONG)&ObpReaperList, 0, 1) != 1));
}
/*++

View file

@ -50,21 +50,27 @@ ObReferenceObjectSafe(IN PVOID Object)
VOID
NTAPI
ObpDeferObjectDeletion(IN PVOID Object)
ObpDeferObjectDeletion(IN POBJECT_HEADER Header)
{
POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object);
PVOID Entry, NewEntry;
/* Add us to the list */
/* Loop while trying to update the list */
do
{
Header->NextToFree = ObpReaperList;
} while (InterlockedCompareExchangePointer(&ObpReaperList,
Header,
Header->NextToFree) !=
Header->NextToFree);
/* Get the current entry */
Entry = ObpReaperList;
/* Queue the work item */
ExQueueWorkItem(&ObpReaperWorkItem, DelayedWorkQueue);
/* Link our object to the list */
Header->NextToFree = Entry;
NewEntry = Header;
/* Update the list */
} while (InterlockedCompareExchangePointer(&ObpReaperList,
NewEntry,
Entry) != Entry);
/* Queue the work item if needed */
if (!Entry) ExQueueWorkItem(&ObpReaperWorkItem, CriticalWorkQueue);
}
LONG
@ -91,11 +97,7 @@ ObDereferenceObjectEx(IN PVOID Object,
/* Check whether the object can now be deleted. */
NewCount = InterlockedExchangeAdd(&Header->PointerCount, -Count);
if (!Count)
{
/* Add us to the deferred deletion list */
ObpDeferObjectDeletion(Object);
}
if (!Count) ObpDeferObjectDeletion(Header);
/* Return the current count */
return NewCount;
@ -308,12 +310,12 @@ ObfDereferenceObject(IN PVOID Object)
if (KeGetCurrentIrql() == PASSIVE_LEVEL)
{
/* Remove the object */
ObpDeleteObject(Object);
ObpDeleteObject(Object, FALSE);
}
else
{
/* Add us to the deferred deletion list */
ObpDeferObjectDeletion(Object);
ObpDeferObjectDeletion(Header);
}
}
@ -325,11 +327,13 @@ VOID
NTAPI
ObDereferenceObjectDeferDelete(IN PVOID Object)
{
POBJECT_HEADER Header = OBJECT_TO_OBJECT_HEADER(Object);
/* Check whether the object can now be deleted. */
if (!(InterlockedDecrement(&OBJECT_TO_OBJECT_HEADER(Object)->PointerCount)))
if (!InterlockedDecrement(&Header->PointerCount))
{
/* Add us to the deferred deletion list */
ObpDeferObjectDeletion(Object);
ObpDeferObjectDeletion(Header);
}
}

View file

@ -50,7 +50,7 @@ VdmSwapContext(IN PKTRAP_FRAME TrapFrame,
/* Make sure that we're at APC_LEVEL and that this is a valid frame */
ASSERT_IRQL(APC_LEVEL);
ASSERT(TrapFrame->DbgArgMark = 0xBADB0D00);
ASSERT(TrapFrame->DbgArgMark == 0xBADB0D00);
/* Check if this is a V86 frame */
if (TrapFrame->EFlags & EFLAGS_V86_MASK)
@ -61,9 +61,9 @@ VdmSwapContext(IN PKTRAP_FRAME TrapFrame,
OutContext->SegEs = TrapFrame->V86Es;
OutContext->SegDs = TrapFrame->V86Ds;
}
else if (TrapFrame->SegCs == (KGDT_R3_CODE | RPL_MASK))
else if (TrapFrame->SegCs != (KGDT_R3_CODE | RPL_MASK))
{
/* This was user mode, copy segment registers */
/* This was kernel mode, copy segment registers */
OutContext->SegGs = TrapFrame->SegGs;
OutContext->SegFs = TrapFrame->SegFs;
OutContext->SegEs = TrapFrame->SegEs;