1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file "COPYING" in the main directory of this archive
4  * for more details.
5  *
6  * Copyright (C) 1999 Ralf Baechle
7  * Copyright (C) 1999 Silicon Graphics, Inc.
8  *
9  * TLB debugging routines.  These perform horribly slow but can easily be
10  * modified for debugging purposes.
11  */
12 #include <linux/linkage.h>
13 #include <linux/kernel.h>
14 #include <linux/sched.h>
15 #include <linux/mm.h>
16 #include <asm/page.h>
17 #include <asm/pgtable.h>
18 #include <asm/ptrace.h>
19 #include <asm/system.h>
20 
21 asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long write,
22                               unsigned long address);
23 
tlb_refill_debug(struct pt_regs regs)24 asmlinkage void tlb_refill_debug(struct pt_regs regs)
25 {
26 	show_regs(&regs);
27 	panic(__FUNCTION__ " called.  This Does Not Happen (TM).");
28 }
29 
xtlb_refill_debug(struct pt_regs * regs)30 asmlinkage void xtlb_refill_debug(struct pt_regs *regs)
31 {
32 	unsigned long addr;
33 	pgd_t *pgd;
34 	pmd_t *pmd;
35 	pte_t *pte;
36 
37 	addr = regs->cp0_badvaddr & ~((PAGE_SIZE << 1) - 1);
38 	pgd = pgd_offset(current->active_mm, addr);
39 	pmd = pmd_offset(pgd, addr);
40 	pte = pte_offset(pmd, addr);
41 
42 	write_c0_entrylo0(pte_val(pte[0]) >> 6);
43 	write_c0_entrylo1(pte_val(pte[1]) >> 6);
44 	__asm__ __volatile__("nop;nop;nop");
45 
46 	tlb_write_random();
47 }
48 
xtlb_mod_debug(struct pt_regs * regs)49 asmlinkage void xtlb_mod_debug(struct pt_regs *regs)
50 {
51 	unsigned long addr;
52 
53 	addr = regs->cp0_badvaddr;
54 	do_page_fault(regs, 1, addr);
55 }
56 
xtlb_tlbl_debug(struct pt_regs * regs)57 asmlinkage void xtlb_tlbl_debug(struct pt_regs *regs)
58 {
59 	unsigned long addr;
60 
61 	addr = regs->cp0_badvaddr;
62 	do_page_fault(regs, 0, addr);
63 }
64 
xtlb_tlbs_debug(struct pt_regs * regs)65 asmlinkage void xtlb_tlbs_debug(struct pt_regs *regs)
66 {
67 	unsigned long addr;
68 
69 	addr = regs->cp0_badvaddr;
70 	do_page_fault(regs, 1, addr);
71 }
72