Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / legion / src / procs / sunsparc / debug / debug.c
CommitLineData
920dae64
AT
1/*
2* ========== Copyright Header Begin ==========================================
3*
4* OpenSPARC T2 Processor File: debug.c
5* Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
6* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
7*
8* The above named program is free software; you can redistribute it and/or
9* modify it under the terms of the GNU General Public
10* License version 2 as published by the Free Software Foundation.
11*
12* The above named program is distributed in the hope that it will be
13* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15* General Public License for more details.
16*
17* You should have received a copy of the GNU General Public
18* License along with this work; if not, write to the Free Software
19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20*
21* ========== Copyright Header End ============================================
22*/
23/*
24 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27#pragma ident "@(#)debug.c 1.29 07/05/30 SMI"
28
29#include <stdio.h>
30
31#include "ss_common.h"
32#include "options.h"
33
34#ifdef ERROR_TRAP_GEN
35#include "ss_err_trap.h"
36#endif
37
38#ifdef NIAGARA1
39#include "niagara.h"
40#endif
41
42#ifdef NIAGARA2
43#include "niagara2.h"
44#endif
45
46#ifdef ROCK
47#include "rock.h"
48#endif
49
50
51void debug_log(simcpu_t *sp, uint32_t rawi);
52
53#define DEBUG_LOG_SIZE 16384 /* XXX FIXME: parse from conf file */
54
55struct debug_log {
56 uint64_t count;
57 uint64_t pc;
58 uint32_t rawi;
59 uint32_t tl;
60 uint32_t tt;
61 uint32_t gl;
62 sparcv9_state_t state;
63};
64
65struct debug_spe {
66 simcpu_t *sp;
67 struct debug_log log[DEBUG_LOG_SIZE];
68 uint64_t log_count;
69 struct debug_spe *next;
70} *debug_spe_head = NULL, *debug_spe_focus = NULL;
71
72char debug_buf[160];
73
74int do_next = false;
75
76void
77debug_hook()
78{
79}
80
81static void
82print_spe_id(struct debug_spe *spe, char *pre, char *post)
83{
84 simcpu_t *sp;
85 sparcv9_cpu_t *v9p;
86 ss_strand_t *nsp;
87
88 sp = spe->sp;
89 v9p = sp->specificp;
90 nsp = v9p->impl_specificp;
91
92 printf("%s%u (proc %u strand %u [core %u thread %u])%s",
93 pre,
94 sp->gid,
95 sp->config_procp->proc_id,
96 nsp->vcore_id, nsp->core, nsp->vthread,
97 post);
98}
99
100void
101debug_focus_show(void)
102{
103 print_spe_id(debug_spe_focus, "focus is ", "\n");
104}
105
106void
107debug_focus_set(int id)
108{
109 struct debug_spe *spe;
110
111 for (spe = debug_spe_head; spe != NULL; spe = spe->next) {
112 if (spe->sp->gid == id)
113 break;
114 }
115
116 if (spe == NULL) {
117 printf("unable to set focus to %d\n", id);
118 } else {
119 debug_spe_focus = spe;
120
121 print_spe_id(debug_spe_focus, "focus is now ", "\n");
122 }
123
124}
125
126void
127debug_clear_breakpoint(tvaddr_t bpaddr)
128{
129 if (debug_spe_head != NULL) {
130 sparcv9_clear_break(
131 (sparcv9_cpu_t *)debug_spe_head->sp->specificp, bpaddr);
132 }
133}
134
135void
136debug_print_breakpoints(void)
137{
138 if (debug_spe_head != NULL) {
139 sparcv9_print_break(
140 (sparcv9_cpu_t *)debug_spe_head->sp->specificp);
141 }
142}
143void
144debug_set_breakpoint(tvaddr_t bpaddr)
145{
146 if (debug_spe_head != NULL) {
147 sparcv9_set_break(
148 (sparcv9_cpu_t *)debug_spe_head->sp->specificp, bpaddr);
149 }
150}
151
152void
153debug_set_breakpoint_next(void)
154{
155 sparcv9_cpu_t *v9p = (sparcv9_cpu_t *)debug_spe_focus->sp->specificp;
156
157 sparcv9_set_break_next(v9p);
158
159 do_next = true;
160}
161
162void
163debug_breakpoint_cb(void *arg)
164{
165 struct debug_spe *spe;
166
167 /* try to set focus appropriately */
168 for (spe = debug_spe_head; spe != NULL; spe = spe->next) {
169 sparcv9_cpu_t *v9p = (sparcv9_cpu_t *)spe->sp->specificp;
170
171 if (sparcv9_hit_break(v9p, spe->sp->pc))
172 break;
173 }
174 if (spe != NULL && spe != debug_spe_focus)
175 debug_focus_set(spe->sp->gid);
176
177
178 if (do_next) {
179 sparcv9_cpu_t *v9p;
180
181 v9p = (sparcv9_cpu_t *)(debug_spe_focus->sp->specificp);
182
183 sparcv9_clear_break_next(v9p);
184 do_next = false;
185 }
186
187 debug_hook();
188
189#if ERROR_TRAP_GEN /* { */
190 check_if_error_event_pending();
191#endif
192
193 if (do_next) {
194 /* if we're single stepping enable only single cpu */
195 for (spe = debug_spe_head; spe != NULL; spe = spe->next) {
196 if (spe != debug_spe_focus) {
197 if (!DISABLED(spe->sp))
198 simcore_cpu_disable(spe->sp);
199 }
200 }
201 } else {
202 /* otherwise we're not single stepping enable all cpus */
203 for (spe = debug_spe_head; spe != NULL; spe = spe->next) {
204 if (DISABLED(spe->sp))
205 simcore_cpu_enable(spe->sp);
206 }
207 }
208
209 /*
210 * this is a bit of a hack, but we assume that if auto_start is set
211 * then gdb is in use and therefore assume someone else will restart
212 * the simulation so don't bother.
213 */
214 if (options.flag_auto_start)
215 simcore_start();
216}
217
218void
219debug_init(simcpu_t *sp)
220{
221 struct debug_spe *spe, *prev, *tmp;
222
223 if (debug_spe_head == NULL)
224 callback_register(CB_Breakpoint, debug_breakpoint_cb, NULL);
225
226 spe = Xcalloc(1, struct debug_spe);
227 spe->sp = sp;
228
229 for (prev = NULL, tmp = debug_spe_head;
230 tmp != NULL;
231 prev = tmp, tmp = tmp->next)
232 ;
233
234 if (prev == NULL) {
235 debug_spe_head = spe;
236 debug_spe_focus = debug_spe_head;
237 } else {
238 prev->next = spe;
239 }
240
241 sp->debug = (void *)spe;
242}
243
244void
245debug_dump_pc_one(struct debug_spe *spe)
246{
247 tvaddr_t xpc;
248 uint64_t xidx;
249 xicache_instn_t *xip;
250
251 xpc = spe->sp->pc;
252 xidx = (xpc >> 2) & XICACHE_NUM_INSTR_MASK;
253 xip = &spe->sp->xicachep->instn[xidx];
254
255 sparcv9_idis(debug_buf, sizeof (debug_buf),
256 FE_INSTN(xip->rawi), spe->sp->pc);
257 printf("pc = 0x%llx:\t%08x\t%s\n", spe->sp->pc, FE_INSTN(xip->rawi),
258 debug_buf);
259}
260
261void
262debug_dump_pc(void)
263{
264 debug_dump_pc_one(debug_spe_focus);
265}
266
267void
268debug_dump_pc_all(void)
269{
270 struct debug_spe *spe;
271
272 for (spe = debug_spe_head; spe != NULL; spe = spe->next) {
273 print_spe_id(spe, "--- ", " ---\n");
274 debug_dump_pc_one(spe);
275 }
276}
277
278
279#define CHUNKSZ (sizeof (uint64_t))
280int
281debug_x(uint64_t addr, int chunks)
282{
283 domain_t *domainp;
284 config_proc_t *config_procp;
285 config_addr_t *cap;
286 uint64_t extent;
287 uint64_t *bufp;
288
289 config_procp = debug_spe_focus->sp->config_procp;
290 domainp = config_procp->domainp;
291
292 addr &= ~(CHUNKSZ - 1); /* force 8-byte alignment */
293
294 cap = find_domain_address(domainp, addr);
295 if (cap == NULL) {
296 printf("0x%llx not mapped in domain\n", addr);
297 return (false);
298 }
299
300 extent = cap->config_devp->dev_typep->dev_cacheable(cap, DA_Load,
301 addr - cap->baseaddr, (uint8_t **)&bufp);
302 if (extent < chunks * CHUNKSZ) {
303 if (extent == 0) {
304 printf("0x%llx not cacheable memory in domain\n", addr);
305 return (false);
306 }
307 if (extent < CHUNKSZ) {
308 printf("0x%llx less than %d bytes to print\n",
309 addr, CHUNKSZ);
310 return (false);
311 }
312 chunks = extent / CHUNKSZ;
313 }
314
315 while (chunks--) {
316 printf("0x%llx\t0x%016llx\n", addr, *bufp);
317 addr += CHUNKSZ;
318 bufp++;
319 }
320
321 return (true);
322}
323
324
325/*
326 * Since the context is not specified for the translate command,
327 * check all entries that match the partition ID and print any
328 * that match.
329 */
330uint_t
331debug_search_tlb(ss_strand_t *nsp, ss_tlb_t *tlbp, uint64_t va, char *nam)
332{
333 tlb_entry_t *tep;
334 ulong_t partid, i;
335 uint_t count = 0;
336
337 partid = nsp->partid;
338
339 for (i = tlbp->nentries, tep = &(tlbp->tlb_entryp[0]);
340 i > 0; i--, tep++) {
341 if (tep->hashidx == -1) continue;
342
343 if (((tep->tag_pfn ^ va) >> tep->match_shift) == 0 &&
344 tep->partid == partid) {
345 uint64_t pa = va + tep->pa_offset;
346 if (tep->is_real)
347 printf("va:0x%016llx real -> pa:0x%016llx %s\n",
348 va, pa, nam);
349 else
350 printf("va:0x%016llx context:0x%x -> "
351 "pa:0x%016llx %s\n",
352 va, tep->tag_context, pa, nam);
353 count++;
354 }
355 }
356
357 return (count);
358}
359
360void
361debug_print_icount(void)
362{
363 simcpu_t *sp = debug_spe_focus->sp;
364
365 lprintf(sp->gid, "icount = 0x%lld\n", ICOUNT(sp));
366}
367
368
369void
370debug_initiate_save_state_now(void)
371{
372 simcpu_t *sp = debug_spe_focus->sp;
373 uint64_t now;
374
375 now = ICOUNT(sp);
376 options.save_restore.trigger_icount = now;
377 lprintf(sp->gid, "Debugger requested save_state. Current"
378 " icount=0x%llx\n", now);
379}
380
381void
382debug_print_scratch(int id)
383{
384 simcpu_t *sp;
385 sparcv9_cpu_t *v9p;
386 ss_strand_t *nsp;
387 int i;
388 struct debug_spe *spe;
389
390 if (id == -1) {
391 /*
392 * simscratch called with no id so we
393 * use the current cpu in focus
394 */
395 spe = debug_spe_focus;
396 } else {
397 /* search for the specific gid */
398 for (spe = debug_spe_head; spe != NULL; spe = spe->next) {
399 if (spe->sp->gid == id)
400 break;
401 }
402 }
403
404 if (spe == NULL) {
405 printf("cpuid%d does not exist\n", id);
406 } else {
407 sp = spe->sp;
408 v9p = (sparcv9_cpu_t *)(sp->specificp);
409 nsp = v9p->impl_specificp;
410
411 print_spe_id(spe, "Scratchpad registers for ", "\n");
412 for (i = 0; i < SSR_Num_Regs; i++) {
413 printf("scratch[%d] = 0x%llx\n", i, nsp->strand_reg[i]);
414 }
415 }
416}
417
418
419int
420debug_trans(uint64_t va)
421{
422 simcpu_t *sp;
423 sparcv9_cpu_t *v9p;
424 ss_strand_t *nsp;
425 ss_tlb_t *tlbp;
426 uint_t found;
427
428 sp = debug_spe_focus->sp;
429 v9p = (sparcv9_cpu_t *)(sp->specificp);
430 nsp = v9p->impl_specificp;
431
432 /*
433 * First search itlb, if not found, search the dtlb.
434 * For Rock, if still not found, also search the
435 * level 2 unified TLB.
436 */
437 tlbp = nsp->itlbp;
438 found = debug_search_tlb(nsp, tlbp, va, "ITLB");
439
440 tlbp = nsp->dtlbp;
441 found += debug_search_tlb(nsp, tlbp, va, "DTLB");
442
443#if defined(ROCK)
444 tlbp = nsp->tlbp;
445 found += debug_search_tlb(nsp, tlbp, va, "CTLB");
446#endif
447
448 if (found == 0)
449 printf("va 0x%llx not found in TLBs\n", va);
450
451 return (true);
452}
453
454
455int
456debug_dis(uint64_t addr, int chunks)
457{
458 domain_t *domainp;
459 config_proc_t *config_procp;
460 config_addr_t *cap;
461 uint64_t extent;
462 uint32_t *bufp;
463
464 config_procp = debug_spe_focus->sp->config_procp;
465 domainp = config_procp->domainp;
466
467 addr &= ~3; /* force 4-byte alignment */
468
469 cap = find_domain_address(domainp, addr);
470 if (cap == NULL) {
471 return (false);
472 }
473
474 extent = cap->config_devp->dev_typep->dev_cacheable(cap, DA_Load,
475 addr - cap->baseaddr, (uint8_t **)&bufp);
476 if (extent < chunks * 4)
477 return (false);
478
479 while (chunks--) {
480 sparcv9_idis(debug_buf, sizeof (debug_buf),
481 FE_INSTN(*bufp), addr);
482 printf("0x%llx\t%08x\t%s\n", addr, FE_INSTN(*bufp), debug_buf);
483 addr += 4;
484 bufp++;
485 }
486
487 return (true);
488}
489
490void
491debug_regs_one(struct debug_spe *spe)
492{
493 sparcv9_cpu_t *v9p;
494 int i, j;
495
496 v9p = (sparcv9_cpu_t *)spe->sp->specificp;
497
498 printf(" %%g (gl=%d) %%o (cwp=%d) "
499 "%%l %%i\n", v9p->gl, v9p->cwp);
500 for (i = 0; i < 8; i++) {
501 printf("%d", i);
502 for (j = 0; j < 4; j++) {
503 printf(" 0x%016llx", spe->sp->intreg[i+j*8]);
504 }
505 printf("\n");
506 }
507
508 printf(" %%pc %%npc "
509 "%%tba %%htba\n");
510 printf(" 0x%016llx 0x%016llx 0x%016llx 0x%016llx\n",
511 spe->sp->pc, spe->sp->npc, v9p->tba, v9p->htba);
512
513 printf(" %%tl %%pil %%pstate\n");
514 printf(" 0x%08x 0x%08x 0x%08x\n", v9p->tl, v9p->pil,
515 ss_read_pstate(v9p));
516
517 printf(" %%tpc %%tnpc "
518 "%%tstate %%tt\n");
519 for (i = 1; i <= v9p->maxtl; i++) {
520 printf("%d 0x%016llx 0x%016llx 0x%016llx 0x%016llx\n",
521 i, N_TPC(v9p, i), N_TNPC(v9p, i), N_TSTATE(v9p, i),
522 N_TT(v9p, i));
523 }
524}
525
526void
527debug_regs(void)
528{
529 debug_regs_one(debug_spe_focus);
530}
531
532void
533debug_regs_all(void)
534{
535 struct debug_spe *spe;
536
537 for (spe = debug_spe_head; spe != NULL; spe = spe->next) {
538 print_spe_id(spe, "--- ", " ---\n");
539 debug_regs_one(spe);
540 }
541}
542
543void
544debug_cmpregs_one(struct debug_spe *spe)
545{
546 simcpu_t *sp = (simcpu_t *)spe->sp;
547 ss_proc_t *npp = (ss_proc_t *)sp->config_procp->procp;
548
549#if defined(NIAGARA2)
550 printf("N2 CMP regs:\n");
551 printf("core_enable_status xir_steering core_run_status"
552 " tick_enable\n");
553 printf("0x%016llx 0x%016llx 0x%016llx 0x%x\n",
554 npp->cmp_regs.core_enable_status, npp->cmp_regs.xir_steering,
555 npp->cmp_regs.core_running_status, npp->cmp_regs.tick_enable);
556
557#elif defined(ROCK)
558 printf("Rock CMP regs:\n");
559 printf("strand_available strand_enable strand_running"
560 " str_running_status\n");
561 printf("0x%016llx 0x%016llx 0x%016llx 0x%016llx\n",
562 npp->cmp_regs.strand_available, npp->cmp_regs.strand_enable,
563 npp->cmp_regs.strand_running, npp->cmp_regs.strand_running_status);
564
565#else
566 printf("No CMP regs defined\n");
567#endif
568}
569
570void
571debug_cmpregs(void)
572{
573 debug_cmpregs_one(debug_spe_focus);
574}
575
576void
577debug_mmuregs_one(struct debug_spe *spe)
578{
579 sparcv9_cpu_t *v9p;
580 ss_strand_t *strandp;
581 simcpu_t *sp;
582 ss_proc_t *pnp;
583
584 v9p = (sparcv9_cpu_t *)spe->sp->specificp;
585 strandp = v9p->impl_specificp;
586 sp = (simcpu_t *)spe->sp;
587 pnp = (ss_proc_t *)sp->config_procp->procp;
588
589 printf("Context registers:\n");
590
591 printf(" Primary ctxt: 0x%04x Secondary ctxt: 0x%04x\n",
592 strandp->pri_context, strandp->sec_context);
593#if defined(NIAGARA1) || defined(NIAGARA2)
594 printf("LSU control register: 0x%016llx\n",
595 strandp->lsu_control_raw);
596#elif defined(ROCK)
597 printf("DCUCR: 0x%016llx\n", pnp->dcucr[strandp->core]);
598 printf("IFUCR: 0x%016llx\n", strandp->ifucr);
599#else
600#error "No valid processor defined."
601#endif
602
603#if defined(NIAGARA1) || defined(NIAGARA2)
604 printf("D-MMU tag access register: 0x%016llx\n",
605 strandp->dmmu.tag_access_reg);
606 printf("I-MMU tag access register: 0x%016llx\n",
607 strandp->immu.tag_access_reg);
608#elif defined(ROCK)
609 printf("MMU fault address: 0x%016llx\n", strandp->mmu.fault_addr);
610 printf("MMU fault context type: %d\n",
611 (strandp->mmu.dsfsr & MASK64(6, 5)) >> 5);
612#else
613#error "No valid processor defined."
614#endif
615 printf("MMU fault TL : %d\n", v9p->tl);
616 if (v9p->tl != 0)
617 printf("MMU fault TPC: 0x%016llx\n", N_TPC(v9p, v9p->tl));
618}
619
620void
621debug_mmuregs(void)
622{
623 debug_mmuregs_one(debug_spe_focus);
624}
625
626void
627debug_mmuregs_all(void)
628{
629 struct debug_spe *spe;
630
631 for (spe = debug_spe_head; spe != NULL; spe = spe->next) {
632 print_spe_id(spe, "--- ", " ---\n");
633 debug_mmuregs_one(spe);
634 }
635}
636
637void
638debug_dump_dtlb_one(struct debug_spe *spe)
639{
640#if defined(NIAGARA1) || defined(NIAGARA2)
641 ss_dump_tlbs_nolock(spe->sp->config_procp, true);
642#elif defined(ROCK)
643 rock_dump_tlbs_nolock(spe->sp->config_procp, true);
644#else
645#error "No valid processor defined."
646#endif
647}
648
649void
650debug_dump_dtlb(void)
651{
652 debug_dump_dtlb_one(debug_spe_focus);
653}
654
655void
656debug_dump_dtlb_all(void)
657{
658 struct debug_spe *spe;
659 config_proc_t *cpp = NULL;
660
661 for (spe = debug_spe_head; spe != NULL; spe = spe->next) {
662 /*
663 * Crude way of going per proc using the spe list.
664 */
665 if (spe->sp->config_procp != cpp) {
666 debug_dump_dtlb_one(spe);
667 cpp = spe->sp->config_procp;
668 }
669 }
670}
671
672void
673debug_dump_itlb_one(struct debug_spe *spe)
674{
675#if defined(NIAGARA1) || defined(NIAGARA2)
676 ss_dump_tlbs(spe->sp->config_procp, false);
677#elif defined(ROCK)
678 rock_dump_tlbs(spe->sp->config_procp, false);
679#else
680#error "No valid processor defined."
681#endif
682}
683
684void
685debug_dump_itlb(void)
686{
687 debug_dump_itlb_one(debug_spe_focus);
688}
689
690void
691debug_dump_itlb_all(void)
692{
693 struct debug_spe *spe;
694 config_proc_t *cpp = NULL;
695
696 for (spe = debug_spe_head; spe != NULL; spe = spe->next) {
697 /*
698 * Crude way of going per proc using the spe list.
699 */
700 if (spe->sp->config_procp != cpp) {
701 debug_dump_itlb_one(spe);
702 cpp = spe->sp->config_procp;
703 }
704 }
705}
706
707void
708debug_log(simcpu_t *sp, uint32_t rawi)
709{
710 struct debug_spe *spe;
711 sparcv9_cpu_t *v9p;
712 int idx;
713
714 spe = (struct debug_spe *)sp->debug;
715 v9p = (sparcv9_cpu_t *)spe->sp->specificp;
716
717 idx = spe->log_count % DEBUG_LOG_SIZE;
718
719 spe->log[idx].count = spe->log_count;
720 spe->log[idx].pc = sp->pc;
721 spe->log[idx].rawi = rawi;
722 spe->log[idx].tl = v9p->tl;
723 spe->log[idx].tt = (v9p->tl == 0) ? 0 : N_TT(v9p, v9p->tl);
724 spe->log[idx].gl = v9p->gl;
725 spe->log[idx].state = v9p->state;
726
727 spe->log_count++;
728}
729
730void
731debug_log_print(void)
732{
733 struct debug_spe *spe;
734
735 for (spe = debug_spe_head; spe != NULL; spe = spe->next) {
736 int i;
737
738 print_spe_id(spe, "--- ", " ---\n");
739 for (i = 0; i < DEBUG_LOG_SIZE; i++) {
740 int idx = (spe->log_count + i) % DEBUG_LOG_SIZE;
741
742 sparcv9_idis(debug_buf, sizeof (debug_buf),
743 FE_INSTN(spe->log[idx].rawi), spe->log[idx].pc);
744
745 printf("%s%llu (%s)%x:%x/%x 0x%llx:\t%08x\t%s\n",
746/* CSTYLED */
747 spe->log[idx].count == (spe->log_count - 1) ? "-> " : " ",
748 spe->log[idx].count,
749 sparcv9_state_name[spe->log[idx].state],
750 spe->log[idx].tl,
751 spe->log[idx].tt,
752 spe->log[idx].gl,
753 spe->log[idx].pc,
754 FE_INSTN(spe->log[idx].rawi),
755 debug_buf);
756 }
757 printf("\n");
758 }
759}
760
761#if ERROR_TRAP_GEN /* { */
762 /*
763 * We need to check if we are here because of a debugger breakpoint
764 * or because of an ERROR_TRAP_GEN breakpoint.
765 *
766 * If we got here because the ERROR_TRAP_GEN framework set
767 * a breakpoint, we need to check all simcpus to see which
768 * one has a pending error to inject, we then notify that
769 * simcpu to inject it's error as we have hit the %pc
770 * that it was waiting for. Once all the search criteria
771 * have been met, we trigger the error and remove the breakpoint.
772 */
773void
774check_if_error_event_pending()
775{
776 struct debug_spe *spe;
777
778 for (spe = debug_spe_head; spe != NULL; spe = spe->next) {
779 simcpu_t *sp = spe->sp;
780 error_event_t *eep = (error_event_t *)(sp->eep);
781 sparcv9_cpu_t *v9p = (sparcv9_cpu_t *)(sp->specificp);
782
783 /* Make sure there is an error pending for this CPU */
784 if (sp->error_pending == false) {
785 continue;
786 }
787
788 /*
789 * Make sure if an instn_cnt was specified, that we have
790 * reached that
791 */
792 if (sp->error_cycle_reached == false) {
793 continue;
794 }
795
796 /* Check if error event has a priv level specified */
797 if ((eep->options.bits.priv) && (eep->priv != v9p->state)) {
798 continue;
799 }
800
801 /* Check if error event has a trap level specified */
802 if ((eep->options.bits.tl) && (eep->tl != v9p->tl)) {
803 continue;
804 }
805
806 /*
807 * We get here because all constraints have been met,
808 * so we trigger the trap
809 */
810/* CSTYLED */
811 lprintf(sp->gid, "ERROR_TRAP_GEN: HIT BREAKPOINT: pc=0x%llx @ instn_cnt=0x%llx priv=%d tl=%d\n",
812 sp->pc, sp->cycle, v9p->state, v9p->tl);
813
814
815 /*
816 * Only clear the breakpoint when trigger_cnt is at 1, otherwise
817 * leave it in place so it will be triggered again.
818 */
819 if (eep->trigger_cnt == 1)
820 debug_clear_breakpoint(eep->pc);
821
822/* CSTYLED */
823 lprintf(sp->gid, "ERROR_TRAP_GEN: TRIGGER: @ pc=0x%llx priv=%d tl=%d trigger_cnt=%d\n",
824 sp->pc, v9p->state, v9p->tl, eep->trigger_cnt);
825
826 eep->ee_status = EE_TRIGGERED;
827 sp->error_pending = false;
828 sp->config_procp->proc_typep->trigger_error_trap(sp);
829 }
830}
831#endif /* } ERROR_TRAP_GEN */
832
833#define BARS "#############################################################"
834#define MSG1 "## Legion Breakpoint File, Do NOT Edit ##"
835#define MSG2 "## Legion session started as: ##"
836#define TARE 7
837void
838debug_dump_breakpoints(char *fname)
839{
840extern clibuf_t inputCliLine;
841
842 FILE *fp;
843
844 if ((fp = fopen(fname, "w")) == NULL) {
845 perror("debug_dump_breakpoints:fopen");
846 return;
847 }
848
849 if (debug_spe_head != NULL) {
850 int cliend = strlen(inputCliLine);
851 int delta = strlen(BARS) - (cliend + TARE);
852
853 fprintf(fp, "%s\n", BARS);
854 fprintf(fp, "%s\n", MSG1);
855 fprintf(fp, "%s\n", MSG2);
856 if (delta > 0) {
857 for (; delta > 0 && cliend < sizeof (inputCliLine);
858 delta--) {
859 inputCliLine[cliend++] = ' ';
860 }
861 inputCliLine[cliend] = '\0';
862 }
863 fprintf(fp, "## %s ##\n", inputCliLine);
864 fprintf(fp, "%s\n", BARS);
865
866 sparcv9_dump_break(
867 (sparcv9_cpu_t *)debug_spe_head->sp->specificp, fp);
868 }
869
870 fclose(fp);
871}
872
873void
874debug_restore_breakpoints(char *fname)
875{
876 FILE *fp;
877
878 if ((fp = fopen(fname, "r")) == NULL) {
879 perror("debug_restore_breakpoints:fopen");
880 return;
881 }
882
883 sparcv9_restore_break(fp);
884
885 fclose(fp);
886}