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)
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

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 = ../../..
@ -20,6 +20,7 @@ clean:
- $(RM) base.tmp
- $(RM) temp.exp
- $(RM) blue.sys
- $(RM) blue.sys.unstripped
.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 = ../../..
@ -20,7 +20,7 @@ clean:
- $(RM) base.tmp
- $(RM) temp.exp
- $(RM) $(TARGET).sys
- $(RM) $(TARGET).nostrip.sys
- $(RM) $(TARGET).sys.unstripped
.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 = ../../..
@ -20,6 +20,7 @@ clean:
- $(RM) base.tmp
- $(RM) temp.exp
- $(RM) $(TARGET).sys
- $(RM) $(TARGET).sys.unstripped
.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/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

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
* PROJECT: ReactOS kernel
@ -119,10 +119,10 @@ NTSTATUS STDCALL CcRequestCachePage(PBCB Bcb,
*BaseAddress = current->BaseAddress;
*CacheSeg = current;
CHECKPOINT;
MmSetPage(NULL,
current->BaseAddress,
PAGE_READWRITE,
(ULONG)MmAllocPage(0));
MmCreateVirtualMapping(NULL,
current->BaseAddress,
PAGE_READWRITE,
(ULONG)MmAllocPage(0));
DPRINT("Returning %x (BaseAddress %x)\n", current, *BaseAddress);

View file

@ -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,10 +48,10 @@ 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,
PVOID Address,
ULONG flProtect,
ULONG PhysicalAddress);
NTSTATUS MmCreateVirtualMapping(struct _EPROCESS* Process,
PVOID Address,
ULONG flProtect,
ULONG PhysicalAddress);
VOID MmSetPageProtect(struct _EPROCESS* Process,

View file

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

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
* 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);
AddressSpace->LowestAddress = MM_LOWEST_USER_ADDRESS;
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);
}

View file

@ -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)),
PAGE_READWRITE,
(ULONG)(LastPhysKernelAddress - (i * PAGESIZE)));
Status = MmCreateVirtualMapping(NULL,
(PVOID)((ULONG)MmPageArray +
(i * PAGESIZE)),
PAGE_READWRITE,
(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
* 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)
{
DbgPrint("MmDeletePageEntry(Address %x) Physical %x "
"Entry %x\n",
Address, PAGE_MASK(*page_tlb),
*page_tlb);
KeBugCheck(0);
}
MmDereferencePage((PVOID)PAGE_MASK(*page_tlb));
MmDereferencePage((PVOID)PAGE_MASK(*Pte));
}
*Pte = 0;
if (Process != NULL &&
Process->AddressSpace.PageTableRefCountTable != NULL &&
ADDR_TO_PAGE_TABLE(Address) < 768)
{
PUSHORT Ptrc;
Ptrc = Process->AddressSpace.PageTableRefCountTable;
Ptrc[ADDR_TO_PAGE_TABLE(Address)]--;
if (Ptrc[ADDR_TO_PAGE_TABLE(Address)] == 0)
{
MmFreePageTable(Process, Address);
}
}
*page_tlb = 0;
if (Process != NULL && Process != CurrentProcess)
{
KeDetachProcess();
@ -323,20 +391,15 @@ BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
}
VOID MmSetPage(PEPROCESS Process,
PVOID Address,
ULONG flProtect,
ULONG PhysicalAddress)
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,

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
* PROJECT: ReactOS kernel
@ -76,10 +76,15 @@ PVOID STDCALL MmMapIoSpace (IN PHYSICAL_ADDRESS PhysicalAddress,
}
for (i = 0; (i <= (NumberOfBytes / PAGESIZE)); i++)
{
MmSetPage (NULL,
(Result + (i * PAGESIZE)),
PAGE_READWRITE,
(PhysicalAddress.u.LowPart + (i * PAGESIZE)));
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);
}

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
* 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);
}

View file

@ -312,10 +312,9 @@ NTSTATUS MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
{
// DPRINT("Freeing %x in kernel address space\n");
}
MmSetPage(AddressSpace->Process,
MemoryArea->BaseAddress + (i*PAGESIZE),
0,
0);
MmDeleteVirtualMapping(AddressSpace->Process,
MemoryArea->BaseAddress + (i*PAGESIZE),
FALSE);
}
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
* 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,
(PVOID)((ULONG)Base+(i*PAGESIZE)),
PAGE_READWRITE,
MdlPages[i]);
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;

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
* 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(),
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READONLY,
(ULONG)MmSharedDataPagePhysicalAddress);
Status = STATUS_SUCCESS;
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
(PVOID)PAGE_ROUND_DOWN(Address),
PAGE_READONLY,
(ULONG)MmSharedDataPagePhysicalAddress);
break;
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
* 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,
(PVOID)KERNEL_SHARED_DATA_BASE,
PAGE_READWRITE,
(ULONG)MmSharedDataPagePhysicalAddress);
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");

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
* PROJECT: ReactOS kernel
@ -65,11 +65,16 @@ PVOID STDCALL MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
}
for (i = 0; (i <= (NumberOfBytes / PAGESIZE)); i++)
{
MmSetPage (NULL,
(Result + (i * PAGESIZE)),
PAGE_READWRITE,
(ULONG)MmAllocPage(0));
}
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);
}

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
* 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,
(PVOID)(start + (i*PAGESIZE)),
PAGE_READWRITE,
(ULONG)MmAllocPage(0));
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);
}
}

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
* PROJECT: ReactOS kernel
@ -148,10 +148,15 @@ NTSTATUS MmUnalignedLoadPageForSection(PMADDRESS_SPACE AddressSpace,
MmLockAddressSpace(AddressSpace);
MmLockSection(Section);
MmSetPage(NULL,
Address,
MemoryArea->Attributes,
(ULONG)Page);
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,
Address,
MemoryArea->Attributes,
(ULONG)Page);
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,
Address,
MemoryArea->Attributes,
(ULONG)Page);
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,
Address,
MemoryArea->Attributes,
(ULONG)Page);
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,
Address,
MemoryArea->Attributes,
(ULONG)Page);
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,
(Result + (i * PAGESIZE)),
PAGE_READWRITE,
(ULONG)MmAllocPage(0));
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);

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
* 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);
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
Address,
MemoryArea->Attributes,
(ULONG)Page);
}
if (!NT_SUCCESS(Status))
{
return(Status);
}
MmAddPageToWorkingSet(PsGetCurrentProcess(), Address);
MmSetPage(PsGetCurrentProcess(),
Address,
MemoryArea->Attributes,
(ULONG)Page);
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;
/*
* 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;
while (CurrentEntry != ListHead && RSize > 0)
while (CurrentEntry != ListHead && RemainingLength > 0)
{
ULONG OldType;
ULONG OldProtect;
ULONG OldLength;
CurrentSegment = CONTAINING_RECORD(CurrentEntry,
MM_SEGMENT,
SegmentListEntry);
if (CurrentSegment->Length > RSize)
/*
* 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);