/[dynamips]/upstream/dynamips-0.2.8-RC1/mips64_cp0.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/dynamips-0.2.8-RC1/mips64_cp0.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 11 - (show annotations)
Sat Oct 6 16:33:40 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 17581 byte(s)
dynamips-0.2.8-RC1

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * MIPS Coprocessor 0 (System Coprocessor) implementation.
6 * We don't use the JIT here, since there is no high performance needed.
7 */
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <string.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <sys/mman.h>
16 #include <fcntl.h>
17
18 #include "device.h"
19 #include "mips64.h"
20 #include "mips64_cp0.h"
21 #include "dynamips.h"
22 #include "memory.h"
23
24 /* MIPS cp0 registers names */
25 char *mips64_cp0_reg_names[MIPS64_CP0_REG_NR] = {
26 "index" ,
27 "random",
28 "entry_lo0",
29 "entry_lo1",
30 "context",
31 "pagemask",
32 "wired",
33 "info",
34 "badvaddr",
35 "count",
36 "entry_hi",
37 "compare",
38 "status",
39 "cause",
40 "epc",
41 "prid",
42 "config",
43 "ll_addr",
44 "watch_lo",
45 "watch_hi",
46 "xcontext",
47 "cp0_r21",
48 "cp0_r22",
49 "cp0_r23",
50 "cp0_r24",
51 "cp0_r25",
52 "ecc",
53 "cache_err",
54 "tag_lo",
55 "tag_hi",
56 "err_epc",
57 "cp0_r31",
58 };
59
60 /* Get cp0 register index given its name */
61 int mips64_cp0_get_reg_index(char *name)
62 {
63 int i;
64
65 for(i=0;i<MIPS64_CP0_REG_NR;i++)
66 if (!strcmp(mips64_cp0_reg_names[i],name))
67 return(i);
68
69 return(-1);
70 }
71
72 /* Get the CPU operating mode (User,Supervisor or Kernel) - inline version */
73 static forced_inline u_int mips64_cp0_get_mode_inline(cpu_mips_t *cpu)
74 {
75 mips_cp0_t *cp0 = &cpu->cp0;
76 u_int cpu_mode;
77
78 cpu_mode = cp0->reg[MIPS_CP0_STATUS] >> MIPS_CP0_STATUS_KSU_SHIFT;
79 cpu_mode &= MIPS_CP0_STATUS_KSU_MASK;
80 return(cpu_mode);
81 }
82
83 /* Get the CPU operating mode (User,Supervisor or Kernel) */
84 u_int mips64_cp0_get_mode(cpu_mips_t *cpu)
85 {
86 return(mips64_cp0_get_mode_inline(cpu));
87 }
88
89 /* Check that we are running in kernel mode */
90 int mips64_cp0_check_kernel_mode(cpu_mips_t *cpu)
91 {
92 u_int cpu_mode;
93
94 cpu_mode = mips64_cp0_get_mode(cpu);
95
96 if (cpu_mode != MIPS_CP0_STATUS_KM) {
97 /* XXX Branch delay slot */
98 mips64_trigger_exception(cpu,MIPS_CP0_CAUSE_ILLOP,0);
99 return(1);
100 }
101
102 return(0);
103 }
104
105 /* Get value of random register */
106 static inline u_int mips64_cp0_get_random_reg(cpu_mips_t *cpu)
107 {
108 u_int wired;
109
110 /* We use the virtual count register as a basic "random" value */
111 wired = cpu->cp0.reg[MIPS_CP0_WIRED];
112 return(wired + (cpu->cp0_virt_cnt_reg % (cpu->cp0.tlb_entries - wired)));
113 }
114
115 /* Get a cp0 register (fast version) */
116 static inline m_uint64_t mips64_cp0_get_reg_fast(cpu_mips_t *cpu,u_int cp0_reg)
117 {
118 mips_cp0_t *cp0 = &cpu->cp0;
119 m_uint32_t delta,res;
120
121 switch(cp0_reg) {
122 case MIPS_CP0_COUNT:
123 delta = cpu->cp0_virt_cmp_reg - cpu->cp0_virt_cnt_reg;
124 res = (m_uint32_t)cp0->reg[MIPS_CP0_COMPARE];
125 res -= cpu->vm->clock_divisor * delta;
126 return(sign_extend(res,32));
127
128 #if 1
129 case MIPS_CP0_COMPARE:
130 return(sign_extend(cp0->reg[MIPS_CP0_COMPARE],32));
131 #else
132 /* really useful and logical ? */
133 case MIPS_CP0_COMPARE:
134 delta = cpu->cp0_virt_cmp_reg - cpu->cp0_virt_cnt_reg;
135 res = (m_uint32_t)cp0->reg[MIPS_CP0_COUNT];
136 res += (cpu->vm->clock_divisor * delta);
137 return(res);
138 #endif
139 case MIPS_CP0_INFO:
140 return(MIPS64_R7000_TLB64_ENABLE);
141
142 case MIPS_CP0_RANDOM:
143 return(mips64_cp0_get_random_reg(cpu));
144
145 default:
146 return(cp0->reg[cp0_reg]);
147 }
148 }
149
150 /* Get a cp0 register */
151 m_uint64_t mips64_cp0_get_reg(cpu_mips_t *cpu,u_int cp0_reg)
152 {
153 return(mips64_cp0_get_reg_fast(cpu,cp0_reg));
154 }
155
156 /* Set a cp0 register */
157 static inline void mips64_cp0_set_reg(cpu_mips_t *cpu,u_int cp0_reg,
158 m_uint64_t val)
159 {
160 mips_cp0_t *cp0 = &cpu->cp0;
161 m_uint32_t delta;
162
163 switch(cp0_reg) {
164 case MIPS_CP0_STATUS:
165 case MIPS_CP0_CAUSE:
166 cp0->reg[cp0_reg] = val;
167 mips64_update_irq_flag(cpu);
168 break;
169
170 case MIPS_CP0_PAGEMASK:
171 cp0->reg[cp0_reg] = val & MIPS_TLB_PAGE_MASK;
172 break;
173
174 case MIPS_CP0_COMPARE:
175 mips64_clear_irq(cpu,7);
176 mips64_update_irq_flag(cpu);
177 cp0->reg[cp0_reg] = val;
178
179 delta = val - cp0->reg[MIPS_CP0_COUNT];
180 cpu->cp0_virt_cnt_reg = 0;
181 cpu->cp0_virt_cmp_reg = delta / cpu->vm->clock_divisor;
182 break;
183
184 case MIPS_CP0_COUNT:
185 cp0->reg[cp0_reg] = val;
186
187 delta = cp0->reg[MIPS_CP0_COMPARE] - val;
188 cpu->cp0_virt_cnt_reg = 0;
189 cpu->cp0_virt_cmp_reg = delta / cpu->vm->clock_divisor;
190 break;
191
192 case MIPS_CP0_TLB_HI:
193 cp0->reg[cp0_reg] = val & MIPS_CP0_HI_SAFE_MASK;
194 break;
195
196 case MIPS_CP0_TLB_LO_0:
197 case MIPS_CP0_TLB_LO_1:
198 cp0->reg[cp0_reg] = val & MIPS_CP0_LO_SAFE_MASK;
199 break;
200
201 case MIPS_CP0_RANDOM:
202 case MIPS_CP0_PRID:
203 case MIPS_CP0_CONFIG:
204 /* read only registers */
205 break;
206
207 case MIPS_CP0_WIRED:
208 cp0->reg[cp0_reg] = val & MIPS64_TLB_IDX_MASK;
209 break;
210
211 default:
212 cp0->reg[cp0_reg] = val;
213 }
214 }
215
216 /* Get a cp0 "set 1" register (R7000) */
217 m_uint64_t mips64_cp0_s1_get_reg(cpu_mips_t *cpu,u_int cp0_s1_reg)
218 {
219 switch(cp0_s1_reg) {
220 case MIPS_CP0_S1_CONFIG:
221 return(0x7F << 25);
222
223 case MIPS_CP0_S1_IPLLO:
224 return(cpu->cp0.ipl_lo);
225
226 case MIPS_CP0_S1_IPLHI:
227 return(cpu->cp0.ipl_hi);
228
229 case MIPS_CP0_S1_INTCTL:
230 return(cpu->cp0.int_ctl);
231
232 case MIPS_CP0_S1_DERRADDR0:
233 return(cpu->cp0.derraddr0);
234
235 case MIPS_CP0_S1_DERRADDR1:
236 return(cpu->cp0.derraddr1);
237
238 default:
239 /* undefined register */
240 cpu_log(cpu->gen,"CP0_S1","trying to read unknown register %u\n",
241 cp0_s1_reg);
242 return(0);
243 }
244 }
245
246 /* Set a cp0 "set 1" register (R7000) */
247 static inline void mips64_cp0_s1_set_reg(cpu_mips_t *cpu,u_int cp0_s1_reg,
248 m_uint64_t val)
249 {
250 mips_cp0_t *cp0 = &cpu->cp0;
251
252 switch(cp0_s1_reg) {
253 case MIPS_CP0_S1_IPLLO:
254 cp0->ipl_lo = val;
255 break;
256
257 case MIPS_CP0_S1_IPLHI:
258 cp0->ipl_hi = val;
259 break;
260
261 case MIPS_CP0_S1_INTCTL:
262 cp0->int_ctl = val;
263 break;
264
265 case MIPS_CP0_S1_DERRADDR0:
266 cp0->derraddr0 = val;
267 break;
268
269 case MIPS_CP0_S1_DERRADDR1:
270 cp0->derraddr1 = val;
271 break;
272
273 default:
274 cpu_log(cpu->gen,
275 "CP0_S1","trying to set unknown register %u (val=0x%x)\n",
276 cp0_s1_reg,val);
277 }
278 }
279
280 /* DMFC0 */
281 fastcall void mips64_cp0_exec_dmfc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
282 {
283 cpu->gpr[gp_reg] = mips64_cp0_get_reg_fast(cpu,cp0_reg);
284 }
285
286 /* DMTC0 */
287 fastcall void mips64_cp0_exec_dmtc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
288 {
289 mips64_cp0_set_reg(cpu,cp0_reg,cpu->gpr[gp_reg]);
290 }
291
292 /* MFC0 */
293 fastcall void mips64_cp0_exec_mfc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
294 {
295 cpu->gpr[gp_reg] = sign_extend(mips64_cp0_get_reg_fast(cpu,cp0_reg),32);
296 }
297
298 /* MTC0 */
299 fastcall void mips64_cp0_exec_mtc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
300 {
301 mips64_cp0_set_reg(cpu,cp0_reg,cpu->gpr[gp_reg] & 0xffffffff);
302 }
303
304 /* CFC0 */
305 fastcall void mips64_cp0_exec_cfc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
306 {
307 cpu->gpr[gp_reg] = sign_extend(mips64_cp0_s1_get_reg(cpu,cp0_reg),32);
308 }
309
310 /* CTC0 */
311 fastcall void mips64_cp0_exec_ctc0(cpu_mips_t *cpu,u_int gp_reg,u_int cp0_reg)
312 {
313 mips64_cp0_s1_set_reg(cpu,cp0_reg,cpu->gpr[gp_reg] & 0xffffffff);
314 }
315
316 /* Get the page size corresponding to a page mask */
317 static inline m_uint32_t get_page_size(m_uint32_t page_mask)
318 {
319 return((page_mask + 0x2000) >> 1);
320 }
321
322 /* Write page size in buffer */
323 static char *get_page_size_str(char *buffer,size_t len,m_uint32_t page_mask)
324 {
325 m_uint32_t page_size;
326
327 page_size = get_page_size(page_mask);
328
329 /* Mb ? */
330 if (page_size >= (1024*1024))
331 snprintf(buffer,len,"%uMB",page_size >> 20);
332 else
333 snprintf(buffer,len,"%uKB",page_size >> 10);
334
335 return buffer;
336 }
337
338 /* Get the VPN2 mask */
339 static forced_inline m_uint64_t mips64_cp0_get_vpn2_mask(cpu_mips_t *cpu)
340 {
341 if (cpu->addr_mode == 64)
342 return(MIPS_TLB_VPN2_MASK_64);
343 else
344 return(MIPS_TLB_VPN2_MASK_32);
345 }
346
347 /* TLB lookup */
348 int mips64_cp0_tlb_lookup(cpu_mips_t *cpu,m_uint64_t vaddr,mts_map_t *res)
349 {
350 mips_cp0_t *cp0 = &cpu->cp0;
351 m_uint64_t vpn_addr,vpn2_mask;
352 m_uint64_t page_mask,hi_addr;
353 m_uint32_t page_size,pca;
354 tlb_entry_t *entry;
355 u_int asid;
356 int i;
357
358 vpn2_mask = mips64_cp0_get_vpn2_mask(cpu);
359 vpn_addr = vaddr & vpn2_mask;
360
361 asid = cp0->reg[MIPS_CP0_TLB_HI] & MIPS_TLB_ASID_MASK;
362
363 for(i=0;i<cp0->tlb_entries;i++) {
364 entry = &cp0->tlb[i];
365
366 page_mask = ~(entry->mask + 0x1FFF);
367 hi_addr = entry->hi & vpn2_mask;
368
369 if (((vpn_addr & page_mask) == hi_addr) &&
370 ((entry->hi & MIPS_TLB_G_MASK) ||
371 ((entry->hi & MIPS_TLB_ASID_MASK) == asid)))
372 {
373 page_size = get_page_size(entry->mask);
374
375 if ((vaddr & page_size) == 0) {
376 /* Even Page */
377 if (entry->lo0 & MIPS_TLB_V_MASK) {
378 res->vaddr = vaddr & MIPS_MIN_PAGE_MASK;
379 res->paddr = (entry->lo0 & MIPS_TLB_PFN_MASK) << 6;
380 res->paddr += (res->vaddr & (page_size-1));
381 res->paddr &= cpu->addr_bus_mask;
382
383 res->offset = vaddr & MIPS_MIN_PAGE_IMASK;
384
385 pca = (entry->lo0 & MIPS_TLB_C_MASK);
386 pca >>= MIPS_TLB_C_SHIFT;
387 res->cached = mips64_cca_cached(pca);
388
389 res->tlb_index = i;
390 return(TRUE);
391 }
392 } else {
393 /* Odd Page */
394 if (entry->lo1 & MIPS_TLB_V_MASK) {
395
396 res->vaddr = vaddr & MIPS_MIN_PAGE_MASK;
397 res->paddr = (entry->lo1 & MIPS_TLB_PFN_MASK) << 6;
398 res->paddr += (res->vaddr & (page_size-1));
399 res->paddr &= cpu->addr_bus_mask;
400
401 res->offset = vaddr & MIPS_MIN_PAGE_IMASK;
402
403 pca = (entry->lo1 & MIPS_TLB_C_MASK);
404 pca >>= MIPS_TLB_C_SHIFT;
405 res->cached = mips64_cca_cached(pca);
406
407 res->tlb_index = i;
408 return(TRUE);
409 }
410 }
411
412 /* Invalid entry */
413 return(FALSE);
414 }
415 }
416
417 /* No matching entry */
418 return(FALSE);
419 }
420
421 /*
422 * Map a TLB entry into the MTS.
423 *
424 * We apply the physical address bus masking here.
425 *
426 * TODO: - Manage ASID
427 * - Manage CPU Mode (user,supervisor or kernel)
428 */
429 void mips64_cp0_map_tlb_to_mts(cpu_mips_t *cpu,int index)
430 {
431 m_uint64_t v0_addr,v1_addr,p0_addr,p1_addr;
432 m_uint32_t page_size,pca;
433 tlb_entry_t *entry;
434 int cacheable;
435
436 entry = &cpu->cp0.tlb[index];
437
438 page_size = get_page_size(entry->mask);
439 v0_addr = entry->hi & mips64_cp0_get_vpn2_mask(cpu);
440 v1_addr = v0_addr + page_size;
441
442 if (entry->lo0 & MIPS_TLB_V_MASK) {
443 pca = (entry->lo0 & MIPS_TLB_C_MASK);
444 pca >>= MIPS_TLB_C_SHIFT;
445 cacheable = mips64_cca_cached(pca);
446
447 p0_addr = (entry->lo0 & MIPS_TLB_PFN_MASK) << 6;
448 cpu->mts_map(cpu,v0_addr,p0_addr & cpu->addr_bus_mask,page_size,
449 cacheable,index);
450 }
451
452 if (entry->lo1 & MIPS_TLB_V_MASK) {
453 pca = (entry->lo1 & MIPS_TLB_C_MASK);
454 pca >>= MIPS_TLB_C_SHIFT;
455 cacheable = mips64_cca_cached(pca);
456
457 p1_addr = (entry->lo1 & MIPS_TLB_PFN_MASK) << 6;
458 cpu->mts_map(cpu,v1_addr,p1_addr & cpu->addr_bus_mask,page_size,
459 cacheable,index);
460 }
461 }
462
463 /*
464 * Unmap a TLB entry in the MTS.
465 */
466 void mips64_cp0_unmap_tlb_to_mts(cpu_mips_t *cpu,int index)
467 {
468 m_uint64_t v0_addr,v1_addr;
469 m_uint32_t page_size;
470 tlb_entry_t *entry;
471
472 entry = &cpu->cp0.tlb[index];
473
474 page_size = get_page_size(entry->mask);
475 v0_addr = entry->hi & mips64_cp0_get_vpn2_mask(cpu);
476 v1_addr = v0_addr + page_size;
477
478 if (entry->lo0 & MIPS_TLB_V_MASK)
479 cpu->mts_unmap(cpu,v0_addr,page_size,MTS_ACC_T,index);
480
481 if (entry->lo1 & MIPS_TLB_V_MASK)
482 cpu->mts_unmap(cpu,v1_addr,page_size,MTS_ACC_T,index);
483 }
484
485 /* Map all TLB entries into the MTS */
486 void mips64_cp0_map_all_tlb_to_mts(cpu_mips_t *cpu)
487 {
488 int i;
489
490 for(i=0;i<cpu->cp0.tlb_entries;i++)
491 mips64_cp0_map_tlb_to_mts(cpu,i);
492 }
493
494 /* TLBP: Probe a TLB entry */
495 fastcall void mips64_cp0_exec_tlbp(cpu_mips_t *cpu)
496 {
497 mips_cp0_t *cp0 = &cpu->cp0;
498 m_uint64_t hi_reg,asid;
499 m_uint64_t vpn2,vpn2_mask;
500 tlb_entry_t *entry;
501 int i;
502
503 vpn2_mask = mips64_cp0_get_vpn2_mask(cpu);
504 hi_reg = cp0->reg[MIPS_CP0_TLB_HI];
505 asid = hi_reg & MIPS_TLB_ASID_MASK;
506 vpn2 = hi_reg & vpn2_mask;
507
508 cp0->reg[MIPS_CP0_INDEX] = 0xffffffff80000000ULL;
509
510 for(i=0;i<cp0->tlb_entries;i++) {
511 entry = &cp0->tlb[i];
512
513 if (((entry->hi & vpn2_mask) == vpn2) &&
514 ((entry->hi & MIPS_TLB_G_MASK) ||
515 ((entry->hi & MIPS_TLB_ASID_MASK) == asid)))
516 {
517 cp0->reg[MIPS_CP0_INDEX] = i;
518 #if DEBUG_TLB_ACTIVITY
519 printf("CPU: CP0_TLBP returned %u\n",i);
520 tlb_dump(cpu);
521 #endif
522 }
523 }
524 }
525
526 /* TLBR: Read Indexed TLB entry */
527 fastcall void mips64_cp0_exec_tlbr(cpu_mips_t *cpu)
528 {
529 mips_cp0_t *cp0 = &cpu->cp0;
530 tlb_entry_t *entry;
531 u_int index;
532
533 index = cp0->reg[MIPS_CP0_INDEX];
534
535 #if DEBUG_TLB_ACTIVITY
536 cpu_log(cpu,"TLB","CP0_TLBR: reading entry %u.\n",index);
537 #endif
538
539 if (index < cp0->tlb_entries)
540 {
541 entry = &cp0->tlb[index];
542
543 cp0->reg[MIPS_CP0_PAGEMASK] = entry->mask;
544 cp0->reg[MIPS_CP0_TLB_HI] = entry->hi;
545 cp0->reg[MIPS_CP0_TLB_LO_0] = entry->lo0;
546 cp0->reg[MIPS_CP0_TLB_LO_1] = entry->lo1;
547
548 /*
549 * The G bit must be reported in both Lo0 and Lo1 registers,
550 * and cleared in Hi register.
551 */
552 if (entry->hi & MIPS_TLB_G_MASK) {
553 cp0->reg[MIPS_CP0_TLB_LO_0] |= MIPS_CP0_LO_G_MASK;
554 cp0->reg[MIPS_CP0_TLB_LO_1] |= MIPS_CP0_LO_G_MASK;
555 cp0->reg[MIPS_CP0_TLB_HI] &= ~MIPS_TLB_G_MASK;
556 }
557 }
558 }
559
560 /* TLBW: Write a TLB entry */
561 static inline void mips64_cp0_exec_tlbw(cpu_mips_t *cpu,u_int index)
562 {
563 mips_cp0_t *cp0 = &cpu->cp0;
564 tlb_entry_t *entry;
565
566 #if DEBUG_TLB_ACTIVITY
567 cpu_log(cpu,"TLB","CP0_TLBWI: writing entry %u "
568 "[mask=0x%8.8llx,hi=0x%8.8llx,lo0=0x%8.8llx,lo1=0x%8.8llx]\n",
569 index,cp0->reg[MIPS_CP0_PAGEMASK],cp0->reg[MIPS_CP0_TLB_HI],
570 cp0->reg[MIPS_CP0_TLB_LO_0],cp0->reg[MIPS_CP0_TLB_LO_1]);
571 #endif
572
573 if (index < cp0->tlb_entries)
574 {
575 entry = &cp0->tlb[index];
576
577 /* Unmap the old entry if it was valid */
578 mips64_cp0_unmap_tlb_to_mts(cpu,index);
579
580 entry->mask = cp0->reg[MIPS_CP0_PAGEMASK] & MIPS_TLB_PAGE_MASK;
581 entry->hi = cp0->reg[MIPS_CP0_TLB_HI] & ~entry->mask;
582 entry->hi &= MIPS_CP0_HI_SAFE_MASK; /* clear G bit */
583 entry->lo0 = cp0->reg[MIPS_CP0_TLB_LO_0];
584 entry->lo1 = cp0->reg[MIPS_CP0_TLB_LO_1];
585
586 /* if G bit is set in lo0 and lo1, set it in hi */
587 if ((entry->lo0 & entry->lo1) & MIPS_CP0_LO_G_MASK)
588 entry->hi |= MIPS_TLB_G_MASK;
589
590 /* Clear G bit in TLB lo0 and lo1 */
591 entry->lo0 &= ~MIPS_CP0_LO_G_MASK;
592 entry->lo1 &= ~MIPS_CP0_LO_G_MASK;
593
594 /* Inform the MTS subsystem */
595 mips64_cp0_map_tlb_to_mts(cpu,index);
596
597 #if DEBUG_TLB_ACTIVITY
598 mips64_tlb_dump_entry(cpu,index);
599 #endif
600 }
601 }
602
603 /* TLBWI: Write Indexed TLB entry */
604 fastcall void mips64_cp0_exec_tlbwi(cpu_mips_t *cpu)
605 {
606 mips64_cp0_exec_tlbw(cpu,cpu->cp0.reg[MIPS_CP0_INDEX]);
607 }
608
609 /* TLBWR: Write Random TLB entry */
610 fastcall void mips64_cp0_exec_tlbwr(cpu_mips_t *cpu)
611 {
612 mips64_cp0_exec_tlbw(cpu,mips64_cp0_get_random_reg(cpu));
613 }
614
615 /* Raw dump of the TLB */
616 void mips64_tlb_raw_dump(cpu_gen_t *cpu)
617 {
618 cpu_mips_t *mcpu = CPU_MIPS64(cpu);
619 tlb_entry_t *entry;
620 u_int i;
621
622 printf("TLB dump:\n");
623
624 for(i=0;i<mcpu->cp0.tlb_entries;i++) {
625 entry = &mcpu->cp0.tlb[i];
626 printf(" %2d: mask=0x%16.16llx hi=0x%16.16llx "
627 "lo0=0x%16.16llx lo1=0x%16.16llx\n",
628 i, entry->mask, entry->hi, entry->lo0, entry->lo1);
629 }
630
631 printf("\n");
632 }
633
634 /* Dump the specified TLB entry */
635 void mips64_tlb_dump_entry(cpu_mips_t *cpu,u_int index)
636 {
637 tlb_entry_t *entry;
638 char buffer[256];
639
640 entry = &cpu->cp0.tlb[index];
641
642 /* virtual Address */
643 printf(" %2d: vaddr=0x%8.8llx ",
644 index, entry->hi & mips64_cp0_get_vpn2_mask(cpu));
645
646 /* global or ASID */
647 if (entry->hi & MIPS_TLB_G_MASK)
648 printf("(global) ");
649 else
650 printf("(asid 0x%2.2llx) ",entry->hi & MIPS_TLB_ASID_MASK);
651
652 /* 1st page: Lo0 */
653 printf("p0=");
654
655 if (entry->lo0 & MIPS_TLB_V_MASK)
656 printf("0x%9.9llx",(entry->lo0 & MIPS_TLB_PFN_MASK) << 6);
657 else
658 printf("(invalid) ");
659
660 printf(" %c ",(entry->lo0 & MIPS_TLB_D_MASK) ? 'D' : ' ');
661
662 /* 2nd page: Lo1 */
663 printf("p1=");
664
665 if (entry->lo1 & MIPS_TLB_V_MASK)
666 printf("0x%9.9llx",(entry->lo1 & MIPS_TLB_PFN_MASK) << 6);
667 else
668 printf("(invalid) ");
669
670 printf(" %c ",(entry->lo1 & MIPS_TLB_D_MASK) ? 'D' : ' ');
671
672 /* page size */
673 printf(" (%s)\n",get_page_size_str(buffer,sizeof(buffer),entry->mask));
674 }
675
676 /* Human-Readable dump of the TLB */
677 void mips64_tlb_dump(cpu_gen_t *cpu)
678 {
679 cpu_mips_t *mcpu = CPU_MIPS64(cpu);
680 u_int i;
681
682 printf("TLB dump:\n");
683
684 for(i=0;i<mcpu->cp0.tlb_entries;i++)
685 mips64_tlb_dump_entry(mcpu,i);
686
687 printf("\n");
688 }

  ViewVC Help
Powered by ViewVC 1.1.26