mirror of
https://github.com/reactos/reactos.git
synced 2024-12-27 01:24:38 +00:00
Improved physical page managment
svn path=/trunk/; revision=353
This commit is contained in:
parent
e4bcefde7d
commit
572d45daca
21 changed files with 285 additions and 295 deletions
|
@ -50,41 +50,13 @@ struct _KDPC;
|
|||
|
||||
typedef struct _KTIMER
|
||||
{
|
||||
/*
|
||||
* Pointers to maintain the linked list of activated timers
|
||||
*/
|
||||
LIST_ENTRY entry;
|
||||
|
||||
/*
|
||||
* Absolute expiration time in system time units
|
||||
*/
|
||||
signed long long expire_time;
|
||||
|
||||
/*
|
||||
* Optional dpc associated with the timer
|
||||
*/
|
||||
struct _KDPC* dpc;
|
||||
|
||||
/*
|
||||
* True if the timer is signaled
|
||||
*/
|
||||
BOOLEAN signaled;
|
||||
|
||||
/*
|
||||
* True if the timer is in the system timer queue
|
||||
*/
|
||||
BOOLEAN running;
|
||||
|
||||
/*
|
||||
* Type of the timer either Notification or Synchronization
|
||||
*/
|
||||
TIMER_TYPE type;
|
||||
|
||||
/*
|
||||
* Period of the timer in milliseconds (zero if once-only)
|
||||
*/
|
||||
ULONG period;
|
||||
|
||||
ULONG period;
|
||||
} KTIMER, *PKTIMER;
|
||||
|
||||
struct _KSPIN_LOCK;
|
||||
|
|
|
@ -33,3 +33,7 @@ typedef struct _MDL
|
|||
ULONG ByteCount;
|
||||
ULONG ByteOffset;
|
||||
} MDL, *PMDL;
|
||||
|
||||
#define MmSmallSystem (0)
|
||||
#define MmMediumSystem (1)
|
||||
#define MmLargeSystem (2)
|
||||
|
|
|
@ -28,23 +28,6 @@ PULONG MmGetPageEntry(PVOID Address);
|
|||
#define PA_SYSTEM (0)
|
||||
|
||||
#define KERNEL_BASE (0xc0000000)
|
||||
#define IDMAP_BASE (0xd0000000)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Return a linear address which can be used to access the physical memory
|
||||
* starting at x
|
||||
*/
|
||||
extern inline unsigned int physical_to_linear(unsigned int x)
|
||||
{
|
||||
return(x+IDMAP_BASE);
|
||||
}
|
||||
|
||||
extern inline unsigned int linear_to_physical(unsigned int x)
|
||||
{
|
||||
return(x-IDMAP_BASE);
|
||||
}
|
||||
|
||||
#define FLUSH_TLB __asm__("movl %cr3,%eax\n\tmovl %eax,%cr3\n\t")
|
||||
|
||||
|
|
|
@ -73,37 +73,6 @@ NTSTATUS MmLockMemoryArea(MEMORY_AREA* MemoryArea);
|
|||
NTSTATUS MmUnlockMemoryArea(MEMORY_AREA* MemoryArea);
|
||||
NTSTATUS MmInitSectionImplementation(VOID);
|
||||
|
||||
|
||||
/*
|
||||
* FUNCTION: Gets a page with a restricted max physical address (i.e.
|
||||
* suitable for dma)
|
||||
* RETURNS:
|
||||
* The physical address of the page if it succeeds
|
||||
* NULL if it fails.
|
||||
* NOTES: This is very inefficent because the list isn't sorted. On the
|
||||
* other hand sorting the list would be quite expensive especially if dma
|
||||
* is only used infrequently. Perhaps a special cache of dma pages should
|
||||
* be maintained?
|
||||
*/
|
||||
unsigned int get_dma_page(unsigned int max_address);
|
||||
|
||||
/*
|
||||
* FUNCTION: Allocate a page and return its physical address
|
||||
* RETURNS: The physical address of the page allocated
|
||||
*/
|
||||
asmlinkage unsigned int get_free_page(void);
|
||||
|
||||
/*
|
||||
* FUNCTION: Adds pages to the free list
|
||||
* ARGUMENTS:
|
||||
* physical_base = Physical address of the base of the region to
|
||||
* be freed
|
||||
* nr = number of continuous pages to free
|
||||
*/
|
||||
asmlinkage void free_page(unsigned int physical_base, unsigned int nr);
|
||||
|
||||
void mark_page_not_writable(unsigned int vaddr);
|
||||
|
||||
void VirtualInit(boot_param* bp);
|
||||
|
||||
#define MM_LOWEST_USER_ADDRESS (4096)
|
||||
|
@ -114,5 +83,12 @@ PMEMORY_AREA MmSplitMemoryArea(PEPROCESS Process,
|
|||
ULONG Length,
|
||||
ULONG NewType,
|
||||
ULONG NewAttributes);
|
||||
PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
|
||||
PVOID LastPhysKernelAddress,
|
||||
ULONG MemorySizeInPages,
|
||||
ULONG LastKernelBase);
|
||||
|
||||
PVOID MmAllocPage(VOID);
|
||||
VOID MmFreePage(PVOID PhysicalAddress, ULONG Nr);
|
||||
VOID MmDeletePageTable(PEPROCESS Process, PVOID Address);
|
||||
#endif
|
||||
|
|
|
@ -84,7 +84,7 @@ VOID NtInit(VOID);
|
|||
/*
|
||||
* Initalization functions (called once by main())
|
||||
*/
|
||||
VOID MmInitialize(boot_param* bp);
|
||||
VOID MmInitialize(boot_param* bp, ULONG LastKernelAddress);
|
||||
VOID HalInit(boot_param* bp);
|
||||
VOID IoInit(VOID);
|
||||
VOID ObInit(VOID);
|
||||
|
|
|
@ -55,7 +55,7 @@ EXCEPT_OBJECTS = except/except.o
|
|||
|
||||
|
||||
OBJECTS = $(MISC_OBJECTS) $(FILE_OBJECTS) $(THREAD_OBJECTS) \
|
||||
$(PROCESS_OBJECTS) $(STRING_OBJECTS) $(MEM_OBJECTS) $(NLS_OBJECTS) \
|
||||
$(PROCESS_OBJECTS) $(STRING_OBJECTS) $(MEM_OBJECTS) \
|
||||
$(INTERNAL_OBJECTS) $(SYNCH_OBJECTS) $(EXCEPT_OBJECTS)
|
||||
|
||||
kernel32.a: $(OBJECTS)
|
||||
|
|
|
@ -29,7 +29,7 @@ LOADERS = dos
|
|||
#
|
||||
# Select the device drivers and filesystems you want
|
||||
#
|
||||
KERNEL_SERVICES = parallel keyboard blues null mouse serial sound ide \
|
||||
KERNEL_SERVICES = parallel keyboard blues null mouse serial ide \
|
||||
minix vfat ext2
|
||||
|
||||
APPS = hello shell args
|
||||
|
|
|
@ -12,10 +12,7 @@ __goxy
|
|||
__wherex
|
||||
__wherey
|
||||
__getscreensize
|
||||
free_page
|
||||
get_dma_page
|
||||
DbgPrint
|
||||
printk
|
||||
ExAcquireFastMutex
|
||||
ExAcquireFastMutexUnsafe
|
||||
ExAcquireResourceExclusive
|
||||
|
|
|
@ -65,6 +65,7 @@ static struct
|
|||
|
||||
#define BIOS32_SIGNATURE (('_' << 0)+('3'<<8)+('2'<<16)+('_'<<24))
|
||||
|
||||
#if 0
|
||||
BOOL static checksum(bios32* service_entry)
|
||||
/*
|
||||
* FUNCTION: Checks the checksum of a bios32 service entry
|
||||
|
@ -89,6 +90,7 @@ BOOL static checksum(bios32* service_entry)
|
|||
}
|
||||
return(FALSE);
|
||||
}
|
||||
#endif
|
||||
|
||||
BOOLEAN Hal_bios32_is_service_present(ULONG service)
|
||||
{
|
||||
|
@ -118,11 +120,13 @@ VOID Hal_bios32_probe()
|
|||
* RETURNS: True if detected
|
||||
*/
|
||||
{
|
||||
return;
|
||||
#if 0
|
||||
int i;
|
||||
|
||||
for (i=0xe0000;i<=0xffff0;i++)
|
||||
{
|
||||
bios32* service_entry = (bios32 *)physical_to_linear(i);
|
||||
/// bios32* service_entry = (bios32 *)physical_to_linear(i);
|
||||
if ( service_entry->signature != BIOS32_SIGNATURE )
|
||||
{
|
||||
continue;
|
||||
|
@ -136,4 +140,5 @@ VOID Hal_bios32_probe()
|
|||
bios32_indirect.address = service_entry->entry;
|
||||
bios32_detected=TRUE;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -214,11 +214,11 @@ asmlinkage void exception_handler(unsigned int edi,
|
|||
__asm__("movl %%cr2,%0\n\t"
|
||||
: "=d" (cr2));
|
||||
DbgPrint("cr2 %x\n",cr2);
|
||||
for(;;);
|
||||
DbgPrint("Process: %x\n",PsGetCurrentProcess());
|
||||
DbgPrint("Thread: %x\n",PsGetCurrentThread()->Cid.UniqueThread);
|
||||
DbgPrint("DS %x ES %x FS %x GS %x\n",ds&0xffff,es&0xffff,fs&0xffff,
|
||||
gs&0xfff);
|
||||
// for(;;);
|
||||
DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n",eax,ebx,ecx);
|
||||
DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n",edx,ebp,esi);
|
||||
DbgPrint("EDI: %.8x EFLAGS: %.8x ",edi,eflags);
|
||||
|
|
|
@ -57,6 +57,20 @@ static ULONG ProtectToPTE(ULONG flProtect)
|
|||
(((ULONG)v / (1024 * 1024))&(~0x3)))
|
||||
#define ADDR_TO_PTE(v) (PULONG)(PAGETABLE_MAP + ((ULONG)v / 1024))
|
||||
|
||||
VOID MmDeletePageTable(PEPROCESS Process, PVOID Address)
|
||||
{
|
||||
if (Process != NULL && Process != PsGetCurrentProcess())
|
||||
{
|
||||
KeAttachProcess(Process);
|
||||
}
|
||||
*(ADDR_TO_PDE(Address)) = 0;
|
||||
FLUSH_TLB;
|
||||
if (Process != NULL && Process != PsGetCurrentProcess())
|
||||
{
|
||||
KeDetachProcess();
|
||||
}
|
||||
}
|
||||
|
||||
ULONG MmGetPageEntryForProcess(PEPROCESS Process, PVOID Address)
|
||||
{
|
||||
ULONG Entry;
|
||||
|
@ -88,8 +102,7 @@ PULONG MmGetPageEntry(PVOID PAddress)
|
|||
DPRINT("page_dir %x *page_dir %x\n",page_dir,*page_dir);
|
||||
if ((*page_dir) == 0)
|
||||
{
|
||||
// (*page_dir) = get_free_page() | (PA_READ | PA_WRITE);
|
||||
(*page_dir) = get_free_page() | 0x7;
|
||||
(*page_dir) = ((ULONG)MmAllocPage()) | 0x7;
|
||||
FLUSH_TLB;
|
||||
}
|
||||
page_tlb = ADDR_TO_PTE(Address);
|
||||
|
|
|
@ -28,6 +28,23 @@
|
|||
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
#define IDMAP_BASE (0xd0000000)
|
||||
|
||||
/*
|
||||
* Return a linear address which can be used to access the physical memory
|
||||
* starting at x
|
||||
*/
|
||||
extern inline unsigned int physical_to_linear(unsigned int x)
|
||||
{
|
||||
return(x+IDMAP_BASE);
|
||||
}
|
||||
|
||||
extern inline unsigned int linear_to_physical(unsigned int x)
|
||||
{
|
||||
return(x-IDMAP_BASE);
|
||||
}
|
||||
|
||||
|
||||
#ifdef BOCHS_DEBUGGING
|
||||
#define BOCHS_LOGGER_PORT (0x3ed)
|
||||
#endif
|
||||
|
|
|
@ -119,6 +119,7 @@ asmlinkage void _main(boot_param* _bp)
|
|||
unsigned int start;
|
||||
unsigned int start1;
|
||||
boot_param bp;
|
||||
unsigned int last_kernel_address;
|
||||
|
||||
memset((void *)&edata,0,((int)&end)-((int)&edata));
|
||||
|
||||
|
@ -143,13 +144,19 @@ asmlinkage void _main(boot_param* _bp)
|
|||
for(;;);
|
||||
}
|
||||
start1 = start+PAGE_ROUND_UP(bp.module_length[1]);
|
||||
|
||||
|
||||
last_kernel_address = KERNEL_BASE;
|
||||
for (i=0; i<=bp.nr_files; i++)
|
||||
{
|
||||
last_kernel_address = last_kernel_address +
|
||||
PAGE_ROUND_UP(bp.module_length[i]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initalize various critical subsystems
|
||||
*/
|
||||
HalInit(&bp);
|
||||
MmInitialize(&bp);
|
||||
MmInitialize(&bp, last_kernel_address);
|
||||
KeInit();
|
||||
ObInit();
|
||||
PsInit();
|
||||
|
|
|
@ -31,6 +31,22 @@
|
|||
|
||||
/* GLOBALS ****************************************************************/
|
||||
|
||||
#define IDMAP_BASE (0xd0000000)
|
||||
|
||||
/*
|
||||
* Return a linear address which can be used to access the physical memory
|
||||
* starting at x
|
||||
*/
|
||||
extern inline unsigned int physical_to_linear(unsigned int x)
|
||||
{
|
||||
return(x+IDMAP_BASE);
|
||||
}
|
||||
|
||||
extern inline unsigned int linear_to_physical(unsigned int x)
|
||||
{
|
||||
return(x-IDMAP_BASE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Current time
|
||||
*/
|
||||
|
|
|
@ -3,20 +3,12 @@
|
|||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/mm/freelist.c
|
||||
* PURPOSE: Handle the list of free physical pages
|
||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||
* PROGRAMMER: David Welch (welch@cwcom.net)
|
||||
* UPDATE HISTORY:
|
||||
* 27/05/98: Created
|
||||
* 18/08/98: Added a fix from Robert Bergkvist
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: The list of free pages is implemented as an unsorted double linked
|
||||
* list. This should make added or removing pages fast when you don't care
|
||||
* about the physical address. Because the entirety of physical memory is
|
||||
* mapped from 0xd0000000 upwards it is easy to do a mapping between
|
||||
* physical and linear address.
|
||||
*/
|
||||
|
||||
/* INCLUDES ****************************************************************/
|
||||
|
||||
#include <internal/stddef.h>
|
||||
|
@ -24,6 +16,7 @@
|
|||
#include <internal/mm.h>
|
||||
#include <internal/ntoskrnl.h>
|
||||
#include <internal/bitops.h>
|
||||
#include <internal/i386/io.h>
|
||||
#include <ddk/ntddk.h>
|
||||
|
||||
#define NDEBUG
|
||||
|
@ -31,175 +24,175 @@
|
|||
|
||||
/* TYPES *******************************************************************/
|
||||
|
||||
typedef struct _free_page
|
||||
/*
|
||||
* PURPOSE: At the start of every region of free physical pages
|
||||
*/
|
||||
#define PHYSICAL_PAGE_FREE (0x1)
|
||||
#define PHYSICAL_PAGE_INUSE (0x2)
|
||||
#define PHYSICAL_PAGE_BIOS (0x4)
|
||||
|
||||
typedef struct _PHYSICAL_PAGE
|
||||
{
|
||||
struct _free_page* next;
|
||||
struct _free_page* previous;
|
||||
unsigned int nr_pages;
|
||||
} free_page_hdr;
|
||||
ULONG Flags;
|
||||
LIST_ENTRY ListEntry;
|
||||
} PHYSICAL_PAGE, *PPHYSICAL_PAGE;
|
||||
|
||||
/* GLOBALS ****************************************************************/
|
||||
|
||||
/*
|
||||
* PURPOSE: Points to the first page in the free list
|
||||
*/
|
||||
free_page_hdr* free_page_list_head=NULL;
|
||||
static PPHYSICAL_PAGE MmPageArray;
|
||||
|
||||
static LIST_ENTRY UsedPageListHead;
|
||||
static KSPIN_LOCK UsedPageListLock;
|
||||
static LIST_ENTRY FreePageListHead;
|
||||
static KSPIN_LOCK FreePageListLock;
|
||||
static LIST_ENTRY BiosPageListHead;
|
||||
static KSPIN_LOCK BiosPageListLock;
|
||||
|
||||
/* FUNCTIONS *************************************************************/
|
||||
|
||||
void free_page(unsigned int physical_base, unsigned int nr)
|
||||
PVOID MmInitializePageList(PVOID FirstPhysKernelAddress,
|
||||
PVOID LastPhysKernelAddress,
|
||||
ULONG MemorySizeInPages,
|
||||
ULONG LastKernelAddress)
|
||||
/*
|
||||
* FUNCTION: Add a physically continuous range of pages to the free list
|
||||
* FUNCTION: Initializes the page list with all pages free
|
||||
* except those known to be reserved and those used by the kernel
|
||||
* ARGUMENTS:
|
||||
* physical_base = The first physical address to free
|
||||
* nr = the size of the region (in pages) to free
|
||||
* NOTES: This function attempts to keep the list partially unfragmented
|
||||
* PageBuffer = Page sized buffer
|
||||
* FirstKernelAddress = First physical address used by the kernel
|
||||
* LastKernelAddress = Last physical address used by the kernel
|
||||
*/
|
||||
{
|
||||
unsigned int eflags;
|
||||
free_page_hdr* hdr=NULL;
|
||||
|
||||
DPRINT("Freeing %x to %x\n",physical_base,physical_base
|
||||
+ (nr*PAGESIZE));
|
||||
ULONG i;
|
||||
ULONG Reserved;
|
||||
|
||||
/*
|
||||
* This must be atomic
|
||||
*/
|
||||
__asm__("pushf\n\tpop %0\n\tcli\n\t"
|
||||
: "=d" (eflags));
|
||||
DPRINT("MmInitializePageList(FirstPhysKernelAddress %x, "
|
||||
"LastPhysKernelAddress %x, "
|
||||
"MemorySizeInPages %x, LastKernelAddress %x)\n",
|
||||
FirstPhysKernelAddress,
|
||||
LastPhysKernelAddress,
|
||||
MemorySizeInPages,
|
||||
LastKernelAddress);
|
||||
|
||||
/*
|
||||
*
|
||||
*/
|
||||
hdr = (free_page_hdr *)physical_to_linear(physical_base);
|
||||
InitializeListHead(&UsedPageListHead);
|
||||
KeInitializeSpinLock(&UsedPageListLock);
|
||||
InitializeListHead(&FreePageListHead);
|
||||
KeInitializeSpinLock(&FreePageListLock);
|
||||
InitializeListHead(&BiosPageListHead);
|
||||
KeInitializeSpinLock(&BiosPageListLock);
|
||||
|
||||
DPRINT("free_page_hdr %x\n",hdr);
|
||||
DPRINT("free_page_list_head %x\n",free_page_list_head);
|
||||
Reserved = (MemorySizeInPages * sizeof(PHYSICAL_PAGE)) / PAGESIZE;
|
||||
MmPageArray = (PHYSICAL_PAGE *)LastKernelAddress;
|
||||
|
||||
if (free_page_list_head!=NULL)
|
||||
DPRINT("Reserved %d\n", Reserved);
|
||||
|
||||
i = 1;
|
||||
if ((ULONG)FirstPhysKernelAddress < 0xa0000)
|
||||
{
|
||||
free_page_list_head->previous=hdr;
|
||||
}
|
||||
hdr->next=free_page_list_head;
|
||||
hdr->previous=NULL;
|
||||
hdr->nr_pages = nr;
|
||||
free_page_list_head=hdr;
|
||||
|
||||
__asm__("push %0\n\tpopf\n\t"
|
||||
:
|
||||
: "d" (eflags));
|
||||
}
|
||||
|
||||
unsigned int get_dma_page(unsigned int max_address)
|
||||
/*
|
||||
* FUNCTION: Gets a page with a restricted max physical address (i.e.
|
||||
* suitable for dma)
|
||||
* ARGUMENTS:
|
||||
* max_address = The maximum address usable by the caller
|
||||
* RETURNS:
|
||||
* The physical address of the page if it succeeds
|
||||
* NULL if it fails.
|
||||
* NOTES: This is very inefficent because the list isn't sorted. On the
|
||||
* other hand sorting the list would be quite expensive especially if dma
|
||||
* is only used infrequently. Perhaps a special cache of dma pages should
|
||||
* be maintained?
|
||||
*/
|
||||
{
|
||||
free_page_hdr* current=NULL;
|
||||
|
||||
if (free_page_list_head==NULL)
|
||||
{
|
||||
printk("CRITICAL: Unable to allocate page\n");
|
||||
KeBugCheck(KBUG_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
/*
|
||||
* Walk the free page list looking for suitable memory
|
||||
*/
|
||||
current = free_page_list_head;
|
||||
while (current!=NULL)
|
||||
{
|
||||
if ( ((int)current) < max_address)
|
||||
for (; i<((ULONG)FirstPhysKernelAddress/PAGESIZE); i++)
|
||||
{
|
||||
/*
|
||||
* We take the first page from the region
|
||||
*/
|
||||
free_page_hdr* nhdr = (free_page_hdr *)(((int)current)+PAGESIZE);
|
||||
if (current->previous!=NULL)
|
||||
{
|
||||
current->previous->next=nhdr;
|
||||
}
|
||||
if (current->next!=NULL)
|
||||
{
|
||||
current->next->previous=nhdr;
|
||||
}
|
||||
nhdr->next=current->next;
|
||||
nhdr->previous=current->previous;
|
||||
nhdr->nr_pages=current->nr_pages-1;
|
||||
if (free_page_list_head==current)
|
||||
{
|
||||
free_page_list_head=nhdr;
|
||||
}
|
||||
|
||||
return ((int)current);
|
||||
MmPageArray[i].Flags = PHYSICAL_PAGE_FREE;
|
||||
InsertTailList(&FreePageListHead,
|
||||
&MmPageArray[i].ListEntry);
|
||||
}
|
||||
for (; i<(0xa0000 / PAGESIZE); i++)
|
||||
{
|
||||
MmPageArray[i].Flags = PHYSICAL_PAGE_INUSE;
|
||||
InsertTailList(&UsedPageListHead,
|
||||
&MmPageArray[i].ListEntry);
|
||||
}
|
||||
for (; i<(0x100000 / PAGESIZE); i++)
|
||||
{
|
||||
MmPageArray[i].Flags = PHYSICAL_PAGE_BIOS;
|
||||
InsertTailList(&BiosPageListHead,
|
||||
&MmPageArray[i].ListEntry);
|
||||
}
|
||||
|
||||
current=current->next;
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
unsigned int get_free_page(void)
|
||||
/*
|
||||
* FUNCTION: Allocates a page
|
||||
* RETURNS: The physical address of the page allocated
|
||||
*/
|
||||
{
|
||||
unsigned int addr;
|
||||
|
||||
/*
|
||||
* This must be atomic wrt everything
|
||||
*/
|
||||
unsigned int eflags;
|
||||
__asm__("pushf\n\tpop %0\n\tcli\n\t"
|
||||
: "=d" (eflags));
|
||||
|
||||
/*
|
||||
* If we are totally out of memory then panic
|
||||
*/
|
||||
if (free_page_list_head==NULL)
|
||||
{
|
||||
printk("CRITICAL: Unable to allocate page\n");
|
||||
KeBugCheck(KBUG_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
addr = 0;
|
||||
|
||||
if (free_page_list_head->nr_pages>1)
|
||||
{
|
||||
free_page_list_head->nr_pages--;
|
||||
addr = ((unsigned int)free_page_list_head) +
|
||||
(free_page_list_head->nr_pages * PAGESIZE);
|
||||
}
|
||||
else
|
||||
{
|
||||
addr = (unsigned int)free_page_list_head;
|
||||
free_page_list_head = free_page_list_head -> next;
|
||||
for (; i<(0xa0000 / PAGESIZE); i++)
|
||||
{
|
||||
MmPageArray[i].Flags = PHYSICAL_PAGE_FREE;
|
||||
InsertTailList(&FreePageListHead,
|
||||
&MmPageArray[i].ListEntry);
|
||||
}
|
||||
for (; i<(0x100000 / PAGESIZE); i++)
|
||||
{
|
||||
MmPageArray[i].Flags = PHYSICAL_PAGE_BIOS;
|
||||
InsertTailList(&BiosPageListHead,
|
||||
&MmPageArray[i].ListEntry);
|
||||
}
|
||||
for (; i<((ULONG)FirstPhysKernelAddress/PAGESIZE); i++)
|
||||
{
|
||||
MmPageArray[i].Flags = PHYSICAL_PAGE_FREE;
|
||||
InsertTailList(&FreePageListHead,
|
||||
&MmPageArray[i].ListEntry);
|
||||
}
|
||||
for (; i<((ULONG)LastPhysKernelAddress/PAGESIZE); i++)
|
||||
{
|
||||
MmPageArray[i].Flags = PHYSICAL_PAGE_INUSE;
|
||||
InsertTailList(&UsedPageListHead,
|
||||
&MmPageArray[i].ListEntry);
|
||||
}
|
||||
}
|
||||
|
||||
__asm__("push %0\n\tpopf\n\t"
|
||||
:
|
||||
: "d" (eflags));
|
||||
|
||||
addr = addr - (IDMAP_BASE);
|
||||
DPRINT("allocated %x\n",addr);
|
||||
for (; i<MemorySizeInPages; i++)
|
||||
{
|
||||
MmPageArray[i].Flags = PHYSICAL_PAGE_FREE;
|
||||
InsertTailList(&FreePageListHead,
|
||||
&MmPageArray[i].ListEntry);
|
||||
}
|
||||
DPRINT("\nMmInitializePageList() = %x\n",
|
||||
LastKernelAddress + Reserved * PAGESIZE);
|
||||
return((PVOID)(LastKernelAddress + Reserved * PAGESIZE));
|
||||
}
|
||||
|
||||
return(addr);
|
||||
VOID MmFreePage(PVOID PhysicalAddress, ULONG Nr)
|
||||
{
|
||||
ULONG i;
|
||||
ULONG Start = (ULONG)PhysicalAddress / PAGESIZE;
|
||||
KIRQL oldIrql;
|
||||
|
||||
DPRINT("MmFreePage(PhysicalAddress %x, Nr %x)\n", PhysicalAddress, Nr);
|
||||
|
||||
for (i=0; i<Nr; i++)
|
||||
{
|
||||
KeAcquireSpinLock(&UsedPageListLock, &oldIrql);
|
||||
RemoveEntryList(&MmPageArray[Start + i].ListEntry);
|
||||
MmPageArray[Start + i].Flags = PHYSICAL_PAGE_FREE;
|
||||
KeReleaseSpinLock(&UsedPageListLock, oldIrql);
|
||||
|
||||
ExInterlockedInsertTailList(&FreePageListHead,
|
||||
&MmPageArray[Start + i].ListEntry,
|
||||
&FreePageListLock);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
PVOID MmAllocPage(VOID)
|
||||
{
|
||||
ULONG offset;
|
||||
PLIST_ENTRY ListEntry;
|
||||
PPHYSICAL_PAGE PageDescriptor;
|
||||
|
||||
DPRINT("MmAllocPage()\n");
|
||||
|
||||
ListEntry = ExInterlockedRemoveHeadList(&FreePageListHead,
|
||||
&FreePageListLock);
|
||||
DPRINT("ListEntry %x\n",ListEntry);
|
||||
PageDescriptor = CONTAINING_RECORD(ListEntry, PHYSICAL_PAGE, ListEntry);
|
||||
if (PageDescriptor == NULL)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
DPRINT("PageDescriptor %x\n",PageDescriptor);
|
||||
PageDescriptor->Flags = PHYSICAL_PAGE_INUSE;
|
||||
ExInterlockedInsertTailList(&UsedPageListHead, ListEntry,
|
||||
&UsedPageListLock);
|
||||
|
||||
DPRINT("PageDescriptor %x MmPageArray %x\n", PageDescriptor, MmPageArray);
|
||||
offset = (ULONG)((ULONG)PageDescriptor - (ULONG)MmPageArray);
|
||||
DPRINT("offset %x\n",offset);
|
||||
offset = offset / sizeof(PHYSICAL_PAGE) * PAGESIZE;
|
||||
DPRINT("offset %x\n",offset);
|
||||
|
||||
DPRINT("MmAllocPage() = %x\n",offset);
|
||||
return((PVOID)offset);
|
||||
}
|
||||
|
|
|
@ -395,6 +395,7 @@ NTSTATUS MmFreeMemoryArea(PEPROCESS Process,
|
|||
MEMORY_AREA* MemoryArea;
|
||||
ULONG i;
|
||||
KIRQL oldlvl;
|
||||
LARGE_INTEGER PhysicalAddr;
|
||||
|
||||
DPRINT("MmFreeMemoryArea(Process %x, BaseAddress %x, Length %x,"
|
||||
"FreePages %d)\n",Process,BaseAddress,Length,FreePages);
|
||||
|
@ -412,9 +413,10 @@ NTSTATUS MmFreeMemoryArea(PEPROCESS Process,
|
|||
{
|
||||
for (i=0;i<=(MemoryArea->Length/PAGESIZE);i++)
|
||||
{
|
||||
free_page(GET_LARGE_INTEGER_LOW_PART(
|
||||
MmGetPhysicalAddress(MemoryArea->BaseAddress + (i*PAGESIZE))),
|
||||
1);
|
||||
PhysicalAddr = MmGetPhysicalAddress(MemoryArea->BaseAddress +
|
||||
(i*PAGESIZE));
|
||||
MmFreePage((PVOID)(ULONG)
|
||||
(GET_LARGE_INTEGER_LOW_PART(PhysicalAddr)), 1);
|
||||
}
|
||||
}
|
||||
for (i=0; i<=(MemoryArea->Length/PAGESIZE); i++)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* PROJECT: ReactOS kernel
|
||||
* FILE: ntoskrnl/mm/mm.c
|
||||
* PURPOSE: kernel memory managment functions
|
||||
* PROGRAMMER: David Welch
|
||||
* PROGRAMMER: David Welch (welch@cwcom.net)
|
||||
* UPDATE HISTORY:
|
||||
* Created 9/4/98
|
||||
*/
|
||||
|
@ -37,39 +37,38 @@ extern unsigned int stext;
|
|||
extern unsigned int etext;
|
||||
extern unsigned int end;
|
||||
|
||||
static BOOLEAN IsThisAnNtAsSystem = FALSE;
|
||||
static MM_SYSTEM_SIZE MmSystemSize = MmSmallSystem;
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
BOOLEAN MmIsThisAnNtAsSystem()
|
||||
BOOLEAN MmIsThisAnNtAsSystem(VOID)
|
||||
{
|
||||
UNIMPLEMENTED
|
||||
return(IsThisAnNtAsSystem);
|
||||
}
|
||||
|
||||
MM_SYSTEM_SIZE MmQuerySystemSize()
|
||||
MM_SYSTEM_SIZE MmQuerySystemSize(VOID)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
return(MmSystemSize);
|
||||
}
|
||||
|
||||
void MmInitialize(boot_param* bp)
|
||||
void MmInitialize(boot_param* bp, ULONG LastKernelAddress)
|
||||
/*
|
||||
* FUNCTION: Initalize memory managment
|
||||
*/
|
||||
{
|
||||
unsigned int kernel_len = bp->end_mem - bp->start_mem;
|
||||
unsigned int first_krnl_phys_addr;
|
||||
unsigned int last_krnl_phys_addr;
|
||||
int i;
|
||||
PULONG page_directory = (PULONG)physical_to_linear(
|
||||
(ULONG)get_page_directory());
|
||||
unsigned int kernel_len;
|
||||
|
||||
DPRINT("InitalizeMM()\n");
|
||||
DPRINT("MmInitialize(bp %x, LastKernelAddress %x)\n", bp,
|
||||
LastKernelAddress);
|
||||
|
||||
CHECKPOINT;
|
||||
/*
|
||||
* Unmap low memory
|
||||
*/
|
||||
page_directory[0]=0;
|
||||
FLUSH_TLB;
|
||||
CHECKPOINT;
|
||||
MmDeletePageTable(NULL, 0);
|
||||
|
||||
/*
|
||||
* Free all pages not used for kernel memory
|
||||
|
@ -84,23 +83,12 @@ void MmInitialize(boot_param* bp)
|
|||
/*
|
||||
* Free physical memory not used by the kernel
|
||||
*/
|
||||
if (first_krnl_phys_addr < 0xa0000)
|
||||
{
|
||||
free_page(0x2000,(first_krnl_phys_addr/PAGESIZE)-2);
|
||||
free_page(last_krnl_phys_addr+PAGESIZE,
|
||||
(0xa0000 - last_krnl_phys_addr - PAGESIZE)/PAGESIZE);
|
||||
free_page(1024*1024,EXTENDED_MEMORY_SIZE/4096);
|
||||
}
|
||||
else
|
||||
{
|
||||
free_page(0x2000,(0xa0000/PAGESIZE)-2);
|
||||
free_page(1024*1024,
|
||||
(first_krnl_phys_addr-(1024*1024))/PAGESIZE);
|
||||
free_page(last_krnl_phys_addr+PAGESIZE,
|
||||
((EXTENDED_MEMORY_SIZE+(1024*1024))
|
||||
-last_krnl_phys_addr)/PAGESIZE);
|
||||
}
|
||||
CHECKPOINT;
|
||||
LastKernelAddress = (ULONG)MmInitializePageList(
|
||||
(PVOID)first_krnl_phys_addr,
|
||||
(PVOID)last_krnl_phys_addr,
|
||||
1024,
|
||||
PAGE_ROUND_UP(LastKernelAddress));
|
||||
kernel_len = last_krnl_phys_addr - first_krnl_phys_addr;
|
||||
|
||||
/*
|
||||
* Create a trap for null pointer references and protect text
|
||||
|
@ -115,17 +103,17 @@ void MmInitialize(boot_param* bp)
|
|||
(PVOID)i,
|
||||
PAGE_EXECUTE_READ);
|
||||
}
|
||||
DPRINT("end %x\n",(int)&end);
|
||||
for (i=PAGE_ROUND_UP(KERNEL_BASE+kernel_len);
|
||||
i<(KERNEL_BASE+PAGE_TABLE_SIZE);i=i+PAGESIZE)
|
||||
{
|
||||
MmSetPage(NULL,
|
||||
(PVOID)i,
|
||||
PAGE_NOACCESS,
|
||||
0);
|
||||
}
|
||||
FLUSH_TLB;
|
||||
|
||||
DPRINT("Invalidating between %x and %x\n",
|
||||
LastKernelAddress,
|
||||
KERNEL_BASE + PAGE_TABLE_SIZE);
|
||||
for (i=(LastKernelAddress);
|
||||
i<(KERNEL_BASE + PAGE_TABLE_SIZE);
|
||||
i=i+PAGESIZE)
|
||||
{
|
||||
MmSetPage(NULL, (PVOID)(i), PAGE_NOACCESS, 0);
|
||||
}
|
||||
DPRINT("Almost done MmInit()\n");
|
||||
/*
|
||||
* Intialize memory areas
|
||||
*/
|
||||
|
|
|
@ -101,7 +101,7 @@ PVOID ExAllocatePage(VOID)
|
|||
MmSetPage(NULL,
|
||||
(PVOID)addr,
|
||||
PAGE_READWRITE,
|
||||
get_free_page());
|
||||
(ULONG)MmAllocPage());
|
||||
KeReleaseSpinLock(&AllocMapLock, oldlvl);
|
||||
return((PVOID)addr);
|
||||
}
|
||||
|
@ -459,7 +459,7 @@ static block_hdr* grow_kernel_pool(unsigned int size)
|
|||
MmSetPage(NULL,
|
||||
(PVOID)(start + (i*PAGESIZE)),
|
||||
PAGE_READWRITE,
|
||||
get_free_page());
|
||||
(ULONG)MmAllocPage());
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ PVOID MmAllocateSection(ULONG Length)
|
|||
MmSetPage(NULL,
|
||||
Result+(i*PAGESIZE),
|
||||
PAGE_READWRITE,
|
||||
get_free_page());
|
||||
(ULONG)MmAllocPage());
|
||||
}
|
||||
return((PVOID)Result);
|
||||
}
|
||||
|
@ -93,7 +93,8 @@ PVOID MmMapIoSpace(PHYSICAL_ADDRESS PhysicalAddress,
|
|||
MmSetPage(NULL,
|
||||
Result + (i * PAGESIZE),
|
||||
PAGE_READWRITE,
|
||||
GET_LARGE_INTEGER_LOW_PART(PhysicalAddress));
|
||||
GET_LARGE_INTEGER_LOW_PART(PhysicalAddress) +
|
||||
(i * PAGESIZE));
|
||||
}
|
||||
return((PVOID)Result);
|
||||
}
|
||||
|
@ -128,7 +129,7 @@ PVOID MmAllocateNonCachedMemory(ULONG NumberOfBytes)
|
|||
MmSetPage(NULL,
|
||||
Result+(i*PAGESIZE),
|
||||
PAGE_READWRITE,
|
||||
get_free_page());
|
||||
(ULONG)MmAllocPage());
|
||||
}
|
||||
return((PVOID)Result);
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ ULONG MmCommitedSectionHandleFault(MEMORY_AREA* MemoryArea, PVOID Address)
|
|||
MmSetPage(PsGetCurrentProcess(),
|
||||
Address,
|
||||
MemoryArea->Attributes,
|
||||
get_free_page());
|
||||
(ULONG)MmAllocPage());
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
|
@ -113,7 +113,7 @@ NTSTATUS MmSectionHandleFault(MEMORY_AREA* MemoryArea, PVOID Address)
|
|||
MmSetPage(NULL,
|
||||
Address,
|
||||
MemoryArea->Attributes,
|
||||
get_free_page());
|
||||
(ULONG)MmAllocPage());
|
||||
|
||||
LARGE_INTEGER_QUAD_PART(Offset) = (Address - MemoryArea->BaseAddress) +
|
||||
MemoryArea->Data.SectionData.ViewOffset;
|
||||
|
|
|
@ -29,6 +29,22 @@ POBJECT_TYPE PsProcessType = NULL;
|
|||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
#define IDMAP_BASE (0xd0000000)
|
||||
|
||||
/*
|
||||
* Return a linear address which can be used to access the physical memory
|
||||
* starting at x
|
||||
*/
|
||||
extern inline unsigned int physical_to_linear(unsigned int x)
|
||||
{
|
||||
return(x+IDMAP_BASE);
|
||||
}
|
||||
|
||||
extern inline unsigned int linear_to_physical(unsigned int x)
|
||||
{
|
||||
return(x-IDMAP_BASE);
|
||||
}
|
||||
|
||||
PEPROCESS PsGetSystemProcess(VOID)
|
||||
{
|
||||
return(SystemProcess);
|
||||
|
@ -195,7 +211,7 @@ NTSTATUS STDCALL ZwCreateProcess(
|
|||
InheritObjectTable,
|
||||
Process);
|
||||
|
||||
PhysicalPageDirectory = (PULONG)get_free_page();
|
||||
PhysicalPageDirectory = (PULONG)MmAllocPage();
|
||||
PageDirectory = (PULONG)physical_to_linear((ULONG)PhysicalPageDirectory);
|
||||
KProcess->PageTableDirectory = PhysicalPageDirectory;
|
||||
|
||||
|
|
Loading…
Reference in a new issue