910 lines
19 KiB
C
910 lines
19 KiB
C
/*++
|
||
|
||
Module Name:
|
||
|
||
region.c
|
||
|
||
Abstract:
|
||
|
||
This module implements the region space management code.
|
||
|
||
Author:
|
||
|
||
Landy Wang (landyw) 18-Feb-1999
|
||
Koichi Yamada (kyamada) 18-Feb-1999
|
||
|
||
Environment:
|
||
|
||
Kernel mode only.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "ki.h"
|
||
|
||
VOID
|
||
KiSetRegionRegister (
|
||
PVOID VirtualAddress,
|
||
ULONGLONG Contents
|
||
);
|
||
|
||
|
||
#define KiMakeValidRegionRegister(Rid, Ps) \
|
||
(((ULONGLONG)Rid << RR_RID) | (Ps << RR_PS) | (1 << RR_VE))
|
||
|
||
ULONG KiMaximumRid = MAXIMUM_RID;
|
||
ULONG KiRegionFlushRequired = 0;
|
||
|
||
|
||
VOID
|
||
KiSyncNewRegionIdTarget (
|
||
IN PULONG SignalDone,
|
||
IN PVOID Parameter1,
|
||
IN PVOID Parameter2,
|
||
IN PVOID Parameter3
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the target function for synchronizing the region IDs.
|
||
|
||
Arguments:
|
||
|
||
SignalDone - Supplies a pointer to a variable that is cleared when the
|
||
requested operation has been performed.
|
||
|
||
Parameter1 - Not used.
|
||
|
||
Parameter2 - Not used.
|
||
|
||
Parameter3 - Not used.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
#if !defined(NT_UP)
|
||
|
||
PKPROCESS Process;
|
||
PREGION_MAP_INFO ProcessRegion;
|
||
PREGION_MAP_INFO MappedSession;
|
||
ULONG NewRid;
|
||
|
||
//
|
||
// get KPROCESS from PCR for MP synchronization
|
||
//
|
||
|
||
Process = (PKPROCESS)PCR->Pcb;
|
||
|
||
ProcessRegion = &Process->ProcessRegion;
|
||
MappedSession = Process->SessionMapInfo;
|
||
|
||
KiAcquireSpinLock(&KiMasterRidLock);
|
||
|
||
if (ProcessRegion->SequenceNumber != KiMasterSequence) {
|
||
|
||
KiMasterRid += 1;
|
||
|
||
ProcessRegion->RegionId = KiMasterRid;
|
||
ProcessRegion->SequenceNumber = KiMasterSequence;
|
||
|
||
}
|
||
|
||
KiSetRegionRegister(MM_LOWEST_USER_ADDRESS,
|
||
KiMakeValidRegionRegister(ProcessRegion->RegionId, PAGE_SHIFT));
|
||
|
||
KiFlushFixedDataTb(TRUE, PDE_UTBASE);
|
||
|
||
KeFillFixedEntryTb((PHARDWARE_PTE)&Process->DirectoryTableBase[0],
|
||
(PVOID)PDE_UTBASE,
|
||
PAGE_SHIFT,
|
||
DTR_UTBASE_INDEX);
|
||
|
||
if (MappedSession->SequenceNumber != KiMasterSequence) {
|
||
|
||
KiMasterRid += 1;
|
||
|
||
MappedSession->RegionId = KiMasterRid;
|
||
MappedSession->SequenceNumber = KiMasterSequence;
|
||
|
||
}
|
||
|
||
KiSetRegionRegister((PVOID)SADDRESS_BASE,
|
||
KiMakeValidRegionRegister(MappedSession->RegionId, PAGE_SHIFT));
|
||
|
||
KiFlushFixedDataTb(TRUE, PDE_STBASE);
|
||
|
||
KeFillFixedEntryTb((PHARDWARE_PTE)&Process->SessionParentBase,
|
||
(PVOID)PDE_STBASE,
|
||
PAGE_SHIFT,
|
||
DTR_STBASE_INDEX);
|
||
|
||
KiReleaseSpinLock(&KiMasterRidLock);
|
||
|
||
KiIpiSignalPacketDone(SignalDone);
|
||
|
||
KeFlushCurrentTb();
|
||
|
||
#endif
|
||
return;
|
||
}
|
||
|
||
BOOLEAN
|
||
KiSyncNewRegionId(
|
||
IN PREGION_MAP_INFO ProcessRegion,
|
||
IN PREGION_MAP_INFO SessionRegion
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Generate a new region id and synchronize the region IDs on all the
|
||
processors if necessary. If the region IDs wrap then flush all
|
||
processor TBs.
|
||
|
||
Arguments:
|
||
|
||
ProcessRegion - Supplies a REGION_MAP_INFO user space pointer.
|
||
|
||
SessionRegion - Supplies a REGION_MAP_INFO session space pointer.
|
||
|
||
Return Value:
|
||
|
||
TRUE - if the region id has been recycled.
|
||
|
||
FALSE -- if the region id has not been recycled.
|
||
|
||
Notes:
|
||
|
||
This routine called by KiSwapProcess, KeAttachSessionSpace and
|
||
KeCreateSessionSpace.
|
||
|
||
Environment:
|
||
|
||
Kernel mode.
|
||
|
||
KiLockDispatcherLock/LockQueuedDispatcherLock or
|
||
KiContextSwapLock (MP) is held.
|
||
|
||
--*/
|
||
|
||
{
|
||
ULONG i;
|
||
LOGICAL RidRecycled;
|
||
KAFFINITY TargetProcessors;
|
||
ULONGLONG PrSequence = ProcessRegion->SequenceNumber;
|
||
ULONGLONG SeSequence = SessionRegion->SequenceNumber;
|
||
|
||
RidRecycled = FALSE;
|
||
|
||
//
|
||
// copy the KPROCESS pointer for MP region synchronization
|
||
//
|
||
|
||
PCR->Pcb = (PVOID)KeGetCurrentThread()->ApcState.Process;
|
||
|
||
//
|
||
// Invalidx1ate the ForwardProgressTb buffer
|
||
//
|
||
|
||
for (i = 0; i < MAXIMUM_FWP_BUFFER_ENTRY; i += 1) {
|
||
|
||
PCR->ForwardProgressBuffer[(i*2)+1] = 0;
|
||
|
||
}
|
||
|
||
if ((PrSequence == KiMasterSequence) && (SeSequence == KiMasterSequence)) {
|
||
|
||
not_recycled:
|
||
|
||
KiSetRegionRegister(MM_LOWEST_USER_ADDRESS,
|
||
KiMakeValidRegionRegister(ProcessRegion->RegionId,
|
||
PAGE_SHIFT));
|
||
|
||
KiSetRegionRegister((PVOID)SADDRESS_BASE,
|
||
KiMakeValidRegionRegister(SessionRegion->RegionId,
|
||
PAGE_SHIFT));
|
||
|
||
#if !defined(NT_UP)
|
||
if (KiRegionFlushRequired) {
|
||
KiRegionFlushRequired = 0;
|
||
goto RegionFlush;
|
||
}
|
||
#endif
|
||
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
if (PrSequence != KiMasterSequence) {
|
||
|
||
if (KiMasterRid + 1 > KiMaximumRid) {
|
||
|
||
RidRecycled = TRUE;
|
||
|
||
} else {
|
||
|
||
KiMasterRid += 1;
|
||
ProcessRegion->RegionId = KiMasterRid;
|
||
ProcessRegion->SequenceNumber = KiMasterSequence;
|
||
}
|
||
|
||
}
|
||
|
||
if ((RidRecycled == FALSE) && (SeSequence != KiMasterSequence)) {
|
||
|
||
if (KiMasterRid + 1 > KiMaximumRid) {
|
||
|
||
RidRecycled = TRUE;
|
||
|
||
} else {
|
||
|
||
KiMasterRid += 1;
|
||
SessionRegion->RegionId = KiMasterRid;
|
||
SessionRegion->SequenceNumber = KiMasterSequence;
|
||
}
|
||
}
|
||
|
||
if (RidRecycled == FALSE) {
|
||
|
||
goto not_recycled;
|
||
|
||
}
|
||
|
||
//
|
||
// The region ID must be recycled.
|
||
//
|
||
|
||
KiMasterRid = START_PROCESS_RID;
|
||
|
||
//
|
||
// Since KiMasterSequence is 64-bits wide, it will
|
||
// not be recycled in your life time.
|
||
//
|
||
|
||
if (KiMasterSequence + 1 > MAXIMUM_SEQUENCE) {
|
||
|
||
KiMasterSequence = START_SEQUENCE;
|
||
|
||
} else {
|
||
|
||
KiMasterSequence += 1;
|
||
}
|
||
|
||
//
|
||
// Update the new process's ProcessRid and ProcessSequence.
|
||
//
|
||
|
||
ProcessRegion->RegionId = KiMasterRid;
|
||
ProcessRegion->SequenceNumber = KiMasterSequence;
|
||
|
||
KiSetRegionRegister(MM_LOWEST_USER_ADDRESS,
|
||
KiMakeValidRegionRegister(ProcessRegion->RegionId, PAGE_SHIFT));
|
||
|
||
KiMasterRid += 1;
|
||
|
||
SessionRegion->RegionId = KiMasterRid;
|
||
SessionRegion->SequenceNumber = KiMasterSequence;
|
||
|
||
KiSetRegionRegister((PVOID)SADDRESS_BASE,
|
||
KiMakeValidRegionRegister(SessionRegion->RegionId, PAGE_SHIFT));
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
RegionFlush:
|
||
|
||
//
|
||
// Broadcast Region Id sync.
|
||
//
|
||
|
||
TargetProcessors = KeActiveProcessors;
|
||
TargetProcessors &= PCR->NotMember;
|
||
|
||
if (TargetProcessors != 0) {
|
||
KiIpiSendPacket(TargetProcessors,
|
||
KiSyncNewRegionIdTarget,
|
||
(PVOID)TRUE,
|
||
NULL,
|
||
NULL);
|
||
}
|
||
|
||
#endif
|
||
|
||
KeFlushCurrentTb();
|
||
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
//
|
||
// Wait until all target processors have finished.
|
||
//
|
||
|
||
if (TargetProcessors != 0) {
|
||
KiIpiStallOnPacketTargets(TargetProcessors);
|
||
}
|
||
|
||
#endif
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
VOID
|
||
KeEnableSessionSharing(
|
||
IN PREGION_MAP_INFO SessionMapInfo,
|
||
IN PFN_NUMBER SessionParentPage
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine initializes a session for use. This includes :
|
||
|
||
1. Allocating a new region ID for the session.
|
||
2. Updating the current region register with this new RID.
|
||
3. Updating the SessionMapInfo fields so context switches will work.
|
||
4. Updating SessionParentBase fields so context switches will work.
|
||
|
||
Upon return from this routine, the session will be available for
|
||
sharing by the current and other processes.
|
||
|
||
Arguments:
|
||
|
||
SessionMapInfo - Supplies a session map info to be shared.
|
||
|
||
SessionParentPage - Supplies the top level parent page mapping the
|
||
argument session space.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Environment:
|
||
|
||
Kernel mode.
|
||
|
||
--*/
|
||
{
|
||
ULONG i;
|
||
KAFFINITY TargetProcessors;
|
||
PKPROCESS Process;
|
||
PKTHREAD Thread;
|
||
KIRQL OldIrql;
|
||
|
||
Thread = KeGetCurrentThread();
|
||
Process = Thread->ApcState.Process;
|
||
|
||
#if defined(NT_UP)
|
||
|
||
OldIrql = KeRaiseIrqlToSynchLevel();
|
||
|
||
#else
|
||
|
||
KiLockContextSwap(&OldIrql);
|
||
|
||
#endif
|
||
|
||
INITIALIZE_DIRECTORY_TABLE_BASE (&Process->SessionParentBase,
|
||
SessionParentPage);
|
||
|
||
//
|
||
// Invalidate the ForwardProgressTb buffer.
|
||
//
|
||
|
||
for (i = 0; i < MAXIMUM_FWP_BUFFER_ENTRY; i += 1) {
|
||
|
||
PCR->ForwardProgressBuffer[(i*2)+1] = 0;
|
||
|
||
}
|
||
|
||
if (KiMasterRid + 1 > KiMaximumRid) {
|
||
|
||
//
|
||
// The region ID must be recycled.
|
||
//
|
||
|
||
KiMasterRid = START_PROCESS_RID;
|
||
|
||
//
|
||
// Since KiMasterSequence is 64-bits wide, it will
|
||
// not be recycled in your life time.
|
||
//
|
||
|
||
if (KiMasterSequence + 1 > MAXIMUM_SEQUENCE) {
|
||
|
||
KiMasterSequence = START_SEQUENCE;
|
||
|
||
} else {
|
||
|
||
KiMasterSequence += 1;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Update the newly created session's RegionId and SequenceNumber.
|
||
//
|
||
|
||
KiMasterRid += 1;
|
||
|
||
Process->SessionMapInfo = SessionMapInfo;
|
||
|
||
SessionMapInfo->RegionId = KiMasterRid;
|
||
SessionMapInfo->SequenceNumber = KiMasterSequence;
|
||
|
||
KiSetRegionRegister((PVOID)SADDRESS_BASE,
|
||
KiMakeValidRegionRegister(SessionMapInfo->RegionId,
|
||
PAGE_SHIFT));
|
||
//
|
||
// Note that all processors must be notified because this thread could
|
||
// context switch onto another processor. If that processor was already
|
||
// running a thread from this same process, no region register update
|
||
// would occur otherwise.
|
||
//
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
//
|
||
// Broadcast Region Id sync.
|
||
//
|
||
|
||
TargetProcessors = KeActiveProcessors;
|
||
TargetProcessors &= PCR->NotMember;
|
||
|
||
if (TargetProcessors != 0) {
|
||
KiIpiSendPacket(TargetProcessors,
|
||
KiSyncNewRegionIdTarget,
|
||
(PVOID)TRUE,
|
||
NULL,
|
||
NULL);
|
||
}
|
||
|
||
#endif
|
||
|
||
KeFlushCurrentTb();
|
||
|
||
KeFillFixedEntryTb((PHARDWARE_PTE)&Process->SessionParentBase,
|
||
(PVOID)PDE_STBASE,
|
||
PAGE_SHIFT,
|
||
DTR_STBASE_INDEX);
|
||
|
||
#if defined(NT_UP)
|
||
|
||
KeLowerIrql(OldIrql);
|
||
|
||
#else
|
||
|
||
//
|
||
// Wait until all target processors have finished.
|
||
//
|
||
|
||
if (TargetProcessors != 0) {
|
||
KiIpiStallOnPacketTargets(TargetProcessors);
|
||
}
|
||
|
||
KiUnlockContextSwap(OldIrql);
|
||
|
||
#endif
|
||
}
|
||
|
||
VOID
|
||
KeAttachSessionSpace(
|
||
PREGION_MAP_INFO SessionMapInfo,
|
||
IN PFN_NUMBER SessionParentPage
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine attaches the current process to the specified session.
|
||
|
||
This includes:
|
||
|
||
1. Updating the current region register with the target RID.
|
||
2. Updating the SessionMapInfo fields so context switches will work.
|
||
3. Updating SessionParentBase fields so context switches will work.
|
||
|
||
Arguments:
|
||
|
||
SessionMapInfo - Supplies the target session map info.
|
||
|
||
SessionParentPage - Supplies the top level parent page mapping the
|
||
argument session space.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Environment:
|
||
|
||
Kernel mode.
|
||
|
||
--*/
|
||
{
|
||
KIRQL OldIrql;
|
||
PKTHREAD Thread;
|
||
PKPROCESS Process;
|
||
|
||
Thread = KeGetCurrentThread();
|
||
Process = Thread->ApcState.Process;
|
||
|
||
#if defined(NT_UP)
|
||
|
||
OldIrql = KeRaiseIrqlToSynchLevel();
|
||
|
||
#else
|
||
|
||
KiLockContextSwap(&OldIrql);
|
||
|
||
#endif
|
||
|
||
ASSERT(SessionMapInfo != NULL);
|
||
|
||
//
|
||
// Attach to the specified session.
|
||
//
|
||
|
||
INITIALIZE_DIRECTORY_TABLE_BASE (&Process->SessionParentBase,
|
||
SessionParentPage);
|
||
|
||
Process->SessionMapInfo = SessionMapInfo;
|
||
|
||
//
|
||
// Note that all processors must be notified because this thread could
|
||
// context switch onto another processor. If that processor was already
|
||
// running a thread from this same process, no region register update
|
||
// would occur. Hence KiRegionFlushRequired is set under ContextSwap lock
|
||
// protection to signify this to KiSyncNewRegionId.
|
||
//
|
||
|
||
ASSERT (KiRegionFlushRequired == 0);
|
||
KiRegionFlushRequired = 1;
|
||
|
||
KiSyncNewRegionId(&Process->ProcessRegion, SessionMapInfo);
|
||
|
||
KiFlushFixedDataTb(TRUE, PDE_STBASE);
|
||
|
||
KeFillFixedEntryTb((PHARDWARE_PTE)&Process->SessionParentBase,
|
||
(PVOID)PDE_STBASE,
|
||
PAGE_SHIFT,
|
||
DTR_STBASE_INDEX);
|
||
|
||
#if defined(NT_UP)
|
||
|
||
KeLowerIrql(OldIrql);
|
||
|
||
#else
|
||
|
||
KiUnlockContextSwap(OldIrql);
|
||
|
||
#endif
|
||
|
||
}
|
||
|
||
VOID
|
||
KiSyncSessionTarget(
|
||
IN PULONG SignalDone,
|
||
IN PKPROCESS Process,
|
||
IN PVOID Parameter1,
|
||
IN PVOID Parameter2
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This is the target function for synchronizing the new session
|
||
region ID. This routine is called when the session space is removed
|
||
and all the processors need to be notified.
|
||
|
||
Arguments:
|
||
|
||
SignalDone - Supplies a pointer to a variable that is cleared when the
|
||
requested operation has been performed.
|
||
|
||
Process - Supplies a KPROCESS pointer which needs to be synchronized.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Environment:
|
||
|
||
Kernel mode.
|
||
|
||
--*/
|
||
{
|
||
#if !defined(NT_UP)
|
||
|
||
ULONG NewRid;
|
||
|
||
//
|
||
// Check to see if the current process is the process that needs to be
|
||
// synchronized.
|
||
//
|
||
|
||
if (Process == (PKPROCESS)PCR->Pcb) {
|
||
|
||
KiAcquireSpinLock(&KiMasterRidLock);
|
||
|
||
//
|
||
// Disable the session region.
|
||
//
|
||
|
||
KiSetRegionRegister((PVOID)SADDRESS_BASE,
|
||
KiMakeValidRegionRegister(Process->SessionMapInfo->RegionId, PAGE_SHIFT));
|
||
|
||
KiFlushFixedDataTb(TRUE, (PVOID)PDE_STBASE);
|
||
|
||
KeFillFixedEntryTb((PHARDWARE_PTE)&Process->SessionParentBase,
|
||
(PVOID)PDE_STBASE,
|
||
PAGE_SHIFT,
|
||
DTR_STBASE_INDEX);
|
||
|
||
KiReleaseSpinLock(&KiMasterRidLock);
|
||
|
||
}
|
||
|
||
KiIpiSignalPacketDone(SignalDone);
|
||
|
||
#endif
|
||
return;
|
||
}
|
||
|
||
|
||
VOID
|
||
KeDetachSessionSpace(
|
||
IN PREGION_MAP_INFO NullSessionMapInfo,
|
||
IN PFN_NUMBER NullSessionPage
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine detaches the current process from the current session
|
||
space.
|
||
|
||
This includes:
|
||
|
||
1. Updating the current region register.
|
||
2. Updating the SessionMapInfo fields so context switches will work.
|
||
3. Updating SessionParentBase fields so context switches will work.
|
||
|
||
Arguments:
|
||
|
||
SessionMapInfo - Supplies a new session map information to use (the
|
||
existing session map info is discarded). This is usually
|
||
a NULL entry.
|
||
|
||
NullSessionPage - Supplies the new top level parent page to use.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Environment:
|
||
|
||
Kernel mode.
|
||
|
||
--*/
|
||
{
|
||
KIRQL OldIrql;
|
||
PKTHREAD Thread;
|
||
PKPROCESS Process;
|
||
#if !defined(NT_UP)
|
||
KAFFINITY TargetProcessors;
|
||
#endif
|
||
|
||
//
|
||
// Raise IRQL to DISPATCH_LEVEL and lock the dispatcher database.
|
||
//
|
||
|
||
Thread = KeGetCurrentThread();
|
||
Process = Thread->ApcState.Process;
|
||
|
||
#if defined(NT_UP)
|
||
|
||
OldIrql = KeRaiseIrqlToSynchLevel();
|
||
|
||
#else
|
||
|
||
KiLockContextSwap(&OldIrql);
|
||
|
||
#endif
|
||
|
||
INITIALIZE_DIRECTORY_TABLE_BASE (&Process->SessionParentBase,
|
||
NullSessionPage);
|
||
|
||
Process->SessionMapInfo = NullSessionMapInfo;
|
||
|
||
#if !defined(NT_UP)
|
||
|
||
//
|
||
// Broadcast the region ID sync.
|
||
//
|
||
|
||
TargetProcessors = KeActiveProcessors;
|
||
TargetProcessors &= PCR->NotMember;
|
||
|
||
if (TargetProcessors != 0) {
|
||
KiIpiSendPacket(TargetProcessors,
|
||
KiSyncSessionTarget,
|
||
Process,
|
||
NULL,
|
||
NULL);
|
||
}
|
||
|
||
#endif
|
||
|
||
KiSetRegionRegister((PVOID)SADDRESS_BASE,
|
||
KiMakeValidRegionRegister(NullSessionMapInfo->RegionId, PAGE_SHIFT));
|
||
|
||
KiFlushFixedDataTb(TRUE, PDE_STBASE);
|
||
|
||
KeFillFixedEntryTb((PHARDWARE_PTE)&Process->SessionParentBase,
|
||
(PVOID)PDE_STBASE,
|
||
PAGE_SHIFT,
|
||
DTR_STBASE_INDEX);
|
||
|
||
#if defined(NT_UP)
|
||
|
||
KeLowerIrql(OldIrql);
|
||
|
||
#else
|
||
|
||
//
|
||
// Wait until all target processors have finished.
|
||
//
|
||
|
||
if (TargetProcessors != 0) {
|
||
KiIpiStallOnPacketTargets(TargetProcessors);
|
||
}
|
||
|
||
KiUnlockContextSwap(OldIrql);
|
||
|
||
#endif
|
||
|
||
}
|
||
|
||
VOID
|
||
KeAddSessionSpace(
|
||
IN PKPROCESS Process,
|
||
IN PREGION_MAP_INFO SessionMapInfo,
|
||
IN PFN_NUMBER SessionParentPage
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Add the session map info to the KPROCESS of the new process.
|
||
|
||
This includes:
|
||
|
||
1. Updating the SessionMapInfo fields so context switches will work.
|
||
2. Updating SessionParentBase fields so context switches will work.
|
||
|
||
Note the dispatcher lock is not needed since the process can't run yet.
|
||
|
||
Arguments:
|
||
|
||
Process - Supplies a pointer to the process being created.
|
||
|
||
SessionMapInfo - Supplies a pointer to the SessionMapInfo.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Environment:
|
||
|
||
Kernel mode, APCs disabled.
|
||
|
||
--*/
|
||
{
|
||
Process->SessionMapInfo = SessionMapInfo;
|
||
|
||
INITIALIZE_DIRECTORY_TABLE_BASE (&Process->SessionParentBase,
|
||
SessionParentPage);
|
||
}
|
||
|
||
VOID
|
||
KiAttachRegion(
|
||
IN PKPROCESS Process
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Attaches the regions of the specified process
|
||
|
||
Arguments:
|
||
|
||
Process - Supplies a pointer to the process
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Environment:
|
||
|
||
Kernel mode, KiContextSwapLock is held.
|
||
|
||
--*/
|
||
{
|
||
PREGION_MAP_INFO ProcessRegion;
|
||
PREGION_MAP_INFO MappedSession;
|
||
|
||
ProcessRegion = &Process->ProcessRegion;
|
||
MappedSession = Process->SessionMapInfo;
|
||
|
||
//
|
||
// attach the target user space
|
||
//
|
||
|
||
KiSetRegionRegister(MM_LOWEST_USER_ADDRESS,
|
||
KiMakeValidRegionRegister(ProcessRegion->RegionId, PAGE_SHIFT));
|
||
|
||
//
|
||
// attach the target session space
|
||
//
|
||
|
||
KiSetRegionRegister((PVOID)SADDRESS_BASE,
|
||
KiMakeValidRegionRegister(MappedSession->RegionId, PAGE_SHIFT));
|
||
}
|
||
|
||
VOID
|
||
KiDetachRegion(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Restores the origial regions
|
||
|
||
Arguments:
|
||
|
||
VOID
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
Environment:
|
||
|
||
Kernel mode, KiContextSwapLock is held.
|
||
|
||
--*/
|
||
{
|
||
PKPROCESS Process;
|
||
PREGION_MAP_INFO ProcessRegion;
|
||
PREGION_MAP_INFO MappedSession;
|
||
|
||
//
|
||
// use KPROCESS from PCR
|
||
//
|
||
|
||
Process = (PKPROCESS)PCR->Pcb;
|
||
|
||
ProcessRegion = &Process->ProcessRegion;
|
||
MappedSession = Process->SessionMapInfo;
|
||
|
||
//
|
||
// attach the original user space
|
||
//
|
||
|
||
KiSetRegionRegister(MM_LOWEST_USER_ADDRESS,
|
||
KiMakeValidRegionRegister(ProcessRegion->RegionId, PAGE_SHIFT));
|
||
|
||
//
|
||
// attach the original session space
|
||
//
|
||
|
||
KiSetRegionRegister((PVOID)SADDRESS_BASE,
|
||
KiMakeValidRegionRegister(MappedSession->RegionId, PAGE_SHIFT));
|
||
|
||
}
|