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

📄 page.h

📁 小型操作系统,以VC为开发环境,需要boachs调试
💻 H
字号:
/***************************************************************************
**     File name   : page.h
**     Author      : x.cheng
**     Create date :
**
**	  Comments:
**		brief Paging header.
**	
**     Revisions:
**     $Log: page.h,v $
**     Revision 1.3  2005/08/19 15:01:21  x.cheng
**     map whole memory to from 0xc0000000, so change macro PHYSICAL
**
**     Revision 1.2  2005/08/02 15:35:45  x.cheng
**     macro changed...
**
**     Revision 1.1.1.1  2005/07/27 06:53:15  x.cheng
**     add into repositories
**
**
***************************************************************************/

#ifndef __PAGING_H__
#define __PAGING_H__

#include <const.h>

// Kernel virtual memory map.
#include "map.h"

//! Determine the page size.
#define PAGE_SHIFT	12

//! Determine the memory area covered by a page directory entry.
#define PAGE_DIR_SHIFT	22

//! The page size.
#define PAGE_SIZE	( 1UL << PAGE_SHIFT )

//! The memory covered by a page directory entry.
#define PAGE_DIR_SIZE	( 1UL << PAGE_DIR_SHIFT )

//! The page mask.
#define PAGE_MASK	( ~(PAGE_SIZE-1) )

//! Page present flag.
#define P_PRESENT	( 1 << 0 )

//! Page writeable flag.
#define P_WRITE		( 1 << 1 )

//! Page at user privilege level.
#define P_USER		( 1 << 2 )

//! Write-through policy.
#define P_WTHROUGH	( 1 << 3 )

//! Page caching disabled.
#define P_NOCACHE	( 1 << 4 )

//! Page accessed flag.
#define P_ACCESSED	( 1 << 5 )

//! Page dirty flag (the page has been written).
#define P_DIRTY		( 1 << 6 )

//! Global page (for TLB invalidation).
#define P_GLOBAL	( 1 << 8 )

//! Rounds an address up to a page boundary.
//获得当前地址的所占的页的下一页的起始地址,常作为当前页的结束地址来使用
#define ulPageUpAlign(ulAddr)	\
	( ((ulAddr) + PAGE_SIZE -1) & -PAGE_SIZE )
#define PAGE_ALIGN_UP(addr)	(((addr) + PAGE_SIZE - 1) & -PAGE_SIZE)

//! Rounds an address down to a page boundary.
// 获得当前地址的所占的页的起始地址
#define ulPageDownAlign(ulAddr)	\
	( (ulAddr) & -PAGE_SIZE )
#define PAGE_ALIGN(addr)	((addr) & -PAGE_SIZE)

//! Rounds an address up to a page directory boundary.
#define ulPageDirUpAlign(ulAddr)	\
	( ((ulAddr) & -(PAGE_SIZE*1024)) + PAGE_SIZE*1024 )
#define PAGE_DIR_ALIGN_UP(addr)	(((addr) & -(PAGE_SIZE*1024)) + PAGE_SIZE*1024)

//! Rounds an address down to a page directory boundary.
#define ulPageDirDownAlign(ulAddr)	\
	( (ulAddr) & -(PAGE_SIZE*1024) )
#define PAGE_DIR_ALIGN(addr)	((addr) & -(PAGE_SIZE*1024))

//! Converts from address to page.
#define ADDR_TO_PAGE(addr)	(addr / PAGE_SIZE)

//! Converts from page to address
#define PAGE_TO_ADDR(p_addr)	(p_addr * PAGE_SIZE)

//! Get current page directory base address.
#define GET_PDBR()		(*ADDR_TO_PDE(PAGE_TABLE_MAP) & -PAGE_SIZE)

//! Access to the page directory entry referred to the
//! virtual address \p addr.
#define pulAddressToPde(ulAddr)	\
	(unsigned long*)(PAGE_DIR_TABLE_START_ADDRESS + ( ( (unsigned long)(ulAddr) / (1024*1024) ) & (~0x03) ) )
#define ADDR_TO_PDE(addr)	(unsigned long *)(PAGE_DIR_MAP + (((unsigned long) (addr) / (1024 * 1024))&(~0x3)))

//! Access to the page table entry referred to the
//! virtual address \p addr.
#define pulAddressToPte(ulAddr)	\
	(unsigned long *)(PAGE_TABLE_AREA_START_ADDRESS + ((((unsigned long) (ulAddr) / 1024))&(~0x3)))
#define ADDR_TO_PTE(addr)	(unsigned long *)(PAGE_TABLE_MAP + ((((unsigned long) (addr) / 1024))&(~0x3)))

// 求当前虚拟地址的在页目录表中的PDE索引号
// 32为虚拟地址的最高十位就是咯!
#define ulPdeIndex( ulAddress )	\
	( ((ulAddress) >> PAGE_DIR_SHIFT) & 1023 )
#define PDE_INDEX( addr ) \
	( ((addr) >> PAGE_DIR_SHIFT) & 1023 )

// 求当前虚拟地址在其页表中的PTE索引号
// 32位虚拟得的第二高的十位就是咯!
#define ulPteIndex( ulAddress )	\
	( ((ulAddress) >> PAGE_SHIFT) & 1023 )
//! Get the page table index of the current address.
#define PTE_INDEX( addr ) \
	( ((addr) >> PAGE_SHIFT) & 1023 )

// 求当前虚拟地址的PDE在页目录表中的距离PDBR的偏移量
// 实际上也可以ulPdbr+ulPdeIndex(ulAddress) << 2
#define pulPdeOffset(ulPdbr, ulAddress )	\
	( (unsigned long*)(ulPdbr) + ulPdeIndex( ulAddress ) )
//! Get the offset of a page directory entry.
#define PDE_OFFSET( pd, addr ) \
	( (uint32_t *)(pd) + PDE_INDEX( addr ) )
// 求当前虚拟地址的PTE在其页表中的距离页表基址的编译量
// 实际上也可以ulPtbr+ulPteIndex(ulAddress) << 2
#define pulPteOffset( ulPtbr, ulAddress )	\
	( (unsigned long *)(ulPtbr) + ulPteIndex(ulAddress) )
//! Get the offset of a page table entry.
#define PTE_OFFSET( pt, addr ) \
	( (uint32_t *)(pt) + PTE_INDEX( addr ) )

//! Access to an address into the mapped physical memory area.
//#define PHYSICAL(ulAddress)		((ulAddress) + KERNEL_PHYS_MEM_START)
#define PHYSICAL(ulAddress)		((ulAddress) + KERNEL_VIRTUAL_START)

//! Convert a virtual address of the low memory area (DMA-memory) into
//! the equivalent physical address.
#define VIRTUAL(ulAddress)		((ulAddress) - KERNEL_PHYS_MEM_START)

//! Page table structure.
typedef struct PAGE_TABLE
{
	unsigned long aulPTE[1024];
} ts_PageTable;

//! Flush every entry into the TLB cache (address translation).
/*#define __flush_tlb_all()		\			*/
#define FlushTlbAll()		\
	do							\
	{							\
		register unsigned int tmpreg;			\
								\
		__asm__ __volatile__(				\
			"movl %%cr3, %0;  # flush TLB \n"	\
			"movl %0, %%cr3;              \n"	\
			: "=r" (tmpreg)				\
			: : "memory");				\
	} while (0)

//! Flush every entry into the TLB cache (address translation),
//! also global pages
#define __flush_tlb_global()					\
	do							\
	{							\
		register unsigned int tmp, cr4;			\
								\
		__asm__ __volatile__(				\
			"movl %%cr4, %1\n"			\
			"test $0x80, %1 ; # pge is on?\n"	\
			"jz 1f\n"				\
			"and $(~0x80), %1 ; # turn off pge\n"	\
			"movl %1, %%cr4\n"			\
			"movl %%cr3, %0 ; # invalidate\n"	\
			"movl %0, %%cr3\n"			\
			"or $0x80, %1 ; # turn on pge\n"	\
			"movl %1, %%cr4\n"			\
			"jmp 2f\n"				\
			"1: "					\
			"movl %%cr3, %0 ; # invalidate\n"	\
			"movl %0, %%cr3\n"			\
			"2:"					\
			: "=&r"(tmp), "=&r"(cr4)		\
			: : "memory"				\
		);						\
	} while ( 0 )

#ifdef ARCH_HAS_GLOBAL_PAGE
	#define flush_tlb_all()		__flush_tlb_all()
#else
	#define flush_tlb_all()		__flush_tlb_global()
#endif

#if defined(CONFIG_M386)
#define flush_tlb_single(addr)	__flush_tlb_all()
#else
//! Flush a single entry into the TLB cache (address translation).
//! \param addr
//!	The virtual address of the page that must be invalidated.
#define flush_tlb_single(addr) \
	__asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
#endif

//! 
//!	Translate a virtual address into the physical address.
//! \param ulVirtualAddress The virtual address to be translated.
static inline unsigned long ulVirtualAddressToPhysical(unsigned long ulVirtualAddress)
{
	if (*pulAddressToPde(ulVirtualAddress) == NULL)
		return(NULL);
	return( (*pulAddressToPte(ulVirtualAddress) & -PAGE_SIZE) + (ulVirtualAddress % PAGE_SIZE) );
}

//! 
//! Switch into a new virtual address space.
//! \warning ulPDBR is the physical address of the page directory!
static inline void vSwitchMMU( unsigned long ulPDBR )
{
	// Switch to the new virtual space.
	__asm__ __volatile__ ( "movl %0, %%cr3" : : "r"(ulPDBR) );
}


#endif  /* end of __PAGING_H__ */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -