📄 pm2_paging.c
字号:
/***************************************************************************
** File name : pm2_paging.c
** Author : x.cheng
** Create date :
**
** Comment:
** 分页内存管理中对正常分页空间的管理模块
**
** Revisions:
** $Log: pm2_paging.c,v $
** Revision 1.5 2005/08/19 15:04:00 x.cheng
** using vector to store free page, and map the whole memory to
** from 0xc0000000, page status funcion exported.
**
** Revision 1.4 2005/08/04 08:37:48 x.cheng
** new page fault exception handling, export handling function.
**
** Revision 1.3 2005/07/30 06:13:03 x.cheng
** bug fix for physical memory managnement, GDTR,PHYSICAL,...
**
** Revision 1.2 2005/07/27 15:53:18 x.cheng
** invoke DmaSetupMemoryEnd( ),将vPm2PageInit(unsigned long ulStartMemory, unsigned long ulEndMemory)
** 改成了vPm2PageInit(unsigned long ulMemoryEnd)
** 同时开始细化该函数,改变了内核代码页的属性。
**
** Revision 1.1.1.1 2005/07/27 06:53:15 x.cheng
** add into repositories
**
**
***************************************************************************/
#include "const.h"
#include "type.h"
#include "stdarg.h"
#include "..\..\Inc\i386\system.h"
#include "..\..\Inc\i386\page.h"
#include "..\..\Inc\i386\map.h"
#include "..\..\Inc\i386\mmx.h"
#include "..\..\Inc\pmm.h"
#include "..\..\inc\tui.h"
#include "..\..\inc\dma.h"
#include "..\..\inc\debug.h"
#define __PMM_SRC__
#include "..\inc\def_pmm.h"
/********************extern varaible**********************/
//the following extern variable is defined in linkscript.ld
extern unsigned long KernelTextSectionStart_, KernelTextSectionEnd_;
/********************global varaible**********************/
unsigned char* g_pucMemoryBitmapStart = (unsigned char*)KERNEL_LINK_VIRTUAL_ADDRESS_END;
unsigned char* g_pucMemoryBitmapEnd = NULL;
unsigned char* g_pucMemoryPageableStart = NULL;
//-------------------------------------
static ts_GDTR g_stGdtr;
/************************************************************
*************************************************************
** Function Name: ulPm2GetOneFreePage
** Author: x.cheng
**
** Comment:
** 取得第一个(实际上是最后一个)空闲页面,并标记为已用
** 如果没有,就返回0
** List of parameters:
** no
**
** Return value:
** 0 - out of memory
** other - 空闲页面起始地址4字节(ax)
** 空闲页面的物理地址(页框号)
** Revisions:
**
*************************************************************
*************************************************************/
unsigned long ulPm2GetOneFreePage(void)
{
unsigned char* pucBitmap=g_pucMemoryPageableStart;
while( pucBitmap<g_pucMemoryBitmapEnd ) {
if ( PAGE_USED != *pucBitmap ) {
//found free page frame.
*pucBitmap = PAGE_USED;
return ( VECTOR_TO_PAGE_FRAME(pucBitmap) );
}
pucBitmap++;
}
return NULL;
}
/************************************************************
*************************************************************
** Function Name: vPm2FreeOnePage
** Author: x.cheng
**
** Comment:
** 释放虚拟线性地址"ulVirtualAddr"所映射在一页物理内存
** 注意,要确定所释放的一页物理内存都确实可以释放
**
** List of parameters:
** ulVirtualAddress - 线性内存地址
**
** Return value:
** no
** Revisions:
** 0.01-找到页表项设为无效(取消映射),设置空闲页框数组
*************************************************************
*************************************************************/
void vPm2FreeOnePage(unsigned long ulVirtualAddress)
{
unsigned long ulFlags;
unsigned long ulPDE, ulPTE, ulPFN;
unsigned long ulTmp;
return;
ulVirtualAddress = ulPageDownAlign(ulVirtualAddress);
SaveEflagsAndCli(ulFlags);
ulPDE = *pulAddressToPde(ulVirtualAddress);
if ( P_PRESENT == (ulPDE * P_PRESENT) ) {
//看看该页目录项对应的页表是否被共享
// if (没共享)
*pulAddressToPde(ulVirtualAddress) |= P_WRITE;
// else { //被共享
// }
} else {
RestoreEflags(ulFlags);
return;
}
ulPTE = *pulAddressToPte(ulVirtualAddress);
if ( P_PRESENT == (ulPTE * P_PRESENT) ) {
//看看对应的页是否被共享
//if (没共享)
unsigned char* pucBitmap;
pucBitmap = (unsigned char*)LINEAR_ADDRESS_TO_VECTOR(ulVirtualAddress);
pucBitmap = 0;
/*
ulPFN = ulPageDownAlign(ulPTE); //得到页框号
if ( (ulPFN >= g_ulLowestPFN<<12) && (ulPFN <= g_ulHighestPFN<<12) ) {
g_aucMemoryBitmap[ulPFN>>12] = 0;
}
*/
} else {
RestoreEflags(ulFlags);
return;
}
//unmap the page
*pulAddressToPte(ulVirtualAddress) = NULL;
//Invalidate the page in the TLB cache
//flush_tlb_single(ulVirtualAddress);
//看看页表中所有的页表项都无效,无效就释放页表所占的页
for ( ulTmp = ulPageDirDownAlign(ulVirtualAddress) ;
ulTmp < ulPageDirUpAlign(ulVirtualAddress) ; ulTmp += PAGE_SIZE ) {
if ( P_PRESENT == (*pulAddressToPte(ulTmp) & P_PRESENT) ) {
RestoreEflags(ulFlags);
return;
}
}
// no pte found, free it
ulPDE = *pulAddressToPde(ulVirtualAddress);
*(g_pucMemoryBitmapStart+(ulPDE>>12)) = 0;
/*
ulPFN = ulPageDirDownAlign(ulPDE);
if ( (ulPFN >= g_ulLowestPFN<<12) && (ulPFN <= g_ulHighestPFN<<12) ) {
g_aucMemoryBitmap[ulPFN>>12] = 0;
}
*/
*pulAddressToPde(ulVirtualAddress) = NULL;
//........
RestoreEflags(ulFlags);
return;
}
/************************************************************
*************************************************************
** Function Name: ulPm2MapPageToVirtualAddress
** Author: x.cheng
**
** Comment:
** 将一内存页面映射到指定线性地址处,返回页面的物理地址
**
**
**
** List of parameters:
** ulPageAddr -
** ulVirtualAddr -
**
** Return value:
** 0- error
** unsigned long - 物理地址
** Revisions:
**
*************************************************************
*************************************************************/
unsigned long ulPm2MapPageToVirtualAddress(unsigned long ulPageAddr, unsigned long ulVirtualAddr, unsigned short uiAttr)
{
unsigned long *pulPFN;
unsigned long i;
unsigned long ulFlags;
#ifdef _DEBUG__
#ifdef _DEBUG_PAGING_
// kprintf("\nmap page: %p to: %p with attr= %X\n", ulPageAddr, ulVirtualAddr, uiAttr);
#endif
#endif
ulPageAddr = PAGE_ALIGN(ulPageAddr);
ulVirtualAddr = PAGE_ALIGN(ulVirtualAddr);
//uiAttr &= 0xFFFF;
SaveEflagsAndCli(ulFlags);
// 如果该线性地址对应的页目录项无效的话,就要创建一个页表,
//并将相应的页目录项设为有效.
if ( *pulAddressToPde(ulVirtualAddr) == NULL ) {
// Create a new page table.
pulPFN = (unsigned long *)ulPm2GetOneFreePage();
#ifdef _DEBUG__
#ifdef _DEBUG_PAGING_
kprintf("%s(): free pfn= %p, for %p\n", __FUNCTION__, pulPFN, ulVirtualAddr);
#endif
#endif
if (pulPFN == NULL) {
// Out of memory!!!
RestoreEflags(ulFlags);
return NULL;
}
// Set the PDE as present, user level, read-write.
*pulAddressToPde(ulVirtualAddr) = (unsigned long)((unsigned long)pulPFN) | P_PRESENT | P_USER | P_WRITE;
// 将新的页表中的所有页表项都设为无效.
for (i = PAGE_DIR_ALIGN(ulVirtualAddr); i < PAGE_DIR_ALIGN_UP(ulVirtualAddr); i += PAGE_SIZE) {
*pulAddressToPte(i) = NULL;
}
/*
if (ulVirtualAddr >= KERNEL_VIRTUAL_START) {
// Other tasks must update their page directory.
if (curr_task != NULL)
curr_task->pdbr_update_counter++;
}
*/
}
// Store the physical address into the page table entry.
*pulAddressToPte(ulVirtualAddr) = (unsigned long)(ulPageAddr) | uiAttr;
// Invalidate the page in the TLB cache.
//flush_tlb_single(ulVirtualAddr);
// vInvalidateCache();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -