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

📄 fault.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
	die("Oops", regs, error_code);	bust_spinlocks(0);	do_exit(SIGKILL);/* * We ran out of memory, or some other thing happened to us that made * us unable to handle the page fault gracefully. */out_of_memory:	up_read(&mm->mmap_sem);	if (tsk->pid == 1) {		yield();		down_read(&mm->mmap_sem);		goto survive;	}	printk("VM: killing process %s\n", tsk->comm);	if (error_code & ACE_USERMODE)		do_exit(SIGKILL);	goto no_context;do_sigbus:	up_read(&mm->mmap_sem);	/* Kernel mode? Handle exception or die */	if (!(error_code & ACE_USERMODE))		goto no_context;	tsk->thread.address = address;	tsk->thread.error_code = error_code;	tsk->thread.trap_no = 14;	info.si_signo = SIGBUS;	info.si_errno = 0;	info.si_code = BUS_ADRERR;	info.si_addr = (void __user *)address;	force_sig_info(SIGBUS, &info, tsk);	return;vmalloc_fault:	{		/*		 * Synchronize this task's top level page-table		 * with the 'reference' page table.		 *		 * Do _not_ use "tsk" here. We might be inside		 * an interrupt in the middle of a task switch..		 */		int offset = pgd_index(address);		pgd_t *pgd, *pgd_k;		pmd_t *pmd, *pmd_k;		pte_t *pte_k;		pgd = (pgd_t *)*(unsigned long *)MPTB;		pgd = offset + (pgd_t *)pgd;		pgd_k = init_mm.pgd + offset;		if (!pgd_present(*pgd_k))			goto no_context;		/*		 * set_pgd(pgd, *pgd_k); here would be useless on PAE		 * and redundant with the set_pmd() on non-PAE.		 */		pmd = pmd_offset(pgd, address);		pmd_k = pmd_offset(pgd_k, address);		if (!pmd_present(*pmd_k))			goto no_context;		set_pmd(pmd, *pmd_k);		pte_k = pte_offset_kernel(pmd_k, address);		if (!pte_present(*pte_k))			goto no_context;		addr = (address & PAGE_MASK) | (error_code & ACE_INSTRUCTION);		update_mmu_cache(NULL, addr, *pte_k);		return;	}}/*======================================================================* * update_mmu_cache() *======================================================================*/#define TLB_MASK	(NR_TLB_ENTRIES - 1)#define ITLB_END	(unsigned long *)(ITLB_BASE + (NR_TLB_ENTRIES * 8))#define DTLB_END	(unsigned long *)(DTLB_BASE + (NR_TLB_ENTRIES * 8))void update_mmu_cache(struct vm_area_struct *vma, unsigned long vaddr,	pte_t pte){	unsigned long *entry1, *entry2;	unsigned long pte_data, flags;	unsigned int *entry_dat;	int inst = get_thread_fault_code() & ACE_INSTRUCTION;	int i;	/* Ptrace may call this routine. */	if (vma && current->active_mm != vma->vm_mm)		return;	local_irq_save(flags);	vaddr = (vaddr & PAGE_MASK) | get_asid();#ifdef CONFIG_CHIP_OPSP	entry1 = (unsigned long *)ITLB_BASE;	for(i = 0 ; i < NR_TLB_ENTRIES; i++) {	        if(*entry1++ == vaddr) {	                pte_data = pte_val(pte);	                set_tlb_data(entry1, pte_data);	                break;	        }	        entry1++;	}	entry2 = (unsigned long *)DTLB_BASE;	for(i = 0 ; i < NR_TLB_ENTRIES ; i++) {	        if(*entry2++ == vaddr) {	                pte_data = pte_val(pte);	                set_tlb_data(entry2, pte_data);	                break;	        }	        entry2++;	}	local_irq_restore(flags);	return;#else	pte_data = pte_val(pte);	/*	 * Update TLB entries	 *  entry1: ITLB entry address	 *  entry2: DTLB entry address	 */	__asm__ __volatile__ (		"seth	%0, #high(%4)	\n\t"		"st	%2, @(%5, %0)	\n\t"		"ldi	%1, #1		\n\t"		"st	%1, @(%6, %0)	\n\t"		"add3	r4, %0, %7	\n\t"		".fillinsn		\n"		"1:			\n\t"		"ld	%1, @(%6, %0)	\n\t"		"bnez	%1, 1b		\n\t"		"ld	%0, @r4+	\n\t"		"ld	%1, @r4		\n\t"		"st	%3, @+%0	\n\t"		"st	%3, @+%1	\n\t"		: "=&r" (entry1), "=&r" (entry2)		: "r" (vaddr), "r" (pte_data), "i" (MMU_REG_BASE),		"i" (MSVA_offset), "i" (MTOP_offset), "i" (MIDXI_offset)		: "r4", "memory"	);	if ((!inst && entry2 >= DTLB_END) || (inst && entry1 >= ITLB_END))		goto notfound;found:	local_irq_restore(flags);	return;	/* Valid entry not found */notfound:	/*	 * Update ITLB or DTLB entry	 *  entry1: TLB entry address	 *  entry2: TLB base address	 */	if (!inst) {		entry2 = (unsigned long *)DTLB_BASE;		entry_dat = &tlb_entry_d;	} else {		entry2 = (unsigned long *)ITLB_BASE;		entry_dat = &tlb_entry_i;	}	entry1 = entry2 + (((*entry_dat - 1) & TLB_MASK) << 1);	for (i = 0 ; i < NR_TLB_ENTRIES ; i++) {		if (!(entry1[1] & 2))	/* Valid bit check */			break;		if (entry1 != entry2)			entry1 -= 2;		else			entry1 += TLB_MASK << 1;	}	if (i >= NR_TLB_ENTRIES) {	/* Empty entry not found */		entry1 = entry2 + (*entry_dat << 1);		*entry_dat = (*entry_dat + 1) & TLB_MASK;	}	*entry1++ = vaddr;	/* Set TLB tag */	set_tlb_data(entry1, pte_data);	goto found;#endif}/*======================================================================* * flush_tlb_page() : flushes one page *======================================================================*/void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long page){	if (vma->vm_mm && mm_context(vma->vm_mm) != NO_CONTEXT) {		unsigned long flags;		local_irq_save(flags);		page &= PAGE_MASK;		page |= (mm_context(vma->vm_mm) & MMU_CONTEXT_ASID_MASK);		__flush_tlb_page(page);		local_irq_restore(flags);	}}/*======================================================================* * flush_tlb_range() : flushes a range of pages *======================================================================*/void local_flush_tlb_range(struct vm_area_struct *vma, unsigned long start,	unsigned long end){	struct mm_struct *mm;	mm = vma->vm_mm;	if (mm_context(mm) != NO_CONTEXT) {		unsigned long flags;		int size;		local_irq_save(flags);		size = (end - start + (PAGE_SIZE - 1)) >> PAGE_SHIFT;		if (size > (NR_TLB_ENTRIES / 4)) { /* Too many TLB to flush */			mm_context(mm) = NO_CONTEXT;			if (mm == current->mm)				activate_context(mm);		} else {			unsigned long asid;			asid = mm_context(mm) & MMU_CONTEXT_ASID_MASK;			start &= PAGE_MASK;			end += (PAGE_SIZE - 1);			end &= PAGE_MASK;			start |= asid;			end   |= asid;			while (start < end) {				__flush_tlb_page(start);				start += PAGE_SIZE;			}		}		local_irq_restore(flags);	}}/*======================================================================* * flush_tlb_mm() : flushes the specified mm context TLB's *======================================================================*/void local_flush_tlb_mm(struct mm_struct *mm){	/* Invalidate all TLB of this process. */	/* Instead of invalidating each TLB, we get new MMU context. */	if (mm_context(mm) != NO_CONTEXT) {		unsigned long flags;		local_irq_save(flags);		mm_context(mm) = NO_CONTEXT;		if (mm == current->mm)			activate_context(mm);		local_irq_restore(flags);	}}/*======================================================================* * flush_tlb_all() : flushes all processes TLBs *======================================================================*/void local_flush_tlb_all(void){	unsigned long flags;	local_irq_save(flags);	__flush_tlb_all();	local_irq_restore(flags);}/*======================================================================* * init_mmu() *======================================================================*/void __init init_mmu(void){	tlb_entry_i = 0;	tlb_entry_d = 0;	mmu_context_cache = MMU_CONTEXT_FIRST_VERSION;	set_asid(mmu_context_cache & MMU_CONTEXT_ASID_MASK);	*(volatile unsigned long *)MPTB = (unsigned long)swapper_pg_dir;}

⌨️ 快捷键说明

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