1 /***********************license start***************
2 * Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * * Neither the name of Cavium Networks nor the names of
19 * its contributors may be used to endorse or promote products
20 * derived from this software without specific prior written
23 * This Software, including technical data, may be subject to U.S. export control
24 * laws, including the U.S. Export Administration Act and its associated
25 * regulations, and may be subject to export or import regulations in other
28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
29 * AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
30 * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
31 * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
32 * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
33 * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
34 * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
35 * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
36 * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
37 * PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
38 ***********************license end**************************************/
44 * Interface to debug exception handler
46 * <hr>$Revision: 50060 $<hr>
49 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
50 #include <linux/module.h>
51 #include <asm/octeon/octeon.h>
52 #include <asm/octeon/cvmx.h>
53 #include <asm/octeon/cvmx-debug.h>
54 #include <asm/octeon/cvmx-core.h>
55 #include <asm/octeon/cvmx-bootmem.h>
56 #include <asm/octeon/octeon-boot-info.h>
59 #include "executive-config.h"
61 #include "cvmx-debug.h"
62 #include "cvmx-bootmem.h"
63 #include "cvmx-core.h"
64 #include "cvmx-coremask.h"
66 #ifndef __OCTEON_NEWLIB__
67 #include "../../bootloader/u-boot/include/octeon_mem_map.h"
69 #include "octeon-boot-info.h"
74 #ifdef CVMX_DEBUG_LOGGING
75 # undef CVMX_DEBUG_LOGGING
76 # define CVMX_DEBUG_LOGGING 1
78 # define CVMX_DEBUG_LOGGING 0
81 #ifndef CVMX_DEBUG_ATTACH
82 # define CVMX_DEBUG_ATTACH 1
85 #define CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_STATUS (0xFFFFFFFFFF301000ull)
86 #define CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ADDRESS(num) (0xFFFFFFFFFF301100ull + 0x100 * (num))
87 #define CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ADDRESS_MASK(num) (0xFFFFFFFFFF301108ull + 0x100 * (num))
88 #define CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ASID(num) (0xFFFFFFFFFF301110ull + 0x100 * (num))
89 #define CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_CONTROL(num) (0xFFFFFFFFFF301118ull + 0x100 * (num))
91 #define CVMX_DEBUG_HW_DATA_BREAKPOINT_STATUS (0xFFFFFFFFFF302000ull)
92 #define CVMX_DEBUG_HW_DATA_BREAKPOINT_ADDRESS(num) (0xFFFFFFFFFF302100ull + 0x100 * (num))
93 #define CVMX_DEBUG_HW_DATA_BREAKPOINT_ADDRESS_MASK(num) (0xFFFFFFFFFF302108ull + 0x100 * (num))
94 #define CVMX_DEBUG_HW_DATA_BREAKPOINT_ASID(num) (0xFFFFFFFFFF302110ull + 0x100 * (num))
95 #define CVMX_DEBUG_HW_DATA_BREAKPOINT_CONTROL(num) (0xFFFFFFFFFF302118ull + 0x100 * (num))
97 #define ERET_INSN 0x42000018U /* Hexcode for eret */
98 #define ISR_DELAY_COUNTER 120000000 /* Could be tuned down */
100 extern cvmx_debug_comm_t cvmx_debug_uart_comm;
101 extern cvmx_debug_comm_t cvmx_debug_remote_comm;
102 static const cvmx_debug_comm_t *cvmx_debug_comms[COMM_SIZE] = {&cvmx_debug_uart_comm, &cvmx_debug_remote_comm};
106 static cvmx_debug_globals_t *cvmx_debug_globals;
113 #ifndef CVMX_BUILD_FOR_LINUX_KERNEL
114 uint64_t __cvmx_debug_save_regs_area[32];
116 volatile uint64_t __cvmx_debug_mode_exception_ignore;
117 volatile uint64_t __cvmx_debug_mode_exception_occured;
119 static char cvmx_debug_stack[8*1024] __attribute ((aligned (16)));
120 char *__cvmx_debug_stack_top = &cvmx_debug_stack[8*1024];
122 #ifndef __OCTEON_NEWLIB__
123 extern int cvmx_interrupt_in_isr;
125 #define cvmx_interrupt_in_isr 0
129 uint64_t __cvmx_debug_save_regs_area_all[OCTEON_NUM_CORES][32];
130 #define __cvmx_debug_save_regs_area __cvmx_debug_save_regs_area_all[cvmx_get_core_num()]
132 volatile uint64_t __cvmx_debug_mode_exception_ignore_all[OCTEON_NUM_CORES];
133 #define __cvmx_debug_mode_exception_ignore __cvmx_debug_mode_exception_ignore_all[cvmx_get_core_num()]
134 volatile uint64_t __cvmx_debug_mode_exception_occured_all[OCTEON_NUM_CORES];
135 #define __cvmx_debug_mode_exception_occured __cvmx_debug_mode_exception_occured_all[cvmx_get_core_num()]
137 static char cvmx_debug_stack_all[OCTEON_NUM_CORES][8*1024] __attribute ((aligned (16)));
138 char *__cvmx_debug_stack_top_all[OCTEON_NUM_CORES];
140 #define cvmx_interrupt_in_isr 0
145 static inline uint32_t cvmx_debug_core_mask(void)
147 #ifndef CVMX_BUILD_FOR_LINUX_KERNEL
148 #ifdef __OCTEON_NEWLIB__
149 extern int __octeon_core_mask;
150 return __octeon_core_mask;
152 return cvmx_sysinfo_get()->core_mask;
154 return octeon_get_boot_coremask ();
158 static inline void cvmx_debug_update_state(cvmx_debug_state_t state)
160 memcpy(cvmx_debug_globals->state, &state, sizeof(cvmx_debug_state_t));
163 static inline cvmx_debug_state_t cvmx_debug_get_state(void)
165 cvmx_debug_state_t state;
166 memcpy(&state, cvmx_debug_globals->state, sizeof(cvmx_debug_state_t));
170 static void cvmx_debug_printf(char *format, ...) __attribute__((format(__printf__, 1, 2)));
171 static void cvmx_debug_printf(char *format, ...)
175 if (!CVMX_DEBUG_LOGGING)
178 va_start(ap, format);
179 cvmx_dvprintf(format, ap);
183 static inline int __cvmx_debug_in_focus(cvmx_debug_state_t state, unsigned core)
185 return state.focus_core == core;
188 static void cvmx_debug_install_handler(unsigned core)
190 extern void __cvmx_debug_handler_stage2(void);
191 int32_t *trampoline = CASTPTR(int32_t, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, BOOTLOADER_DEBUG_TRAMPOLINE_CORE));
194 *trampoline = (int32_t)(long)&__cvmx_debug_handler_stage2;
196 cvmx_debug_printf("Debug handled installed on core %d at %p\n", core, trampoline);
199 static int cvmx_debug_enabled(void)
201 return cvmx_debug_booted() || CVMX_DEBUG_ATTACH;
204 static void cvmx_debug_init_globals(void)
210 if (cvmx_debug_globals)
213 if (cvmx_get_core_num() != 0)
216 /* Delay here just enough for the writing of the version. */
217 for(i = 0; i < sizeof(cvmx_debug_globals_t)/2 + 8; i++)
221 a = cvmx_bootmem_alloc_named(sizeof(cvmx_debug_globals_t), 8, CVMX_DEBUG_GLOBALS_BLOCK_NAME);
224 phys = cvmx_ptr_to_phys(a);
229 const cvmx_bootmem_named_block_desc_t *debug_globals_nblk;
230 debug_globals_nblk = cvmx_bootmem_find_named_block (CVMX_DEBUG_GLOBALS_BLOCK_NAME);
231 phys = debug_globals_nblk->base_addr;
233 cvmx_debug_globals = CASTPTR(cvmx_debug_globals_t, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, phys));
234 cvmx_debug_printf("Debug named block at %p\n", cvmx_debug_globals);
236 cvmx_debug_printf("Debug named block cleared\n");
240 memset (cvmx_debug_globals, 0, sizeof(cvmx_debug_globals_t));
241 cvmx_debug_globals->version = CVMX_DEBUG_GLOBALS_VERSION;
242 cvmx_debug_globals->tlb_entries = cvmx_core_get_tlb_entries();
247 /* Delay here just enough for the writing of the version. */
248 for(i = 0; i < sizeof(cvmx_debug_globals_t) + 8; i++)
254 static void cvmx_debug_globals_check_version(void)
256 if (cvmx_debug_globals->version != CVMX_DEBUG_GLOBALS_VERSION)
258 cvmx_dprintf("Wrong version on the globals struct spinining; expected %d, got: %d.\n", (int)CVMX_DEBUG_GLOBALS_VERSION, (int)(cvmx_debug_globals->version));
259 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
260 panic("Wrong version.\n");
267 static inline volatile cvmx_debug_core_context_t *cvmx_debug_core_context(void);
268 static inline void cvmx_debug_save_core_context(volatile cvmx_debug_core_context_t *context);
270 void cvmx_debug_init(void)
272 cvmx_debug_state_t state;
274 const cvmx_debug_comm_t *comm;
275 cvmx_spinlock_t *lock;
276 unsigned int coremask = cvmx_debug_core_mask();
278 if (!cvmx_debug_enabled())
281 cvmx_debug_init_globals();
283 #ifndef CVMX_BUILD_FOR_LINUX_KERNEL
284 // Put a barrier until all cores have got to this point.
285 cvmx_coremask_barrier_sync(coremask);
287 cvmx_debug_globals_check_version();
290 comm = cvmx_debug_comms[cvmx_debug_globals->comm_type];
291 lock = &cvmx_debug_globals->lock;
293 core = cvmx_get_core_num();
294 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
295 /* Install the debugger handler on the cores. */
298 for (core1 = 0; core1 < OCTEON_NUM_CORES; core1++)
300 if ((1<<core1) & coremask)
301 cvmx_debug_install_handler(core1);
305 cvmx_debug_install_handler(core);
312 cvmx_spinlock_lock(lock);
313 state = cvmx_debug_get_state();
314 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
315 state.known_cores |= coremask;
316 state.core_finished &= ~coremask;
318 state.known_cores |= (1 << core);
319 state.core_finished &= ~(1 << core);
321 cvmx_debug_update_state(state);
322 cvmx_spinlock_unlock(lock);
325 #ifndef CVMX_BUILD_FOR_LINUX_KERNEL
326 // Put a barrier until all cores have got to this point.
327 cvmx_coremask_barrier_sync(coremask);
329 if (cvmx_coremask_first_core(coremask))
332 cvmx_debug_printf("cvmx_debug_init core: %d\n", core);
333 state = cvmx_debug_get_state();
334 state.focus_core = core;
335 state.active_cores = state.known_cores;
336 state.focus_switch = 1;
338 cvmx_debug_printf("Known cores at init: 0x%x\n", (int)state.known_cores);
339 cvmx_debug_update_state(state);
341 /* Initialize __cvmx_debug_stack_top_all. */
342 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
345 for (i = 0; i < OCTEON_NUM_CORES; i++)
346 __cvmx_debug_stack_top_all[i] = &cvmx_debug_stack_all[i][8*1024];
349 cvmx_debug_globals->init_complete = 1;
352 while (!cvmx_debug_globals->init_complete)
354 /* Spin waiting for init to complete */
357 if (cvmx_debug_booted())
358 cvmx_debug_trigger_exception();
360 /* Install the break handler after might tripper the debugger exception. */
361 #ifndef CVMX_BUILD_FOR_LINUX_KERNEL
362 if (cvmx_coremask_first_core(coremask))
365 if (comm->install_break_handler)
366 comm->install_break_handler();
370 static int cvmx_debug_putpacket_noformat(char *packet);
372 static __attribute__ ((format (printf, 1, 2))) int cvmx_debug_putpacket(char *format, ...)
376 char packet[CVMX_DEBUG_MAX_RESPONSE_SIZE];
378 if (cvmx_debug_comms[cvmx_debug_globals->comm_type]->putpacket == NULL)
381 va_start(ap, format);
382 n = vsnprintf(packet, sizeof(packet), format, ap);
385 if (n >= sizeof(packet))
387 cvmx_debug_printf("packet truncated (needed %d bytes): %s\n", (int)n, packet);
390 return cvmx_debug_putpacket_noformat(packet);
393 static int cvmx_debug_putpacket_noformat(char *packet)
395 if (cvmx_debug_comms[cvmx_debug_globals->comm_type]->putpacket == NULL)
397 cvmx_debug_printf("Reply: %s\n", packet);
398 return cvmx_debug_comms[cvmx_debug_globals->comm_type]->putpacket(packet);
401 static int cvmx_debug_active_core(cvmx_debug_state_t state, int core)
403 return state.active_cores & (1 << core);
406 static volatile cvmx_debug_core_context_t *cvmx_debug_core_context(void)
408 return &cvmx_debug_globals->contextes[cvmx_get_core_num()];
411 static volatile uint64_t *cvmx_debug_regnum_to_context_ref(int regnum, volatile cvmx_debug_core_context_t *context)
413 /* Must be kept in sync with mips_octeon_reg_names in gdb/mips-tdep.c. */
415 return &context->regs[regnum];
418 case 32: return &context->cop0.status;
419 case 33: return &context->lo;
420 case 34: return &context->hi;
421 case 35: return &context->cop0.badvaddr;
422 case 36: return &context->cop0.cause;
423 case 37: return &context->cop0.depc;
424 default: return NULL;
428 static int cvmx_debug_probe_load(unsigned char *ptr, unsigned char *result)
430 volatile unsigned char *p = ptr;
435 __cvmx_debug_mode_exception_ignore = 1;
436 __cvmx_debug_mode_exception_occured = 0;
437 /* We don't handle debug-mode exceptions in delay slots. Avoid them. */
438 asm volatile (".set push \n\t"
439 ".set noreorder \n\t"
443 ".set pop" : "=r"(tem) : "m"(*p));
444 ok = __cvmx_debug_mode_exception_occured == 0;
445 __cvmx_debug_mode_exception_ignore = 0;
446 __cvmx_debug_mode_exception_occured = 0;
452 static int cvmx_debug_probe_store(unsigned char *ptr)
454 volatile unsigned char *p = ptr;
457 __cvmx_debug_mode_exception_ignore = 1;
458 __cvmx_debug_mode_exception_occured = 0;
459 /* We don't handle debug-mode exceptions in delay slots. Avoid them. */
460 asm volatile (".set push \n\t"
461 ".set noreorder \n\t"
465 ".set pop" : "=m"(*p));
466 ok = __cvmx_debug_mode_exception_occured == 0;
468 __cvmx_debug_mode_exception_ignore = 0;
469 __cvmx_debug_mode_exception_occured = 0;
473 /* Put the hex value of t into str. */
474 static void strhex(char *str, unsigned char t)
476 char a[] = "0123456789ABCDEF";
483 * Initialize the performance counter control registers.
486 static void cvmx_debug_set_perf_control_reg (int perf_event, int perf_counter)
488 volatile cvmx_debug_core_context_t *context = cvmx_debug_core_context();
489 cvmx_core_perf_control_t control;
497 control.s.m = 1 - perf_counter;
498 control.s.event = perf_event;
500 context->cop0.perfctrl[perf_counter] = control.u32;
503 static cvmx_debug_command_t cvmx_debug_process_packet(char *packet)
505 const char *buf = packet;
506 cvmx_debug_command_t result = COMMAND_NOP;
507 cvmx_debug_state_t state = cvmx_debug_get_state();
509 /* A one letter command code represents what to do. */
512 case '?': /* What protocol do I speak? */
513 cvmx_debug_putpacket_noformat("S0A");
516 case '\003': /* Control-C */
517 cvmx_debug_putpacket_noformat("T9");
520 case 'F': /* Change the focus core */
523 sscanf(buf, "%x", &core);
525 /* Only cores in the exception handler may become the focus.
526 If a core not in the exception handler got focus the
527 debugger would hang since nobody would talk to it. */
528 if (state.handler_cores & (1 << core))
530 /* Focus change reply must be sent before the focus
531 changes. Otherwise the new focus core will eat our ACK
532 from the debugger. */
533 cvmx_debug_putpacket("F%02x", core);
534 cvmx_debug_comms[cvmx_debug_globals->comm_type]->change_core(state.focus_core, core);
535 state.focus_core = core;
536 cvmx_debug_update_state(state);
540 cvmx_debug_putpacket_noformat("!Core is not in the exception handler. Focus not changed.");
541 /* Nothing changed, so we send back the old value */
544 case 'f': /* Get the focus core */
545 cvmx_debug_putpacket("F%02x", (unsigned)state.focus_core);
548 case 'J': /* Set the flag for skip-over-isr in Single-Stepping mode */
551 state.step_isr = 1; /* Step in ISR */
553 state.step_isr = 0; /* Step over ISR */
554 cvmx_debug_update_state(state);
556 /* Fall through. The reply to the set step-isr command is the
557 same as the get step-isr command */
559 case 'j': /* Reply with step_isr status */
560 cvmx_debug_putpacket("J%x", (unsigned)state.step_isr);
564 case 'I': /* Set the active cores */
566 long long active_cores;
567 sscanf(buf, "%llx", &active_cores);
568 /* Limit the active mask to the known to exist cores */
569 state.active_cores = active_cores & state.known_cores;
571 /* Lazy user hack to have 0 be all cores */
572 if (state.active_cores == 0)
573 state.active_cores = state.known_cores;
575 /* The focus core must be in the active_cores mask */
576 if ((state.active_cores & (1 << state.focus_core)) == 0)
578 cvmx_debug_putpacket_noformat("!Focus core was added to the masked.");
579 state.active_cores |= 1 << state.focus_core;
582 cvmx_debug_update_state(state);
584 /* Fall through. The reply to the set active cores command is the
585 same as the get active cores command */
587 case 'i': /* Get the active cores */
588 cvmx_debug_putpacket("I%llx", (long long) state.active_cores);
591 case 'A': /* Setting the step mode all or one */
594 state.step_all = 1; /* A step or continue will start all cores */
596 state.step_all = 0; /* A step or continue only affects the focus core */
597 cvmx_debug_update_state(state);
599 /* Fall through. The reply to the set step-all command is the
600 same as the get step-all command */
602 case 'a': /* Getting the current step mode */
603 cvmx_debug_putpacket("A%x", (unsigned)state.step_all);
606 case 'g': /* read a register from global place. */
608 volatile cvmx_debug_core_context_t *context = cvmx_debug_core_context();
610 volatile uint64_t *reg;
612 /* Get the register number to read */
613 sscanf(buf, "%x", ®no);
615 reg = cvmx_debug_regnum_to_context_ref(regno, context);
617 cvmx_debug_printf("Register #%d is not valid\n", regno);
618 cvmx_debug_putpacket("%llx", (unsigned long long) *reg);
622 case 'G': /* set the value of a register. */
624 volatile cvmx_debug_core_context_t *context = cvmx_debug_core_context();
626 volatile uint64_t *reg;
629 /* Get the register number to read */
630 if (sscanf(buf, "%x,%llx", ®no, &value) != 2)
632 cvmx_debug_printf("G packet corrupt: %s\n", buf);
636 reg = cvmx_debug_regnum_to_context_ref(regno, context);
639 cvmx_debug_printf("Register #%d is not valid\n", regno);
646 case 'm': /* Memory read. mAA..AA,LLLL Read LLLL bytes at address AA..AA */
648 long long addr, i, length;
652 if (sscanf(buf, "%llx,%llx", &addr, &length) != 2)
654 cvmx_debug_printf("m packet corrupt: %s\n", buf);
659 cvmx_debug_printf("m packet length out of range: %lld\n", length);
663 reply = __builtin_alloca(length * 2 + 1);
664 ptr = (unsigned char *)(long)addr;
665 for (i = 0; i < length; i++)
667 /* Probe memory. If not accessible fail. */
669 if (!cvmx_debug_probe_load(&ptr[i], &t))
671 strhex(&reply[i * 2], t);
673 cvmx_debug_putpacket_noformat(reply);
677 case 'M': /* Memory write. MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
679 long long addr, i, length;
683 if (sscanf(buf, "%llx,%llx:%1024s", &addr, &length, value) != 3)
685 cvmx_debug_printf("M packet corrupt: %s\n", buf);
689 ptr = (unsigned char *)(long)addr;
690 for (i = 0; i < length; i++)
694 char tempstr[3] = {0, 0, 0};
695 memcpy (tempstr, &value[i * 2], 2);
697 n = sscanf(tempstr, "%2x", &c);
700 cvmx_debug_printf("M packet corrupt: %s\n", &value[i * 2]);
703 /* Probe memory. If not accessible fail. */
704 if (!cvmx_debug_probe_store(&ptr[i]))
706 cvmx_debug_printf("M cannot write: %p\n", &ptr[i]);
711 cvmx_debug_putpacket_noformat("+");
715 case 'e': /* Set/get performance counter events. e[1234]XX..X: [01]
716 is the performance counter to set X is the performance
717 event. [34] is to get the same thing. */
720 int counter, encoded_counter;
721 volatile cvmx_debug_core_context_t *context = cvmx_debug_core_context();
722 sscanf(buf, "%1d%x", &encoded_counter, &perf_event);
724 switch (encoded_counter)
726 case 1: /* Set performance counter0 event. */
727 case 2: /* Set performance counter1 event. */
729 counter = encoded_counter - 1;
730 context->cop0.perfval[counter] = 0;
731 cvmx_debug_set_perf_control_reg(perf_event, counter);
734 case 3: /* Get performance counter0 event. */
735 case 4: /* Get performance counter1 event. */
737 cvmx_core_perf_control_t c;
738 counter = encoded_counter - 3;
739 /* Pass performance counter0 event and counter to
741 c.u32 = context->cop0.perfctrl[counter];
742 cvmx_debug_putpacket("%llx,%llx", (long long) context->cop0.perfval[counter], (long long) c.s.event);
750 case 't': /* Return the trace buffer read data register contents. */
756 /* If trace buffer is disabled no trace data information is available. */
757 if ((tra_ctl & 0x1) == 0)
759 cvmx_debug_putpacket_noformat("!Trace buffer not enabled\n");
760 cvmx_debug_putpacket_noformat("t");
764 cvmx_debug_putpacket_noformat("!Trace buffer is enabled\n");
765 tra_data = cvmx_read_csr(OCTEON_TRA_READ_DATA);
766 mem2hex (&tra_data, tmp, 8);
767 strcpy (debug_output_buffer, "t");
768 strcat (debug_output_buffer, tmp);
769 cvmx_debug_putpacket_noformat(debug_output_buffer);
775 case 'Z': /* Insert hardware breakpoint: Z[di]NN..N,AA.A, [di] data or
776 instruction, NN..Nth at address AA..A */
789 const int BE = 1, TE = 4;
791 volatile cvmx_debug_core_context_t *context = cvmx_debug_core_context();
793 n = sscanf(buf, "%c%x,%llx,%x,%x", &bp_type, &num, &addr, &size, &type);
796 case 'i': // Instruction hardware breakpoint
797 if (n != 3 || num > 4)
799 cvmx_debug_printf("Z packet corrupt: %s\n", buf);
803 context->hw_ibp.address[num] = addr;
804 context->hw_ibp.address_mask[num] = 0;
805 context->hw_ibp.asid[num] = 0;
806 context->hw_ibp.control[num] = BE | TE;
809 case 'd': // Data hardware breakpoint
811 uint64_t dbc = 0xff0 | BE | TE;
813 if (n != 5 || num > 4)
815 cvmx_debug_printf("Z packet corrupt: %s\n", buf);
819 /* Set DBC[BE,TE,BLM]. */
820 context->hw_dbp.address[num] = addr;
821 context->hw_dbp.asid[num] = 0;
823 dbc |= type == WP_STORE ? 0x1000 : type == WP_LOAD ? 0x2000 : 0;
824 /* Mask the bits depending on the size for
825 debugger to stop while accessing parts of the
827 dbm = (size == 8) ? 0x7 : ((size == 4) ? 3
828 : (size == 2) ? 1 : 0);
829 context->hw_dbp.address_mask[num] = dbm;
830 context->hw_dbp.control[num] = dbc;
834 cvmx_debug_printf("z packet corrupt: %s\n", buf);
840 case 'z': /* Remove hardware breakpoint: z[di]NN..N remove NN..Nth
845 volatile cvmx_debug_core_context_t *context = cvmx_debug_core_context();
847 if (sscanf(buf, "%c%x", &bp_type, &num) != 2 || num > 4)
849 cvmx_debug_printf("z packet corrupt: %s\n", buf);
855 case 'i': // Instruction hardware breakpoint
856 context->hw_ibp.address[num] = 0;
857 context->hw_ibp.address_mask[num] = 0;
858 context->hw_ibp.asid[num] = 0;
859 context->hw_ibp.control[num] = 0;
861 case 'd': // Data hardware breakpoint
862 context->hw_dbp.address[num] = 0;
863 context->hw_dbp.address_mask[num] = 0;
864 context->hw_dbp.asid[num] = 0;
865 context->hw_dbp.control[num] = 0;
868 cvmx_debug_printf("z packet corrupt: %s\n", buf);
874 case 's': /* Single step. sAA..AA Step one instruction from AA..AA (optional) */
875 result = COMMAND_STEP;
878 case 'c': /* Continue. cAA..AA Continue at address AA..AA (optional) */
879 result = COMMAND_CONTINUE;
882 case '+': /* Don't know. I think it is a communications sync */
883 /* Ignoring this command */
887 cvmx_debug_printf("Unknown debug command: %s\n", buf - 1);
889 cvmx_debug_putpacket_noformat("-");
896 static cvmx_debug_command_t cvmx_debug_process_next_packet(void)
898 char packet[CVMX_DEBUG_MAX_REQUEST_SIZE];
899 if (cvmx_debug_comms[cvmx_debug_globals->comm_type]->getpacket(packet, CVMX_DEBUG_MAX_REQUEST_SIZE))
901 cvmx_debug_printf("Request: %s\n", packet);
902 return cvmx_debug_process_packet(packet);
907 /* If a core isn't in the active core mask we need to start him up again. We
908 can only do this if the core didn't hit a breakpoint or single step. If the
909 core hit CVMX_CIU_DINT interrupt (generally happens when while executing
910 _exit() at the end of the program). Remove the core from known cores so
911 that when the cores in active core mask are done executing the program, the
912 focus will not be transfered to this core. */
914 static int cvmx_debug_stop_core(cvmx_debug_state_t state, unsigned core, cvmx_debug_register_t *debug_reg, int proxy)
916 if (!cvmx_debug_active_core(state, core) && !debug_reg->s.dbp && !debug_reg->s.dss && (debug_reg->s.dint != 1))
918 debug_reg->s.sst = 0;
919 cvmx_debug_printf("Core #%d not in active cores, continuing.\n", core);
922 if ((state.core_finished & (1<<core)) && proxy)
927 /* check to see if current exc is single-stepped and that no other exc
928 was also simultaneously noticed. */
929 static int cvmx_debug_single_step_exc(cvmx_debug_register_t *debug_reg)
931 if (debug_reg->s.dss && !debug_reg->s.dib && !debug_reg->s.dbp && !debug_reg->s.ddbs && !debug_reg->s.ddbl)
936 static void cvmx_debug_set_focus_core(cvmx_debug_state_t *state, int core)
938 if (state->ever_been_in_debug)
939 cvmx_debug_putpacket("!Core %2x taking focus.", core);
940 cvmx_debug_comms[cvmx_debug_globals->comm_type]->change_core (state->focus_core, core);
941 state->focus_core = core;
944 static void cvmx_debug_may_elect_as_focus_core(cvmx_debug_state_t *state, int core, cvmx_debug_register_t *debug_reg)
946 /* If another core has already elected itself as the focus core, we're late. */
947 if (state->handler_cores & (1 << state->focus_core))
950 /* If we hit a breakpoint, elect ourselves. */
951 if (debug_reg->s.dib || debug_reg->s.dbp || debug_reg->s.ddbs || debug_reg->s.ddbl)
952 cvmx_debug_set_focus_core(state, core);
954 /* It is possible the focus core has completed processing and exited the
955 program. When this happens the focus core will not be in
956 known_cores. If this is the case we need to elect a new focus. */
957 if ((state->known_cores & (1 << state->focus_core)) == 0)
958 cvmx_debug_set_focus_core(state, core);
961 static void cvmx_debug_send_stop_reason(cvmx_debug_register_t *debug_reg, volatile cvmx_debug_core_context_t *context)
963 /* Handle Debug Data Breakpoint Store/Load Exception. */
964 if (debug_reg->s.ddbs || debug_reg->s.ddbl)
965 cvmx_debug_putpacket("T8:%x", (int) context->hw_dbp.status);
967 cvmx_debug_putpacket_noformat("T9");
971 static void cvmx_debug_clear_status(volatile cvmx_debug_core_context_t *context)
973 /* SW needs to clear the BreakStatus bits after a watchpoint is hit or on
975 context->hw_dbp.status &= ~0x3fff;
977 /* Clear MCD0, which is write-1-to-clear. */
978 context->cop0.multicoredebug |= 1;
981 static void cvmx_debug_sync_up_cores(void)
983 cvmx_debug_state_t state;
985 state = cvmx_debug_get_state();
986 } while (state.step_all && state.handler_cores != 0);
989 /* Delay the focus core a little if it is likely another core needs to steal
990 focus. Once we enter the main loop focus can't be stolen */
991 static void cvmx_debug_delay_focus_core(cvmx_debug_state_t state, unsigned core, cvmx_debug_register_t *debug_reg)
994 if (debug_reg->s.dss || debug_reg->s.dbp || core != state.focus_core)
996 for (i = 0; i < 24000; i++)
998 asm volatile (".set push \n\t"
999 ".set noreorder \n\t"
1005 /* Spin giving the breakpoint core time to steal focus */
1010 /* If this core was single-stepping in a group,
1011 && it was not the last focus-core,
1012 && last focus-core happens to be inside an ISR, blocking focus-switch
1013 then burn some cycles, to avoid unnecessary focus toggles. */
1014 static void cvmx_debug_delay_isr_core(unsigned core, uint32_t depc, int single_stepped_exc_only,
1015 cvmx_debug_state_t state)
1017 volatile uint64_t i;
1018 if(!single_stepped_exc_only || state.step_isr || core == state.focus_core || state.focus_switch)
1021 cvmx_debug_printf ("Core #%u spinning for focus at 0x%x\n", core, (unsigned int)depc);
1023 for(i = ISR_DELAY_COUNTER; i > 0 ; i--)
1025 state = cvmx_debug_get_state();
1026 /* Spin giving the focus core time to service ISR */
1027 /* But cut short the loop, if we can. Shrink down i, only once. */
1028 if (i > 600000 && state.focus_switch)
1034 static int cvmx_debug_perform_proxy(cvmx_debug_register_t *debug_reg, volatile cvmx_debug_core_context_t *context)
1036 unsigned core = cvmx_get_core_num();
1037 cvmx_debug_state_t state = cvmx_debug_get_state();
1038 cvmx_debug_command_t command = COMMAND_NOP;
1039 int single_stepped_exc_only = cvmx_debug_single_step_exc (debug_reg);
1041 /* All cores should respect the focus core if it has to
1042 stop focus switching while servicing an interrupt.
1043 If the system is single-stepping, then the following
1044 code path is valid. If the current core tripped on a
1045 break-point or some other error while going through
1046 an ISR, then we shouldn't be returning unconditionally.
1047 In that case (non-single-step case) we must enter
1048 the debugger exception stub fully. */
1049 if (!state.step_isr && (cvmx_interrupt_in_isr || (context->cop0.status & 0x2ULL)) && single_stepped_exc_only)
1051 cvmx_spinlock_lock(&cvmx_debug_globals->lock);
1052 state = cvmx_debug_get_state();
1053 /* If this is the focus core, switch off focus switching
1054 till ISR_DELAY_COUNTER. This will let focus core
1055 keep the focus until the ISR is completed. */
1056 if(state.focus_switch && core == state.focus_core)
1058 cvmx_debug_printf ("Core #%u stopped focus stealing at 0x%llx\n", core, (unsigned long long)context->cop0.depc);
1059 state.focus_switch = 0;
1061 /* Alow other cores to steal focus.
1062 Focus core has completed ISR. */
1063 if (*(uint32_t*)((__SIZE_TYPE__)context->cop0.depc) == ERET_INSN && core == state.focus_core)
1065 cvmx_debug_printf ("Core #%u resumed focus stealing at 0x%llx\n", core, (unsigned long long)context->cop0.depc);
1066 state.focus_switch = 1;
1068 cvmx_debug_update_state(state);
1069 cvmx_spinlock_unlock(&cvmx_debug_globals->lock);
1070 cvmx_debug_printf ("Core #%u resumed skipping isr.\n", core);
1074 /* Delay the focus core a little if it is likely another core needs to
1075 steal focus. Once we enter the main loop focus can't be stolen */
1076 cvmx_debug_delay_focus_core(state, core, debug_reg);
1078 cvmx_debug_delay_isr_core (core, context->cop0.depc, single_stepped_exc_only, state);
1080 /* The following section of code does two critical things. First, it
1081 populates the handler_cores bitmask of all cores in the exception
1082 handler. Only one core at a time can update this field. Second it
1083 changes the focus core if needed. */
1085 cvmx_debug_printf("Core #%d stopped\n", core);
1086 cvmx_spinlock_lock(&cvmx_debug_globals->lock);
1087 state = cvmx_debug_get_state();
1089 state.handler_cores |= (1 << core);
1090 cvmx_debug_may_elect_as_focus_core(&state, core, debug_reg);
1092 /* Push all updates before exiting the critical section */
1093 state.focus_switch = 1;
1094 cvmx_debug_update_state(state);
1095 cvmx_spinlock_unlock(&cvmx_debug_globals->lock);
1097 if (__cvmx_debug_in_focus(state, core))
1098 cvmx_debug_send_stop_reason(debug_reg, context);
1101 state = cvmx_debug_get_state();
1102 /* Note the focus core can change in this loop. */
1103 if (__cvmx_debug_in_focus(state, core))
1105 command = cvmx_debug_process_next_packet();
1106 state = cvmx_debug_get_state();
1107 /* When resuming let the other cores resume as well with
1109 if (command != COMMAND_NOP && state.step_all)
1111 state.command = command;
1112 cvmx_debug_update_state(state);
1115 /* When steping all cores, update the non focus core's command too. */
1116 else if (state.step_all)
1117 command = state.command;
1119 /* If we did not get a command and the communication changed return,
1120 we are changing the communications. */
1121 if (command == COMMAND_NOP && cvmx_debug_globals->comm_changed)
1123 /* FIXME, this should a sync not based on cvmx_coremask_barrier_sync. */
1124 #ifndef CVMX_BUILD_FOR_LINUX_KERNEL
1126 cvmx_coremask_barrier_sync(state.handler_cores);
1130 } while (command == COMMAND_NOP);
1132 debug_reg->s.sst = command == COMMAND_STEP;
1133 cvmx_debug_printf("Core #%d running\n", core);
1136 cvmx_spinlock_lock(&cvmx_debug_globals->lock);
1137 state = cvmx_debug_get_state();
1138 state.handler_cores ^= (1 << core);
1139 cvmx_debug_update_state(state);
1140 cvmx_spinlock_unlock(&cvmx_debug_globals->lock);
1143 cvmx_debug_sync_up_cores();
1144 /* Now that all cores are out, reset the command. */
1145 if (__cvmx_debug_in_focus(state, core))
1147 cvmx_spinlock_lock(&cvmx_debug_globals->lock);
1148 state = cvmx_debug_get_state();
1149 state.command = COMMAND_NOP;
1150 cvmx_debug_update_state(state);
1151 cvmx_spinlock_unlock(&cvmx_debug_globals->lock);
1156 static void cvmx_debug_save_core_context(volatile cvmx_debug_core_context_t *context)
1159 memcpy((char *) context->regs, __cvmx_debug_save_regs_area, sizeof(context->regs));
1160 asm("mflo %0" : "=r"(context->lo));
1161 asm("mfhi %0" : "=r"(context->hi));
1162 CVMX_MF_COP0(context->cop0.index, COP0_INDEX);
1163 CVMX_MF_COP0(context->cop0.entrylo[0], COP0_ENTRYLO0);
1164 CVMX_MF_COP0(context->cop0.entrylo[1], COP0_ENTRYLO1);
1165 CVMX_MF_COP0(context->cop0.entryhi, COP0_ENTRYHI);
1166 CVMX_MF_COP0(context->cop0.pagemask, COP0_PAGEMASK);
1167 CVMX_MF_COP0(context->cop0.status, COP0_STATUS);
1168 CVMX_MF_COP0(context->cop0.cause, COP0_CAUSE);
1169 CVMX_MF_COP0(context->cop0.debug, COP0_DEBUG);
1170 CVMX_MF_COP0(context->cop0.multicoredebug, COP0_MULTICOREDEBUG);
1171 CVMX_MF_COP0(context->cop0.perfval[0], COP0_PERFVALUE0);
1172 CVMX_MF_COP0(context->cop0.perfval[1], COP0_PERFVALUE1);
1173 CVMX_MF_COP0(context->cop0.perfctrl[0], COP0_PERFCONTROL0);
1174 CVMX_MF_COP0(context->cop0.perfctrl[1], COP0_PERFCONTROL1);
1175 /* Save DEPC and DESAVE since debug-mode exceptions (see
1176 debug_probe_{load,store}) can clobber these. */
1177 CVMX_MF_COP0(context->cop0.depc, COP0_DEPC);
1178 CVMX_MF_COP0(context->cop0.desave, COP0_DESAVE);
1180 context->hw_ibp.status = cvmx_read_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_STATUS);
1181 for (i = 0; i < 4; i++)
1183 context->hw_ibp.address[i] = cvmx_read_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ADDRESS(i));
1184 context->hw_ibp.address_mask[i] = cvmx_read_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ADDRESS_MASK(i));
1185 context->hw_ibp.asid[i] = cvmx_read_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ASID(i));
1186 context->hw_ibp.control[i] = cvmx_read_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_CONTROL(i));
1189 context->hw_dbp.status = cvmx_read_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_STATUS);
1190 for (i = 0; i < 4; i++)
1192 context->hw_dbp.address[i] = cvmx_read_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_ADDRESS(i));
1193 context->hw_dbp.address_mask[i] = cvmx_read_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_ADDRESS_MASK(i));
1194 context->hw_dbp.asid[i] = cvmx_read_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_ASID(i));
1195 context->hw_dbp.control[i] = cvmx_read_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_CONTROL(i));
1198 for (i = 0; i < cvmx_debug_globals->tlb_entries; i++)
1200 CVMX_MT_COP0(i, COP0_INDEX);
1201 asm volatile ("tlbr");
1202 CVMX_MF_COP0(context->tlbs[i].entrylo[0], COP0_ENTRYLO0);
1203 CVMX_MF_COP0(context->tlbs[i].entrylo[1], COP0_ENTRYLO1);
1204 CVMX_MF_COP0(context->tlbs[i].entryhi, COP0_ENTRYHI);
1205 CVMX_MF_COP0(context->tlbs[i].pagemask, COP0_PAGEMASK);
1210 static void cvmx_debug_restore_core_context(volatile cvmx_debug_core_context_t *context)
1213 memcpy(__cvmx_debug_save_regs_area, (char *) context->regs, sizeof(context->regs));
1214 asm("mtlo %0" :: "r"(context->lo));
1215 asm("mthi %0" :: "r"(context->hi));
1216 /* We don't change the TLB so no need to restore it. */
1217 cvmx_write_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_STATUS, context->hw_dbp.status);
1218 for (i = 0; i < 4; i++)
1220 cvmx_write_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_ADDRESS(i), context->hw_dbp.address[i]);
1221 cvmx_write_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_ADDRESS_MASK(i), context->hw_dbp.address_mask[i]);
1222 cvmx_write_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_ASID(i), context->hw_dbp.asid[i]);
1223 cvmx_write_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_CONTROL(i), context->hw_dbp.control[i]);
1225 cvmx_write_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_STATUS, context->hw_ibp.status);
1226 for (i = 0; i < 4; i++)
1228 cvmx_write_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ADDRESS(i), context->hw_ibp.address[i]);
1229 cvmx_write_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ADDRESS_MASK(i), context->hw_ibp.address_mask[i]);
1230 cvmx_write_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ASID(i), context->hw_ibp.asid[i]);
1231 cvmx_write_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_CONTROL(i), context->hw_ibp.control[i]);
1233 CVMX_MT_COP0(context->cop0.index, COP0_INDEX);
1234 CVMX_MT_COP0(context->cop0.entrylo[0], COP0_ENTRYLO0);
1235 CVMX_MT_COP0(context->cop0.entrylo[1], COP0_ENTRYLO1);
1236 CVMX_MT_COP0(context->cop0.entryhi, COP0_ENTRYHI);
1237 CVMX_MT_COP0(context->cop0.pagemask, COP0_PAGEMASK);
1238 CVMX_MT_COP0(context->cop0.status, COP0_STATUS);
1239 CVMX_MT_COP0(context->cop0.cause, COP0_CAUSE);
1240 CVMX_MT_COP0(context->cop0.debug, COP0_DEBUG);
1241 CVMX_MT_COP0(context->cop0.multicoredebug, COP0_MULTICOREDEBUG);
1242 CVMX_MT_COP0(context->cop0.perfval[0], COP0_PERFVALUE0);
1243 CVMX_MT_COP0(context->cop0.perfval[1], COP0_PERFVALUE1);
1244 CVMX_MT_COP0(context->cop0.perfctrl[0], COP0_PERFCONTROL0);
1245 CVMX_MT_COP0(context->cop0.perfctrl[1], COP0_PERFCONTROL1);
1246 CVMX_MT_COP0(context->cop0.depc, COP0_DEPC);
1247 CVMX_MT_COP0(context->cop0.desave, COP0_DESAVE);
1250 static inline void cvmx_debug_print_cause(volatile cvmx_debug_core_context_t *context)
1252 if (!CVMX_DEBUG_LOGGING)
1254 if (context->cop0.multicoredebug & 1)
1255 cvmx_dprintf("MCD0 was pulsed\n");
1256 if (context->cop0.multicoredebug & (1 << 16))
1257 cvmx_dprintf("Exception %lld in Debug Mode\n", (long long)((context->cop0.debug >> 10) & 0x1f));
1258 if (context->cop0.debug & (1 << 19))
1259 cvmx_dprintf("DDBSImpr\n");
1260 if (context->cop0.debug & (1 << 18))
1261 cvmx_dprintf("DDBLImpr\n");
1262 if (context->cop0.debug & (1 << 5))
1263 cvmx_dprintf("DINT\n");
1264 if (context->cop0.debug & (1 << 4))
1265 cvmx_dprintf("Debug Instruction Breakpoint (DIB) exception\n");
1266 if (context->cop0.debug & (1 << 3))
1267 cvmx_dprintf("Debug Date Break Store (DDBS) exception\n");
1268 if (context->cop0.debug & (1 << 2))
1269 cvmx_dprintf("Debug Date Break Load (DDBL) exception\n");
1270 if (context->cop0.debug & (1 << 1))
1271 cvmx_dprintf("Debug Breakpoint (DBp) exception\n");
1272 if (context->cop0.debug & (1 << 0))
1273 cvmx_dprintf("Debug Single Step (DSS) exception\n");
1276 void __cvmx_debug_handler_stage3 (void)
1278 volatile cvmx_debug_core_context_t *context;
1279 int comms_changed = 0;
1281 cvmx_debug_printf("Entering debug exception handler\n");
1282 cvmx_debug_printf("Debug named block at %p\n", cvmx_debug_globals);
1283 if (__cvmx_debug_mode_exception_occured)
1286 CVMX_MF_COP0(depc, COP0_DEPC);
1287 cvmx_dprintf("Unexpected debug-mode exception occured at 0x%llx, 0x%llx spinning\n", (long long) depc, (long long)(__cvmx_debug_mode_exception_occured));
1288 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1289 panic("Unexpected debug-mode exception occured at 0x%llx, 0x%llx\n", (long long) depc, (long long)(__cvmx_debug_mode_exception_occured));
1295 context = cvmx_debug_core_context();
1296 cvmx_debug_save_core_context(context);
1299 cvmx_debug_state_t state;
1300 cvmx_spinlock_lock(&cvmx_debug_globals->lock);
1301 state = cvmx_debug_get_state();
1302 state.ever_been_in_debug = 1;
1303 cvmx_debug_update_state (state);
1304 cvmx_spinlock_unlock(&cvmx_debug_globals->lock);
1306 cvmx_debug_print_cause(context);
1312 /* If the communication changes, change it. */
1313 cvmx_spinlock_lock(&cvmx_debug_globals->lock);
1314 if (cvmx_debug_globals->comm_changed)
1316 cvmx_debug_printf("Communication changed: %d\n", (int)cvmx_debug_globals->comm_changed);
1317 if (cvmx_debug_globals->comm_changed > COMM_SIZE)
1319 cvmx_dprintf("Unknown communication spinning: %lld > %d.\n", (long long)cvmx_debug_globals->comm_changed, (int)(COMM_SIZE));
1320 #ifdef CVMX_BUILD_FOR_LINUX_KERNEL
1321 panic("Unknown communication.\n");
1326 cvmx_debug_globals->comm_type = cvmx_debug_globals->comm_changed - 1;
1327 cvmx_debug_globals->comm_changed = 0;
1329 cvmx_spinlock_unlock(&cvmx_debug_globals->lock);
1330 needs_proxy = cvmx_debug_comms[cvmx_debug_globals->comm_type]->needs_proxy;
1333 cvmx_debug_register_t debug_reg;
1334 cvmx_debug_state_t state;
1335 unsigned core = cvmx_get_core_num();
1337 state = cvmx_debug_get_state();
1338 debug_reg.u64 = context->cop0.debug;
1339 /* All cores stop on any exception. See if we want nothing from this and
1340 it should resume. This needs to be done for non proxy based debugging
1341 so that some non active-cores can control the other cores. */
1342 if (!cvmx_debug_stop_core(state, core, &debug_reg, needs_proxy))
1344 context->cop0.debug = debug_reg.u64;
1351 cvmx_debug_register_t debug_reg;
1352 debug_reg.u64 = context->cop0.debug;
1353 cvmx_debug_printf("Starting to proxy\n");
1354 comms_changed = cvmx_debug_perform_proxy(&debug_reg, context);
1355 context->cop0.debug = debug_reg.u64;
1359 cvmx_debug_printf("Starting to wait for remote host\n");
1360 cvmx_debug_comms[cvmx_debug_globals->comm_type]->wait_for_resume(context, cvmx_debug_get_state());
1362 } while (comms_changed);
1364 cvmx_debug_clear_status(context);
1366 cvmx_debug_restore_core_context(context);
1367 cvmx_debug_printf("Exiting debug exception handler\n");
1370 void cvmx_debug_trigger_exception(void)
1372 /* Set CVMX_CIU_DINT to enter debug exception handler. */
1373 cvmx_write_csr (CVMX_CIU_DINT, 1 << cvmx_get_core_num ());
1374 /* Perform an immediate read after every write to an RSL register to force
1375 the write to complete. It doesn't matter what RSL read we do, so we
1376 choose CVMX_MIO_BOOT_BIST_STAT because it is fast and harmless */
1377 cvmx_read_csr (CVMX_MIO_BOOT_BIST_STAT);
1381 * Inform debugger about the end of the program. This is
1382 * called from crt0 after all the C cleanup code finishes.
1383 * Our current stack is the C one, not the debug exception
1385 void cvmx_debug_finish(void)
1387 unsigned coreid = cvmx_get_core_num();
1388 cvmx_debug_state_t state;
1390 cvmx_debug_printf ("Debug _exit reached!, core %d, cvmx_debug_globals = %p\n", coreid, cvmx_debug_globals);
1392 #ifndef CVMX_BUILD_FOR_LINUX_KERNEL
1397 cvmx_spinlock_lock(&cvmx_debug_globals->lock);
1398 state = cvmx_debug_get_state();
1399 state.known_cores ^= (1 << coreid);
1400 state.core_finished |= (1<<coreid);
1401 cvmx_debug_update_state(state);
1403 /* Tell the user the core has finished. */
1404 if (state.ever_been_in_debug)
1405 cvmx_debug_putpacket("!Core %d finish.", coreid);
1407 /* Notify the debugger if all cores have completed the program */
1408 if ((cvmx_debug_core_mask () & state.core_finished) == cvmx_debug_core_mask ())
1410 cvmx_debug_printf("All cores done!\n");
1411 if (state.ever_been_in_debug)
1412 cvmx_debug_putpacket_noformat("D0");
1414 if (state.focus_core == coreid && state.known_cores != 0)
1416 /* Loop through cores looking for someone to handle interrupts.
1417 Since we already check that known_cores is non zero, this
1418 should always find a core */
1420 for (newcore = 0; newcore < CVMX_DEBUG_MAX_CORES; newcore++)
1422 if (state.known_cores & (1<<newcore))
1424 cvmx_debug_printf("Routing uart interrupts to Core #%u.\n", newcore);
1425 cvmx_debug_set_focus_core(&state, newcore);
1426 cvmx_debug_update_state(state);
1431 cvmx_spinlock_unlock(&cvmx_debug_globals->lock);
1433 /* If we ever been in the debug, report to it that we have exited the core. */
1434 if (state.ever_been_in_debug)
1435 cvmx_debug_trigger_exception();