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;