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

📄 mmu.h

📁 sun公司的sparc v8处理器的配置代码。
💻 H
字号:
#ifndef _MMU_H#define _MMU_H/* page table param */#define PAGE_SHIFT   12#define PAGE_SIZE   1<<PAGE_SHIFT/* PMD_SHIFT determines the size of the area a second-level page table can map */#define SRMMU_PMD_SHIFT         18#define SRMMU_PMD_SIZE          (1UL << SRMMU_PMD_SHIFT)#define SRMMU_PMD_MASK          (~(SRMMU_PMD_SIZE-1))#define SRMMU_PMD_ALIGN(addr)   (((addr)+SRMMU_PMD_SIZE-1)&SRMMU_PMD_MASK)/* PGDIR_SHIFT determines what a third-level page table entry can map */#define SRMMU_PGDIR_SHIFT       24#define SRMMU_PGDIR_SIZE        (1UL << SRMMU_PGDIR_SHIFT)#define SRMMU_PGDIR_MASK        (~(SRMMU_PGDIR_SIZE-1))#define SRMMU_PGDIR_ALIGN(addr) (((addr)+SRMMU_PGDIR_SIZE-1)&SRMMU_PGDIR_MASK)#define SRMMU_PTRS_PER_PTE      64#define SRMMU_PTRS_PER_PMD      64#define SRMMU_PTRS_PER_PGD      256#define SRMMU_PTRS_PER_CTX      256#define SRMMU_PTE_TABLE_SIZE    0x100 /* 64 entries, 4 bytes a piece */#define SRMMU_PMD_TABLE_SIZE    0x100 /* 64 entries, 4 bytes a piece */#define SRMMU_PGD_TABLE_SIZE    0x400 /* 256 entries, 4 bytes a piece *//* Definition of the values in the ET field of PTD's and PTE's */#define SRMMU_ET_MASK         0x3#define SRMMU_ET_INVALID      0x0#define SRMMU_ET_PTD          0x1#define SRMMU_ET_PTE          0x2#define SRMMU_ET_REPTE        0x3 /* AIEEE, SuperSparc II reverse endian page! *//* Physical page extraction from PTP's and PTE's. */#define SRMMU_CTX_PMASK    0xfffffff0#define SRMMU_PTD_PMASK    0xfffffff0#define SRMMU_PTE_PMASK    0xffffff00/* The pte non-page bits.  Some notes: * 1) cache, dirty, valid, and ref are frobbable *    for both supervisor and user pages. * 2) exec and write will only give the desired effect *    on user pages * 3) use priv and priv_readonly for changing the *    characteristics of supervisor ptes */#define SRMMU_CACHE        0x80#define SRMMU_DIRTY        0x40#define SRMMU_REF          0x20#define SRMMU_EXEC         0x08#define SRMMU_WRITE        0x04#define SRMMU_VALID        0x02 /* SRMMU_ET_PTE */#define SRMMU_PRIV         0x1c#define SRMMU_PRIV_RDONLY  0x18#define SRMMU_CHG_MASK    (0xffffff00 | SRMMU_REF | SRMMU_DIRTY)/* Some day I will implement true fine grained access bits for * user pages because the SRMMU gives us the capabilities to * enforce all the protection levels that vma's can have. * XXX But for now... */#define SRMMU_PAGE_NONE    __pgprot(SRMMU_VALID | SRMMU_CACHE | \				    SRMMU_PRIV | SRMMU_REF)#define SRMMU_PAGE_SHARED  __pgprot(SRMMU_VALID | SRMMU_CACHE | \				    SRMMU_EXEC | SRMMU_WRITE | SRMMU_REF)#define SRMMU_PAGE_COPY    __pgprot(SRMMU_VALID | SRMMU_CACHE | \				    SRMMU_EXEC | SRMMU_REF)#define SRMMU_PAGE_RDONLY  __pgprot(SRMMU_VALID | SRMMU_CACHE | \				    SRMMU_EXEC | SRMMU_REF)#define SRMMU_PAGE_KERNEL  __pgprot(SRMMU_VALID | SRMMU_CACHE | SRMMU_PRIV | \				    SRMMU_DIRTY | SRMMU_REF)/* mmu asi spaces*/#define ASI_M_FLUSH_PROBE  0x18#define ASI_M_MMUREGS      0x19#define ASI_MMU_BP         0x1c#define SRMMU_CTRL_REG           0x00000000#define SRMMU_CTXTBL_PTR         0x00000100#define SRMMU_CTX_REG            0x00000200#define SRMMU_FAULT_STATUS       0x00000300#define SRMMU_FAULT_ADDR         0x00000400#ifndef __ASSEMBLER__static inline void srmmu_set_mmureg(unsigned long regval){        asm volatile("sta %0, [%%g0] %1\n\t" : :		     "r" (regval), "i" (ASI_M_MMUREGS) : "memory");}static inline int srmmu_get_mmureg(void){	register int retval;	asm volatile("lda [%%g0] %1, %0\n\t" :		     "=r" (retval) :		     "i" (ASI_M_MMUREGS));	return retval;}static inline void srmmu_set_ctable_ptr(unsigned long paddr){	paddr = ((paddr >> 4) & SRMMU_CTX_PMASK);	asm volatile("sta %0, [%1] %2\n\t" : :		     "r" (paddr), "r" (SRMMU_CTXTBL_PTR),		     "i" (ASI_M_MMUREGS) :		     "memory");}static inline unsigned long srmmu_get_ctable_ptr(void){	unsigned int retval;	asm volatile("lda [%1] %2, %0\n\t" :		     "=r" (retval) :		     "r" (SRMMU_CTXTBL_PTR),		     "i" (ASI_M_MMUREGS));	return (retval & SRMMU_CTX_PMASK) << 4;}static inline void srmmu_set_context(int context){	asm volatile("sta %0, [%1] %2\n\t" : :		     "r" (context), "r" (SRMMU_CTX_REG),		     "i" (ASI_M_MMUREGS) : "memory");}static inline int srmmu_get_context(void){	register int retval;	asm volatile("lda [%1] %2, %0\n\t" :		     "=r" (retval) :		     "r" (SRMMU_CTX_REG),		     "i" (ASI_M_MMUREGS));	return retval;}static inline void srmmu_flush_whole_tlb(void){	__asm__ __volatile__("sta %%g0, [%0] %1\n\t": :			     "r" (0x400),        /* Flush entire TLB!! */			     "i" (ASI_M_FLUSH_PROBE) : "memory");}typedef unsigned long pte_t;typedef unsigned long iopte_t;typedef unsigned long pmd_t;typedef unsigned long pgd_t;typedef unsigned long ctxd_t;typedef unsigned long pgprot_t;typedef unsigned long iopgprot_t;#define pte_val(x)	(x)#define iopte_val(x)	(x)#define pmd_val(x)      (x)#define pgd_val(x)	(x)#define ctxd_val(x)	(x)#define pgprot_val(x)	(x)#define iopgprot_val(x)	(x)#define __pte(x)	(x)#define __iopte(x)	(x)#define __pmd(x)        (x)#define __pgd(x)	(x)#define __ctxd(x)	(x)#define __pgprot(x)	(x)#define __iopgprot(x)	(x)/* * In general all page table modifications should use the V8 atomic * swap instruction.  This insures the mmu and the cpu are in sync * with respect to ref/mod bits in the page tables. */static  unsigned long srmmu_swap(unsigned long *addr, unsigned long value){  #ifndef IMAGE_CREATE	__asm__ __volatile__("swap [%2], %0" : "=&r" (value) : "0" (value), "r" (addr));  #else	unsigned long old;	*addr = value;	value = old;  #endif	return value;}static  void srmmu_set_pte(pte_t *ptep, pte_t pteval){	srmmu_swap((unsigned long *)ptep, pte_val(pteval));}/* The very generic SRMMU page table operations. */static  int srmmu_device_memory(unsigned long x){	return ((x & 0xF0000000) != 0);}int srmmu_cache_pagetables;/* XXX Make this dynamic based on ram size - Anton */#define SRMMU_NOCACHE_BITMAP_SIZE (SRMMU_NOCACHE_NPAGES * 16)#define SRMMU_NOCACHE_BITMAP_SHIFT (PAGE_SHIFT - 4)void *srmmu_nocache_pool;void *srmmu_nocache_bitmap;int srmmu_nocache_low;int srmmu_nocache_used;//spinlock_t srmmu_nocache_spinlock;/* This makes sense. Honest it does - Anton */#define __nocache_pa(VADDR) VADDR // (((unsigned long)VADDR) - SRMMU_NOCACHE_VADDR + __pa((unsigned long)srmmu_nocache_pool))#define __nocache_va(PADDR) PADDR // (__va((unsigned long)PADDR) - (unsigned long)srmmu_nocache_pool + SRMMU_NOCACHE_VADDR)#define __nocache_fix(VADDR) VADDR // __va(__nocache_pa(VADDR))static  unsigned long srmmu_pgd_page(pgd_t pgd){ return srmmu_device_memory(pgd_val(pgd))?~0:(unsigned long)__nocache_va((pgd_val(pgd) & SRMMU_PTD_PMASK) << 4); }static  unsigned long srmmu_pmd_page(pmd_t pmd){ return srmmu_device_memory(pmd_val(pmd))?~0:(unsigned long)__nocache_va((pmd_val(pmd) & SRMMU_PTD_PMASK) << 4); }//static  struct page *srmmu_pte_page(pte_t pte)//{ return (mem_map + (unsigned long)(srmmu_device_memory(pte_val(pte))?~0:(((pte_val(pte) & SRMMU_PTE_PMASK) << 4) >> PAGE_SHIFT))); }static  int srmmu_pte_none(pte_t pte){ return !(pte_val(pte) & 0xFFFFFFF); }static  int srmmu_pte_present(pte_t pte){ return ((pte_val(pte) & SRMMU_ET_MASK) == SRMMU_ET_PTE); }static  void srmmu_pte_clear(pte_t *ptep){ srmmu_set_pte(ptep, __pte(0)); }static  int srmmu_pmd_none(pmd_t pmd){ return !(pmd_val(pmd) & 0xFFFFFFF); }static  int srmmu_pmd_bad(pmd_t pmd){ return (pmd_val(pmd) & SRMMU_ET_MASK) != SRMMU_ET_PTD; }static  int srmmu_pmd_present(pmd_t pmd){ return ((pmd_val(pmd) & SRMMU_ET_MASK) == SRMMU_ET_PTD); }static  void srmmu_pmd_clear(pmd_t *pmdp){ srmmu_set_pte((pte_t *)pmdp, __pte(0)); }static  int srmmu_pgd_none(pgd_t pgd)          { return !(pgd_val(pgd) & 0xFFFFFFF); }static  int srmmu_pgd_bad(pgd_t pgd){ return (pgd_val(pgd) & SRMMU_ET_MASK) != SRMMU_ET_PTD; }static  int srmmu_pgd_present(pgd_t pgd){ return ((pgd_val(pgd) & SRMMU_ET_MASK) == SRMMU_ET_PTD); }static  void srmmu_pgd_clear(pgd_t * pgdp){ srmmu_set_pte((pte_t *)pgdp, __pte(0)); }static  int srmmu_pte_write(pte_t pte){ return pte_val(pte) & SRMMU_WRITE; }static  int srmmu_pte_dirty(pte_t pte){ return pte_val(pte) & SRMMU_DIRTY; }static  int srmmu_pte_young(pte_t pte){ return pte_val(pte) & SRMMU_REF; }static  pte_t srmmu_pte_wrprotect(pte_t pte){ return __pte(pte_val(pte) & ~SRMMU_WRITE);}static  pte_t srmmu_pte_mkclean(pte_t pte){ return __pte(pte_val(pte) & ~SRMMU_DIRTY);}static  pte_t srmmu_pte_mkold(pte_t pte){ return __pte(pte_val(pte) & ~SRMMU_REF);}static  pte_t srmmu_pte_mkwrite(pte_t pte){ return __pte(pte_val(pte) | SRMMU_WRITE);}static  pte_t srmmu_pte_mkdirty(pte_t pte){ return __pte(pte_val(pte) | SRMMU_DIRTY);}static  pte_t srmmu_pte_mkyoung(pte_t pte){ return __pte(pte_val(pte) | SRMMU_REF);}/* * Conversion functions: convert a page and protection to a page entry, * and a page entry and page directory to the page they refer to. *///static pte_t srmmu_mk_pte(struct page *page, pgprot_t pgprot)//{ return __pte((((page - mem_map) << PAGE_SHIFT) >> 4) | pgprot_val(pgprot)); }static pte_t srmmu_mk_pte_phys(unsigned long page, pgprot_t pgprot){ return __pte(((page) >> 4) | pgprot_val(pgprot)); }static pte_t srmmu_mk_pte_io(unsigned long page, pgprot_t pgprot, int space){ return __pte(((page) >> 4) | (space << 28) | pgprot_val(pgprot)); }/* XXX should we hyper_flush_whole_icache here - Anton */static  void srmmu_ctxd_set(ctxd_t *ctxp, pgd_t *pgdp){ srmmu_set_pte((pte_t *)ctxp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pgdp) >> 4))); }static  void srmmu_pgd_set(pgd_t * pgdp, pmd_t * pmdp){ srmmu_set_pte((pte_t *)pgdp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) pmdp) >> 4))); }static  void srmmu_pmd_set(pmd_t * pmdp, pte_t * ptep){ srmmu_set_pte((pte_t *)pmdp, (SRMMU_ET_PTD | (__nocache_pa((unsigned long) ptep) >> 4))); }static  pte_t srmmu_pte_modify(pte_t pte, pgprot_t newprot){ return __pte((pte_val(pte) & SRMMU_CHG_MASK) | pgprot_val(newprot)); }/* to find an entry in a top-level page table... *///extern  pgd_t *srmmu_pgd_offset(struct mm_struct * mm, unsigned long address)//{ return mm->pgd + (address >> SRMMU_PGDIR_SHIFT); }/* Find an entry in the second-level page table.. */static  pmd_t *srmmu_pmd_offset(pgd_t * dir, unsigned long address){ return (pmd_t *) srmmu_pgd_page(*dir) + ((address >> SRMMU_PMD_SHIFT) & (SRMMU_PTRS_PER_PMD - 1)); }/* Find an entry in the third-level page table.. */ static  pte_t *srmmu_pte_offset(pmd_t * dir, unsigned long address){ return (pte_t *) srmmu_pmd_page(*dir) + ((address >> PAGE_SHIFT) & (SRMMU_PTRS_PER_PTE - 1)); }/* do a physical address bypass write, i.e. for 0x80000000 */static __inline__ void leon_store_bp(unsigned long paddr,unsigned long value){	__asm__ __volatile__("sta %0, [%1] %2\n\t": :			     "r" (value), "r" (paddr),			     "i" (ASI_MMU_BP) : "memory");}/* do a physical address bypass load, i.e. for 0x80000000 */static __inline__ unsigned long leon_load_bp(unsigned long paddr){	unsigned long retval;	__asm__ __volatile__("lda [%1] %2, %0\n\t" :			     "=r" (retval) :			     "r" (paddr), "i" (ASI_MMU_BP));	return retval;}#endif /*__ASSEMBLER__*/#endif /* _MMU_H */

⌨️ 快捷键说明

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