Allow mapping of MDLs which describe I/O memory (device memory) into usermode. I hope the changes are correct :-/

svn path=/trunk/; revision=14109
This commit is contained in:
Gregor Anich 2005-03-15 22:07:05 +00:00
parent 23475fc1f9
commit 43bfb5dd4e
4 changed files with 79 additions and 30 deletions

View file

@ -628,6 +628,7 @@ PFN_TYPE MmGetLRUFirstUserPage(VOID);
VOID MmSetLRULastPage(PFN_TYPE Page); VOID MmSetLRULastPage(PFN_TYPE Page);
VOID MmLockPage(PFN_TYPE Page); VOID MmLockPage(PFN_TYPE Page);
VOID MmLockPageUnsafe(PFN_TYPE Page);
VOID MmUnlockPage(PFN_TYPE Page); VOID MmUnlockPage(PFN_TYPE Page);
@ -712,6 +713,7 @@ LONG MmAllocPagesSpecifyRange(ULONG Consumer,
VOID MmDereferencePage(PFN_TYPE Page); VOID MmDereferencePage(PFN_TYPE Page);
VOID MmReferencePage(PFN_TYPE Page); VOID MmReferencePage(PFN_TYPE Page);
VOID MmReferencePageUnsafe(PFN_TYPE Page);
BOOLEAN MmIsAccessedAndResetAccessPage(struct _EPROCESS* Process, PVOID Address); BOOLEAN MmIsAccessedAndResetAccessPage(struct _EPROCESS* Process, PVOID Address);

View file

@ -623,15 +623,15 @@ MmGetSavedSwapEntryPage(PFN_TYPE Pfn)
} }
VOID VOID
MmReferencePage(PFN_TYPE Pfn) MmReferencePageUnsafe(PFN_TYPE Pfn)
{ {
KIRQL oldIrql; KIRQL oldIrql;
DPRINT("MmReferencePage(PysicalAddress %x)\n", Pfn << PAGE_SHIFT); DPRINT("MmReferencePageUnsafe(PysicalAddress %x)\n", Pfn << PAGE_SHIFT);
if (Pfn == 0 || Pfn >= MmPageArraySize) if (Pfn == 0 || Pfn >= MmPageArraySize)
{ {
KEBUGCHECK(0); return;
} }
KeAcquireSpinLock(&PageListLock, &oldIrql); KeAcquireSpinLock(&PageListLock, &oldIrql);
@ -646,6 +646,19 @@ MmReferencePage(PFN_TYPE Pfn)
KeReleaseSpinLock(&PageListLock, oldIrql); KeReleaseSpinLock(&PageListLock, oldIrql);
} }
VOID
MmReferencePage(PFN_TYPE Pfn)
{
DPRINT("MmReferencePage(PysicalAddress %x)\n", Pfn << PAGE_SHIFT);
if (Pfn == 0 || Pfn >= MmPageArraySize)
{
KEBUGCHECK(0);
}
MmReferencePageUnsafe(Pfn);
}
ULONG ULONG
MmGetReferenceCountPage(PFN_TYPE Pfn) MmGetReferenceCountPage(PFN_TYPE Pfn)
{ {
@ -792,15 +805,15 @@ MmGetLockCountPage(PFN_TYPE Pfn)
} }
VOID VOID
MmLockPage(PFN_TYPE Pfn) MmLockPageUnsafe(PFN_TYPE Pfn)
{ {
KIRQL oldIrql; KIRQL oldIrql;
DPRINT("MmLockPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT); DPRINT("MmLockPageUnsafe(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
if (Pfn == 0 || Pfn >= MmPageArraySize) if (Pfn == 0 || Pfn >= MmPageArraySize)
{ {
KEBUGCHECK(0); return;
} }
KeAcquireSpinLock(&PageListLock, &oldIrql); KeAcquireSpinLock(&PageListLock, &oldIrql);
@ -815,6 +828,19 @@ MmLockPage(PFN_TYPE Pfn)
KeReleaseSpinLock(&PageListLock, oldIrql); KeReleaseSpinLock(&PageListLock, oldIrql);
} }
VOID
MmLockPage(PFN_TYPE Pfn)
{
DPRINT("MmLockPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
if (Pfn == 0 || Pfn >= MmPageArraySize)
{
KEBUGCHECK(0);
}
MmLockPageUnsafe(Pfn);
}
VOID VOID
MmUnlockPage(PFN_TYPE Pfn) MmUnlockPage(PFN_TYPE Pfn)
{ {

View file

@ -29,7 +29,7 @@ extern ULONG MmPageArraySize;
/* /*
MDL Flags desc. MDL Flags desc.
MDL_PAGES_LOCKED MmProbelAndLockPages has been called for this mdl MDL_PAGES_LOCKED MmProbeAndLockPages has been called for this mdl
MDL_SOURCE_IS_NONPAGED_POOL mdl has been build by MmBuildMdlForNonPagedPool MDL_SOURCE_IS_NONPAGED_POOL mdl has been build by MmBuildMdlForNonPagedPool
MDL_PARTIAL mdl has been built by IoBuildPartialMdl MDL_PARTIAL mdl has been built by IoBuildPartialMdl
MDL_MAPPING_CAN_FAIL in case of an error, MmMapLockedPages will return NULL instead of to bugcheck MDL_MAPPING_CAN_FAIL in case of an error, MmMapLockedPages will return NULL instead of to bugcheck
@ -233,7 +233,7 @@ MmUnmapLockedPages(PVOID BaseAddress, PMDL Mdl)
/* Unmap all the pages. */ /* Unmap all the pages. */
for (i = 0; i < PageCount; i++) for (i = 0; i < PageCount; i++)
{ {
MmDeleteVirtualMapping(NULL, MmDeleteVirtualMapping(Mdl->Process,
(char*)BaseAddress + (i * PAGE_SIZE), (char*)BaseAddress + (i * PAGE_SIZE),
FALSE, FALSE,
NULL, NULL,
@ -300,7 +300,7 @@ MmBuildMdlFromPages(PMDL Mdl, PPFN_TYPE Pages)
{ {
memcpy(Mdl + 1, Pages, sizeof(PFN_TYPE) * (PAGE_ROUND_UP(Mdl->ByteOffset+Mdl->ByteCount)/PAGE_SIZE)); memcpy(Mdl + 1, Pages, sizeof(PFN_TYPE) * (PAGE_ROUND_UP(Mdl->ByteOffset+Mdl->ByteCount)/PAGE_SIZE));
//FIXME: this flag should be set by the caller perhaps? /* FIXME: this flag should be set by the caller perhaps? */
Mdl->MdlFlags |= MDL_IO_PAGE_READ; Mdl->MdlFlags |= MDL_IO_PAGE_READ;
} }
@ -375,8 +375,8 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
ASSERT(NrPages <= (Mdl->Size - sizeof(MDL))/sizeof(PFN_TYPE)); ASSERT(NrPages <= (Mdl->Size - sizeof(MDL))/sizeof(PFN_TYPE));
if (Mdl->StartVa >= (PVOID)KERNEL_BASE && if (Mdl->StartVa >= (PVOID)KERNEL_BASE &&
MmGetPfnForProcess(NULL, Mdl->StartVa) > MmPageArraySize) MmGetPfnForProcess(NULL, Mdl->StartVa) >= MmPageArraySize)
{ {
/* phys addr is not phys memory so this must be io memory */ /* phys addr is not phys memory so this must be io memory */
@ -392,14 +392,14 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
if (Mdl->StartVa >= (PVOID)KERNEL_BASE) if (Mdl->StartVa >= (PVOID)KERNEL_BASE)
{ {
//FIXME: why isn't AccessMode used? /* FIXME: why isn't AccessMode used? */
Mode = KernelMode; Mode = KernelMode;
Mdl->Process = NULL; Mdl->Process = NULL;
AddressSpace = MmGetKernelAddressSpace(); AddressSpace = MmGetKernelAddressSpace();
} }
else else
{ {
//FIXME: why isn't AccessMode used? /* FIXME: why isn't AccessMode used? */
Mode = UserMode; Mode = UserMode;
Mdl->Process = CurrentProcess; Mdl->Process = CurrentProcess;
AddressSpace = &CurrentProcess->AddressSpace; AddressSpace = &CurrentProcess->AddressSpace;
@ -430,8 +430,11 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
{ {
Page = MdlPages[j]; Page = MdlPages[j];
MmUnlockPage(Page); if (Page < MmPageArraySize)
MmDereferencePage(Page); {
MmUnlockPage(Page);
MmDereferencePage(Page);
}
} }
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
ExRaiseStatus(Status); ExRaiseStatus(Status);
@ -451,8 +454,11 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
{ {
Page = MdlPages[j]; Page = MdlPages[j];
MmUnlockPage(Page); if (Page < MmPageArraySize)
MmDereferencePage(Page); {
MmUnlockPage(Page);
MmDereferencePage(Page);
}
} }
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
ExRaiseStatus(Status); ExRaiseStatus(Status);
@ -460,7 +466,10 @@ VOID STDCALL MmProbeAndLockPages (PMDL Mdl,
} }
Page = MmGetPfnForProcess(NULL, Address); Page = MmGetPfnForProcess(NULL, Address);
MdlPages[i] = Page; MdlPages[i] = Page;
MmReferencePage(Page); if (Page >= MmPageArraySize)
Mdl->MdlFlags |= MDL_IO_SPACE;
else
MmReferencePage(Page);
} }
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
@ -843,6 +852,8 @@ MmMapLockedPagesSpecifyCache ( IN PMDL Mdl,
} }
KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql); KeReleaseSpinLock(&MiMdlMappingRegionLock, oldIrql);
Mdl->Process = NULL;
} }
/* Set the virtual mappings for the MDL pages. */ /* Set the virtual mappings for the MDL pages. */
@ -853,11 +864,18 @@ MmMapLockedPagesSpecifyCache ( IN PMDL Mdl,
Protect |= PAGE_NOCACHE; Protect |= PAGE_NOCACHE;
else if (CacheType == MmWriteCombined) else if (CacheType == MmWriteCombined)
DPRINT("CacheType MmWriteCombined not supported!\n"); DPRINT("CacheType MmWriteCombined not supported!\n");
Status = MmCreateVirtualMapping(CurrentProcess, if (Mdl->MdlFlags & MDL_IO_SPACE)
Base, Status = MmCreateVirtualMappingUnsafe(CurrentProcess,
Protect, Base,
MdlPages, Protect,
PageCount); MdlPages,
PageCount);
else
Status = MmCreateVirtualMapping(CurrentProcess,
Base,
Protect,
MdlPages,
PageCount);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DbgPrint("Unable to create virtual mapping\n"); DbgPrint("Unable to create virtual mapping\n");

View file

@ -727,6 +727,9 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
MmSharePageEntrySectionSegment(Segment, Offset); MmSharePageEntrySectionSegment(Segment, Offset);
/* FIXME: Should we call MmCreateVirtualMappingUnsafe if
* (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true?
*/
Status = MmCreateVirtualMapping(MemoryArea->Process, Status = MmCreateVirtualMapping(MemoryArea->Process,
Address, Address,
Attributes, Attributes,
@ -829,14 +832,14 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
* Just map the desired physical page * Just map the desired physical page
*/ */
Page = (Offset + MemoryArea->Data.SectionData.ViewOffset) >> PAGE_SHIFT; Page = (Offset + MemoryArea->Data.SectionData.ViewOffset) >> PAGE_SHIFT;
Status = MmCreateVirtualMapping(AddressSpace->Process, Status = MmCreateVirtualMappingUnsafe(AddressSpace->Process,
Address, Address,
Region->Protect, Region->Protect,
&Page, &Page,
1); 1);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT("MmCreateVirtualMapping failed, not out of memory\n"); DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n");
KEBUGCHECK(0); KEBUGCHECK(0);
return(Status); return(Status);
} }
@ -846,7 +849,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
*/ */
if (Locked) if (Locked)
{ {
MmLockPage(Page); MmLockPageUnsafe(Page);
} }
/* /*