pgtable.h
来自「基于组件方式开发操作系统的OSKIT源代码」· C头文件 代码 · 共 638 行 · 第 1/2 页
H
638 行
#define PMD_TYPE_MASK 0x0003#define PMD_TYPE_FAULT 0x0000#define PMD_TYPE_TABLE 0x0001#define PMD_TYPE_SECT 0x0002#define PMD_UPDATABLE 0x0010#define PMD_SECT_CACHEABLE 0x0008#define PMD_SECT_BUFFERABLE 0x0004#define PMD_SECT_AP_WRITE 0x0400#define PMD_SECT_AP_READ 0x0800#define PMD_DOMAIN(x) ((x) << 5)#define _PAGE_USER_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_USER))#define _PAGE_KERNEL_TABLE (PMD_TYPE_TABLE | PMD_DOMAIN(DOMAIN_KERNEL))#define pmd_none(pmd) (!pmd_val(pmd))#define pmd_clear(pmdp) set_pmd(pmdp, __pmd(0))#define pmd_bad(pmd) (pmd_val(pmd) & 2)#define mk_user_pmd(ptep) __mk_pmd(ptep, _PAGE_USER_TABLE)#define mk_kernel_pmd(ptep) __mk_pmd(ptep, _PAGE_KERNEL_TABLE)#define set_pmd(pmdp,pmd) processor.u.armv3v4._set_pmd(pmdp,pmd)/* Find an entry in the second-level page table.. */#define pmd_offset(dir, address) ((pmd_t *)(dir))extern __inline__ int pmd_present(pmd_t pmd){ return ((pmd_val(pmd) + 1) & 2);}/* We don't use pmd cache, so this is a dummy routine */extern __inline__ pmd_t *get_pmd_fast(void){ return (pmd_t *)0;}extern __inline__ void free_pmd_fast(pmd_t *pmd){}extern __inline__ void free_pmd_slow(pmd_t *pmd){}extern void __bad_pmd(pmd_t *pmd);extern void __bad_pmd_kernel(pmd_t *pmd);/* * allocating and freeing a pmd is trivial: the 1-entry pmd is * inside the pgd, so has no extra memory associated with it. */extern __inline__ void pmd_free(pmd_t *pmd){}extern __inline__ pmd_t *pmd_alloc(pgd_t *pgd, unsigned long address){ return (pmd_t *) pgd;}#define pmd_free_kernel pmd_free#define pmd_alloc_kernel pmd_allocextern __inline__ pmd_t __mk_pmd(pte_t *ptep, unsigned long prot){ unsigned long pte_ptr = (unsigned long)ptep; pmd_t pmd; pte_ptr -= PTRS_PER_PTE * BYTES_PER_PTR; /* * The pmd must be loaded with the physical * address of the PTE table */ pmd_val(pmd) = __virt_to_phys(pte_ptr) | prot; return pmd;}extern __inline__ unsigned long pmd_page(pmd_t pmd){ unsigned long ptr; ptr = pmd_val(pmd) & ~(PTRS_PER_PTE * BYTES_PER_PTR - 1); ptr += PTRS_PER_PTE * BYTES_PER_PTR; return __phys_to_virt(ptr);}/***************** PTE functions *****************//* PTE types (actially level 2 descriptor) */#define PTE_TYPE_MASK 0x0003#define PTE_TYPE_FAULT 0x0000#define PTE_TYPE_LARGE 0x0001#define PTE_TYPE_SMALL 0x0002#define PTE_AP_READ 0x0aa0#define PTE_AP_WRITE 0x0550#define PTE_CACHEABLE 0x0008#define PTE_BUFFERABLE 0x0004#define pte_none(pte) (!pte_val(pte))#define pte_clear(ptep) set_pte(ptep, __pte(0))/* * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. */extern __inline__ pte_t mk_pte(unsigned long page, pgprot_t pgprot){ pte_t pte; pte_val(pte) = __virt_to_phys(page) | pgprot_val(pgprot); return pte;}/* This takes a physical page address that is used by the remapping functions */extern __inline__ pte_t mk_pte_phys(unsigned long physpage, pgprot_t pgprot){ pte_t pte; pte_val(pte) = physpage + pgprot_val(pgprot); return pte;}#define set_pte(ptep, pte) processor.u.armv3v4._set_pte(ptep,pte)extern __inline__ unsigned long pte_page(pte_t pte){ return __phys_to_virt(pte_val(pte) & PAGE_MASK);}extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);extern pte_t *get_pte_kernel_slow(pmd_t *pmd, unsigned long address_preadjusted);extern __inline__ pte_t *get_pte_fast(void){ unsigned long *ret; if((ret = (unsigned long *)pte_quicklist) != NULL) { pte_quicklist = (unsigned long *)(*ret); ret[0] = ret[1]; clean_cache_area(ret, 4); pgtable_cache_size--; } return (pte_t *)ret;}extern __inline__ void free_pte_fast(pte_t *pte){ *(unsigned long *)pte = (unsigned long) pte_quicklist; pte_quicklist = (unsigned long *) pte; pgtable_cache_size++;}extern __inline__ void free_pte_slow(pte_t *pte){ free_page_2k((unsigned long)(pte - PTRS_PER_PTE));}#define pte_free_kernel(pte) free_pte_fast(pte)#define pte_free(pte) free_pte_fast(pte)/*############################################################################### * New PageTableEntry stuff... *//* We now keep two sets of ptes - the physical and the linux version. * This gives us many advantages, and allows us greater flexibility. * * The Linux pte's contain: * bit meaning * 0 page present * 1 young * 2 bufferable - matches physical pte * 3 cacheable - matches physical pte * 4 user * 5 write * 6 execute * 7 dirty * 8-11 unused * 12-31 virtual page address * * These are stored at the pte pointer; the physical PTE is at -1024bytes */#define L_PTE_PRESENT (1 << 0)#define L_PTE_YOUNG (1 << 1)#define L_PTE_BUFFERABLE (1 << 2)#define L_PTE_CACHEABLE (1 << 3)#define L_PTE_USER (1 << 4)#define L_PTE_WRITE (1 << 5)#define L_PTE_EXEC (1 << 6)#define L_PTE_DIRTY (1 << 7)/* * The following macros handle the cache and bufferable bits... */#define _L_PTE_DEFAULT L_PTE_PRESENT | L_PTE_YOUNG#define _L_PTE_READ L_PTE_USER | L_PTE_CACHEABLE#define _L_PTE_EXEC _L_PTE_READ | L_PTE_EXEC#define PAGE_NONE __pgprot(_L_PTE_DEFAULT)#define PAGE_COPY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_BUFFERABLE)#define PAGE_SHARED __pgprot(_L_PTE_DEFAULT | _L_PTE_READ | L_PTE_BUFFERABLE | L_PTE_WRITE)#define PAGE_READONLY __pgprot(_L_PTE_DEFAULT | _L_PTE_READ)#define PAGE_KERNEL __pgprot(_L_PTE_DEFAULT | L_PTE_CACHEABLE | L_PTE_BUFFERABLE | L_PTE_DIRTY | L_PTE_WRITE)#define _PAGE_CHG_MASK (PAGE_MASK | L_PTE_DIRTY | L_PTE_YOUNG)/* * The table below defines the page protection levels that we insert into our * Linux page table version. These get translated into the best that the * architecture can perform. Note that on most ARM hardware: * 1) We cannot do execute protection * 2) If we could do execute protection, then read is implied * 3) write implies read permissions */#define __P000 PAGE_NONE#define __P001 PAGE_READONLY#define __P010 PAGE_COPY#define __P011 PAGE_COPY#define __P100 PAGE_READONLY#define __P101 PAGE_READONLY#define __P110 PAGE_COPY#define __P111 PAGE_COPY#define __S000 PAGE_NONE#define __S001 PAGE_READONLY#define __S010 PAGE_SHARED#define __S011 PAGE_SHARED#define __S100 PAGE_READONLY#define __S101 PAGE_READONLY#define __S110 PAGE_SHARED#define __S111 PAGE_SHARED#define pte_present(pte) (pte_val(pte) & L_PTE_PRESENT)/* * The following only work if pte_present() is true. * Undefined behaviour if not.. */#define pte_read(pte) (pte_val(pte) & L_PTE_USER)#define pte_write(pte) (pte_val(pte) & L_PTE_WRITE)#define pte_exec(pte) (pte_val(pte) & L_PTE_EXEC)#define pte_dirty(pte) (pte_val(pte) & L_PTE_DIRTY)#define pte_young(pte) (pte_val(pte) & L_PTE_YOUNG)#define PTE_BIT_FUNC(fn,op) \extern inline pte_t fn##(pte_t pte) { pte_val(pte) op##; return pte; }//PTE_BIT_FUNC(pte_rdprotect, &= ~L_PTE_USER);PTE_BIT_FUNC(pte_wrprotect, &= ~L_PTE_WRITE);PTE_BIT_FUNC(pte_exprotect, &= ~L_PTE_EXEC);PTE_BIT_FUNC(pte_mkclean, &= ~L_PTE_DIRTY);PTE_BIT_FUNC(pte_mkold, &= ~L_PTE_YOUNG);//PTE_BIT_FUNC(pte_mkread, |= L_PTE_USER);PTE_BIT_FUNC(pte_mkwrite, |= L_PTE_WRITE);PTE_BIT_FUNC(pte_mkexec, |= L_PTE_EXEC);PTE_BIT_FUNC(pte_mkdirty, |= L_PTE_DIRTY);PTE_BIT_FUNC(pte_mkyoung, |= L_PTE_YOUNG);PTE_BIT_FUNC(pte_nocache, &= ~L_PTE_CACHEABLE);extern __inline__ pte_t pte_modify(pte_t pte, pgprot_t newprot){ pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot); return pte;}/* Find an entry in the third-level page table.. */extern __inline__ pte_t * pte_offset(pmd_t * dir, unsigned long address){ return (pte_t *) pmd_page(*dir) + ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1));}extern __inline__ pte_t * pte_alloc_kernel(pmd_t *pmd, unsigned long address){ address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); if (pmd_none(*pmd)) { pte_t *page = (pte_t *) get_pte_fast(); if (!page) return get_pte_kernel_slow(pmd, address); set_pmd(pmd, mk_kernel_pmd(page)); return page + address; } if (pmd_bad(*pmd)) { __bad_pmd_kernel(pmd); return NULL; } return (pte_t *) pmd_page(*pmd) + address;}extern __inline__ pte_t * pte_alloc(pmd_t * pmd, unsigned long address){ address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1); if (pmd_none(*pmd)) { pte_t *page = (pte_t *) get_pte_fast(); if (!page) return get_pte_slow(pmd, address); set_pmd(pmd, mk_user_pmd(page)); return page + address; } if (pmd_bad(*pmd)) { __bad_pmd(pmd); return NULL; } return (pte_t *) pmd_page(*pmd) + address;}#define SWP_TYPE(entry) (((entry) >> 2) & 0x7f)#define SWP_OFFSET(entry) ((entry) >> 9)#define SWP_ENTRY(type,offset) (((type) << 2) | ((offset) << 9))#endif /* __ASM_PROC_PAGE_H */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?