⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pm2_paging.c

📁 小型操作系统,以VC为开发环境,需要boachs调试
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************
**     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 + -