- Checked in MmMapLockedPages patch from Anich Gregor.

svn path=/trunk/; revision=8689
This commit is contained in:
David Welch 2004-03-13 19:14:16 +00:00
parent 35f3e5b524
commit 988f1d5968
2 changed files with 121 additions and 37 deletions

View file

@ -1,4 +1,4 @@
/* $Id: mdl.c,v 1.59 2004/03/06 22:21:20 dwelch Exp $
/* $Id: mdl.c,v 1.60 2004/03/13 19:14:16 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel
@ -152,42 +152,78 @@ MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode)
KIRQL oldIrql;
ULONG RegionSize;
ULONG StartingOffset;
PEPROCESS CurrentProcess, OldProcess;
DPRINT("MmMapLockedPages(Mdl %x, AccessMode %x)\n", Mdl, AccessMode);
if (Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL)
if ((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) && AccessMode != UserMode)
{
return(Mdl->MappedSystemVa);
}
if (AccessMode == UserMode)
{
DPRINT1("MDL mapping to user-mode not yet handled.\n");
KEBUGCHECK(0);
}
/* Calculate the number of pages required. */
RegionSize = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE;
/* Allocate that number of pages from the mdl mapping region. */
KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql);
if (AccessMode == UserMode)
{
MEMORY_AREA *Result;
LARGE_INTEGER BoundaryAddressMultiple;
NTSTATUS Status;
StartingOffset = RtlFindClearBitsAndSet(&MiMdlMappingRegionAllocMap, RegionSize, MiMdlMappingRegionHint);
BoundaryAddressMultiple.QuadPart = 0;
Base = NULL;
if (StartingOffset == 0xffffffff)
{
DPRINT1("Out of MDL mapping space\n");
KEBUGCHECK(0);
}
CurrentProcess = OldProcess = PsGetCurrentProcess();
if (Mdl->Process != CurrentProcess)
{
KeAttachProcess(Mdl->Process);
CurrentProcess = Mdl->Process;
}
Base = (char*)MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE;
MmLockAddressSpace(&CurrentProcess->AddressSpace);
Status = MmCreateMemoryArea(CurrentProcess,
&CurrentProcess->AddressSpace,
MEMORY_AREA_MDL_MAPPING,
&Base,
RegionSize * PAGE_SIZE,
0, /* PAGE_READWRITE? */
&Result,
FALSE,
FALSE,
BoundaryAddressMultiple);
MmUnlockAddressSpace(&CurrentProcess->AddressSpace);
if (!NT_SUCCESS(Status))
{
KEBUGCHECK(0);
/* FIXME: handle this? */
}
}
else
{
CurrentProcess = OldProcess = NULL;
/* Allocate that number of pages from the mdl mapping region. */
KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql);
StartingOffset = RtlFindClearBitsAndSet(&MiMdlMappingRegionAllocMap, RegionSize, MiMdlMappingRegionHint);
if (StartingOffset == 0xffffffff)
{
DPRINT1("Out of MDL mapping space\n");
KEBUGCHECK(0);
}
Base = (char*)MiMdlMappingRegionBase + StartingOffset * PAGE_SIZE;
if (MiMdlMappingRegionHint == StartingOffset)
{
MiMdlMappingRegionHint +=RegionSize;
}
KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql);
}
if (MiMdlMappingRegionHint == StartingOffset)
{
MiMdlMappingRegionHint +=RegionSize;
}
KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql);
/* Set the virtual mappings for the MDL pages. */
MdlPages = (PULONG)(Mdl + 1);
@ -198,7 +234,7 @@ MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode)
PHYSICAL_ADDRESS dummyJunkNeeded;
dummyJunkNeeded.QuadPart = MdlPages[i];
#endif
Status = MmCreateVirtualMapping(NULL,
Status = MmCreateVirtualMapping(CurrentProcess,
(PVOID)((ULONG)Base+(i*PAGE_SIZE)),
PAGE_READWRITE,
#if defined(__GNUC__)
@ -214,6 +250,11 @@ MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode)
}
}
if (AccessMode == UserMode && CurrentProcess != OldProcess)
{
KeDetachProcess();
}
/* Mark the MDL has having being mapped. */
Mdl->MdlFlags = Mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
Mdl->MappedSystemVa = (char*)Base + Mdl->ByteOffset;
@ -236,6 +277,7 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl)
ULONG i;
ULONG RegionSize;
ULONG Base;
PEPROCESS CurrentProcess, OldProcess;
DPRINT("MmUnmapLockedPages(BaseAddress %x, Mdl %x)\n", BaseAddress, Mdl);
@ -243,11 +285,26 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl)
* In this case, the MDL has the same system address as the base address
* so there is no need to free it
*/
if (Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL)
if ((Mdl->MdlFlags & MDL_SOURCE_IS_NONPAGED_POOL) &&
((ULONG_PTR)BaseAddress >= KERNEL_BASE))
{
return;
}
if ((ULONG_PTR)BaseAddress >= KERNEL_BASE)
{
CurrentProcess = OldProcess = NULL;
}
else
{
CurrentProcess = OldProcess = PsGetCurrentProcess();
if (Mdl->Process != CurrentProcess)
{
KeAttachProcess(Mdl->Process);
CurrentProcess = Mdl->Process;
}
}
/* Calculate the number of pages we mapped. */
RegionSize = PAGE_ROUND_UP(Mdl->ByteCount + Mdl->ByteOffset) / PAGE_SIZE;
#if defined(__GNUC__)
@ -270,15 +327,36 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl)
NULL);
}
KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql);
/* Deallocate all the pages used. */
Base = (ULONG)((char*)BaseAddress - (char*)MiMdlMappingRegionBase) / PAGE_SIZE;
if ((DWORD)BaseAddress >= KERNEL_BASE)
{
KeAcquireSpinLock(&MiMdlMappingRegionLock, &oldIrql);
/* Deallocate all the pages used. */
Base = (ULONG)((char*)BaseAddress - (char*)MiMdlMappingRegionBase) / PAGE_SIZE;
RtlClearBits(&MiMdlMappingRegionAllocMap, Base, RegionSize);
RtlClearBits(&MiMdlMappingRegionAllocMap, Base, RegionSize);
MiMdlMappingRegionHint = min (MiMdlMappingRegionHint, Base);
MiMdlMappingRegionHint = min (MiMdlMappingRegionHint, Base);
KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql);
KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql);
}
else
{
MEMORY_AREA *Marea;
Marea = MmOpenMemoryAreaByAddress( &CurrentProcess->AddressSpace, BaseAddress );
if (Marea == NULL)
{
DPRINT1( "Couldn't open memory area when unmapping user-space pages!\n" );
KEBUGCHECK(0);
}
MmFreeMemoryArea( &CurrentProcess->AddressSpace, Marea->BaseAddress, 0, NULL, NULL );
if (CurrentProcess != OldProcess)
{
KeDetachProcess();
}
}
/* Reset the MDL state. */
Mdl->MdlFlags = Mdl->MdlFlags & ~MDL_MAPPED_TO_SYSTEM_VA;

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: mm.c,v 1.68 2004/02/15 19:03:29 hbirr Exp $
/* $Id: mm.c,v 1.69 2004/03/13 19:14:15 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel
@ -35,6 +35,7 @@
#include <internal/ntoskrnl.h>
#include <internal/io.h>
#include <internal/ps.h>
#include <reactos/bugcodes.h>
#define NDEBUG
#include <internal/debug.h>
@ -78,6 +79,11 @@ NTSTATUS MmReleaseMemoryArea(PEPROCESS Process, PMEMORY_AREA Marea)
NULL,
NULL);
break;
case MEMORY_AREA_MDL_MAPPING:
KEBUGCHECK(PROCESS_HAS_LOCKED_PAGES);
break;
default:
KEBUGCHECK(0);
}