Fixed memory manager bugs

Removed page directory references from machine independant code
Implemented page table reference counting
Added vm test application

svn path=/trunk/; revision=1309
This commit is contained in:
David Welch 2000-08-20 17:02:10 +00:00
parent 7c29439d2b
commit 8434fc42db
23 changed files with 632 additions and 254 deletions

View file

@ -44,7 +44,7 @@ NET_DRIVERS = ndis tcpip tditest
KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS) $(NET_DRIVERS) KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS) $(NET_DRIVERS)
APPS = args hello shell test cat bench apc shm lpc thread event file gditest \ APPS = args hello shell test cat bench apc shm lpc thread event file gditest \
pteb consume dump_shared_data pteb consume dump_shared_data vmtest
# objdir # objdir

View file

@ -0,0 +1,42 @@
#
#
#
PATH_TO_TOP = ../..
OBJECTS = vmtest.o
PROGS = vmtest.exe
LIBS =
CLEAN_FILES = vmtest.o vmtest.exe
all: vmtest.exe
clean: $(CLEAN_FILES:%=%_clean)
$(CLEAN_FILES:%=%_clean): %_clean:
- $(RM) $*
.phony: clean $(CLEAN_FILES:%=%_clean)
floppy: $(PROGS:%=$(FLOPPY_DIR)/apps/%)
$(PROGS:%=$(FLOPPY_DIR)/apps/%): $(FLOPPY_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* $(FLOPPY_DIR)\apps\$*
else
$(CP) $* $(FLOPPY_DIR)/apps/$*
endif
dist: $(PROGS:%=../../$(DIST_DIR)/apps/%)
$(PROGS:%=../../$(DIST_DIR)/apps/%): ../../$(DIST_DIR)/apps/%: %
ifeq ($(DOSCLI),yes)
$(CP) $* ..\..\$(DIST_DIR)\apps\$*
else
$(CP) $* ../../$(DIST_DIR)/apps/$*
endif
vmtest.exe: $(OBJECTS)
$(CC) $(OBJECTS) -o vmtest.exe
BASE_CFLAGS = -I../../include
include ../../rules.mak

View file

@ -0,0 +1,53 @@
#include <stdio.h>
#include <windows.h>
int main()
{
PVOID Base;
PVOID Ret;
Base = VirtualAlloc(NULL,
1048576,
MEM_RESERVE,
PAGE_READWRITE);
if (Base == NULL)
{
printf("VirtualAlloc failed 1\n");
}
Ret = VirtualAlloc(Base + 4096,
4096,
MEM_COMMIT,
PAGE_READWRITE);
if (Ret == NULL)
{
printf("VirtualAlloc failed 2\n");
}
Ret = VirtualAlloc(Base + 12288,
4096,
MEM_COMMIT,
PAGE_READWRITE);
if (Ret == NULL)
{
printf("VirtualAlloc failed 3\n");
}
Ret = VirtualAlloc(Base + 20480,
4096,
MEM_COMMIT,
PAGE_READWRITE);
if (Ret == NULL)
{
printf("VirtualAlloc failed 4\n");
}
Ret = VirtualAlloc(Base + 4096,
28672,
MEM_RESERVE,
PAGE_READWRITE);
if (Ret == NULL)
{
printf("VirtualAlloc failed 5\n");
}
}

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.13 2000/08/18 22:27:04 dwelch Exp $ # $Id: makefile,v 1.14 2000/08/20 17:02:09 dwelch Exp $
# #
# #
PATH_TO_TOP = ../../.. PATH_TO_TOP = ../../..
@ -20,6 +20,7 @@ clean:
- $(RM) base.tmp - $(RM) base.tmp
- $(RM) temp.exp - $(RM) temp.exp
- $(RM) blue.sys - $(RM) blue.sys
- $(RM) blue.sys.unstripped
.phony: clean .phony: clean

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.15 2000/08/18 22:27:04 dwelch Exp $ # $Id: makefile,v 1.16 2000/08/20 17:02:10 dwelch Exp $
# #
# #
PATH_TO_TOP = ../../.. PATH_TO_TOP = ../../..
@ -20,7 +20,7 @@ clean:
- $(RM) base.tmp - $(RM) base.tmp
- $(RM) temp.exp - $(RM) temp.exp
- $(RM) $(TARGET).sys - $(RM) $(TARGET).sys
- $(RM) $(TARGET).nostrip.sys - $(RM) $(TARGET).sys.unstripped
.phony: clean .phony: clean

View file

@ -1,4 +1,4 @@
# $Id: makefile,v 1.11 2000/08/18 22:27:05 dwelch Exp $ # $Id: makefile,v 1.12 2000/08/20 17:02:10 dwelch Exp $
# #
# #
PATH_TO_TOP = ../../.. PATH_TO_TOP = ../../..
@ -20,6 +20,7 @@ clean:
- $(RM) base.tmp - $(RM) base.tmp
- $(RM) temp.exp - $(RM) temp.exp
- $(RM) $(TARGET).sys - $(RM) $(TARGET).sys
- $(RM) $(TARGET).sys.unstripped
.phony: clean .phony: clean

View file

@ -36,3 +36,4 @@ cp apps/pteb/pteb.exe $1/reactos/bin
cp apps/consume/consume.exe $1/reactos/bin cp apps/consume/consume.exe $1/reactos/bin
cp apps/float/float.exe $1/reactos/bin cp apps/float/float.exe $1/reactos/bin
cp apps/dump_shared_data/dump_shared_data.exe $1/reactos/bin cp apps/dump_shared_data/dump_shared_data.exe $1/reactos/bin
cp apps/vmtest/vmtest.exe $1/reactos/bin

View file

@ -1,4 +1,4 @@
/* $Id: view.c,v 1.9 2000/07/04 08:52:36 dwelch Exp $ /* $Id: view.c,v 1.10 2000/08/20 17:02:07 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -119,7 +119,7 @@ NTSTATUS STDCALL CcRequestCachePage(PBCB Bcb,
*BaseAddress = current->BaseAddress; *BaseAddress = current->BaseAddress;
*CacheSeg = current; *CacheSeg = current;
CHECKPOINT; CHECKPOINT;
MmSetPage(NULL, MmCreateVirtualMapping(NULL,
current->BaseAddress, current->BaseAddress,
PAGE_READWRITE, PAGE_READWRITE,
(ULONG)MmAllocPage(0)); (ULONG)MmAllocPage(0));

View file

@ -7,11 +7,6 @@
struct _EPROCESS; struct _EPROCESS;
#define PAGESIZE (4096)
PULONG MmGetPageEntry(PVOID Address);
/* /*
* Page access attributes (or these together) * Page access attributes (or these together)
*/ */
@ -27,6 +22,10 @@ PULONG MmGetPageEntry(PVOID Address);
#define PA_USER (1<<2) #define PA_USER (1<<2)
#define PA_SYSTEM (0) #define PA_SYSTEM (0)
#define PAGESIZE (4096)
PULONG MmGetPageEntry(PVOID Address);
#define KERNEL_BASE (0xc0000000) #define KERNEL_BASE (0xc0000000)
#define FLUSH_TLB __asm__("movl %cr3,%eax\n\tmovl %eax,%cr3\n\t") #define FLUSH_TLB __asm__("movl %cr3,%eax\n\tmovl %eax,%cr3\n\t")
@ -49,7 +48,7 @@ extern inline PULONG get_page_directory(void)
#define VADDR_TO_PT_OFFSET(x) (((x/1024)%4096)) #define VADDR_TO_PT_OFFSET(x) (((x/1024)%4096))
#define VADDR_TO_PD_OFFSET(x) ((x)/(4*1024*1024)) #define VADDR_TO_PD_OFFSET(x) ((x)/(4*1024*1024))
VOID MmSetPage(struct _EPROCESS* Process, NTSTATUS MmCreateVirtualMapping(struct _EPROCESS* Process,
PVOID Address, PVOID Address,
ULONG flProtect, ULONG flProtect,
ULONG PhysicalAddress); ULONG PhysicalAddress);

View file

@ -108,6 +108,8 @@ typedef struct _MADDRESS_SPACE
ULONG WorkingSetLruFirst; ULONG WorkingSetLruFirst;
ULONG WorkingSetLruLast; ULONG WorkingSetLruLast;
ULONG WorkingSetPagesAllocated; ULONG WorkingSetPagesAllocated;
PUSHORT PageTableRefCountTable;
ULONG PageTableRefCountTableSize;
} MADDRESS_SPACE, *PMADDRESS_SPACE; } MADDRESS_SPACE, *PMADDRESS_SPACE;
/* FUNCTIONS */ /* FUNCTIONS */
@ -164,7 +166,7 @@ NTSTATUS MmCopyMmInfo(struct _EPROCESS* Src,
struct _EPROCESS* Dest); struct _EPROCESS* Dest);
NTSTATUS MmReleaseMmInfo(struct _EPROCESS* Process); NTSTATUS MmReleaseMmInfo(struct _EPROCESS* Process);
NTSTATUS Mmi386ReleaseMmInfo(struct _EPROCESS* Process); NTSTATUS Mmi386ReleaseMmInfo(struct _EPROCESS* Process);
VOID MmDeletePageEntry(struct _EPROCESS* Process, VOID MmDeleteVirtualMapping(struct _EPROCESS* Process,
PVOID Address, PVOID Address,
BOOL FreePage); BOOL FreePage);

View file

@ -1,4 +1,4 @@
/* $Id: aspace.c,v 1.3 2000/07/04 08:52:42 dwelch Exp $ /* $Id: aspace.c,v 1.4 2000/08/20 17:02:08 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -40,7 +40,6 @@ VOID MmUnlockAddressSpace(PMADDRESS_SPACE AddressSpace)
VOID MmInitializeKernelAddressSpace(VOID) VOID MmInitializeKernelAddressSpace(VOID)
{ {
MmInitializeAddressSpace(NULL, &KernelAddressSpace); MmInitializeAddressSpace(NULL, &KernelAddressSpace);
KernelAddressSpace.LowestAddress = KERNEL_BASE;
} }
PMADDRESS_SPACE MmGetCurrentAddressSpace(VOID) PMADDRESS_SPACE MmGetCurrentAddressSpace(VOID)
@ -58,12 +57,30 @@ NTSTATUS MmInitializeAddressSpace(PEPROCESS Process,
{ {
InitializeListHead(&AddressSpace->MAreaListHead); InitializeListHead(&AddressSpace->MAreaListHead);
KeInitializeMutex(&AddressSpace->Lock, 1); KeInitializeMutex(&AddressSpace->Lock, 1);
if (Process != NULL)
{
AddressSpace->LowestAddress = MM_LOWEST_USER_ADDRESS; AddressSpace->LowestAddress = MM_LOWEST_USER_ADDRESS;
}
else
{
AddressSpace->LowestAddress = KERNEL_BASE;
}
AddressSpace->Process = Process; AddressSpace->Process = Process;
if (Process != NULL) if (Process != NULL)
{ {
MmInitializeWorkingSet(Process, AddressSpace); MmInitializeWorkingSet(Process, AddressSpace);
} }
if (Process != NULL)
{
AddressSpace->PageTableRefCountTable =
ExAllocatePool(NonPagedPool, 768 * sizeof(USHORT));
AddressSpace->PageTableRefCountTableSize = 768;
}
else
{
AddressSpace->PageTableRefCountTable = NULL;
AddressSpace->PageTableRefCountTableSize = 0;
}
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }

View file

@ -64,6 +64,7 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
{ {
ULONG i; ULONG i;
ULONG Reserved; ULONG Reserved;
NTSTATUS Status;
DPRINT("MmInitializePageList(FirstPhysKernelAddress %x, " DPRINT("MmInitializePageList(FirstPhysKernelAddress %x, "
"LastPhysKernelAddress %x, " "LastPhysKernelAddress %x, "
@ -100,10 +101,17 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
if (!MmIsPagePresent(NULL, if (!MmIsPagePresent(NULL,
(PVOID)((ULONG)MmPageArray + (i * PAGESIZE)))) (PVOID)((ULONG)MmPageArray + (i * PAGESIZE))))
{ {
MmSetPage(NULL, Status = MmCreateVirtualMapping(NULL,
(PVOID)((ULONG)MmPageArray + (i * PAGESIZE)), (PVOID)((ULONG)MmPageArray +
(i * PAGESIZE)),
PAGE_READWRITE, PAGE_READWRITE,
(ULONG)(LastPhysKernelAddress - (i * PAGESIZE))); (ULONG)(LastPhysKernelAddress
- (i * PAGESIZE)));
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
} }
} }

View file

@ -1,4 +1,4 @@
/* $Id: page.c,v 1.13 2000/07/19 14:18:19 dwelch Exp $ /* $Id: page.c,v 1.14 2000/08/20 17:02:09 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top directory * COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -56,6 +56,8 @@ static ULONG ProtectToPTE(ULONG flProtect)
return(Attributes); return(Attributes);
} }
#define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (4 * 1024 * 1024))
#define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \ #define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \
(((ULONG)v / (1024 * 1024))&(~0x3))) (((ULONG)v / (1024 * 1024))&(~0x3)))
#define ADDR_TO_PTE(v) (PULONG)(PAGETABLE_MAP + ((((ULONG)v / 1024))&(~0x3))) #define ADDR_TO_PTE(v) (PULONG)(PAGETABLE_MAP + ((((ULONG)v / 1024))&(~0x3)))
@ -121,6 +123,63 @@ VOID MmDeletePageTable(PEPROCESS Process, PVOID Address)
} }
} }
VOID MmFreePageTable(PEPROCESS Process, PVOID Address)
{
PEPROCESS CurrentProcess = PsGetCurrentProcess();
PULONG PageTable;
ULONG i;
ULONG npage;
if (Process != NULL && Process != CurrentProcess)
{
KeAttachProcess(Process);
}
PageTable = (PULONG)PAGE_ROUND_DOWN((PVOID)ADDR_TO_PTE(Address));
for (i = 0; i < 1024; i++)
{
if (PageTable[i] != 0)
{
DbgPrint("Page table entry not clear\n");
KeBugCheck(0);
}
}
npage = *(ADDR_TO_PDE(Address));
*(ADDR_TO_PDE(Address)) = 0;
MmDereferencePage((PVOID)PAGE_MASK(npage));
FLUSH_TLB;
if (Process != NULL && Process != CurrentProcess)
{
KeDetachProcess();
}
}
NTSTATUS MmGetPageEntry2(PVOID PAddress, PULONG* Pte)
/*
* FUNCTION: Get a pointer to the page table entry for a virtual address
*/
{
PULONG Pde;
ULONG Address = (ULONG)PAddress;
ULONG npage;
DPRINT("MmGetPageEntry(Address %x)\n", Address);
Pde = ADDR_TO_PDE(Address);
if ((*Pde) == 0)
{
npage = (ULONG)MmAllocPage(0);
if (npage == 0)
{
return(STATUS_NO_MEMORY);
}
(*Pde) = npage | 0x7;
memset((PVOID)PAGE_ROUND_DOWN(ADDR_TO_PTE(Address)), 0, PAGESIZE);
FLUSH_TLB;
}
*Pte = ADDR_TO_PTE(Address);
return(STATUS_SUCCESS);
}
ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address) ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
{ {
ULONG Entry; ULONG Entry;
@ -192,18 +251,21 @@ ULONG MmGetPhysicalAddressForProcess(PEPROCESS Process,
return(PAGE_MASK(PageEntry)); return(PAGE_MASK(PageEntry));
} }
VOID MmDeletePageEntry(PEPROCESS Process, PVOID Address, BOOL FreePage) VOID MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage)
/*
* FUNCTION: Delete a virtual mapping
*/
{ {
PULONG page_tlb; PULONG Pte;
PULONG page_dir; PULONG Pde;
PEPROCESS CurrentProcess = PsGetCurrentProcess(); PEPROCESS CurrentProcess = PsGetCurrentProcess();
if (Process != NULL && Process != CurrentProcess) if (Process != NULL && Process != CurrentProcess)
{ {
KeAttachProcess(Process); KeAttachProcess(Process);
} }
page_dir = ADDR_TO_PDE(Address); Pde = ADDR_TO_PDE(Address);
if ((*page_dir) == 0) if ((*Pde) == 0)
{ {
if (Process != NULL && Process != CurrentProcess) if (Process != NULL && Process != CurrentProcess)
{ {
@ -211,20 +273,26 @@ VOID MmDeletePageEntry(PEPROCESS Process, PVOID Address, BOOL FreePage)
} }
return; return;
} }
page_tlb = ADDR_TO_PTE(Address); Pte = ADDR_TO_PTE(Address);
if (FreePage && PAGE_MASK(*page_tlb) != 0) if (FreePage && PAGE_MASK(*Pte) != 0)
{ {
if (PAGE_MASK(*page_tlb) >= 0x400000) MmDereferencePage((PVOID)PAGE_MASK(*Pte));
}
*Pte = 0;
if (Process != NULL &&
Process->AddressSpace.PageTableRefCountTable != NULL &&
ADDR_TO_PAGE_TABLE(Address) < 768)
{ {
DbgPrint("MmDeletePageEntry(Address %x) Physical %x " PUSHORT Ptrc;
"Entry %x\n",
Address, PAGE_MASK(*page_tlb), Ptrc = Process->AddressSpace.PageTableRefCountTable;
*page_tlb);
KeBugCheck(0); Ptrc[ADDR_TO_PAGE_TABLE(Address)]--;
if (Ptrc[ADDR_TO_PAGE_TABLE(Address)] == 0)
{
MmFreePageTable(Process, Address);
} }
MmDereferencePage((PVOID)PAGE_MASK(*page_tlb));
} }
*page_tlb = 0;
if (Process != NULL && Process != CurrentProcess) if (Process != NULL && Process != CurrentProcess)
{ {
KeDetachProcess(); KeDetachProcess();
@ -323,20 +391,15 @@ BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
} }
VOID MmSetPage(PEPROCESS Process, NTSTATUS MmCreateVirtualMapping(PEPROCESS Process,
PVOID Address, PVOID Address,
ULONG flProtect, ULONG flProtect,
ULONG PhysicalAddress) ULONG PhysicalAddress)
{ {
PEPROCESS CurrentProcess = PsGetCurrentProcess(); PEPROCESS CurrentProcess = PsGetCurrentProcess();
ULONG Attributes = 0; ULONG Attributes = 0;
PULONG Pte;
if (((ULONG)PhysicalAddress) >= 0x400000) NTSTATUS Status;
{
DbgPrint("MmSetPage(Process %x, Address %x, PhysicalAddress %x)\n",
Process, Address, PhysicalAddress);
KeBugCheck(0);
}
Attributes = ProtectToPTE(flProtect); Attributes = ProtectToPTE(flProtect);
@ -344,12 +407,34 @@ VOID MmSetPage(PEPROCESS Process,
{ {
KeAttachProcess(Process); KeAttachProcess(Process);
} }
(*MmGetPageEntry(Address)) = PhysicalAddress | Attributes;
Status = MmGetPageEntry2(Address, &Pte);
if (!NT_SUCCESS(Status))
{
if (Process != NULL && Process != CurrentProcess)
{
KeDetachProcess();
}
return(Status);
}
*Pte = PhysicalAddress | Attributes;
if (Process != NULL &&
Process->AddressSpace.PageTableRefCountTable != NULL &&
ADDR_TO_PAGE_TABLE(Address) < 768 &&
Attributes & PA_PRESENT)
{
PUSHORT Ptrc;
Ptrc = Process->AddressSpace.PageTableRefCountTable;
Ptrc[ADDR_TO_PAGE_TABLE(Address)]++;
}
FLUSH_TLB; FLUSH_TLB;
if (Process != NULL && Process != CurrentProcess) if (Process != NULL && Process != CurrentProcess)
{ {
KeDetachProcess(); KeDetachProcess();
} }
return(STATUS_SUCCESS);
} }
VOID MmSetPageProtect(PEPROCESS Process, VOID MmSetPageProtect(PEPROCESS Process,

View file

@ -1,4 +1,4 @@
/* $Id: iospace.c,v 1.5 2000/07/04 08:52:42 dwelch Exp $ /* $Id: iospace.c,v 1.6 2000/08/20 17:02:08 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -76,10 +76,15 @@ PVOID STDCALL MmMapIoSpace (IN PHYSICAL_ADDRESS PhysicalAddress,
} }
for (i = 0; (i <= (NumberOfBytes / PAGESIZE)); i++) for (i = 0; (i <= (NumberOfBytes / PAGESIZE)); i++)
{ {
MmSetPage (NULL, Status = MmCreateVirtualMapping (NULL,
(Result + (i * PAGESIZE)), (Result + (i * PAGESIZE)),
PAGE_READWRITE, PAGE_READWRITE,
(PhysicalAddress.u.LowPart + (i * PAGESIZE))); (PhysicalAddress.u.LowPart + (i * PAGESIZE)));
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
} }
return ((PVOID)Result); return ((PVOID)Result);
} }

View file

@ -1,4 +1,4 @@
/* $Id: kmap.c,v 1.2 2000/07/04 08:52:42 dwelch Exp $ /* $Id: kmap.c,v 1.3 2000/08/20 17:02:08 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -46,7 +46,7 @@ VOID ExUnmapPage(PVOID Addr)
DPRINT("i %x\n",i); DPRINT("i %x\n",i);
KeAcquireSpinLock(&AllocMapLock, &oldIrql); KeAcquireSpinLock(&AllocMapLock, &oldIrql);
MmSetPage(NULL, (PVOID)Addr, 0, 0); MmDeleteVirtualMapping(NULL, (PVOID)Addr, FALSE);
clear_bit(i%32, &alloc_map[i/32]); clear_bit(i%32, &alloc_map[i/32]);
KeReleaseSpinLock(&AllocMapLock, oldIrql); KeReleaseSpinLock(&AllocMapLock, oldIrql);
} }
@ -57,6 +57,7 @@ PVOID ExAllocatePage(VOID)
ULONG addr; ULONG addr;
ULONG i; ULONG i;
ULONG PhysPage; ULONG PhysPage;
NTSTATUS Status;
PhysPage = (ULONG)MmAllocPage(0); PhysPage = (ULONG)MmAllocPage(0);
DPRINT("Allocated page %x\n",PhysPage); DPRINT("Allocated page %x\n",PhysPage);
@ -73,7 +74,15 @@ PVOID ExAllocatePage(VOID)
DPRINT("i %x\n",i); DPRINT("i %x\n",i);
set_bit(i%32,&alloc_map[i/32]); set_bit(i%32,&alloc_map[i/32]);
addr = (ULONG)(kernel_pool_base + (i*PAGESIZE)); addr = (ULONG)(kernel_pool_base + (i*PAGESIZE));
MmSetPage(NULL, (PVOID)addr, PAGE_READWRITE, PhysPage); Status = MmCreateVirtualMapping(NULL,
(PVOID)addr,
PAGE_READWRITE,
PhysPage);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
KeReleaseSpinLock(&AllocMapLock, oldlvl); KeReleaseSpinLock(&AllocMapLock, oldlvl);
return((PVOID)addr); return((PVOID)addr);
} }

View file

@ -312,10 +312,9 @@ NTSTATUS MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
{ {
// DPRINT("Freeing %x in kernel address space\n"); // DPRINT("Freeing %x in kernel address space\n");
} }
MmSetPage(AddressSpace->Process, MmDeleteVirtualMapping(AddressSpace->Process,
MemoryArea->BaseAddress + (i*PAGESIZE), MemoryArea->BaseAddress + (i*PAGESIZE),
0, FALSE);
0);
} }
RemoveEntryList(&(MemoryArea->Entry)); RemoveEntryList(&(MemoryArea->Entry));

View file

@ -1,4 +1,4 @@
/* $Id: mdl.c,v 1.24 2000/07/08 16:53:33 dwelch Exp $ /* $Id: mdl.c,v 1.25 2000/08/20 17:02:08 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -112,10 +112,15 @@ PVOID STDCALL MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode)
MdlPages = (PULONG)(Mdl + 1); MdlPages = (PULONG)(Mdl + 1);
for (i=0; i<(PAGE_ROUND_UP(Mdl->ByteCount+Mdl->ByteOffset)/PAGESIZE); i++) for (i=0; i<(PAGE_ROUND_UP(Mdl->ByteCount+Mdl->ByteOffset)/PAGESIZE); i++)
{ {
MmSetPage(NULL, Status = MmCreateVirtualMapping(NULL,
(PVOID)((ULONG)Base+(i*PAGESIZE)), (PVOID)((ULONG)Base+(i*PAGESIZE)),
PAGE_READWRITE, PAGE_READWRITE,
MdlPages[i]); MdlPages[i]);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
} }
MmUnlockAddressSpace(MmGetKernelAddressSpace()); MmUnlockAddressSpace(MmGetKernelAddressSpace());
Mdl->MdlFlags = Mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA; Mdl->MdlFlags = Mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;

View file

@ -1,4 +1,4 @@
/* $Id: mm.c,v 1.36 2000/08/18 22:27:03 dwelch Exp $ /* $Id: mm.c,v 1.37 2000/08/20 17:02:08 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top directory * COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -56,7 +56,7 @@ NTSTATUS MmReleaseMemoryArea(PEPROCESS Process, PMEMORY_AREA Marea)
i < (Marea->BaseAddress + Marea->Length); i < (Marea->BaseAddress + Marea->Length);
i = i+PAGESIZE) i = i+PAGESIZE)
{ {
MmDeletePageEntry(Process, i, TRUE); MmDeleteVirtualMapping(Process, i, TRUE);
} }
ExFreePool(Marea); ExFreePool(Marea);
@ -198,11 +198,10 @@ NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode,
break; break;
case MEMORY_AREA_SHARED_DATA: case MEMORY_AREA_SHARED_DATA:
MmSetPage(PsGetCurrentProcess(), Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
(PVOID)PAGE_ROUND_DOWN(Address), (PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READONLY, PAGE_READONLY,
(ULONG)MmSharedDataPagePhysicalAddress); (ULONG)MmSharedDataPagePhysicalAddress);
Status = STATUS_SUCCESS;
break; break;
default: default:

View file

@ -1,4 +1,4 @@
/* $Id: mminit.c,v 1.5 2000/08/12 19:33:22 dwelch Exp $ /* $Id: mminit.c,v 1.6 2000/08/20 17:02:08 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top directory * COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -85,6 +85,7 @@ VOID MmInitVirtualMemory(PLOADER_PARAMETER_BLOCK bp, ULONG LastKernelAddress)
PVOID BaseAddress; PVOID BaseAddress;
ULONG Length; ULONG Length;
ULONG ParamLength = kernel_len; ULONG ParamLength = kernel_len;
NTSTATUS Status;
DPRINT("MmInitVirtualMemory(%x)\n",bp); DPRINT("MmInitVirtualMemory(%x)\n",bp);
@ -155,10 +156,15 @@ VOID MmInitVirtualMemory(PLOADER_PARAMETER_BLOCK bp, ULONG LastKernelAddress)
0, 0,
&kernel_shared_data_desc); &kernel_shared_data_desc);
MmSharedDataPagePhysicalAddress = MmAllocPage(0); MmSharedDataPagePhysicalAddress = MmAllocPage(0);
MmSetPage(NULL, Status = MmCreateVirtualMapping(NULL,
(PVOID)KERNEL_SHARED_DATA_BASE, (PVOID)KERNEL_SHARED_DATA_BASE,
PAGE_READWRITE, PAGE_READWRITE,
(ULONG)MmSharedDataPagePhysicalAddress); (ULONG)MmSharedDataPagePhysicalAddress);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
((PKUSER_SHARED_DATA)KERNEL_SHARED_DATA_BASE)->TickCountLow = 0xdeadbeef; ((PKUSER_SHARED_DATA)KERNEL_SHARED_DATA_BASE)->TickCountLow = 0xdeadbeef;
DPRINT1("Finished creating shared data page\n"); DPRINT1("Finished creating shared data page\n");
@ -250,7 +256,7 @@ VOID MmInit1(PLOADER_PARAMETER_BLOCK bp, ULONG LastKernelAddress)
i<(KERNEL_BASE + PAGE_TABLE_SIZE); i<(KERNEL_BASE + PAGE_TABLE_SIZE);
i=i+PAGESIZE) i=i+PAGESIZE)
{ {
MmSetPage(NULL, (PVOID)(i), PAGE_NOACCESS, 0); MmDeleteVirtualMapping(NULL, (PVOID)(i), FALSE);
} }
DPRINT("Almost done MmInit()\n"); DPRINT("Almost done MmInit()\n");

View file

@ -1,4 +1,4 @@
/* $Id: ncache.c,v 1.5 2000/07/04 08:52:42 dwelch Exp $ /* $Id: ncache.c,v 1.6 2000/08/20 17:02:08 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -65,10 +65,15 @@ PVOID STDCALL MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
} }
for (i = 0; (i <= (NumberOfBytes / PAGESIZE)); i++) for (i = 0; (i <= (NumberOfBytes / PAGESIZE)); i++)
{ {
MmSetPage (NULL, Status = MmCreateVirtualMapping (NULL,
(Result + (i * PAGESIZE)), (Result + (i * PAGESIZE)),
PAGE_READWRITE, PAGE_READWRITE,
(ULONG)MmAllocPage(0)); (ULONG)MmAllocPage(0));
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
} }
return ((PVOID)Result); return ((PVOID)Result);
} }

View file

@ -1,4 +1,4 @@
/* $Id: npool.c,v 1.30 2000/07/04 08:52:42 dwelch Exp $ /* $Id: npool.c,v 1.31 2000/08/20 17:02:08 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -374,16 +374,22 @@ static block_hdr* grow_kernel_pool(unsigned int size)
block_hdr* used_blk=NULL; block_hdr* used_blk=NULL;
block_hdr* free_blk=NULL; block_hdr* free_blk=NULL;
int i; int i;
NTSTATUS Status;
OLD_DPRINT("growing heap for block size %d, ",size); OLD_DPRINT("growing heap for block size %d, ",size);
OLD_DPRINT("start %x\n",start); OLD_DPRINT("start %x\n",start);
for (i=0;i<nr_pages;i++) for (i=0;i<nr_pages;i++)
{ {
MmSetPage(NULL, Status = MmCreateVirtualMapping(NULL,
(PVOID)(start + (i*PAGESIZE)), (PVOID)(start + (i*PAGESIZE)),
PAGE_READWRITE, PAGE_READWRITE,
(ULONG)MmAllocPage(0)); (ULONG)MmAllocPage(0));
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
} }

View file

@ -1,4 +1,4 @@
/* $Id: section.c,v 1.37 2000/07/07 10:30:56 dwelch Exp $ /* $Id: section.c,v 1.38 2000/08/20 17:02:08 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -148,10 +148,15 @@ NTSTATUS MmUnalignedLoadPageForSection(PMADDRESS_SPACE AddressSpace,
MmLockAddressSpace(AddressSpace); MmLockAddressSpace(AddressSpace);
MmLockSection(Section); MmLockSection(Section);
MmSetPage(NULL, Status = MmCreateVirtualMapping(NULL,
Address, Address,
MemoryArea->Attributes, MemoryArea->Attributes,
(ULONG)Page); (ULONG)Page);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
MmUnlockSection(Section); MmUnlockSection(Section);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
@ -246,10 +251,15 @@ NTSTATUS MmWaitForPendingOperationSection(PMADDRESS_SPACE AddressSpace,
* and have a reference to a page containing valid data for the * and have a reference to a page containing valid data for the
* section offset. Set the page and return success. * section offset. Set the page and return success.
*/ */
MmSetPage(NULL, Status = MmCreateVirtualMapping(NULL,
Address, Address,
MemoryArea->Attributes, MemoryArea->Attributes,
(ULONG)Page); (ULONG)Page);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
MmUnlockSection(Section); MmUnlockSection(Section);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
@ -350,10 +360,15 @@ NTSTATUS MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
Page = (PVOID)Entry; Page = (PVOID)Entry;
MmReferencePage(Page); MmReferencePage(Page);
MmSetPage(NULL, Status = MmCreateVirtualMapping(NULL,
Address, Address,
MemoryArea->Attributes, MemoryArea->Attributes,
(ULONG)Page); (ULONG)Page);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
MmUnlockSection(Section); MmUnlockSection(Section);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
@ -434,10 +449,15 @@ NTSTATUS MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
*/ */
MmSetWaitPage(Page); MmSetWaitPage(Page);
MmSetPage(NULL, Status = MmCreateVirtualMapping(NULL,
Address, Address,
MemoryArea->Attributes, MemoryArea->Attributes,
(ULONG)Page); (ULONG)Page);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
MmUnlockSection(Section); MmUnlockSection(Section);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
@ -462,10 +482,15 @@ NTSTATUS MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
Page = (PVOID)Entry; Page = (PVOID)Entry;
MmReferencePage(Page); MmReferencePage(Page);
MmSetPage(NULL, Status = MmCreateVirtualMapping(NULL,
Address, Address,
MemoryArea->Attributes, MemoryArea->Attributes,
(ULONG)Page); (ULONG)Page);
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
MmUnlockSection(Section); MmUnlockSection(Section);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
@ -1024,10 +1049,15 @@ PVOID STDCALL MmAllocateSection (IN ULONG Length)
DPRINT("Result %p\n",Result); DPRINT("Result %p\n",Result);
for (i = 0; (i <= (Length / PAGESIZE)); i++) for (i = 0; (i <= (Length / PAGESIZE)); i++)
{ {
MmSetPage (NULL, Status = MmCreateVirtualMapping (NULL,
(Result + (i * PAGESIZE)), (Result + (i * PAGESIZE)),
PAGE_READWRITE, PAGE_READWRITE,
(ULONG)MmAllocPage(0)); (ULONG)MmAllocPage(0));
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
} }
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
return ((PVOID)Result); return ((PVOID)Result);

View file

@ -1,4 +1,4 @@
/* $Id: virtual.c,v 1.33 2000/08/18 22:27:03 dwelch Exp $ /* $Id: virtual.c,v 1.34 2000/08/20 17:02:09 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top directory * COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -189,10 +189,7 @@ ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
MmRemovePageFromWorkingSet(AddressSpace->Process, MmRemovePageFromWorkingSet(AddressSpace->Process,
Address); Address);
MmSetPage(PsGetCurrentProcess(), MmDeleteVirtualMapping(PsGetCurrentProcess(), Address, FALSE);
Address,
0,
0);
MmDereferencePage((PVOID)PhysicalAddress.u.LowPart); MmDereferencePage((PVOID)PhysicalAddress.u.LowPart);
*Ul = TRUE; *Ul = TRUE;
return(1); return(1);
@ -219,6 +216,9 @@ NTSTATUS MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
PMM_SEGMENT Segment; PMM_SEGMENT Segment;
PVOID CurrentAddress; PVOID CurrentAddress;
/*
* Get the segment corresponding to the virtual address
*/
Segment = MmGetSegmentForAddress(MemoryArea, Address, &CurrentAddress); Segment = MmGetSegmentForAddress(MemoryArea, Address, &CurrentAddress);
if (Segment == NULL) if (Segment == NULL)
{ {
@ -234,6 +234,9 @@ NTSTATUS MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
/*
* Try to allocate a page
*/
Page = MmAllocPage(0); Page = MmAllocPage(0);
while (Page == NULL) while (Page == NULL)
{ {
@ -246,8 +249,21 @@ NTSTATUS MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
} }
Page = MmAllocPage(0); Page = MmAllocPage(0);
} }
Status = MmCreatePageTable(Address);
while (!NT_SUCCESS(Status)) /*
* Add the page to the process's working set
*/
MmAddPageToWorkingSet(PsGetCurrentProcess(), Address);
/*
* Set the page. If we fail because we are out of memory then
* try again
*/
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
Address,
MemoryArea->Attributes,
(ULONG)Page);
while (Status == STATUS_NO_MEMORY)
{ {
MmUnlockAddressSpace(AddressSpace); MmUnlockAddressSpace(AddressSpace);
MmWaitForFreePages(); MmWaitForFreePages();
@ -257,13 +273,15 @@ NTSTATUS MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
MmDereferencePage(Page); MmDereferencePage(Page);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
Status = MmCreatePageTable(Address); Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
}
MmAddPageToWorkingSet(PsGetCurrentProcess(), Address);
MmSetPage(PsGetCurrentProcess(),
Address, Address,
MemoryArea->Attributes, MemoryArea->Attributes,
(ULONG)Page); (ULONG)Page);
}
if (!NT_SUCCESS(Status))
{
return(Status);
}
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
@ -275,6 +293,9 @@ VOID MmModifyAttributes(PMADDRESS_SPACE AddressSpace,
ULONG OldProtect, ULONG OldProtect,
ULONG NewType, ULONG NewType,
ULONG NewProtect) ULONG NewProtect)
/*
* FUNCTION: Modify the attributes of a memory region
*/
{ {
if (NewType == MEM_RESERVE && if (NewType == MEM_RESERVE &&
OldType == MEM_COMMIT) OldType == MEM_COMMIT)
@ -314,6 +335,9 @@ VOID MmModifyAttributes(PMADDRESS_SPACE AddressSpace,
VOID InsertAfterEntry(PLIST_ENTRY Previous, VOID InsertAfterEntry(PLIST_ENTRY Previous,
PLIST_ENTRY Entry) PLIST_ENTRY Entry)
/*
* FUNCTION: Insert a list entry after another entry in the list
*/
{ {
Previous->Flink->Blink = Entry; Previous->Flink->Blink = Entry;
@ -323,78 +347,127 @@ VOID InsertAfterEntry(PLIST_ENTRY Previous,
Previous->Flink = Entry; Previous->Flink = Entry;
} }
VOID MmDumpSegmentsMemoryArea(PMEMORY_AREA MemoryArea)
{
PVOID CurrentAddress;
PLIST_ENTRY CurrentEntry;
PMM_SEGMENT CurrentSegment;
PLIST_ENTRY ListHead;
CurrentEntry = MemoryArea->Data.VirtualMemoryData.SegmentListHead.Flink;
ListHead = &MemoryArea->Data.VirtualMemoryData.SegmentListHead;
CurrentAddress = MemoryArea->BaseAddress;
while (CurrentEntry != ListHead)
{
CurrentSegment = CONTAINING_RECORD(CurrentEntry,
MM_SEGMENT,
SegmentListEntry);
DbgPrint("0x%x 0x%x %d %d\n",
CurrentAddress,
CurrentSegment->Length,
CurrentSegment->Type,
CurrentSegment->Protect);
CurrentAddress = CurrentAddress + CurrentSegment->Length;
CurrentEntry = CurrentEntry->Flink;
}
}
NTSTATUS MmSplitSegment(PMADDRESS_SPACE AddressSpace, NTSTATUS MmSplitSegment(PMADDRESS_SPACE AddressSpace,
PMEMORY_AREA MemoryArea, PMEMORY_AREA MemoryArea,
PVOID BaseAddress, PVOID RegionAddress,
ULONG RegionSize, ULONG RegionLength,
ULONG Type, ULONG Type,
ULONG Protect, ULONG Protect,
PMM_SEGMENT CurrentSegment, PMM_SEGMENT FirstSegment,
PVOID CurrentAddress) PVOID FirstAddress)
/* /*
* FUNCTION: Split a memory segment internally * FUNCTION: Split a memory segment internally
*/ */
{ {
PMM_SEGMENT NewSegment;
PMM_SEGMENT NewTopSegment; PMM_SEGMENT NewTopSegment;
PMM_SEGMENT PreviousSegment; PMM_SEGMENT RegionSegment;
ULONG OldType; ULONG OldType;
ULONG OldProtect; ULONG OldProtect;
ULONG OldLength;
OldType = CurrentSegment->Type; /*
OldProtect = CurrentSegment->Protect; * Save the type and protection and length of the current segment
*/
OldType = FirstSegment->Type;
OldProtect = FirstSegment->Protect;
OldLength = FirstSegment->Length;
NewSegment = ExAllocatePool(NonPagedPool, sizeof(MM_SEGMENT)); /*
if (NewSegment == NULL) * Allocate the segment we might need here because if the allocation
{ * fails below it will be difficult to undo what we've done already.
return(STATUS_NO_MEMORY); */
}
NewTopSegment = ExAllocatePool(NonPagedPool, sizeof(MM_SEGMENT)); NewTopSegment = ExAllocatePool(NonPagedPool, sizeof(MM_SEGMENT));
if (NewTopSegment == NULL) if (NewTopSegment == NULL)
{ {
ExFreePool(NewSegment);
return(STATUS_NO_MEMORY); return(STATUS_NO_MEMORY);
} }
if (CurrentSegment->Type == Type && /*
CurrentSegment->Protect == Protect) * If the segment is already of the right type and protection then
* there is nothing to do.
*/
if (FirstSegment->Type == Type && FirstSegment->Protect == Protect)
{ {
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
if (CurrentAddress < BaseAddress) if (FirstAddress < RegionAddress)
{ {
NewSegment->Type = Type; /*
NewSegment->Protect = Protect; * If the region to be affected starts at a higher address than
NewSegment->Length = RegionSize; * the current segment then create a new segment for the
* affected portion
*/
RegionSegment = ExAllocatePool(NonPagedPool, sizeof(MM_SEGMENT));
if (RegionSegment == NULL)
{
ExFreePool(NewTopSegment);
return(STATUS_NO_MEMORY);
}
CurrentSegment->Length = BaseAddress - CurrentAddress; RegionSegment->Type = Type;
RegionSegment->Protect = Protect;
RegionSegment->Length = RegionLength;
InsertAfterEntry(&CurrentSegment->SegmentListEntry, FirstSegment->Length = RegionAddress - FirstAddress;
&NewSegment->SegmentListEntry);
PreviousSegment = NewSegment; InsertAfterEntry(&FirstSegment->SegmentListEntry,
&RegionSegment->SegmentListEntry);
} }
else else
{ {
CurrentSegment->Type = Type; /*
CurrentSegment->Protect = Protect; * Otherwise just set its type and protection and length
*/
PreviousSegment = CurrentSegment; FirstSegment->Type = Type;
FirstSegment->Protect = Protect;
FirstSegment->Length = RegionLength;
ExFreePool(NewSegment); RegionSegment = FirstSegment;
NewSegment = NULL;
} }
if ((CurrentAddress + CurrentSegment->Length) > (BaseAddress + RegionSize)) if ((FirstAddress + OldLength) > (RegionAddress + RegionLength))
{ {
/*
* If the top of the current segment extends after the affected
* region then create a segment for the unaffected portion
*/
NewTopSegment->Type = OldType; NewTopSegment->Type = OldType;
NewTopSegment->Protect = OldProtect; NewTopSegment->Protect = OldProtect;
NewTopSegment->Length = NewTopSegment->Length = (FirstAddress + OldLength) -
(CurrentAddress + CurrentSegment->Length) - (RegionAddress + RegionLength);
(BaseAddress + RegionSize);
InsertAfterEntry(&PreviousSegment->SegmentListEntry, InsertAfterEntry(&RegionSegment->SegmentListEntry,
&NewTopSegment->SegmentListEntry); &NewTopSegment->SegmentListEntry);
} }
else else
@ -403,19 +476,27 @@ NTSTATUS MmSplitSegment(PMADDRESS_SPACE AddressSpace,
NewTopSegment = NULL; NewTopSegment = NULL;
} }
MmModifyAttributes(AddressSpace, BaseAddress, RegionSize, /*
OldType, OldProtect, Type, Protect); * Actually set the type and protection of the affected region
*/
MmModifyAttributes(AddressSpace,
RegionAddress,
RegionLength,
OldType,
OldProtect,
Type,
Protect);
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
NTSTATUS MmGatherSegment(PMADDRESS_SPACE AddressSpace, NTSTATUS MmGatherSegment(PMADDRESS_SPACE AddressSpace,
PMEMORY_AREA MemoryArea, PMEMORY_AREA MemoryArea,
PVOID BaseAddress, PVOID RegionAddress,
ULONG RegionSize, ULONG RegionLength,
ULONG Type, ULONG Type,
ULONG Protect, ULONG Protect,
PMM_SEGMENT CurrentSegment, PMM_SEGMENT FirstSegment,
PVOID CurrentAddress) PVOID FirstAddress)
/* /*
* FUNCTION: Do a virtual memory operation that will effect several * FUNCTION: Do a virtual memory operation that will effect several
* memory segments. * memory segments.
@ -432,53 +513,46 @@ NTSTATUS MmGatherSegment(PMADDRESS_SPACE AddressSpace,
* RETURNS: Status * RETURNS: Status
*/ */
{ {
PMM_SEGMENT NewSegment; PMM_SEGMENT RegionSegment;
PMM_SEGMENT NewTopSegment; PVOID CurrentAddress;
PMM_SEGMENT PreviousSegment; ULONG RemainingLength;
PVOID LAddress;
ULONG RSize;
PLIST_ENTRY CurrentEntry; PLIST_ENTRY CurrentEntry;
PLIST_ENTRY ListHead; PLIST_ENTRY ListHead;
PMM_SEGMENT CurrentSegment;
/* if (FirstAddress < RegionAddress)
* We will need a maximum of two new segments. Allocate them now
* because if we fail latter we may not be able to reverse the
* what we've already done
*/
NewSegment = ExAllocatePool(NonPagedPool, sizeof(MM_SEGMENT));
if (NewSegment == NULL)
{
return(STATUS_NO_MEMORY);
}
NewTopSegment = ExAllocatePool(NonPagedPool, sizeof(MM_SEGMENT));
if (NewTopSegment == NULL)
{
ExFreePool(NewSegment);
return(STATUS_NO_MEMORY);
}
if (CurrentAddress < BaseAddress)
{ {
/* /*
* If a portion of the first segment is not covered by the region then * If a portion of the first segment is not covered by the region then
* we need to split it into two segments * we need to split it into two segments
*/ */
NewSegment->Type = Type; RegionSegment = ExAllocatePool(NonPagedPool, sizeof(MM_SEGMENT));
NewSegment->Protect = Protect; if (RegionSegment == NULL)
NewSegment->Length = RegionSize; {
return(STATUS_NO_MEMORY);
}
CurrentSegment->Length = RegionSegment->Type = Type;
BaseAddress - CurrentAddress; RegionSegment->Protect = Protect;
RegionSegment->Length = (FirstAddress + FirstSegment->Length) -
RegionAddress;
InsertAfterEntry(&CurrentSegment->SegmentListEntry, FirstSegment->Length = RegionAddress - FirstAddress;
&NewSegment->SegmentListEntry);
PreviousSegment = NewSegment; InsertAfterEntry(&FirstSegment->SegmentListEntry,
&RegionSegment->SegmentListEntry);
MmModifyAttributes(AddressSpace, BaseAddress, NewSegment->Length, MmModifyAttributes(AddressSpace,
CurrentSegment->Type, RegionAddress,
CurrentSegment->Protect, Type, Protect); RegionSegment->Length,
FirstSegment->Type,
FirstSegment->Protect,
Type,
Protect);
CurrentAddress = FirstAddress + FirstSegment->Length +
RegionSegment->Length;
} }
else else
{ {
@ -489,75 +563,106 @@ NTSTATUS MmGatherSegment(PMADDRESS_SPACE AddressSpace,
ULONG OldType; ULONG OldType;
ULONG OldProtect; ULONG OldProtect;
OldType = CurrentSegment->Type; OldType = FirstSegment->Type;
OldProtect = CurrentSegment->Protect; OldProtect = FirstSegment->Protect;
CurrentSegment->Type = Type; FirstSegment->Type = Type;
CurrentSegment->Protect = Protect; FirstSegment->Protect = Protect;
PreviousSegment = CurrentSegment; RegionSegment = FirstSegment;
ExFreePool(NewSegment); MmModifyAttributes(AddressSpace,
NewSegment = NULL; RegionAddress,
FirstSegment->Length,
OldType,
OldProtect,
Type,
Protect);
MmModifyAttributes(AddressSpace, BaseAddress, CurrentSegment->Length, CurrentAddress = FirstAddress + RegionSegment->Length;
OldType, OldProtect, Type, Protect);
} }
LAddress = BaseAddress + PreviousSegment->Length; /*
RSize = RegionSize - PreviousSegment->Length; * Change the attributes of all the complete segments lying inside the
CurrentEntry = PreviousSegment->SegmentListEntry.Flink; * affected region
ListHead = &MemoryArea->Data.VirtualMemoryData.SegmentListHead; */
RemainingLength = RegionLength - RegionSegment->Length;
while (CurrentEntry != ListHead && RSize > 0) CurrentEntry = RegionSegment->SegmentListEntry.Flink;
{
ULONG OldType;
ULONG OldProtect;
CurrentSegment = CONTAINING_RECORD(CurrentEntry, CurrentSegment = CONTAINING_RECORD(CurrentEntry,
MM_SEGMENT, MM_SEGMENT,
SegmentListEntry); SegmentListEntry);
ListHead = &MemoryArea->Data.VirtualMemoryData.SegmentListHead;
if (CurrentSegment->Length > RSize) while (CurrentEntry != ListHead && RemainingLength > 0)
{
ULONG OldType;
ULONG OldProtect;
ULONG OldLength;
/*
* If this segment will not be completely covered by the
* affected region then break
*/
if (CurrentSegment->Length > RemainingLength)
{ {
break; break;
} }
OldType = CurrentSegment->Type; OldType = CurrentSegment->Type;
OldProtect = CurrentSegment->Protect; OldProtect = CurrentSegment->Protect;
CurrentSegment->Type = Type; OldLength = CurrentSegment->Length;
CurrentSegment->Protect = Protect;
MmModifyAttributes(AddressSpace, LAddress, CurrentSegment->Length,
OldType, OldProtect, Type, Protect);
RSize = RSize - CurrentSegment->Length;
LAddress = LAddress + CurrentSegment->Length;
/*
* Extend the length of the previous segment to cover this one
*/
RegionSegment->Length = RegionSegment->Length + OldLength;
RemainingLength = RemainingLength - OldLength;
CurrentAddress = CurrentAddress + OldLength;
CurrentEntry = CurrentEntry->Flink; CurrentEntry = CurrentEntry->Flink;
/*
* Remove the current segment from the list
*/
RemoveEntryList(&CurrentSegment->SegmentListEntry);
ExFreePool(CurrentSegment);
MmModifyAttributes(AddressSpace,
CurrentAddress,
OldLength,
OldType,
OldProtect,
Type,
Protect);
CurrentSegment = CONTAINING_RECORD(CurrentEntry,
MM_SEGMENT,
SegmentListEntry);
} }
if (CurrentEntry == ListHead && RSize > 0) /*
* If we've run off the top of the memory area then bug check
*/
if (CurrentEntry == ListHead && RemainingLength > 0)
{ {
KeBugCheck(0); KeBugCheck(0);
} }
if (RSize > 0) /*
* We've only affected a portion of a segment then split it in two
*/
if (RemainingLength > 0)
{ {
NewTopSegment->Type = CurrentSegment->Type; CurrentSegment->Length = CurrentSegment->Length - RemainingLength;
NewTopSegment->Protect = CurrentSegment->Protect;
NewTopSegment->Length = CurrentSegment->Length - RSize;
CurrentSegment->Length = RSize; RegionSegment->Length = RegionSegment->Length + RemainingLength;
CurrentSegment->Type = Type;
CurrentSegment->Protect = Protect;
InsertAfterEntry(&CurrentSegment->SegmentListEntry, MmModifyAttributes(AddressSpace,
&NewTopSegment->SegmentListEntry); CurrentAddress,
RemainingLength,
MmModifyAttributes(AddressSpace, LAddress, RSize, CurrentSegment->Type,
NewTopSegment->Type, CurrentSegment->Protect,
NewTopSegment->Protect, Type, Protect); Type,
Protect);
} }
return(STATUS_SUCCESS); return(STATUS_SUCCESS);