mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
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:
parent
7c29439d2b
commit
8434fc42db
23 changed files with 632 additions and 254 deletions
|
@ -44,7 +44,7 @@ NET_DRIVERS = ndis tcpip tditest
|
|||
KERNEL_SERVICES = $(DEVICE_DRIVERS) $(FS_DRIVERS) $(NET_DRIVERS)
|
||||
|
||||
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
|
||||
|
||||
|
|
42
reactos/apps/tests/vmtest/Makefile
Normal file
42
reactos/apps/tests/vmtest/Makefile
Normal 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
|
53
reactos/apps/tests/vmtest/vmtest.c
Normal file
53
reactos/apps/tests/vmtest/vmtest.c
Normal 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");
|
||||
}
|
||||
}
|
|
@ -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 = ../../..
|
||||
|
@ -20,6 +20,7 @@ clean:
|
|||
- $(RM) base.tmp
|
||||
- $(RM) temp.exp
|
||||
- $(RM) blue.sys
|
||||
- $(RM) blue.sys.unstripped
|
||||
|
||||
.phony: clean
|
||||
|
||||
|
|
|
@ -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 = ../../..
|
||||
|
@ -20,7 +20,7 @@ clean:
|
|||
- $(RM) base.tmp
|
||||
- $(RM) temp.exp
|
||||
- $(RM) $(TARGET).sys
|
||||
- $(RM) $(TARGET).nostrip.sys
|
||||
- $(RM) $(TARGET).sys.unstripped
|
||||
|
||||
.phony: clean
|
||||
|
||||
|
|
|
@ -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 = ../../..
|
||||
|
@ -20,6 +20,7 @@ clean:
|
|||
- $(RM) base.tmp
|
||||
- $(RM) temp.exp
|
||||
- $(RM) $(TARGET).sys
|
||||
- $(RM) $(TARGET).sys.unstripped
|
||||
|
||||
.phony: clean
|
||||
|
||||
|
|
|
@ -36,3 +36,4 @@ cp apps/pteb/pteb.exe $1/reactos/bin
|
|||
cp apps/consume/consume.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/vmtest/vmtest.exe $1/reactos/bin
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -119,7 +119,7 @@ NTSTATUS STDCALL CcRequestCachePage(PBCB Bcb,
|
|||
*BaseAddress = current->BaseAddress;
|
||||
*CacheSeg = current;
|
||||
CHECKPOINT;
|
||||
MmSetPage(NULL,
|
||||
MmCreateVirtualMapping(NULL,
|
||||
current->BaseAddress,
|
||||
PAGE_READWRITE,
|
||||
(ULONG)MmAllocPage(0));
|
||||
|
|
|
@ -7,11 +7,6 @@
|
|||
|
||||
struct _EPROCESS;
|
||||
|
||||
#define PAGESIZE (4096)
|
||||
|
||||
PULONG MmGetPageEntry(PVOID Address);
|
||||
|
||||
|
||||
/*
|
||||
* Page access attributes (or these together)
|
||||
*/
|
||||
|
@ -27,6 +22,10 @@ PULONG MmGetPageEntry(PVOID Address);
|
|||
#define PA_USER (1<<2)
|
||||
#define PA_SYSTEM (0)
|
||||
|
||||
#define PAGESIZE (4096)
|
||||
|
||||
PULONG MmGetPageEntry(PVOID Address);
|
||||
|
||||
#define KERNEL_BASE (0xc0000000)
|
||||
|
||||
#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_PD_OFFSET(x) ((x)/(4*1024*1024))
|
||||
|
||||
VOID MmSetPage(struct _EPROCESS* Process,
|
||||
NTSTATUS MmCreateVirtualMapping(struct _EPROCESS* Process,
|
||||
PVOID Address,
|
||||
ULONG flProtect,
|
||||
ULONG PhysicalAddress);
|
||||
|
|
|
@ -108,6 +108,8 @@ typedef struct _MADDRESS_SPACE
|
|||
ULONG WorkingSetLruFirst;
|
||||
ULONG WorkingSetLruLast;
|
||||
ULONG WorkingSetPagesAllocated;
|
||||
PUSHORT PageTableRefCountTable;
|
||||
ULONG PageTableRefCountTableSize;
|
||||
} MADDRESS_SPACE, *PMADDRESS_SPACE;
|
||||
|
||||
/* FUNCTIONS */
|
||||
|
@ -164,7 +166,7 @@ NTSTATUS MmCopyMmInfo(struct _EPROCESS* Src,
|
|||
struct _EPROCESS* Dest);
|
||||
NTSTATUS MmReleaseMmInfo(struct _EPROCESS* Process);
|
||||
NTSTATUS Mmi386ReleaseMmInfo(struct _EPROCESS* Process);
|
||||
VOID MmDeletePageEntry(struct _EPROCESS* Process,
|
||||
VOID MmDeleteVirtualMapping(struct _EPROCESS* Process,
|
||||
PVOID Address,
|
||||
BOOL FreePage);
|
||||
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -40,7 +40,6 @@ VOID MmUnlockAddressSpace(PMADDRESS_SPACE AddressSpace)
|
|||
VOID MmInitializeKernelAddressSpace(VOID)
|
||||
{
|
||||
MmInitializeAddressSpace(NULL, &KernelAddressSpace);
|
||||
KernelAddressSpace.LowestAddress = KERNEL_BASE;
|
||||
}
|
||||
|
||||
PMADDRESS_SPACE MmGetCurrentAddressSpace(VOID)
|
||||
|
@ -58,12 +57,30 @@ NTSTATUS MmInitializeAddressSpace(PEPROCESS Process,
|
|||
{
|
||||
InitializeListHead(&AddressSpace->MAreaListHead);
|
||||
KeInitializeMutex(&AddressSpace->Lock, 1);
|
||||
if (Process != NULL)
|
||||
{
|
||||
AddressSpace->LowestAddress = MM_LOWEST_USER_ADDRESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddressSpace->LowestAddress = KERNEL_BASE;
|
||||
}
|
||||
AddressSpace->Process = Process;
|
||||
if (Process != NULL)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -64,6 +64,7 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
|
|||
{
|
||||
ULONG i;
|
||||
ULONG Reserved;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("MmInitializePageList(FirstPhysKernelAddress %x, "
|
||||
"LastPhysKernelAddress %x, "
|
||||
|
@ -100,10 +101,17 @@ PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
|
|||
if (!MmIsPagePresent(NULL,
|
||||
(PVOID)((ULONG)MmPageArray + (i * PAGESIZE))))
|
||||
{
|
||||
MmSetPage(NULL,
|
||||
(PVOID)((ULONG)MmPageArray + (i * PAGESIZE)),
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
(PVOID)((ULONG)MmPageArray +
|
||||
(i * PAGESIZE)),
|
||||
PAGE_READWRITE,
|
||||
(ULONG)(LastPhysKernelAddress - (i * PAGESIZE)));
|
||||
(ULONG)(LastPhysKernelAddress
|
||||
- (i * PAGESIZE)));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -56,6 +56,8 @@ static ULONG ProtectToPTE(ULONG flProtect)
|
|||
return(Attributes);
|
||||
}
|
||||
|
||||
#define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (4 * 1024 * 1024))
|
||||
|
||||
#define ADDR_TO_PDE(v) (PULONG)(PAGEDIRECTORY_MAP + \
|
||||
(((ULONG)v / (1024 * 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 Entry;
|
||||
|
@ -192,18 +251,21 @@ ULONG MmGetPhysicalAddressForProcess(PEPROCESS Process,
|
|||
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 page_dir;
|
||||
PULONG Pte;
|
||||
PULONG Pde;
|
||||
PEPROCESS CurrentProcess = PsGetCurrentProcess();
|
||||
|
||||
if (Process != NULL && Process != CurrentProcess)
|
||||
{
|
||||
KeAttachProcess(Process);
|
||||
}
|
||||
page_dir = ADDR_TO_PDE(Address);
|
||||
if ((*page_dir) == 0)
|
||||
Pde = ADDR_TO_PDE(Address);
|
||||
if ((*Pde) == 0)
|
||||
{
|
||||
if (Process != NULL && Process != CurrentProcess)
|
||||
{
|
||||
|
@ -211,20 +273,26 @@ VOID MmDeletePageEntry(PEPROCESS Process, PVOID Address, BOOL FreePage)
|
|||
}
|
||||
return;
|
||||
}
|
||||
page_tlb = ADDR_TO_PTE(Address);
|
||||
if (FreePage && PAGE_MASK(*page_tlb) != 0)
|
||||
Pte = ADDR_TO_PTE(Address);
|
||||
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 "
|
||||
"Entry %x\n",
|
||||
Address, PAGE_MASK(*page_tlb),
|
||||
*page_tlb);
|
||||
KeBugCheck(0);
|
||||
PUSHORT Ptrc;
|
||||
|
||||
Ptrc = Process->AddressSpace.PageTableRefCountTable;
|
||||
|
||||
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)
|
||||
{
|
||||
KeDetachProcess();
|
||||
|
@ -323,20 +391,15 @@ BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
|
|||
}
|
||||
|
||||
|
||||
VOID MmSetPage(PEPROCESS Process,
|
||||
NTSTATUS MmCreateVirtualMapping(PEPROCESS Process,
|
||||
PVOID Address,
|
||||
ULONG flProtect,
|
||||
ULONG PhysicalAddress)
|
||||
{
|
||||
PEPROCESS CurrentProcess = PsGetCurrentProcess();
|
||||
ULONG Attributes = 0;
|
||||
|
||||
if (((ULONG)PhysicalAddress) >= 0x400000)
|
||||
{
|
||||
DbgPrint("MmSetPage(Process %x, Address %x, PhysicalAddress %x)\n",
|
||||
Process, Address, PhysicalAddress);
|
||||
KeBugCheck(0);
|
||||
}
|
||||
PULONG Pte;
|
||||
NTSTATUS Status;
|
||||
|
||||
Attributes = ProtectToPTE(flProtect);
|
||||
|
||||
|
@ -344,12 +407,34 @@ VOID MmSetPage(PEPROCESS 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;
|
||||
if (Process != NULL && Process != CurrentProcess)
|
||||
{
|
||||
KeDetachProcess();
|
||||
}
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
VOID MmSetPageProtect(PEPROCESS Process,
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -76,10 +76,15 @@ PVOID STDCALL MmMapIoSpace (IN PHYSICAL_ADDRESS PhysicalAddress,
|
|||
}
|
||||
for (i = 0; (i <= (NumberOfBytes / PAGESIZE)); i++)
|
||||
{
|
||||
MmSetPage (NULL,
|
||||
Status = MmCreateVirtualMapping (NULL,
|
||||
(Result + (i * PAGESIZE)),
|
||||
PAGE_READWRITE,
|
||||
(PhysicalAddress.u.LowPart + (i * PAGESIZE)));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
}
|
||||
return ((PVOID)Result);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -46,7 +46,7 @@ VOID ExUnmapPage(PVOID Addr)
|
|||
DPRINT("i %x\n",i);
|
||||
|
||||
KeAcquireSpinLock(&AllocMapLock, &oldIrql);
|
||||
MmSetPage(NULL, (PVOID)Addr, 0, 0);
|
||||
MmDeleteVirtualMapping(NULL, (PVOID)Addr, FALSE);
|
||||
clear_bit(i%32, &alloc_map[i/32]);
|
||||
KeReleaseSpinLock(&AllocMapLock, oldIrql);
|
||||
}
|
||||
|
@ -57,6 +57,7 @@ PVOID ExAllocatePage(VOID)
|
|||
ULONG addr;
|
||||
ULONG i;
|
||||
ULONG PhysPage;
|
||||
NTSTATUS Status;
|
||||
|
||||
PhysPage = (ULONG)MmAllocPage(0);
|
||||
DPRINT("Allocated page %x\n",PhysPage);
|
||||
|
@ -73,7 +74,15 @@ PVOID ExAllocatePage(VOID)
|
|||
DPRINT("i %x\n",i);
|
||||
set_bit(i%32,&alloc_map[i/32]);
|
||||
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);
|
||||
return((PVOID)addr);
|
||||
}
|
||||
|
|
|
@ -312,10 +312,9 @@ NTSTATUS MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
|
|||
{
|
||||
// DPRINT("Freeing %x in kernel address space\n");
|
||||
}
|
||||
MmSetPage(AddressSpace->Process,
|
||||
MmDeleteVirtualMapping(AddressSpace->Process,
|
||||
MemoryArea->BaseAddress + (i*PAGESIZE),
|
||||
0,
|
||||
0);
|
||||
FALSE);
|
||||
}
|
||||
|
||||
RemoveEntryList(&(MemoryArea->Entry));
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -112,10 +112,15 @@ PVOID STDCALL MmMapLockedPages(PMDL Mdl, KPROCESSOR_MODE AccessMode)
|
|||
MdlPages = (PULONG)(Mdl + 1);
|
||||
for (i=0; i<(PAGE_ROUND_UP(Mdl->ByteCount+Mdl->ByteOffset)/PAGESIZE); i++)
|
||||
{
|
||||
MmSetPage(NULL,
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
(PVOID)((ULONG)Base+(i*PAGESIZE)),
|
||||
PAGE_READWRITE,
|
||||
MdlPages[i]);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
}
|
||||
MmUnlockAddressSpace(MmGetKernelAddressSpace());
|
||||
Mdl->MdlFlags = Mdl->MdlFlags | MDL_MAPPED_TO_SYSTEM_VA;
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -56,7 +56,7 @@ NTSTATUS MmReleaseMemoryArea(PEPROCESS Process, PMEMORY_AREA Marea)
|
|||
i < (Marea->BaseAddress + Marea->Length);
|
||||
i = i+PAGESIZE)
|
||||
{
|
||||
MmDeletePageEntry(Process, i, TRUE);
|
||||
MmDeleteVirtualMapping(Process, i, TRUE);
|
||||
}
|
||||
ExFreePool(Marea);
|
||||
|
||||
|
@ -198,11 +198,10 @@ NTSTATUS MmNotPresentFault(KPROCESSOR_MODE Mode,
|
|||
break;
|
||||
|
||||
case MEMORY_AREA_SHARED_DATA:
|
||||
MmSetPage(PsGetCurrentProcess(),
|
||||
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
||||
(PVOID)PAGE_ROUND_DOWN(Address),
|
||||
PAGE_READONLY,
|
||||
(ULONG)MmSharedDataPagePhysicalAddress);
|
||||
Status = STATUS_SUCCESS;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -85,6 +85,7 @@ VOID MmInitVirtualMemory(PLOADER_PARAMETER_BLOCK bp, ULONG LastKernelAddress)
|
|||
PVOID BaseAddress;
|
||||
ULONG Length;
|
||||
ULONG ParamLength = kernel_len;
|
||||
NTSTATUS Status;
|
||||
|
||||
DPRINT("MmInitVirtualMemory(%x)\n",bp);
|
||||
|
||||
|
@ -155,10 +156,15 @@ VOID MmInitVirtualMemory(PLOADER_PARAMETER_BLOCK bp, ULONG LastKernelAddress)
|
|||
0,
|
||||
&kernel_shared_data_desc);
|
||||
MmSharedDataPagePhysicalAddress = MmAllocPage(0);
|
||||
MmSetPage(NULL,
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
(PVOID)KERNEL_SHARED_DATA_BASE,
|
||||
PAGE_READWRITE,
|
||||
(ULONG)MmSharedDataPagePhysicalAddress);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
((PKUSER_SHARED_DATA)KERNEL_SHARED_DATA_BASE)->TickCountLow = 0xdeadbeef;
|
||||
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=i+PAGESIZE)
|
||||
{
|
||||
MmSetPage(NULL, (PVOID)(i), PAGE_NOACCESS, 0);
|
||||
MmDeleteVirtualMapping(NULL, (PVOID)(i), FALSE);
|
||||
}
|
||||
DPRINT("Almost done MmInit()\n");
|
||||
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -65,10 +65,15 @@ PVOID STDCALL MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
|
|||
}
|
||||
for (i = 0; (i <= (NumberOfBytes / PAGESIZE)); i++)
|
||||
{
|
||||
MmSetPage (NULL,
|
||||
Status = MmCreateVirtualMapping (NULL,
|
||||
(Result + (i * PAGESIZE)),
|
||||
PAGE_READWRITE,
|
||||
(ULONG)MmAllocPage(0));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
}
|
||||
return ((PVOID)Result);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -374,16 +374,22 @@ static block_hdr* grow_kernel_pool(unsigned int size)
|
|||
block_hdr* used_blk=NULL;
|
||||
block_hdr* free_blk=NULL;
|
||||
int i;
|
||||
NTSTATUS Status;
|
||||
|
||||
OLD_DPRINT("growing heap for block size %d, ",size);
|
||||
OLD_DPRINT("start %x\n",start);
|
||||
|
||||
for (i=0;i<nr_pages;i++)
|
||||
{
|
||||
MmSetPage(NULL,
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
(PVOID)(start + (i*PAGESIZE)),
|
||||
PAGE_READWRITE,
|
||||
(ULONG)MmAllocPage(0));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -148,10 +148,15 @@ NTSTATUS MmUnalignedLoadPageForSection(PMADDRESS_SPACE AddressSpace,
|
|||
MmLockAddressSpace(AddressSpace);
|
||||
MmLockSection(Section);
|
||||
|
||||
MmSetPage(NULL,
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
Address,
|
||||
MemoryArea->Attributes,
|
||||
(ULONG)Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
MmUnlockSection(Section);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
|
@ -246,10 +251,15 @@ NTSTATUS MmWaitForPendingOperationSection(PMADDRESS_SPACE AddressSpace,
|
|||
* and have a reference to a page containing valid data for the
|
||||
* section offset. Set the page and return success.
|
||||
*/
|
||||
MmSetPage(NULL,
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
Address,
|
||||
MemoryArea->Attributes,
|
||||
(ULONG)Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
MmUnlockSection(Section);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
|
@ -350,10 +360,15 @@ NTSTATUS MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
|||
Page = (PVOID)Entry;
|
||||
MmReferencePage(Page);
|
||||
|
||||
MmSetPage(NULL,
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
Address,
|
||||
MemoryArea->Attributes,
|
||||
(ULONG)Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
MmUnlockSection(Section);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
|
@ -434,10 +449,15 @@ NTSTATUS MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
|||
*/
|
||||
MmSetWaitPage(Page);
|
||||
|
||||
MmSetPage(NULL,
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
Address,
|
||||
MemoryArea->Attributes,
|
||||
(ULONG)Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
MmUnlockSection(Section);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
|
@ -462,10 +482,15 @@ NTSTATUS MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
|
|||
Page = (PVOID)Entry;
|
||||
MmReferencePage(Page);
|
||||
|
||||
MmSetPage(NULL,
|
||||
Status = MmCreateVirtualMapping(NULL,
|
||||
Address,
|
||||
MemoryArea->Attributes,
|
||||
(ULONG)Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
MmUnlockSection(Section);
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
|
@ -1024,10 +1049,15 @@ PVOID STDCALL MmAllocateSection (IN ULONG Length)
|
|||
DPRINT("Result %p\n",Result);
|
||||
for (i = 0; (i <= (Length / PAGESIZE)); i++)
|
||||
{
|
||||
MmSetPage (NULL,
|
||||
Status = MmCreateVirtualMapping (NULL,
|
||||
(Result + (i * PAGESIZE)),
|
||||
PAGE_READWRITE,
|
||||
(ULONG)MmAllocPage(0));
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DbgPrint("Unable to create virtual mapping\n");
|
||||
KeBugCheck(0);
|
||||
}
|
||||
}
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
return ((PVOID)Result);
|
||||
|
|
|
@ -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
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -189,10 +189,7 @@ ULONG MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
|||
|
||||
MmRemovePageFromWorkingSet(AddressSpace->Process,
|
||||
Address);
|
||||
MmSetPage(PsGetCurrentProcess(),
|
||||
Address,
|
||||
0,
|
||||
0);
|
||||
MmDeleteVirtualMapping(PsGetCurrentProcess(), Address, FALSE);
|
||||
MmDereferencePage((PVOID)PhysicalAddress.u.LowPart);
|
||||
*Ul = TRUE;
|
||||
return(1);
|
||||
|
@ -219,6 +216,9 @@ NTSTATUS MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
|||
PMM_SEGMENT Segment;
|
||||
PVOID CurrentAddress;
|
||||
|
||||
/*
|
||||
* Get the segment corresponding to the virtual address
|
||||
*/
|
||||
Segment = MmGetSegmentForAddress(MemoryArea, Address, &CurrentAddress);
|
||||
if (Segment == NULL)
|
||||
{
|
||||
|
@ -234,6 +234,9 @@ NTSTATUS MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
|||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to allocate a page
|
||||
*/
|
||||
Page = MmAllocPage(0);
|
||||
while (Page == NULL)
|
||||
{
|
||||
|
@ -246,8 +249,21 @@ NTSTATUS MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
|||
}
|
||||
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);
|
||||
MmWaitForFreePages();
|
||||
|
@ -257,13 +273,15 @@ NTSTATUS MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
|
|||
MmDereferencePage(Page);
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
Status = MmCreatePageTable(Address);
|
||||
}
|
||||
MmAddPageToWorkingSet(PsGetCurrentProcess(), Address);
|
||||
MmSetPage(PsGetCurrentProcess(),
|
||||
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
|
||||
Address,
|
||||
MemoryArea->Attributes,
|
||||
(ULONG)Page);
|
||||
}
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
}
|
||||
|
@ -275,6 +293,9 @@ VOID MmModifyAttributes(PMADDRESS_SPACE AddressSpace,
|
|||
ULONG OldProtect,
|
||||
ULONG NewType,
|
||||
ULONG NewProtect)
|
||||
/*
|
||||
* FUNCTION: Modify the attributes of a memory region
|
||||
*/
|
||||
{
|
||||
if (NewType == MEM_RESERVE &&
|
||||
OldType == MEM_COMMIT)
|
||||
|
@ -314,6 +335,9 @@ VOID MmModifyAttributes(PMADDRESS_SPACE AddressSpace,
|
|||
|
||||
VOID InsertAfterEntry(PLIST_ENTRY Previous,
|
||||
PLIST_ENTRY Entry)
|
||||
/*
|
||||
* FUNCTION: Insert a list entry after another entry in the list
|
||||
*/
|
||||
{
|
||||
Previous->Flink->Blink = Entry;
|
||||
|
||||
|
@ -323,78 +347,127 @@ VOID InsertAfterEntry(PLIST_ENTRY Previous,
|
|||
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,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PVOID BaseAddress,
|
||||
ULONG RegionSize,
|
||||
PVOID RegionAddress,
|
||||
ULONG RegionLength,
|
||||
ULONG Type,
|
||||
ULONG Protect,
|
||||
PMM_SEGMENT CurrentSegment,
|
||||
PVOID CurrentAddress)
|
||||
PMM_SEGMENT FirstSegment,
|
||||
PVOID FirstAddress)
|
||||
/*
|
||||
* FUNCTION: Split a memory segment internally
|
||||
*/
|
||||
{
|
||||
PMM_SEGMENT NewSegment;
|
||||
PMM_SEGMENT NewTopSegment;
|
||||
PMM_SEGMENT PreviousSegment;
|
||||
PMM_SEGMENT RegionSegment;
|
||||
ULONG OldType;
|
||||
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)
|
||||
{
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
/*
|
||||
* Allocate the segment we might need here because if the allocation
|
||||
* fails below it will be difficult to undo what we've done already.
|
||||
*/
|
||||
NewTopSegment = ExAllocatePool(NonPagedPool, sizeof(MM_SEGMENT));
|
||||
if (NewTopSegment == NULL)
|
||||
{
|
||||
ExFreePool(NewSegment);
|
||||
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);
|
||||
}
|
||||
|
||||
if (CurrentAddress < BaseAddress)
|
||||
if (FirstAddress < RegionAddress)
|
||||
{
|
||||
NewSegment->Type = Type;
|
||||
NewSegment->Protect = Protect;
|
||||
NewSegment->Length = RegionSize;
|
||||
/*
|
||||
* If the region to be affected starts at a higher address than
|
||||
* 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,
|
||||
&NewSegment->SegmentListEntry);
|
||||
FirstSegment->Length = RegionAddress - FirstAddress;
|
||||
|
||||
PreviousSegment = NewSegment;
|
||||
InsertAfterEntry(&FirstSegment->SegmentListEntry,
|
||||
&RegionSegment->SegmentListEntry);
|
||||
}
|
||||
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);
|
||||
NewSegment = NULL;
|
||||
RegionSegment = FirstSegment;
|
||||
}
|
||||
|
||||
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->Protect = OldProtect;
|
||||
NewTopSegment->Length =
|
||||
(CurrentAddress + CurrentSegment->Length) -
|
||||
(BaseAddress + RegionSize);
|
||||
NewTopSegment->Length = (FirstAddress + OldLength) -
|
||||
(RegionAddress + RegionLength);
|
||||
|
||||
InsertAfterEntry(&PreviousSegment->SegmentListEntry,
|
||||
InsertAfterEntry(&RegionSegment->SegmentListEntry,
|
||||
&NewTopSegment->SegmentListEntry);
|
||||
}
|
||||
else
|
||||
|
@ -403,19 +476,27 @@ NTSTATUS MmSplitSegment(PMADDRESS_SPACE AddressSpace,
|
|||
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);
|
||||
}
|
||||
|
||||
NTSTATUS MmGatherSegment(PMADDRESS_SPACE AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PVOID BaseAddress,
|
||||
ULONG RegionSize,
|
||||
PVOID RegionAddress,
|
||||
ULONG RegionLength,
|
||||
ULONG Type,
|
||||
ULONG Protect,
|
||||
PMM_SEGMENT CurrentSegment,
|
||||
PVOID CurrentAddress)
|
||||
PMM_SEGMENT FirstSegment,
|
||||
PVOID FirstAddress)
|
||||
/*
|
||||
* FUNCTION: Do a virtual memory operation that will effect several
|
||||
* memory segments.
|
||||
|
@ -432,53 +513,46 @@ NTSTATUS MmGatherSegment(PMADDRESS_SPACE AddressSpace,
|
|||
* RETURNS: Status
|
||||
*/
|
||||
{
|
||||
PMM_SEGMENT NewSegment;
|
||||
PMM_SEGMENT NewTopSegment;
|
||||
PMM_SEGMENT PreviousSegment;
|
||||
PVOID LAddress;
|
||||
ULONG RSize;
|
||||
PMM_SEGMENT RegionSegment;
|
||||
PVOID CurrentAddress;
|
||||
ULONG RemainingLength;
|
||||
PLIST_ENTRY CurrentEntry;
|
||||
PLIST_ENTRY ListHead;
|
||||
PMM_SEGMENT CurrentSegment;
|
||||
|
||||
/*
|
||||
* 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 (FirstAddress < RegionAddress)
|
||||
{
|
||||
/*
|
||||
* If a portion of the first segment is not covered by the region then
|
||||
* we need to split it into two segments
|
||||
*/
|
||||
|
||||
NewSegment->Type = Type;
|
||||
NewSegment->Protect = Protect;
|
||||
NewSegment->Length = RegionSize;
|
||||
RegionSegment = ExAllocatePool(NonPagedPool, sizeof(MM_SEGMENT));
|
||||
if (RegionSegment == NULL)
|
||||
{
|
||||
return(STATUS_NO_MEMORY);
|
||||
}
|
||||
|
||||
CurrentSegment->Length =
|
||||
BaseAddress - CurrentAddress;
|
||||
RegionSegment->Type = Type;
|
||||
RegionSegment->Protect = Protect;
|
||||
RegionSegment->Length = (FirstAddress + FirstSegment->Length) -
|
||||
RegionAddress;
|
||||
|
||||
InsertAfterEntry(&CurrentSegment->SegmentListEntry,
|
||||
&NewSegment->SegmentListEntry);
|
||||
FirstSegment->Length = RegionAddress - FirstAddress;
|
||||
|
||||
PreviousSegment = NewSegment;
|
||||
InsertAfterEntry(&FirstSegment->SegmentListEntry,
|
||||
&RegionSegment->SegmentListEntry);
|
||||
|
||||
MmModifyAttributes(AddressSpace, BaseAddress, NewSegment->Length,
|
||||
CurrentSegment->Type,
|
||||
CurrentSegment->Protect, Type, Protect);
|
||||
MmModifyAttributes(AddressSpace,
|
||||
RegionAddress,
|
||||
RegionSegment->Length,
|
||||
FirstSegment->Type,
|
||||
FirstSegment->Protect,
|
||||
Type,
|
||||
Protect);
|
||||
|
||||
CurrentAddress = FirstAddress + FirstSegment->Length +
|
||||
RegionSegment->Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -489,75 +563,106 @@ NTSTATUS MmGatherSegment(PMADDRESS_SPACE AddressSpace,
|
|||
ULONG OldType;
|
||||
ULONG OldProtect;
|
||||
|
||||
OldType = CurrentSegment->Type;
|
||||
OldProtect = CurrentSegment->Protect;
|
||||
OldType = FirstSegment->Type;
|
||||
OldProtect = FirstSegment->Protect;
|
||||
|
||||
CurrentSegment->Type = Type;
|
||||
CurrentSegment->Protect = Protect;
|
||||
FirstSegment->Type = Type;
|
||||
FirstSegment->Protect = Protect;
|
||||
|
||||
PreviousSegment = CurrentSegment;
|
||||
RegionSegment = FirstSegment;
|
||||
|
||||
ExFreePool(NewSegment);
|
||||
NewSegment = NULL;
|
||||
MmModifyAttributes(AddressSpace,
|
||||
RegionAddress,
|
||||
FirstSegment->Length,
|
||||
OldType,
|
||||
OldProtect,
|
||||
Type,
|
||||
Protect);
|
||||
|
||||
MmModifyAttributes(AddressSpace, BaseAddress, CurrentSegment->Length,
|
||||
OldType, OldProtect, Type, Protect);
|
||||
CurrentAddress = FirstAddress + RegionSegment->Length;
|
||||
}
|
||||
|
||||
LAddress = BaseAddress + PreviousSegment->Length;
|
||||
RSize = RegionSize - PreviousSegment->Length;
|
||||
CurrentEntry = PreviousSegment->SegmentListEntry.Flink;
|
||||
ListHead = &MemoryArea->Data.VirtualMemoryData.SegmentListHead;
|
||||
|
||||
while (CurrentEntry != ListHead && RSize > 0)
|
||||
{
|
||||
ULONG OldType;
|
||||
ULONG OldProtect;
|
||||
|
||||
/*
|
||||
* Change the attributes of all the complete segments lying inside the
|
||||
* affected region
|
||||
*/
|
||||
RemainingLength = RegionLength - RegionSegment->Length;
|
||||
CurrentEntry = RegionSegment->SegmentListEntry.Flink;
|
||||
CurrentSegment = CONTAINING_RECORD(CurrentEntry,
|
||||
MM_SEGMENT,
|
||||
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;
|
||||
}
|
||||
|
||||
OldType = CurrentSegment->Type;
|
||||
OldProtect = CurrentSegment->Protect;
|
||||
CurrentSegment->Type = Type;
|
||||
CurrentSegment->Protect = Protect;
|
||||
|
||||
MmModifyAttributes(AddressSpace, LAddress, CurrentSegment->Length,
|
||||
OldType, OldProtect, Type, Protect);
|
||||
|
||||
RSize = RSize - CurrentSegment->Length;
|
||||
LAddress = LAddress + CurrentSegment->Length;
|
||||
OldLength = 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;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
if (RSize > 0)
|
||||
/*
|
||||
* We've only affected a portion of a segment then split it in two
|
||||
*/
|
||||
if (RemainingLength > 0)
|
||||
{
|
||||
NewTopSegment->Type = CurrentSegment->Type;
|
||||
NewTopSegment->Protect = CurrentSegment->Protect;
|
||||
NewTopSegment->Length = CurrentSegment->Length - RSize;
|
||||
CurrentSegment->Length = CurrentSegment->Length - RemainingLength;
|
||||
|
||||
CurrentSegment->Length = RSize;
|
||||
CurrentSegment->Type = Type;
|
||||
CurrentSegment->Protect = Protect;
|
||||
RegionSegment->Length = RegionSegment->Length + RemainingLength;
|
||||
|
||||
InsertAfterEntry(&CurrentSegment->SegmentListEntry,
|
||||
&NewTopSegment->SegmentListEntry);
|
||||
|
||||
MmModifyAttributes(AddressSpace, LAddress, RSize,
|
||||
NewTopSegment->Type,
|
||||
NewTopSegment->Protect, Type, Protect);
|
||||
MmModifyAttributes(AddressSpace,
|
||||
CurrentAddress,
|
||||
RemainingLength,
|
||||
CurrentSegment->Type,
|
||||
CurrentSegment->Protect,
|
||||
Type,
|
||||
Protect);
|
||||
}
|
||||
|
||||
return(STATUS_SUCCESS);
|
||||
|
|
Loading…
Reference in a new issue