mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
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:
parent
23475fc1f9
commit
43bfb5dd4e
4 changed files with 79 additions and 30 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue