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