xref: /openbmc/linux/arch/mips/lib/r3k_dump_tlb.c (revision 4becef1d)
14becef1dSAtsushi Nemoto /*
24becef1dSAtsushi Nemoto  * Dump R3000 TLB for debugging purposes.
34becef1dSAtsushi Nemoto  *
44becef1dSAtsushi Nemoto  * Copyright (C) 1994, 1995 by Waldorf Electronics, written by Ralf Baechle.
54becef1dSAtsushi Nemoto  * Copyright (C) 1999 by Silicon Graphics, Inc.
64becef1dSAtsushi Nemoto  * Copyright (C) 1999 by Harald Koerfgen
74becef1dSAtsushi Nemoto  */
84becef1dSAtsushi Nemoto #include <linux/kernel.h>
94becef1dSAtsushi Nemoto #include <linux/mm.h>
104becef1dSAtsushi Nemoto #include <linux/sched.h>
114becef1dSAtsushi Nemoto #include <linux/string.h>
124becef1dSAtsushi Nemoto 
134becef1dSAtsushi Nemoto #include <asm/bootinfo.h>
144becef1dSAtsushi Nemoto #include <asm/cachectl.h>
154becef1dSAtsushi Nemoto #include <asm/cpu.h>
164becef1dSAtsushi Nemoto #include <asm/mipsregs.h>
174becef1dSAtsushi Nemoto #include <asm/page.h>
184becef1dSAtsushi Nemoto #include <asm/pgtable.h>
194becef1dSAtsushi Nemoto 
204becef1dSAtsushi Nemoto extern int r3k_have_wired_reg;	/* defined in tlb-r3k.c */
214becef1dSAtsushi Nemoto 
224becef1dSAtsushi Nemoto void dump_tlb(int first, int last)
234becef1dSAtsushi Nemoto {
244becef1dSAtsushi Nemoto 	int	i;
254becef1dSAtsushi Nemoto 	unsigned int asid;
264becef1dSAtsushi Nemoto 	unsigned long entryhi, entrylo0;
274becef1dSAtsushi Nemoto 
284becef1dSAtsushi Nemoto 	asid = read_c0_entryhi() & 0xfc0;
294becef1dSAtsushi Nemoto 
304becef1dSAtsushi Nemoto 	for (i = first; i <= last; i++) {
314becef1dSAtsushi Nemoto 		write_c0_index(i<<8);
324becef1dSAtsushi Nemoto 		__asm__ __volatile__(
334becef1dSAtsushi Nemoto 			".set\tnoreorder\n\t"
344becef1dSAtsushi Nemoto 			"tlbr\n\t"
354becef1dSAtsushi Nemoto 			"nop\n\t"
364becef1dSAtsushi Nemoto 			".set\treorder");
374becef1dSAtsushi Nemoto 		entryhi  = read_c0_entryhi();
384becef1dSAtsushi Nemoto 		entrylo0 = read_c0_entrylo0();
394becef1dSAtsushi Nemoto 
404becef1dSAtsushi Nemoto 		/* Unused entries have a virtual address of KSEG0.  */
414becef1dSAtsushi Nemoto 		if ((entryhi & 0xffffe000) != 0x80000000
424becef1dSAtsushi Nemoto 		    && (entryhi & 0xfc0) == asid) {
434becef1dSAtsushi Nemoto 			/*
444becef1dSAtsushi Nemoto 			 * Only print entries in use
454becef1dSAtsushi Nemoto 			 */
464becef1dSAtsushi Nemoto 			printk("Index: %2d ", i);
474becef1dSAtsushi Nemoto 
484becef1dSAtsushi Nemoto 			printk("va=%08lx asid=%08lx"
494becef1dSAtsushi Nemoto 			       "  [pa=%06lx n=%d d=%d v=%d g=%d]",
504becef1dSAtsushi Nemoto 			       (entryhi & 0xffffe000),
514becef1dSAtsushi Nemoto 			       entryhi & 0xfc0,
524becef1dSAtsushi Nemoto 			       entrylo0 & PAGE_MASK,
534becef1dSAtsushi Nemoto 			       (entrylo0 & (1 << 11)) ? 1 : 0,
544becef1dSAtsushi Nemoto 			       (entrylo0 & (1 << 10)) ? 1 : 0,
554becef1dSAtsushi Nemoto 			       (entrylo0 & (1 << 9)) ? 1 : 0,
564becef1dSAtsushi Nemoto 			       (entrylo0 & (1 << 8)) ? 1 : 0);
574becef1dSAtsushi Nemoto 		}
584becef1dSAtsushi Nemoto 	}
594becef1dSAtsushi Nemoto 	printk("\n");
604becef1dSAtsushi Nemoto 
614becef1dSAtsushi Nemoto 	write_c0_entryhi(asid);
624becef1dSAtsushi Nemoto }
634becef1dSAtsushi Nemoto 
644becef1dSAtsushi Nemoto void dump_tlb_all(void)
654becef1dSAtsushi Nemoto {
664becef1dSAtsushi Nemoto 	dump_tlb(0, current_cpu_data.tlbsize - 1);
674becef1dSAtsushi Nemoto }
684becef1dSAtsushi Nemoto 
694becef1dSAtsushi Nemoto void dump_tlb_wired(void)
704becef1dSAtsushi Nemoto {
714becef1dSAtsushi Nemoto 	int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
724becef1dSAtsushi Nemoto 
734becef1dSAtsushi Nemoto 	printk("Wired: %d", wired);
744becef1dSAtsushi Nemoto 	dump_tlb(0, wired - 1);
754becef1dSAtsushi Nemoto }
764becef1dSAtsushi Nemoto 
774becef1dSAtsushi Nemoto void dump_tlb_addr(unsigned long addr)
784becef1dSAtsushi Nemoto {
794becef1dSAtsushi Nemoto 	unsigned long flags, oldpid;
804becef1dSAtsushi Nemoto 	int index;
814becef1dSAtsushi Nemoto 
824becef1dSAtsushi Nemoto 	local_irq_save(flags);
834becef1dSAtsushi Nemoto 	oldpid = read_c0_entryhi() & 0xff;
844becef1dSAtsushi Nemoto 	write_c0_entryhi((addr & PAGE_MASK) | oldpid);
854becef1dSAtsushi Nemoto 	tlb_probe();
864becef1dSAtsushi Nemoto 	index = read_c0_index();
874becef1dSAtsushi Nemoto 	write_c0_entryhi(oldpid);
884becef1dSAtsushi Nemoto 	local_irq_restore(flags);
894becef1dSAtsushi Nemoto 
904becef1dSAtsushi Nemoto 	if (index < 0) {
914becef1dSAtsushi Nemoto 		printk("No entry for address 0x%08lx in TLB\n", addr);
924becef1dSAtsushi Nemoto 		return;
934becef1dSAtsushi Nemoto 	}
944becef1dSAtsushi Nemoto 
954becef1dSAtsushi Nemoto 	printk("Entry %d maps address 0x%08lx\n", index, addr);
964becef1dSAtsushi Nemoto 	dump_tlb(index, index);
974becef1dSAtsushi Nemoto }
984becef1dSAtsushi Nemoto 
994becef1dSAtsushi Nemoto void dump_tlb_nonwired(void)
1004becef1dSAtsushi Nemoto {
1014becef1dSAtsushi Nemoto 	int wired = r3k_have_wired_reg ? read_c0_wired() : 8;
1024becef1dSAtsushi Nemoto 	dump_tlb(wired, current_cpu_data.tlbsize - 1);
1034becef1dSAtsushi Nemoto }
1044becef1dSAtsushi Nemoto 
1054becef1dSAtsushi Nemoto void dump_list_process(struct task_struct *t, void *address)
1064becef1dSAtsushi Nemoto {
1074becef1dSAtsushi Nemoto 	pgd_t	*page_dir, *pgd;
1084becef1dSAtsushi Nemoto 	pud_t	*pud;
1094becef1dSAtsushi Nemoto 	pmd_t	*pmd;
1104becef1dSAtsushi Nemoto 	pte_t	*pte, page;
1114becef1dSAtsushi Nemoto 	unsigned int addr;
1124becef1dSAtsushi Nemoto 	unsigned long val;
1134becef1dSAtsushi Nemoto 
1144becef1dSAtsushi Nemoto 	addr = (unsigned int) address;
1154becef1dSAtsushi Nemoto 
1164becef1dSAtsushi Nemoto 	printk("Addr                 == %08x\n", addr);
1174becef1dSAtsushi Nemoto 	printk("tasks->mm.pgd        == %08x\n", (unsigned int) t->mm->pgd);
1184becef1dSAtsushi Nemoto 
1194becef1dSAtsushi Nemoto 	page_dir = pgd_offset(t->mm, 0);
1204becef1dSAtsushi Nemoto 	printk("page_dir == %08x\n", (unsigned int) page_dir);
1214becef1dSAtsushi Nemoto 
1224becef1dSAtsushi Nemoto 	pgd = pgd_offset(t->mm, addr);
1234becef1dSAtsushi Nemoto 	printk("pgd == %08x, ", (unsigned int) pgd);
1244becef1dSAtsushi Nemoto 
1254becef1dSAtsushi Nemoto 	pud = pud_offset(pgd, addr);
1264becef1dSAtsushi Nemoto 	printk("pud == %08x, ", (unsigned int) pud);
1274becef1dSAtsushi Nemoto 
1284becef1dSAtsushi Nemoto 	pmd = pmd_offset(pud, addr);
1294becef1dSAtsushi Nemoto 	printk("pmd == %08x, ", (unsigned int) pmd);
1304becef1dSAtsushi Nemoto 
1314becef1dSAtsushi Nemoto 	pte = pte_offset(pmd, addr);
1324becef1dSAtsushi Nemoto 	printk("pte == %08x, ", (unsigned int) pte);
1334becef1dSAtsushi Nemoto 
1344becef1dSAtsushi Nemoto 	page = *pte;
1354becef1dSAtsushi Nemoto 	printk("page == %08x\n", (unsigned int) pte_val(page));
1364becef1dSAtsushi Nemoto 
1374becef1dSAtsushi Nemoto 	val = pte_val(page);
1384becef1dSAtsushi Nemoto 	if (val & _PAGE_PRESENT) printk("present ");
1394becef1dSAtsushi Nemoto 	if (val & _PAGE_READ) printk("read ");
1404becef1dSAtsushi Nemoto 	if (val & _PAGE_WRITE) printk("write ");
1414becef1dSAtsushi Nemoto 	if (val & _PAGE_ACCESSED) printk("accessed ");
1424becef1dSAtsushi Nemoto 	if (val & _PAGE_MODIFIED) printk("modified ");
1434becef1dSAtsushi Nemoto 	if (val & _PAGE_GLOBAL) printk("global ");
1444becef1dSAtsushi Nemoto 	if (val & _PAGE_VALID) printk("valid ");
1454becef1dSAtsushi Nemoto 	printk("\n");
1464becef1dSAtsushi Nemoto }
1474becef1dSAtsushi Nemoto 
1484becef1dSAtsushi Nemoto void dump_list_current(void *address)
1494becef1dSAtsushi Nemoto {
1504becef1dSAtsushi Nemoto 	dump_list_process(current, address);
1514becef1dSAtsushi Nemoto }
1524becef1dSAtsushi Nemoto 
1534becef1dSAtsushi Nemoto unsigned int vtop(void *address)
1544becef1dSAtsushi Nemoto {
1554becef1dSAtsushi Nemoto 	pgd_t	*pgd;
1564becef1dSAtsushi Nemoto 	pud_t	*pud;
1574becef1dSAtsushi Nemoto 	pmd_t	*pmd;
1584becef1dSAtsushi Nemoto 	pte_t	*pte;
1594becef1dSAtsushi Nemoto 	unsigned int addr, paddr;
1604becef1dSAtsushi Nemoto 
1614becef1dSAtsushi Nemoto 	addr = (unsigned long) address;
1624becef1dSAtsushi Nemoto 	pgd = pgd_offset(current->mm, addr);
1634becef1dSAtsushi Nemoto 	pud = pud_offset(pgd, addr);
1644becef1dSAtsushi Nemoto 	pmd = pmd_offset(pud, addr);
1654becef1dSAtsushi Nemoto 	pte = pte_offset(pmd, addr);
1664becef1dSAtsushi Nemoto 	paddr = (KSEG1 | (unsigned int) pte_val(*pte)) & PAGE_MASK;
1674becef1dSAtsushi Nemoto 	paddr |= (addr & ~PAGE_MASK);
1684becef1dSAtsushi Nemoto 
1694becef1dSAtsushi Nemoto 	return paddr;
1704becef1dSAtsushi Nemoto }
1714becef1dSAtsushi Nemoto 
1724becef1dSAtsushi Nemoto void dump16(unsigned long *p)
1734becef1dSAtsushi Nemoto {
1744becef1dSAtsushi Nemoto 	int i;
1754becef1dSAtsushi Nemoto 
1764becef1dSAtsushi Nemoto 	for (i = 0; i < 8; i++) {
1774becef1dSAtsushi Nemoto 		printk("*%08lx == %08lx, ", (unsigned long)p, *p);
1784becef1dSAtsushi Nemoto 		p++;
1794becef1dSAtsushi Nemoto 		printk("*%08lx == %08lx\n", (unsigned long)p, *p);
1804becef1dSAtsushi Nemoto 		p++;
1814becef1dSAtsushi Nemoto 	}
1824becef1dSAtsushi Nemoto }
183