You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
929 lines
20 KiB
929 lines
20 KiB
/*++
|
|
|
|
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;
|
|
|
|
|
|
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;
|
|
|
|
//
|
|
// 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();
|
|
|
|
#else
|
|
UNREFERENCED_PARAMETER (SignalDone);
|
|
#endif
|
|
|
|
UNREFERENCED_PARAMETER (Parameter1);
|
|
UNREFERENCED_PARAMETER (Parameter2);
|
|
UNREFERENCED_PARAMETER (Parameter3);
|
|
|
|
return;
|
|
}
|
|
|
|
BOOLEAN
|
|
KiSyncNewRegionId(
|
|
IN PREGION_MAP_INFO ProcessRegion,
|
|
IN PREGION_MAP_INFO SessionRegion,
|
|
IN BOOLEAN RegionFlushRequired
|
|
)
|
|
/*++
|
|
|
|
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.
|
|
|
|
LockHeld - KiRegionSwapLock is held by the caller
|
|
|
|
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 and KeAttachSessionSpace.
|
|
|
|
Environment:
|
|
|
|
Kernel mode.
|
|
|
|
Called at SYNCH_LEVEL
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG i;
|
|
LOGICAL RidRecycled;
|
|
#if !defined(NT_UP)
|
|
KAFFINITY TargetProcessors;
|
|
KIRQL OldIrql;
|
|
#endif
|
|
ULONGLONG PrSequence;
|
|
ULONGLONG SeSequence;
|
|
|
|
|
|
RidRecycled = FALSE;
|
|
|
|
ASSERT (KeGetCurrentIrql () == SYNCH_LEVEL);
|
|
|
|
//
|
|
// 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;
|
|
|
|
}
|
|
|
|
not_recycled:
|
|
|
|
#if !defined(NT_UP)
|
|
KeRaiseIrql(HIGH_LEVEL, &OldIrql);
|
|
#endif
|
|
|
|
PrSequence = ProcessRegion->SequenceNumber;
|
|
SeSequence = SessionRegion->SequenceNumber;
|
|
|
|
if ((PrSequence == KiMasterSequence) && (SeSequence == KiMasterSequence)) {
|
|
|
|
|
|
KiSetRegionRegister(MM_LOWEST_USER_ADDRESS,
|
|
KiMakeValidRegionRegister(ProcessRegion->RegionId,
|
|
PAGE_SHIFT));
|
|
|
|
KiSetRegionRegister((PVOID)SADDRESS_BASE,
|
|
KiMakeValidRegionRegister(SessionRegion->RegionId,
|
|
PAGE_SHIFT));
|
|
#if !defined(NT_UP)
|
|
KeLowerIrql(OldIrql);
|
|
#endif
|
|
|
|
#if !defined(NT_UP)
|
|
if (RegionFlushRequired) {
|
|
|
|
KiAcquireSpinLock (&KiRegionSwapLock);
|
|
goto RegionFlush;
|
|
}
|
|
#endif
|
|
UNREFERENCED_PARAMETER (RegionFlushRequired);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
#if !defined(NT_UP)
|
|
KeLowerIrql(OldIrql);
|
|
|
|
KiAcquireSpinLock (&KiRegionSwapLock);
|
|
#endif
|
|
|
|
PrSequence = ProcessRegion->SequenceNumber;
|
|
SeSequence = SessionRegion->SequenceNumber;
|
|
|
|
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) {
|
|
|
|
KiReleaseSpinLock(&KiRegionSwapLock);
|
|
|
|
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
|
|
|
|
#if !defined(NT_UP)
|
|
KiReleaseSpinLock (&KiRegionSwapLock);
|
|
#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;
|
|
#if !defined(NT_UP)
|
|
KAFFINITY TargetProcessors;
|
|
#endif
|
|
PKPROCESS Process;
|
|
PKTHREAD Thread;
|
|
KIRQL OldIrql;
|
|
|
|
Thread = KeGetCurrentThread();
|
|
Process = Thread->ApcState.Process;
|
|
|
|
OldIrql = KeRaiseIrqlToSynchLevel();
|
|
|
|
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 !defined(NT_UP)
|
|
|
|
KiAcquireSpinLock(&KiRegionSwapLock);
|
|
|
|
#endif
|
|
|
|
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)
|
|
|
|
//
|
|
// Wait until all target processors have finished.
|
|
//
|
|
|
|
if (TargetProcessors != 0) {
|
|
KiIpiStallOnPacketTargets(TargetProcessors);
|
|
}
|
|
|
|
KiReleaseSpinLock(&KiRegionSwapLock);
|
|
|
|
#endif
|
|
|
|
KeLowerIrql(OldIrql);
|
|
|
|
}
|
|
|
|
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;
|
|
|
|
|
|
OldIrql = KeRaiseIrqlToSynchLevel();
|
|
|
|
|
|
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.
|
|
//
|
|
|
|
KiSyncNewRegionId(&Process->ProcessRegion, SessionMapInfo, TRUE);
|
|
|
|
KiFlushFixedDataTb(TRUE, PDE_STBASE);
|
|
|
|
KeFillFixedEntryTb((PHARDWARE_PTE)&Process->SessionParentBase,
|
|
(PVOID)PDE_STBASE,
|
|
PAGE_SHIFT,
|
|
DTR_STBASE_INDEX);
|
|
|
|
|
|
KeLowerIrql(OldIrql);
|
|
|
|
}
|
|
|
|
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.
|
|
|
|
--*/
|
|
{
|
|
UNREFERENCED_PARAMETER (Parameter1);
|
|
UNREFERENCED_PARAMETER (Parameter2);
|
|
|
|
#if !defined(NT_UP)
|
|
|
|
//
|
|
// 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);
|
|
|
|
#else
|
|
UNREFERENCED_PARAMETER (SignalDone);
|
|
UNREFERENCED_PARAMETER (Process);
|
|
#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;
|
|
|
|
OldIrql = KeRaiseIrqlToSynchLevel();
|
|
|
|
INITIALIZE_DIRECTORY_TABLE_BASE (&Process->SessionParentBase,
|
|
NullSessionPage);
|
|
|
|
Process->SessionMapInfo = NullSessionMapInfo;
|
|
|
|
#if !defined(NT_UP)
|
|
|
|
KiAcquireSpinLock(&KiRegionSwapLock);
|
|
|
|
//
|
|
// 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)
|
|
|
|
//
|
|
// Wait until all target processors have finished.
|
|
//
|
|
|
|
if (TargetProcessors != 0) {
|
|
KiIpiStallOnPacketTargets(TargetProcessors);
|
|
}
|
|
|
|
KiReleaseSpinLock(&KiRegionSwapLock);
|
|
|
|
#endif
|
|
|
|
KeLowerIrql(OldIrql);
|
|
}
|
|
|
|
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, KiRegionSwapLock 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, KiRegionSwapLock 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));
|
|
|
|
}
|