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

📄 tlb-r3k.c

📁 一个2.4.21版本的嵌入式linux内核
💻 C
字号:
/* * r2300.c: R2000 and R3000 specific mmu/cache code. * * Copyright (C) 1996 David S. Miller (dm@engr.sgi.com) * * with a lot of changes to make this thing work for R3000s * Tx39XX R4k style caches added. HK * Copyright (C) 1998, 1999, 2000 Harald Koerfgen * Copyright (C) 1998 Gleb Raiko & Vladimir Roganov */#include <linux/config.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/mm.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/mmu_context.h>#include <asm/system.h>#include <asm/isadep.h>#include <asm/io.h>#include <asm/bootinfo.h>#include <asm/cpu.h>extern char except_vec0_r2300;#undef DEBUG_TLBint r3k_have_wired_reg = 0;	/* should be in mips_cpu? *//* TLB operations. */void local_flush_tlb_all(void){	unsigned long flags;	unsigned long old_ctx;	int entry;#ifdef DEBUG_TLB	printk("[tlball]");#endif	save_and_cli(flags);	old_ctx = (get_entryhi() & 0xfc0);	write_32bit_cp0_register(CP0_ENTRYLO0, 0);#ifdef CONFIG_CPU_TX39XX	entry = r3k_have_wired_reg ? get_wired() : 8;#else	entry = 8;#endif	for (; entry < mips_cpu.tlbsize; entry++) {		write_32bit_cp0_register(CP0_INDEX, entry << 8);		write_32bit_cp0_register(CP0_ENTRYHI, ((entry | 0x80000) << 12));		__asm__ __volatile__("tlbwi");	}	set_entryhi(old_ctx);	restore_flags(flags);}void local_flush_tlb_mm(struct mm_struct *mm){	if (mm->context != 0) {		unsigned long flags;#ifdef DEBUG_TLB		printk("[tlbmm<%lu>]", (unsigned long) mm->context);#endif		save_and_cli(flags);		get_new_mmu_context(mm, smp_processor_id());		if (mm == current->active_mm)			set_entryhi(mm->context & 0xfc0);		restore_flags(flags);	}}void local_flush_tlb_range(struct mm_struct *mm, unsigned long start,                     unsigned long end){	if (mm->context != 0) {		unsigned long flags;		int size;#ifdef DEBUG_TLB		printk("[tlbrange<%lu,0x%08lx,0x%08lx>]",			(mm->context & 0xfc0), start, end);#endif		save_and_cli(flags);		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;		if (size <= mips_cpu.tlbsize) {			int oldpid = (get_entryhi() & 0xfc0);			int newpid = (mm->context & 0xfc0);			start &= PAGE_MASK;			end += (PAGE_SIZE - 1);			end &= PAGE_MASK;			while (start < end) {				int idx;				set_entryhi(start | newpid);				start += PAGE_SIZE;				tlb_probe();				idx = get_index();				set_entrylo0(0);				set_entryhi(KSEG0);				if (idx < 0)					continue;				tlb_write_indexed();			}			set_entryhi(oldpid);		} else {			get_new_mmu_context(mm, smp_processor_id());			if (mm == current->active_mm)				set_entryhi(mm->context & 0xfc0);		}		restore_flags(flags);	}}void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page){	if (!vma || vma->vm_mm->context != 0) {		unsigned long flags;		int oldpid, newpid, idx;#ifdef DEBUG_TLB		printk("[tlbpage<%lu,0x%08lx>]", vma->vm_mm->context, page);#endif		newpid = (vma->vm_mm->context & 0xfc0);		page &= PAGE_MASK;		save_and_cli(flags);		oldpid = (get_entryhi() & 0xfc0);		set_entryhi(page | newpid);		tlb_probe();		idx = get_index();		set_entrylo0(0);		set_entryhi(KSEG0);		if (idx < 0)			goto finish;		tlb_write_indexed();finish:		set_entryhi(oldpid);		restore_flags(flags);	}}void update_mmu_cache(struct vm_area_struct * vma, unsigned long address,                      pte_t pte){	unsigned long flags;	pgd_t *pgdp;	pmd_t *pmdp;	pte_t *ptep;	int idx, pid;	/*	 * Handle debugger faulting in for debugee.	 */	if (current->active_mm != vma->vm_mm)		return;	pid = get_entryhi() & 0xfc0;#ifdef DEBUG_TLB	if ((pid != (vma->vm_mm->context & 0xfc0)) || (vma->vm_mm->context == 0)) {		printk("update_mmu_cache: Wheee, bogus tlbpid mmpid=%lu tlbpid=%d\n",		       (vma->vm_mm->context & 0xfc0), pid);	}#endif	save_and_cli(flags);	address &= PAGE_MASK;	set_entryhi(address | (pid));	pgdp = pgd_offset(vma->vm_mm, address);	tlb_probe();	pmdp = pmd_offset(pgdp, address);	idx = get_index();	ptep = pte_offset(pmdp, address);	set_entrylo0(pte_val(*ptep));	set_entryhi(address | (pid));	if (idx < 0) {		tlb_write_random();#if 0		printk("[MISS]");#endif	} else {		tlb_write_indexed();#if 0		printk("[HIT]");#endif	}	set_entryhi(pid);	restore_flags(flags);}void __init add_wired_entry(unsigned long entrylo0, unsigned long entrylo1,                     unsigned long entryhi, unsigned long pagemask){	unsigned long flags;	unsigned long old_ctx;	static unsigned long wired = 0;#ifdef CONFIG_CPU_TX39XX	if (r3k_have_wired_reg) {		unsigned long old_pagemask;		unsigned long w;#ifdef DEBUG_TLB		printk("[tlbwired]");		printk("ently lo0 %8x, hi %8x\n, pagemask %8x\n",		       entrylo0, entryhi, pagemask);#endif		save_and_cli(flags);		/* Save old context and create impossible VPN2 value */		old_ctx = (get_entryhi() & 0xff);		old_pagemask = get_pagemask();		w = get_wired();		set_wired (w + 1);		if (get_wired() != w + 1) {			printk("[tlbwired] No WIRED reg?\n");			return;		}		set_index (w << 8);		set_pagemask (pagemask);		set_entryhi(entryhi);		set_entrylo0(entrylo0);		tlb_write_indexed();		set_entryhi(old_ctx);		set_pagemask (old_pagemask);		local_flush_tlb_all();		restore_flags(flags);		return;	}#endif	if (wired < 8) {		__save_and_cli(flags);		old_ctx = get_entryhi() & 0xfc0;		set_entrylo0(entrylo0);		set_entryhi(entryhi);		set_index(wired);		wired++;		tlb_write_indexed();		set_entryhi(old_ctx);	        local_flush_tlb_all();		__restore_flags(flags);	}}void __init r3k_tlb_init(void){	local_flush_tlb_all();	memcpy((void *)KSEG0, &except_vec0_r2300, 0x80);	flush_icache_range(KSEG0, KSEG0 + 0x80);}

⌨️ 快捷键说明

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