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

📄 pgalloc.h

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 H
字号:
#ifndef _ASM_PGALLOC_H#define _ASM_PGALLOC_H/* The usual comment is "Caches aren't brain-dead on the <architecture>". * Unfortunately, that doesn't apply to PA-RISC. */#include <asm/processor.h>#include <asm/fixmap.h>#include <linux/threads.h>#include <asm/pgtable.h>#include <asm/cache.h>/* Internal use D/I cache flushing routines... *//* XXX: these functions must not access memory between f[di]ce instructions. */static inline void __flush_dcache_range(unsigned long start, unsigned long size){#if 0	register unsigned long count = (size / L1_CACHE_BYTES);	register unsigned long loop = cache_info.dc_loop;	register unsigned long i, j;	if (size > 64 * 1024) {		/* Just punt and clear the whole damn thing */		flush_data_cache();		return;	}	for(i = 0; i <= count; i++, start += L1_CACHE_BYTES)		for(j = 0; j < loop; j++)			fdce(start);#else	flush_data_cache();#endif}static inline void __flush_icache_range(unsigned long start, unsigned long size){#if 0	register unsigned long count = (size / L1_CACHE_BYTES);	register unsigned long loop = cache_info.ic_loop;	register unsigned long i, j;	if (size > 64 * 1024) {		/* Just punt and clear the whole damn thing */		flush_instruction_cache();		return;	}	for(i = 0; i <= count; i++, start += L1_CACHE_BYTES)		for(j = 0; j < loop; j++)			fice(start);#else	flush_instruction_cache();#endif}static inline voidflush_kernel_dcache_range(unsigned long start, unsigned long size){	register unsigned long end = start + size;	register unsigned long i;	start &= ~(L1_CACHE_BYTES - 1);	for (i = start; i < end; i += L1_CACHE_BYTES) {		kernel_fdc(i);	}	asm volatile("sync" : : );	asm volatile("syncdma" : : );}extern void __flush_page_to_ram(unsigned long address);#define flush_cache_all()			flush_all_caches()#define flush_cache_mm(foo)			flush_all_caches()#if 0/* This is how I think the cache flushing should be done -- mrw */extern inline void flush_cache_mm(struct mm_struct *mm) {	if (mm == current->mm) {		flush_user_dcache_range(mm->start_data, mm->end_data);		flush_user_icache_range(mm->start_code, mm->end_code);	} else {		flush_other_dcache_range(mm->context, mm->start_data, mm->end_data);		flush_other_icache_range(mm->context, mm->start_code, mm->end_code);	}}#endif#define flush_cache_range(mm, start, end) do { \                __flush_dcache_range(start, (unsigned long)end - (unsigned long)start); \                __flush_icache_range(start, (unsigned long)end - (unsigned long)start); \} while(0)#define flush_cache_page(vma, vmaddr) do { \                __flush_dcache_range(vmaddr, PAGE_SIZE); \                __flush_icache_range(vmaddr, PAGE_SIZE); \} while(0)#define flush_page_to_ram(page)	\        __flush_page_to_ram((unsigned long)page_address(page))#define flush_icache_range(start, end) \        __flush_icache_range(start, end - start)#define flush_icache_page(vma, page) \	__flush_icache_range(page_address(page), PAGE_SIZE)#define flush_dcache_page(page) \	__flush_dcache_range(page_address(page), PAGE_SIZE)/* TLB flushing routines.... */extern void flush_data_tlb(void);extern void flush_instruction_tlb(void);#define flush_tlb() do { \        flush_data_tlb(); \	flush_instruction_tlb(); \} while(0);#define flush_tlb_all() 	flush_tlb()	/* XXX p[id]tlb */extern __inline__ void flush_tlb_pgtables(struct mm_struct *mm, unsigned long start, unsigned long end){} static inline void flush_instruction_tlb_range(unsigned long start,					unsigned long size){#if 0	register unsigned long count = (size / PAGE_SIZE);	register unsigned long loop = cache_info.it_loop;	register unsigned long i, j;		for(i = 0; i <= count; i++, start += PAGE_SIZE)		for(j = 0; j < loop; j++)			pitlbe(start);#else	flush_instruction_tlb();#endif}static inline void flush_data_tlb_range(unsigned long start,					unsigned long size){#if 0	register unsigned long count = (size / PAGE_SIZE);	register unsigned long loop = cache_info.dt_loop;	register unsigned long i, j;		for(i = 0; i <= count; i++, start += PAGE_SIZE)		for(j = 0; j < loop; j++)			pdtlbe(start);#else	flush_data_tlb();#endif}static inline void __flush_tlb_range(unsigned long space, unsigned long start,		       unsigned long size){	unsigned long old_sr1;	if(!size)		return;	old_sr1 = mfsp(1);	mtsp(space, 1);		flush_data_tlb_range(start, size);	flush_instruction_tlb_range(start, size);	mtsp(old_sr1, 1);}extern void __flush_tlb_space(unsigned long space);static inline void flush_tlb_mm(struct mm_struct *mm){#if 0	__flush_tlb_space(mm->context);#else	flush_tlb();#endif}static inline void flush_tlb_page(struct vm_area_struct *vma,	unsigned long addr){	__flush_tlb_range(vma->vm_mm->context, addr, PAGE_SIZE);		}static inline void flush_tlb_range(struct mm_struct *mm,	unsigned long start, unsigned long end){	__flush_tlb_range(mm->context, start, end - start);}/* * NOTE: Many of the below macros use PT_NLEVELS because *       it is convenient that PT_NLEVELS == LOG2(pte size in bytes), *       i.e. we use 3 level page tables when we use 8 byte pte's *       (for 64 bit) and 2 level page tables when we use 4 byte pte's */#ifdef __LP64__#define PT_NLEVELS 3#define PT_INITIAL 4 /* Number of initial page tables */#else#define PT_NLEVELS 2#define PT_INITIAL 2 /* Number of initial page tables */#endif/* Definitions for 1st level */#define PGDIR_SHIFT  (PAGE_SHIFT + (PT_NLEVELS - 1)*(PAGE_SHIFT - PT_NLEVELS))#define PGDIR_SIZE	(1UL << PGDIR_SHIFT)#define PGDIR_MASK	(~(PGDIR_SIZE-1))#define PTRS_PER_PGD    (1UL << (PAGE_SHIFT - PT_NLEVELS))#define USER_PTRS_PER_PGD	(TASK_SIZE/PGDIR_SIZE)/* Definitions for 2nd level */#define PMD_SHIFT       (PAGE_SHIFT + (PAGE_SHIFT - PT_NLEVELS))#define PMD_SIZE	(1UL << PMD_SHIFT)#define PMD_MASK	(~(PMD_SIZE-1))#if PT_NLEVELS == 3#define PTRS_PER_PMD    (1UL << (PAGE_SHIFT - PT_NLEVELS))#else#define PTRS_PER_PMD    1#endif/* Definitions for 3rd level */#define PTRS_PER_PTE    (1UL << (PAGE_SHIFT - PT_NLEVELS))#define get_pgd_fast get_pgd_slow#define free_pgd_fast free_pgd_slowextern __inline__ pgd_t *get_pgd_slow(void){	extern unsigned long gateway_pgd_offset;	extern unsigned long gateway_pgd_entry;	pgd_t *ret = (pgd_t *)__get_free_page(GFP_KERNEL);	if (ret) {	    memset (ret, 0, PTRS_PER_PGD * sizeof(pgd_t));	    /* Install HP-UX and Linux gateway page translations */	    pgd_val(*(ret + gateway_pgd_offset)) = gateway_pgd_entry;	}	return ret;}extern __inline__ void free_pgd_slow(pgd_t *pgd){	free_page((unsigned long)pgd);}#if PT_NLEVELS == 3/* Three Level Page Table Support for pmd's */extern __inline__ pmd_t *get_pmd_fast(void){	return NULL; /* la la */}#if 0extern __inline__ void free_pmd_fast(pmd_t *pmd){}#else#define free_pmd_fast free_pmd_slow#endifextern __inline__ pmd_t *get_pmd_slow(void){	pmd_t *pmd = (pmd_t *) __get_free_page(GFP_KERNEL);	if (pmd)		clear_page(pmd);	return pmd;}extern __inline__ void free_pmd_slow(pmd_t *pmd){	free_page((unsigned long)pmd);}extern void __bad_pgd(pgd_t *pgd);extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address){	address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);	if (pgd_none(*pgd))		goto getnew;	if (pgd_bad(*pgd))		goto fix;	return (pmd_t *) pgd_page(*pgd) + address;getnew:{	pmd_t *page = get_pmd_fast();		if (!page)		page = get_pmd_slow();	if (page) {		if (pgd_none(*pgd)) {		    pgd_val(*pgd) = _PAGE_TABLE + __pa((unsigned long)page);		    return page + address;		}		else		    free_pmd_fast(page);	}	else {		return NULL;	}}fix:	__bad_pgd(pgd);	return NULL;}#else/* Two Level Page Table Support for pmd's */extern inline pmd_t * pmd_alloc(pgd_t * pgd, unsigned long address){	return (pmd_t *) pgd;}extern inline void free_pmd_fast(pmd_t * pmd){}#endifextern __inline__ pte_t *get_pte_fast(void){	return NULL; /* la la */}#if 0extern __inline__ void free_pte_fast(pte_t *pte){}#else#define free_pte_fast free_pte_slow#endifextern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);extern __inline__ void free_pte_slow(pte_t *pte){	free_page((unsigned long)pte);}#define pmd_alloc_kernel	pmd_alloc#define pte_alloc_kernel	pte_alloc#define pte_free(pte)		free_pte_fast(pte)#define pmd_free(pmd)           free_pmd_fast(pmd)#define pgd_free(pgd)		free_pgd_fast(pgd)#define pgd_alloc(mm)		get_pgd_fast()extern void __bad_pmd(pmd_t *pmd);extern inline pte_t * pte_alloc(pmd_t * pmd, unsigned long address){	address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);	if (pmd_none(*pmd))		goto getnew;	if (pmd_bad(*pmd))		goto fix;	return (pte_t *) pmd_page(*pmd) + address;getnew:{	pte_t *page = get_pte_fast();		if (!page)		return get_pte_slow(pmd, address);	pmd_val(*pmd) = _PAGE_TABLE + __pa((unsigned long)page);	return page + address;}fix:	__bad_pmd(pmd);	return NULL;}extern int do_check_pgt_cache(int, int);#endif

⌨️ 快捷键说明

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