Hi!
I have changed the memory manager to allow mapping of sections from \Device\PhysicalMemory which are outside of RAM - this gets NVIDIA OpenGL working. I hope my changes are correct (according to Hartmuts suggestions in this mail: http://reactos.com:8080/archives/public/ros-kernel/2004-August/004444.html)
I changed MmProbeAndLockPages to set MDL_IO_SPACE in the MdlFlags of the Mdl if one of the Pfns described in the MDL is outside of the RAM (>= MmPageArraySize) which is then used in MmMapLockedPagesSpecifyCache to decide wether to call MmCreateVirtualMapping or MmCreateVirtualMappingUnsafe (in order to prevent bugchecks in mm/freelist.c when Pfns are checked against MmPageArraySize)
- blight
Index: include/internal/mm.h =================================================================== --- include/internal/mm.h (revision 13428) +++ include/internal/mm.h (working copy) @@ -626,6 +626,7 @@ VOID MmSetLRULastPage(PFN_TYPE Page);
VOID MmLockPage(PFN_TYPE Page); +VOID MmLockPageUnsafe(PFN_TYPE Page);
VOID MmUnlockPage(PFN_TYPE Page);
@@ -710,6 +711,7 @@ VOID MmDereferencePage(PFN_TYPE Page);
VOID MmReferencePage(PFN_TYPE Page); +VOID MmReferencePageUnsafe(PFN_TYPE Page);
BOOLEAN MmIsAccessedAndResetAccessPage(struct _EPROCESS* Process, PVOID Address);
Index: mm/section.c =================================================================== --- mm/section.c (revision 13428) +++ mm/section.c (working copy) @@ -721,6 +721,9 @@
MmSharePageEntrySectionSegment(Segment, Offset);
+ /* FIXME: Should we call MmCreateVirtualMappingUnsafe if + * (Section->AllocationAttributes & SEC_PHYSICALMEMORY) is true? + */ Status = MmCreateVirtualMapping(MemoryArea->Process, Address, Attributes, @@ -823,14 +826,14 @@ * Just map the desired physical page */ Page = (Offset + MemoryArea->Data.SectionData.ViewOffset) >> PAGE_SHIFT; - Status = MmCreateVirtualMapping(AddressSpace->Process, - Address, - Region->Protect, - &Page, - 1); + Status = MmCreateVirtualMappingUnsafe(AddressSpace->Process, + Address, + Region->Protect, + &Page, + 1); if (!NT_SUCCESS(Status)) { - DPRINT("MmCreateVirtualMapping failed, not out of memory\n"); + DPRINT("MmCreateVirtualMappingUnsafe failed, not out of memory\n"); KEBUGCHECK(0); return(Status); } @@ -840,7 +843,7 @@ */ if (Locked) { - MmLockPage(Page); + MmLockPageUnsafe(Page); }
/* Index: mm/mdl.c =================================================================== --- mm/mdl.c (revision 13428) +++ mm/mdl.c (working copy) @@ -29,7 +29,7 @@ /* 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_PARTIAL mdl has been built by IoBuildPartialMdl MDL_MAPPING_CAN_FAIL in case of an error, MmMapLockedPages will return NULL instead of to bugcheck @@ -300,7 +300,7 @@ { 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; }
@@ -374,8 +374,8 @@ ASSERT(NrPages <= (Mdl->Size - sizeof(MDL))/sizeof(PFN_TYPE));
- if (Mdl->StartVa >= (PVOID)KERNEL_BASE && - MmGetPfnForProcess(NULL, Mdl->StartVa) > MmPageArraySize) + if (Mdl->StartVa >= (PVOID)KERNEL_BASE && + MmGetPfnForProcess(NULL, Mdl->StartVa) >= MmPageArraySize) { /* phys addr is not phys memory so this must be io memory */
@@ -391,13 +391,13 @@
if (Mdl->StartVa >= (PVOID)KERNEL_BASE) { - //FIXME: why isn't AccessMode used? + /* FIXME: why isn't AccessMode used? */ Mode = KernelMode; Mdl->Process = NULL; } else { - //FIXME: why isn't AccessMode used? + /* FIXME: why isn't AccessMode used? */ Mode = UserMode; Mdl->Process = CurrentProcess; } @@ -455,7 +455,10 @@ } Page = MmGetPfnForProcess(NULL, Address); MdlPages[i] = Page; - MmReferencePage(Page); + if (Page >= MmPageArraySize) + Mdl->MdlFlags |= MDL_IO_SPACE; + else + MmReferencePage(Page); }
MmUnlockAddressSpace(&CurrentProcess->AddressSpace); @@ -848,11 +851,18 @@ Protect |= PAGE_NOCACHE; else if (CacheType == MmWriteCombined) DPRINT("CacheType MmWriteCombined not supported!\n"); - Status = MmCreateVirtualMapping(CurrentProcess, - Base, - Protect, - MdlPages, - PageCount); + if (Mdl->MdlFlags & MDL_IO_SPACE) + Status = MmCreateVirtualMappingUnsafe(CurrentProcess, + Base, + Protect, + MdlPages, + PageCount); + else + Status = MmCreateVirtualMapping(CurrentProcess, + Base, + Protect, + MdlPages, + PageCount); if (!NT_SUCCESS(Status)) { DbgPrint("Unable to create virtual mapping\n"); Index: mm/freelist.c =================================================================== --- mm/freelist.c (revision 13428) +++ mm/freelist.c (working copy) @@ -612,15 +612,15 @@ }
VOID -MmReferencePage(PFN_TYPE Pfn) +MmReferencePageUnsafe(PFN_TYPE Pfn) { KIRQL oldIrql;
- DPRINT("MmReferencePage(PysicalAddress %x)\n", Pfn << PAGE_SHIFT); + DPRINT("MmReferencePageUnsafe(PysicalAddress %x)\n", Pfn << PAGE_SHIFT);
if (Pfn == 0 || Pfn >= MmPageArraySize) { - KEBUGCHECK(0); + return; }
KeAcquireSpinLock(&PageListLock, &oldIrql); @@ -635,6 +635,19 @@ 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 MmGetReferenceCountPage(PFN_TYPE Pfn) { @@ -781,15 +794,15 @@ }
VOID -MmLockPage(PFN_TYPE Pfn) +MmLockPageUnsafe(PFN_TYPE Pfn) { KIRQL oldIrql;
- DPRINT("MmLockPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT); + DPRINT("MmLockPageUnsafe(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT);
if (Pfn == 0 || Pfn >= MmPageArraySize) { - KEBUGCHECK(0); + return; }
KeAcquireSpinLock(&PageListLock, &oldIrql); @@ -805,6 +818,19 @@ }
VOID +MmLockPage(PFN_TYPE Pfn) +{ + DPRINT("MmLockPage(PhysicalAddress %x)\n", Pfn << PAGE_SHIFT); + + if (Pfn == 0 || Pfn >= MmPageArraySize) + { + KEBUGCHECK(0); + } + + MmLockPageUnsafe(Pfn); +} + +VOID MmUnlockPage(PFN_TYPE Pfn) { KIRQL oldIrql;