1 /*--------------------------------------------------------------------------
2 --
3 -- Identity : Linux50 Debug Funcions
4 --
5 -- File     : arch/sh64/lib/dbg.C
6 --
7 -- Copyright 2000, 2001 STMicroelectronics Limited.
8 --
9 --------------------------------------------------------------------------*/
10 #include <linux/types.h>
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <linux/mm.h>
14 #include <asm/mmu_context.h>
15 
16 typedef u64 regType_t;
17 
getConfigReg(u64 id)18 static regType_t getConfigReg(u64 id)
19 {
20 	register u64 reg __asm__("r2");
21 	asm volatile ("getcfg   %1, 0, %0":"=r" (reg):"r"(id));
22 	return (reg);
23 }
24 
25 /* ======================================================================= */
26 
27 static char *szTab[] = { "4k", "64k", "1M", "512M" };
28 static char *protTab[] = { "----",
29 	"---R",
30 	"--X-",
31 	"--XR",
32 	"-W--",
33 	"-W-R",
34 	"-WX-",
35 	"-WXR",
36 	"U---",
37 	"U--R",
38 	"U-X-",
39 	"U-XR",
40 	"UW--",
41 	"UW-R",
42 	"UWX-",
43 	"UWXR"
44 };
45 #define  ITLB_BASE	0x00000000
46 #define  DTLB_BASE	0x00800000
47 #define  MAX_TLBs		64
48 /* PTE High */
49 #define  GET_VALID(pte)        ((pte) & 0x1)
50 #define  GET_SHARED(pte)       ((pte) & 0x2)
51 #define  GET_ASID(pte)         ((pte >> 2) & 0x0ff)
52 #define  GET_EPN(pte)          ((pte) & 0xfffff000)
53 
54 /* PTE Low */
55 #define  GET_CBEHAVIOR(pte)    ((pte) & 0x3)
56 #define  GET_PAGE_SIZE(pte)    szTab[((pte >> 3) & 0x3)]
57 #define  GET_PROTECTION(pte)   protTab[((pte >> 6) & 0xf)]
58 #define  GET_PPN(pte)          ((pte) & 0xfffff000)
59 
60 #define PAGE_1K_MASK           0x00000000
61 #define PAGE_4K_MASK           0x00000010
62 #define PAGE_64K_MASK          0x00000080
63 #define MMU_PAGESIZE_MASK      (PAGE_64K_MASK | PAGE_4K_MASK)
64 #define PAGE_1MB_MASK          MMU_PAGESIZE_MASK
65 #define PAGE_1K                (1024)
66 #define PAGE_4K                (1024 * 4)
67 #define PAGE_64K               (1024 * 64)
68 #define PAGE_1MB               (1024 * 1024)
69 
70 #define HOW_TO_READ_TLB_CONTENT  \
71        "[ ID]  PPN         EPN        ASID  Share  CB  P.Size   PROT.\n"
72 
print_single_tlb(unsigned long tlb,int single_print)73 void print_single_tlb(unsigned long tlb, int single_print)
74 {
75 	regType_t pteH;
76 	regType_t pteL;
77 	unsigned int valid, shared, asid, epn, cb, ppn;
78 	char *pSize;
79 	char *pProt;
80 
81 	/*
82 	   ** in case of single print <single_print> is true, this implies:
83 	   **   1) print the TLB in any case also if NOT VALID
84 	   **   2) print out the header
85 	 */
86 
87 	pteH = getConfigReg(tlb);
88 	valid = GET_VALID(pteH);
89 	if (single_print)
90 		printk(HOW_TO_READ_TLB_CONTENT);
91 	else if (!valid)
92 		return;
93 
94 	pteL = getConfigReg(tlb + 1);
95 
96 	shared = GET_SHARED(pteH);
97 	asid = GET_ASID(pteH);
98 	epn = GET_EPN(pteH);
99 	cb = GET_CBEHAVIOR(pteL);
100 	pSize = GET_PAGE_SIZE(pteL);
101 	pProt = GET_PROTECTION(pteL);
102 	ppn = GET_PPN(pteL);
103 	printk("[%c%2ld]  0x%08x  0x%08x  %03d   %02x    %02x   %4s    %s\n",
104 	       ((valid) ? ' ' : 'u'), ((tlb & 0x0ffff) / TLB_STEP),
105 	       ppn, epn, asid, shared, cb, pSize, pProt);
106 }
107 
print_dtlb(void)108 void print_dtlb(void)
109 {
110 	int count;
111 	unsigned long tlb;
112 
113 	printk(" ================= SH-5 D-TLBs Status ===================\n");
114 	printk(HOW_TO_READ_TLB_CONTENT);
115 	tlb = DTLB_BASE;
116 	for (count = 0; count < MAX_TLBs; count++, tlb += TLB_STEP)
117 		print_single_tlb(tlb, 0);
118 	printk
119 	    (" =============================================================\n");
120 }
121 
print_itlb(void)122 void print_itlb(void)
123 {
124 	int count;
125 	unsigned long tlb;
126 
127 	printk(" ================= SH-5 I-TLBs Status ===================\n");
128 	printk(HOW_TO_READ_TLB_CONTENT);
129 	tlb = ITLB_BASE;
130 	for (count = 0; count < MAX_TLBs; count++, tlb += TLB_STEP)
131 		print_single_tlb(tlb, 0);
132 	printk
133 	    (" =============================================================\n");
134 }
135 
136 /* ======================================================================= */
137 
138 #include "syscalltab.h"
139 
evt_debug(int evt,int ret_addr,int event,int tra)140 void evt_debug(int evt, int ret_addr, int event, int tra)
141 {
142 	int syscallno = tra & 0xff;
143 
144 	// if (event != 0) printk("<%03x>",evt);
145 
146 	if ((event == 2) && (evt == 0x160)) {
147 		if (syscallno < NUM_SYSCALL_INFO_ENTRIES)
148 			printk("Task %d: %s()\n",
149 			       current->pid,
150 			       syscall_info_table[syscallno].name);
151 	}
152 }
153 
evt_debug2(unsigned int ret)154 void evt_debug2(unsigned int ret)
155 {
156 	printk("Task %d: syscall returns %08x\n", current->pid, ret);
157 }
158 
159 /* ======================================================================= */
160 
show_excp_regs(char * from,int trapnr,int signr,struct pt_regs * regs)161 void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs)
162 {
163 
164 	unsigned long long ah, al, bh, bl, ch, cl;
165 
166 	printk("\n");
167 	printk("EXCEPTION - %s: task %d; Linux trap # %d; signal = %d\n",
168 	       ((from) ? from : "???"), current->pid, trapnr, signr);
169 
170 	asm volatile ("getcon   " __c5 ", %0":"=r"(ah));
171 	asm volatile ("getcon   " __c5 ", %0":"=r"(al));
172 	ah = (ah) >> 32;
173 	al = (al) & 0xffffffff;
174 	asm volatile ("getcon   " __c18 ", %0":"=r"(bh));
175 	asm volatile ("getcon   " __c18 ", %0":"=r"(bl));
176 	bh = (bh) >> 32;
177 	bl = (bl) & 0xffffffff;
178 	asm volatile ("getcon   " __c4 ", %0":"=r"(ch));
179 	asm volatile ("getcon   " __c4 ", %0":"=r"(cl));
180 	ch = (ch) >> 32;
181 	cl = (cl) & 0xffffffff;
182 	printk("EXPE: %08Lx%08Lx KCR1: %08Lx%08Lx INTE: %08Lx%08Lx\n",
183 	       ah, al, bh, bl, ch, cl);
184 
185 	asm volatile ("getcon   " __c6 ", %0":"=r"(ah));
186 	asm volatile ("getcon   " __c6 ", %0":"=r"(al));
187 	ah = (ah) >> 32;
188 	al = (al) & 0xffffffff;
189 	asm volatile ("getcon   " __c9 ", %0":"=r"(bh));
190 	asm volatile ("getcon   " __c9 ", %0":"=r"(bl));
191 	bh = (bh) >> 32;
192 	bl = (bl) & 0xffffffff;
193 	asm volatile ("getcon   " __c2 ", %0":"=r"(ch));
194 	asm volatile ("getcon   " __c2 ", %0":"=r"(cl));
195 	ch = (ch) >> 32;
196 	cl = (cl) & 0xffffffff;
197 	printk("PEXP: %08Lx%08Lx PSPC: %08Lx%08Lx PSSR: %08Lx%08Lx\n",
198 	       ah, al, bh, bl, ch, cl);
199 
200 	ah = (regs->pc) >> 32;
201 	al = (regs->pc) & 0xffffffff;
202 	bh = (regs->regs[18]) >> 32;
203 	bl = (regs->regs[18]) & 0xffffffff;
204 	ch = (regs->regs[15]) >> 32;
205 	cl = (regs->regs[15]) & 0xffffffff;
206 	printk("PC  : %08Lx%08Lx LINK: %08Lx%08Lx SP  : %08Lx%08Lx\n",
207 	       ah, al, bh, bl, ch, cl);
208 
209 	ah = (regs->sr) >> 32;
210 	al = (regs->sr) & 0xffffffff;
211 	asm volatile ("getcon   " __c13 ", %0":"=r"(bh));
212 	asm volatile ("getcon   " __c13 ", %0":"=r"(bl));
213 	bh = (bh) >> 32;
214 	bl = (bl) & 0xffffffff;
215 	asm volatile ("getcon   " __c17 ", %0":"=r"(ch));
216 	asm volatile ("getcon   " __c17 ", %0":"=r"(cl));
217 	ch = (ch) >> 32;
218 	cl = (cl) & 0xffffffff;
219 	printk("SR  : %08Lx%08Lx TEA : %08Lx%08Lx KCR0: %08Lx%08Lx\n",
220 	       ah, al, bh, bl, ch, cl);
221 
222 	ah = (regs->regs[0]) >> 32;
223 	al = (regs->regs[0]) & 0xffffffff;
224 	bh = (regs->regs[1]) >> 32;
225 	bl = (regs->regs[1]) & 0xffffffff;
226 	ch = (regs->regs[2]) >> 32;
227 	cl = (regs->regs[2]) & 0xffffffff;
228 	printk("R0  : %08Lx%08Lx R1  : %08Lx%08Lx R2  : %08Lx%08Lx\n",
229 	       ah, al, bh, bl, ch, cl);
230 
231 	ah = (regs->regs[3]) >> 32;
232 	al = (regs->regs[3]) & 0xffffffff;
233 	bh = (regs->regs[4]) >> 32;
234 	bl = (regs->regs[4]) & 0xffffffff;
235 	ch = (regs->regs[5]) >> 32;
236 	cl = (regs->regs[5]) & 0xffffffff;
237 	printk("R3  : %08Lx%08Lx R4  : %08Lx%08Lx R5  : %08Lx%08Lx\n",
238 	       ah, al, bh, bl, ch, cl);
239 
240 	ah = (regs->regs[6]) >> 32;
241 	al = (regs->regs[6]) & 0xffffffff;
242 	bh = (regs->regs[7]) >> 32;
243 	bl = (regs->regs[7]) & 0xffffffff;
244 	ch = (regs->regs[8]) >> 32;
245 	cl = (regs->regs[8]) & 0xffffffff;
246 	printk("R6  : %08Lx%08Lx R7  : %08Lx%08Lx R8  : %08Lx%08Lx\n",
247 	       ah, al, bh, bl, ch, cl);
248 
249 	ah = (regs->regs[9]) >> 32;
250 	al = (regs->regs[9]) & 0xffffffff;
251 	bh = (regs->regs[10]) >> 32;
252 	bl = (regs->regs[10]) & 0xffffffff;
253 	ch = (regs->regs[11]) >> 32;
254 	cl = (regs->regs[11]) & 0xffffffff;
255 	printk("R9  : %08Lx%08Lx R10 : %08Lx%08Lx R11 : %08Lx%08Lx\n",
256 	       ah, al, bh, bl, ch, cl);
257 	printk("....\n");
258 
259 	ah = (regs->tregs[0]) >> 32;
260 	al = (regs->tregs[0]) & 0xffffffff;
261 	bh = (regs->tregs[1]) >> 32;
262 	bl = (regs->tregs[1]) & 0xffffffff;
263 	ch = (regs->tregs[2]) >> 32;
264 	cl = (regs->tregs[2]) & 0xffffffff;
265 	printk("T0  : %08Lx%08Lx T1  : %08Lx%08Lx T2  : %08Lx%08Lx\n",
266 	       ah, al, bh, bl, ch, cl);
267 	printk("....\n");
268 
269 	print_dtlb();
270 	print_itlb();
271 }
272 
273 /* ======================================================================= */
274 
275 /*
276 ** Depending on <base> scan the MMU, Data or Instrction side
277 ** looking for a valid mapping matching Eaddr & asid.
278 ** Return -1 if not found or the TLB id entry otherwise.
279 ** Note: it works only for 4k pages!
280 */
281 static unsigned long
lookup_mmu_side(unsigned long base,unsigned long Eaddr,unsigned long asid)282 lookup_mmu_side(unsigned long base, unsigned long Eaddr, unsigned long asid)
283 {
284 	regType_t pteH;
285 	unsigned long epn;
286 	int count;
287 
288 	epn = Eaddr & 0xfffff000;
289 
290 	for (count = 0; count < MAX_TLBs; count++, base += TLB_STEP) {
291 		pteH = getConfigReg(base);
292 		if (GET_VALID(pteH))
293 			if ((unsigned long) GET_EPN(pteH) == epn)
294 				if ((unsigned long) GET_ASID(pteH) == asid)
295 					break;
296 	}
297 	return ((unsigned long) ((count < MAX_TLBs) ? base : -1));
298 }
299 
lookup_dtlb(unsigned long Eaddr)300 unsigned long lookup_dtlb(unsigned long Eaddr)
301 {
302 	unsigned long asid = get_asid();
303 	return (lookup_mmu_side((u64) DTLB_BASE, Eaddr, asid));
304 }
305 
lookup_itlb(unsigned long Eaddr)306 unsigned long lookup_itlb(unsigned long Eaddr)
307 {
308 	unsigned long asid = get_asid();
309 	return (lookup_mmu_side((u64) ITLB_BASE, Eaddr, asid));
310 }
311 
print_page(struct page * page)312 void print_page(struct page *page)
313 {
314 	printk("  page[%p] -> index 0x%lx,  count 0x%x,  flags 0x%lx\n",
315 	       page, page->index, atomic_read(&page->count), page->flags);
316 	printk("       address_space = %p, pages =%ld\n", page->mapping,
317 	       page->mapping->nrpages);
318 
319 }
320