📄 page.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 + -