📄 pagealloc.c
字号:
//-----------------------------------------------------------------------------------------------------------------------
// Phy Page Alloc For FireXOS 1.10
//
// Version 1.10
//
// Create by xiaofan 2004.9.20
//
// Update by xiaofan 2004.9.20
//------------------------------------------------------------------------------------------------------------------------
#include "PageAlloc.h"
#include "Console.h"
#include "BootMem.h"
#include "Page.h"
#include "Process.h"
#include "String.h"
#include "Traps.h"
#include "CTYPE.h"
static unsigned long HIGHT_MEM=0; //内存高端地址
static unsigned long LOW_MEM=0; //内存低端地址
static PageStruct* mem_map;
unsigned long PAGING_PAGES=0;
//------------------------------------------------------------------------------------------
//
//
// 物理内存分页表扩展(其中0~4MB 页表已初始化)
//
//
//
//-------------------------------------------------------------------------------------------
unsigned long PhysicalPageTableExpand(unsigned long end_mem)
{
unsigned long page_table_num=0;
unsigned long page_residue_num=0; //不足一页表的剩余页面数
unsigned long index;
unsigned long page_table_addr;
ConsolePrintf("Expand the physical page table ");
page_table_num=(end_mem-0x400000)/(4096*1024);
page_residue_num=((end_mem-0x400000)%(4096*1024))/4096;
if(page_residue_num) page_table_num+=1;
page_table_addr=(unsigned long)BootMemMalloc(page_table_num*4096);
//重新设置Kernel Page_Dir
//重新设置 VM 0~4MB 为空把 0 ~ 4MB 的映射断开
for(index=0;index<1;index++)
{
//*(unsigned long *)(PG_DIR_ADDR+index*4) = 0;
}
//设置Kernel Page_Dir
//设置物理空间 0 ~ 4MB 1 个页表
for(index=0x300;index<0x301;index++)
{
*(unsigned long *)(__va(PG_DIR_ADDR)+index*4) = (PG_TABLE_ADDR+(index-0x300)*4096)|7;
}
//设置Kernel Page_Dir
//设置物理空间 4MB ~ end_mem page_table_num 个页表
for(index=0x301;index<0x301+page_table_num;index++)
{
*(unsigned long *)(__va(PG_DIR_ADDR)+index*4) = (__pa(page_table_addr)+(index-0x301)*4096)|7;
}
//ConsoleMsg(" Expand Mem First 4MB page_table = %08x\n",page_table_addr);
//设置扩展物理页表映射到物理内存 4MB ~ end_mem
if(page_residue_num)
for (index=0;index<0x400*(page_table_num-1)+page_residue_num;index++)
{
*((unsigned long*)(page_table_addr+index*4)) = (0x400000+index*4096)|7;
}
else
for (index=0;index<0x400*page_table_num;index++)
{
*((unsigned long*)(page_table_addr+index*4)) = (0x400000+index*4096)|7;
}
InvalidatePageDir(PG_DIR_ADDR);
ConsolePrintOK();
if(page_residue_num)
return (page_table_num-1)*1024+page_residue_num;
else
return page_table_num*1024;
}
//------------------------------------------------------------------------------------------
//
//
// 内存页面扫描,并输出结果
//
//
//
//-------------------------------------------------------------------------------------------
int PageManagerScan(void)
{
int i,free=0;
for(i=0;i<PAGING_PAGES;i++)
if(!TestPageUsed(&mem_map[i])) free++;
//ConsoleMsg(" Total %d pages to alloc %d pages free\n",PAGING_PAGES,free);
return free;
}
//------------------------------------------------------------------------------------------
//
//
// 内存分页初始化
//
//
//
//-------------------------------------------------------------------------------------------
void PageManagerInit(unsigned long end_mem)
{
unsigned long i;
unsigned long page_num=0;
unsigned long low_page_num=0;
HIGHT_MEM=__va(end_mem);
//在扩展了物理内存页面之后就不能在访问低端内存了 3GB 以下
page_num=PhysicalPageTableExpand(end_mem);
ConsoleMsg(" Expand %ld physical pages total %ld KB\n",page_num,page_num*4);
ConsoleMsg(" Physical page table set at vitrual address %08x\n",PAGE_OFFSET+PG_TABLE_ADDR);
page_num=(end_mem)/4096;
ConsolePrintf("Malloc the mem_map array for page alloc");
mem_map=(PageStruct*)BootMemMalloc(page_num*sizeof(PageStruct));
ConsolePrintOK();
ConsoleMsg(" The mem_map array base is %08x size is %d KB \n",mem_map,page_num*sizeof(PageStruct)/1024);
BootMemEnd(&LOW_MEM);
ConsoleMsg(" The low mem of alloc page is %08x\n",LOW_MEM);
low_page_num=(__pa(LOW_MEM)/4096)+1; //向高端4KB 对齐
PAGING_PAGES=page_num;
for(i=0;i<low_page_num;i++)
{
SetPageReferenced(&mem_map[i]); //将内核页设为在内存中
SetPageUsed(&mem_map[i]); //将内核页设为被占用
SetPageLocked(&mem_map[i]); //将内核页设为锁定
mem_map[i].count=0;
}
for(i=low_page_num;i<page_num;i++)
{
SetPageReferenced(&mem_map[i]); //将分配页设为在内存中
SetPageUnUsed(&mem_map[i]); //将分配页设为被未占用
SetPageUnLocked(&mem_map[i]); //将分配页设为被未锁定
mem_map[i].count=0;
}
PageManagerScan();
}
//------------------------------------------------------------------------------------------
//
//
// 内存页面映射表,找到一个空闲的页面,并将该页面的实际物理内存清零
//
//
//
//-------------------------------------------------------------------------------------------
unsigned long GetFreePage(void)
{
unsigned long i;
for(i=0;i<PAGING_PAGES;i++)
if(!TestPageUsed(&mem_map[i])) //若找到了一个空闲的页
{
SetPageUsed(&mem_map[i]);
mem_map[i].count++;
i<<=12; //i*4K 得到实际的页偏移地址
i=__va(i);
//以下代码将页面的实际的物理地址清零
/*
__asm__("std; \n\t"
"movl %%ecx,%%edx\n\t"
"movl $1024,%%ecx\n\t" //ecx计数器置1024
"leal 4092(%%edx),%%edi\n\t"
"rep: stosl\n\t"
"movl %%edx,%%eax"
:"=a"(__res) //输出的结果
:"c"(i)); //将i送入ecx
*/
memset((void*)i,0,4096);
return i;
}
KernelPanic("No enough physical memory to get a free page ");
return 0;
}
//------------------------------------------------------------------------------------------
//
//
// 内存页面映射表,找到n个空闲的连续页面,并将该页面的实际物理内存清零
//
//
//
//-------------------------------------------------------------------------------------------
unsigned long GetFreePages(int page_num)
{
unsigned long i;
unsigned long start,end;
int num=0;
start=end=0;
for(i=0;i<PAGING_PAGES;i++)
if(!TestPageUsed(&mem_map[i])) //若找到了一个空闲的页
{
if(num==0) start=i;
num++;
if(num>=page_num)
{
end=i;
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -