File: /usr/src/linux/arch/mips/lib/r3k_dump_tlb.c

1     /*
2      * Dump R3000 TLB for debugging purposes.
3      *
4      * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
5      * Copyright (C) 1999 by Silicon Graphics, Inc.
6      * Copyright (C) 1999 by Harald Koerfgen
7      */
8     #include <linux/kernel.h>
9     #include <linux/mm.h>
10     #include <linux/sched.h>
11     #include <linux/string.h>
12     
13     #include <asm/bootinfo.h>
14     #include <asm/cachectl.h>
15     #include <asm/mipsregs.h>
16     #include <asm/page.h>
17     #include <asm/pgtable.h>
18     
19     #define mips_tlb_entries 64
20     
21     void
22     dump_tlb(int first, int last)
23     {
24     	int	i;
25     	unsigned int asid;
26     	unsigned long entryhi, entrylo0;
27     
28     	asid = get_entryhi() & 0xfc0;
29     
30     	for(i=first;i<=last;i++)
31     	{
32     		write_32bit_cp0_register(CP0_INDEX, i<<8);
33     		__asm__ __volatile__(
34     			".set\tnoreorder\n\t"
35     			"tlbr\n\t"
36     			"nop\n\t"
37     			".set\treorder");
38     		entryhi  = read_32bit_cp0_register(CP0_ENTRYHI);
39     		entrylo0 = read_32bit_cp0_register(CP0_ENTRYLO0);
40     
41     		/* Unused entries have a virtual address of KSEG0.  */
42     		if ((entryhi & 0xffffe000) != 0x80000000
43     		    && (entryhi & 0xfc0) == asid) {
44     			/*
45     			 * Only print entries in use
46     			 */
47     			printk("Index: %2d ", i);
48     
49     			printk("va=%08lx asid=%08lx"
50     			       "  [pa=%06lx n=%d d=%d v=%d g=%d]",
51     			       (entryhi & 0xffffe000),
52     			       entryhi & 0xfc0,
53     			       entrylo0 & PAGE_MASK,
54     			       (entrylo0 & (1 << 11)) ? 1 : 0,
55     			       (entrylo0 & (1 << 10)) ? 1 : 0,
56     			       (entrylo0 & (1 << 9)) ? 1 : 0,
57     			       (entrylo0 & (1 << 8)) ? 1 : 0);
58     		}
59     	}
60     	printk("\n");
61     
62     	set_entryhi(asid);
63     }
64     
65     void
66     dump_tlb_all(void)
67     {
68     	dump_tlb(0, mips_tlb_entries - 1);
69     }
70     
71     void
72     dump_tlb_wired(void)
73     {
74     	int	wired = 7;
75     
76     	printk("Wired: %d", wired);
77     	dump_tlb(0, read_32bit_cp0_register(CP0_WIRED));
78     }
79     
80     void
81     dump_tlb_addr(unsigned long addr)
82     {
83     	unsigned int flags, oldpid;
84     	int index;
85     
86     	__save_and_cli(flags);
87     	oldpid = get_entryhi() & 0xff;
88     	set_entryhi((addr & PAGE_MASK) | oldpid);
89     	tlb_probe();
90     	index = get_index();
91     	set_entryhi(oldpid);
92     	__restore_flags(flags);
93     
94     	if (index < 0) {
95     		printk("No entry for address 0x%08lx in TLB\n", addr);
96     		return;
97     	}
98     
99     	printk("Entry %d maps address 0x%08lx\n", index, addr);
100     	dump_tlb(index, index);
101     }
102     
103     void
104     dump_tlb_nonwired(void)
105     {
106     	dump_tlb(8, mips_tlb_entries - 1);
107     }
108     
109     void
110     dump_list_process(struct task_struct *t, void *address)
111     {
112     	pgd_t	*page_dir, *pgd;
113     	pmd_t	*pmd;
114     	pte_t	*pte, page;
115     	unsigned int addr;
116     	unsigned long val;
117     
118     	addr = (unsigned int) address;
119     
120     	printk("Addr                 == %08x\n", addr);
121     	printk("tasks->mm.pgd        == %08x\n", (unsigned int) t->mm->pgd);
122     
123     	page_dir = pgd_offset(t->mm, 0);
124     	printk("page_dir == %08x\n", (unsigned int) page_dir);
125     
126     	pgd = pgd_offset(t->mm, addr);
127     	printk("pgd == %08x, ", (unsigned int) pgd);
128     
129     	pmd = pmd_offset(pgd, addr);
130     	printk("pmd == %08x, ", (unsigned int) pmd);
131     
132     	pte = pte_offset(pmd, addr);
133     	printk("pte == %08x, ", (unsigned int) pte);
134     
135     	page = *pte;
136     	printk("page == %08x\n", (unsigned int) pte_val(page));
137     
138     	val = pte_val(page);
139     	if (val & _PAGE_PRESENT) printk("present ");
140     	if (val & _PAGE_READ) printk("read ");
141     	if (val & _PAGE_WRITE) printk("write ");
142     	if (val & _PAGE_ACCESSED) printk("accessed ");
143     	if (val & _PAGE_MODIFIED) printk("modified ");
144     	if (val & _PAGE_GLOBAL) printk("global ");
145     	if (val & _PAGE_VALID) printk("valid ");
146     	printk("\n");
147     }
148     
149     void
150     dump_list_current(void *address)
151     {
152     	dump_list_process(current, address);
153     }
154     
155     unsigned int
156     vtop(void *address)
157     {
158     	pgd_t	*pgd;
159     	pmd_t	*pmd;
160     	pte_t	*pte;
161     	unsigned int addr, paddr;
162     
163     	addr = (unsigned long) address;
164     	pgd = pgd_offset(current->mm, addr);
165     	pmd = pmd_offset(pgd, addr);
166     	pte = pte_offset(pmd, addr);
167     	paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
168     	paddr |= (addr & ~PAGE_MASK);
169     
170     	return paddr;
171     }
172     
173     void
174     dump16(unsigned long *p)
175     {
176     	int i;
177     
178     	for(i=0;i<8;i++)
179     	{
180     		printk("*%08lx == %08lx, ",
181     		       (unsigned long)p, (unsigned long)*p++);
182     		printk("*%08lx == %08lx\n",
183     		       (unsigned long)p, (unsigned long)*p++);
184     	}
185     }
186