1/***********************license start*************** 2 * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3 * reserved. 4 * 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 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. 17 18 * * Neither the name of Cavium Inc. nor the names of 19 * its contributors may be used to endorse or promote products 20 * derived from this software without specific prior written 21 * permission. 22 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 26 * countries. 27 28 * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29 * AND WITH ALL FAULTS AND CAVIUM INC. 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**************************************/ 39 40 41/* 42 * @file 43 * 44 * Interface to debug exception handler 45 * NOTE: CARE SHOULD BE TAKE WHEN USING STD C LIBRARY FUNCTIONS IN 46 * THIS FILE IF SOMEONE PUTS A BREAKPOINT ON THOSE FUNCTIONS 47 * DEBUGGING WILL FAIL. 48 * 49 * <hr>$Revision: 50060 $<hr> 50 */ 51 52#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 53#include <linux/module.h> 54#include <asm/octeon/octeon.h> 55#include <asm/octeon/cvmx.h> 56#include <asm/octeon/cvmx-debug.h> 57#include <asm/octeon/cvmx-core.h> 58#include <asm/octeon/cvmx-bootmem.h> 59#include <asm/octeon/octeon-boot-info.h> 60#else 61#include <stdint.h> 62#include "cvmx.h" 63#include "cvmx-debug.h" 64#include "cvmx-bootmem.h" 65#include "cvmx-core.h" 66#include "cvmx-coremask.h" 67#include "octeon-boot-info.h" 68#endif 69 70#ifdef CVMX_DEBUG_LOGGING 71# undef CVMX_DEBUG_LOGGING 72# define CVMX_DEBUG_LOGGING 1 73#else 74# define CVMX_DEBUG_LOGGING 0 75#endif 76 77#ifndef CVMX_DEBUG_ATTACH 78# define CVMX_DEBUG_ATTACH 1 79#endif 80 81#define CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_STATUS (0xFFFFFFFFFF301000ull) 82#define CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ADDRESS(num) (0xFFFFFFFFFF301100ull + 0x100 * (num)) 83#define CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ADDRESS_MASK(num) (0xFFFFFFFFFF301108ull + 0x100 * (num)) 84#define CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ASID(num) (0xFFFFFFFFFF301110ull + 0x100 * (num)) 85#define CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_CONTROL(num) (0xFFFFFFFFFF301118ull + 0x100 * (num)) 86 87#define CVMX_DEBUG_HW_DATA_BREAKPOINT_STATUS (0xFFFFFFFFFF302000ull) 88#define CVMX_DEBUG_HW_DATA_BREAKPOINT_ADDRESS(num) (0xFFFFFFFFFF302100ull + 0x100 * (num)) 89#define CVMX_DEBUG_HW_DATA_BREAKPOINT_ADDRESS_MASK(num) (0xFFFFFFFFFF302108ull + 0x100 * (num)) 90#define CVMX_DEBUG_HW_DATA_BREAKPOINT_ASID(num) (0xFFFFFFFFFF302110ull + 0x100 * (num)) 91#define CVMX_DEBUG_HW_DATA_BREAKPOINT_CONTROL(num) (0xFFFFFFFFFF302118ull + 0x100 * (num)) 92 93#define ERET_INSN 0x42000018U /* Hexcode for eret */ 94#define ISR_DELAY_COUNTER 120000000 /* Could be tuned down */ 95 96extern cvmx_debug_comm_t cvmx_debug_uart_comm; 97extern cvmx_debug_comm_t cvmx_debug_remote_comm; 98static const cvmx_debug_comm_t *cvmx_debug_comms[COMM_SIZE] = {&cvmx_debug_uart_comm, &cvmx_debug_remote_comm}; 99 100 101 102static cvmx_debug_globals_t *cvmx_debug_globals; 103 104/** 105 * @file 106 * 107 */ 108 109#ifndef CVMX_BUILD_FOR_LINUX_KERNEL 110uint64_t __cvmx_debug_save_regs_area[32]; 111 112volatile uint64_t __cvmx_debug_mode_exception_ignore; 113volatile uint64_t __cvmx_debug_mode_exception_occured; 114 115static char cvmx_debug_stack[8*1024] __attribute ((aligned (16))); 116char *__cvmx_debug_stack_top = &cvmx_debug_stack[8*1024]; 117 118#ifndef CVMX_BUILD_FOR_TOOLCHAIN 119extern int cvmx_interrupt_in_isr; 120#else 121#define cvmx_interrupt_in_isr 0 122#endif 123 124#else 125uint64_t __cvmx_debug_save_regs_area_all[CVMX_MAX_CORES][32]; 126#define __cvmx_debug_save_regs_area __cvmx_debug_save_regs_area_all[cvmx_get_core_num()] 127 128volatile uint64_t __cvmx_debug_mode_exception_ignore_all[CVMX_MAX_CORES]; 129#define __cvmx_debug_mode_exception_ignore __cvmx_debug_mode_exception_ignore_all[cvmx_get_core_num()] 130volatile uint64_t __cvmx_debug_mode_exception_occured_all[CVMX_MAX_CORES]; 131#define __cvmx_debug_mode_exception_occured __cvmx_debug_mode_exception_occured_all[cvmx_get_core_num()] 132 133static char cvmx_debug_stack_all[CVMX_MAX_CORES][8*1024] __attribute ((aligned (16))); 134char *__cvmx_debug_stack_top_all[CVMX_MAX_CORES]; 135 136#define cvmx_interrupt_in_isr 0 137 138#endif 139 140 141static size_t cvmx_debug_strlen (const char *str) 142{ 143 size_t size = 0; 144 while (*str) 145 { 146 size++; 147 str++; 148 } 149 return size; 150} 151static void cvmx_debug_strcpy (char *dest, const char *src) 152{ 153 while (*src) 154 { 155 *dest = *src; 156 src++; 157 dest++; 158 } 159 *dest = 0; 160} 161 162static void cvmx_debug_memcpy_align (void *dest, const void *src, int size) __attribute__ ((__noinline__)); 163static void cvmx_debug_memcpy_align (void *dest, const void *src, int size) 164{ 165 long long *dest1 = (long long*)dest; 166 const long long *src1 = (const long long*)src; 167 int i; 168 if (size == 40) 169 { 170 long long a0, a1, a2, a3, a4; 171 a0 = src1[0]; 172 a1 = src1[1]; 173 a2 = src1[2]; 174 a3 = src1[3]; 175 a4 = src1[4]; 176 dest1[0] = a0; 177 dest1[1] = a1; 178 dest1[2] = a2; 179 dest1[3] = a3; 180 dest1[4] = a4; 181 return; 182 } 183 for(i = 0;i < size;i+=8) 184 { 185 *dest1 = *src1; 186 dest1++; 187 src1++; 188 } 189} 190 191 192static inline uint32_t cvmx_debug_core_mask(void) 193{ 194#ifndef CVMX_BUILD_FOR_LINUX_KERNEL 195#ifdef CVMX_BUILD_FOR_TOOLCHAIN 196 extern int __octeon_core_mask; 197 return __octeon_core_mask; 198#endif 199return cvmx_sysinfo_get()->core_mask; 200#else 201return octeon_get_boot_coremask (); 202#endif 203} 204 205static inline void cvmx_debug_update_state(cvmx_debug_state_t state) 206{ 207 cvmx_debug_memcpy_align(cvmx_debug_globals->state, &state, sizeof(cvmx_debug_state_t)); 208} 209 210static inline cvmx_debug_state_t cvmx_debug_get_state(void) 211{ 212 cvmx_debug_state_t state; 213 cvmx_debug_memcpy_align(&state, cvmx_debug_globals->state, sizeof(cvmx_debug_state_t)); 214 return state; 215} 216 217static void cvmx_debug_printf(char *format, ...) __attribute__((format(__printf__, 1, 2))); 218static void cvmx_debug_printf(char *format, ...) 219{ 220 va_list ap; 221 222 if (!CVMX_DEBUG_LOGGING) 223 return; 224 225 va_start(ap, format); 226 cvmx_dvprintf(format, ap); 227 va_end(ap); 228} 229 230static inline int __cvmx_debug_in_focus(cvmx_debug_state_t state, unsigned core) 231{ 232 return state.focus_core == core; 233} 234 235static void cvmx_debug_install_handler(unsigned core) 236{ 237 extern void __cvmx_debug_handler_stage2(void); 238 int32_t *trampoline = CASTPTR(int32_t, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, BOOTLOADER_DEBUG_TRAMPOLINE_CORE)); 239 trampoline += core; 240 241 *trampoline = (int32_t)(long)&__cvmx_debug_handler_stage2; 242 243 cvmx_debug_printf("Debug handled installed on core %d at %p\n", core, trampoline); 244} 245 246static int cvmx_debug_enabled(void) 247{ 248 return cvmx_debug_booted() || CVMX_DEBUG_ATTACH; 249} 250 251static void cvmx_debug_init_global_ptr (void *ptr) 252{ 253 uint64_t phys = cvmx_ptr_to_phys (ptr); 254 cvmx_debug_globals_t *p; 255 /* Since at this point, TLBs are not mapped 1 to 1, we should just use KSEG0 accesses. */ 256 p = CASTPTR(cvmx_debug_globals_t, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, phys)); 257 memset (p, 0, sizeof(cvmx_debug_globals_t)); 258 p->version = CVMX_DEBUG_GLOBALS_VERSION; 259 p->tlb_entries = cvmx_core_get_tlb_entries(); 260} 261 262static void cvmx_debug_init_globals(void) 263{ 264 uint64_t phys; 265 void *ptr; 266 267 if (cvmx_debug_globals) 268 return; 269 ptr = cvmx_bootmem_alloc_named_range_once(sizeof(cvmx_debug_globals_t), 0, /* KSEG0 max, 512MB=*/0/*1024*1024*512*/, 8, 270 CVMX_DEBUG_GLOBALS_BLOCK_NAME, cvmx_debug_init_global_ptr); 271 phys = cvmx_ptr_to_phys (ptr); 272 273 /* Since TLBs are not always mapped 1 to 1, we should just use access via KSEG0. */ 274 cvmx_debug_globals = CASTPTR(cvmx_debug_globals_t, CVMX_ADD_SEG32(CVMX_MIPS32_SPACE_KSEG0, phys)); 275 cvmx_debug_printf("Debug named block at %p\n", cvmx_debug_globals); 276} 277 278 279static void cvmx_debug_globals_check_version(void) 280{ 281 if (cvmx_debug_globals->version != CVMX_DEBUG_GLOBALS_VERSION) 282 { 283 cvmx_dprintf("Wrong version on the globals struct spinining; expected %d, got: %d.\n", (int)CVMX_DEBUG_GLOBALS_VERSION, (int)(cvmx_debug_globals->version)); 284#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 285 panic("Wrong version.\n"); 286#endif 287 while (1) 288 ; 289 } 290} 291 292static inline volatile cvmx_debug_core_context_t *cvmx_debug_core_context(void); 293static inline void cvmx_debug_save_core_context(volatile cvmx_debug_core_context_t *context, uint64_t hi, uint64_t lo); 294 295void cvmx_debug_init(void) 296{ 297 cvmx_debug_state_t state; 298 int core; 299 const cvmx_debug_comm_t *comm; 300 cvmx_spinlock_t *lock; 301 unsigned int coremask = cvmx_debug_core_mask(); 302 303 if (!cvmx_debug_enabled()) 304 return; 305 306 cvmx_debug_init_globals(); 307 308#ifndef CVMX_BUILD_FOR_LINUX_KERNEL 309 // Put a barrier until all cores have got to this point. 310 cvmx_coremask_barrier_sync(coremask); 311#endif 312 cvmx_debug_globals_check_version(); 313 314 315 comm = cvmx_debug_comms[cvmx_debug_globals->comm_type]; 316 lock = &cvmx_debug_globals->lock; 317 318 core = cvmx_get_core_num(); 319#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 320 /* Install the debugger handler on the cores. */ 321 { 322 int core1 = 0; 323 for (core1 = 0; core1 < CVMX_MAX_CORES; core1++) 324 { 325 if ((1u<<core1) & coremask) 326 cvmx_debug_install_handler(core1); 327 } 328 } 329#else 330 cvmx_debug_install_handler(core); 331#endif 332 333 if (comm->init) 334 comm->init(); 335 336 { 337 cvmx_spinlock_lock(lock); 338 state = cvmx_debug_get_state(); 339#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 340 state.known_cores |= coremask; 341 state.core_finished &= ~coremask; 342#else 343 state.known_cores |= (1u << core); 344 state.core_finished &= ~(1u << core); 345#endif 346 cvmx_debug_update_state(state); 347 cvmx_spinlock_unlock(lock); 348 } 349 350#ifndef CVMX_BUILD_FOR_LINUX_KERNEL 351 // Put a barrier until all cores have got to this point. 352 cvmx_coremask_barrier_sync(coremask); 353 354 if (cvmx_coremask_first_core(coremask)) 355#endif 356 { 357 cvmx_debug_printf("cvmx_debug_init core: %d\n", core); 358 state = cvmx_debug_get_state(); 359 state.focus_core = core; 360 state.active_cores = state.known_cores; 361 state.focus_switch = 1; 362 state.step_isr = 1; 363 cvmx_debug_printf("Known cores at init: 0x%x\n", (int)state.known_cores); 364 cvmx_debug_update_state(state); 365 366 /* Initialize __cvmx_debug_stack_top_all. */ 367#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 368 { 369 int i; 370 for (i = 0; i < CVMX_MAX_CORES; i++) 371 __cvmx_debug_stack_top_all[i] = &cvmx_debug_stack_all[i][8*1024]; 372 } 373#endif 374 cvmx_debug_globals->init_complete = 1; 375 CVMX_SYNCW; 376 } 377 while (!cvmx_debug_globals->init_complete) 378 { 379 /* Spin waiting for init to complete */ 380 } 381 382 if (cvmx_debug_booted()) 383 cvmx_debug_trigger_exception(); 384 385 /* Install the break handler after might tripper the debugger exception. */ 386#ifndef CVMX_BUILD_FOR_LINUX_KERNEL 387 if (cvmx_coremask_first_core(coremask)) 388#endif 389 { 390 if (comm->install_break_handler) 391 comm->install_break_handler(); 392 } 393} 394 395static const char cvmx_debug_hexchar[] = "0123456789ABCDEF"; 396/* Put the hex value of t into str. */ 397static void cvmx_debug_int8_to_strhex(char *str, unsigned char t) 398{ 399 str[0] = cvmx_debug_hexchar[(t>>4)&0xf]; 400 str[1] = cvmx_debug_hexchar[t&0xF]; 401 str[2] = 0; 402} 403 404static void cvmx_debug_int64_to_strhex(char *str, uint64_t t) 405{ 406 str[0] = cvmx_debug_hexchar[(t>>60)&0xF]; 407 str[1] = cvmx_debug_hexchar[(t>>56)&0xF]; 408 str[2] = cvmx_debug_hexchar[(t>>52)&0xF]; 409 str[3] = cvmx_debug_hexchar[(t>>48)&0xF]; 410 str[4] = cvmx_debug_hexchar[(t>>44)&0xF]; 411 str[5] = cvmx_debug_hexchar[(t>>40)&0xF]; 412 str[6] = cvmx_debug_hexchar[(t>>36)&0xF]; 413 str[7] = cvmx_debug_hexchar[(t>>32)&0xF]; 414 str[8] = cvmx_debug_hexchar[(t>>28)&0xF]; 415 str[9] = cvmx_debug_hexchar[(t>>24)&0xF]; 416 str[10] = cvmx_debug_hexchar[(t>>20)&0xF]; 417 str[11] = cvmx_debug_hexchar[(t>>16)&0xF]; 418 str[12] = cvmx_debug_hexchar[(t>>12)&0xF]; 419 str[13] = cvmx_debug_hexchar[(t>>8)&0xF]; 420 str[14] = cvmx_debug_hexchar[(t>>4)&0xF]; 421 str[15] = cvmx_debug_hexchar[(t>>0)&0xF]; 422 str[16] = 0; 423} 424 425static int cvmx_debug_putpacket_noformat(char *packet) 426{ 427 if (cvmx_debug_comms[cvmx_debug_globals->comm_type]->putpacket == NULL) 428 return 0; 429 cvmx_debug_printf("Reply: %s\n", packet); 430 return cvmx_debug_comms[cvmx_debug_globals->comm_type]->putpacket(packet); 431} 432 433static int cvmx_debug_putcorepacket(char *buf, int core) 434{ 435 char *tmp = "!Core XX "; 436 int tmpsize = cvmx_debug_strlen(tmp); 437 int bufsize = cvmx_debug_strlen(buf); 438 char *packet = __builtin_alloca(tmpsize + bufsize + 1); 439 cvmx_debug_strcpy(packet, tmp); 440 cvmx_debug_strcpy(&packet[tmpsize], buf); 441 if (core < 10) 442 { 443 packet[6] = ' '; 444 packet[7] = core + '0'; 445 } 446 else if (core < 20) 447 { 448 packet[6] = '1'; 449 packet[7] = core - 10 + '0'; 450 } 451 else if (core < 30) 452 { 453 packet[6] = '2'; 454 packet[7] = core - 20 + '0'; 455 } 456 else 457 { 458 packet[6] = '3'; 459 packet[7] = core - 30 + '0'; 460 } 461 return cvmx_debug_putpacket_noformat(packet); 462} 463 464/* Put a buf followed by an integer formated as a hex. */ 465static int cvmx_debug_putpacket_hexint(char *buf, uint64_t value) 466{ 467 size_t size = cvmx_debug_strlen(buf); 468 char *packet = __builtin_alloca(size + 16 + 1); 469 cvmx_debug_strcpy(packet, buf); 470 cvmx_debug_int64_to_strhex(&packet[size], value); 471 return cvmx_debug_putpacket_noformat(packet); 472} 473 474static int cvmx_debug_active_core(cvmx_debug_state_t state, unsigned core) 475{ 476 return state.active_cores & (1u << core); 477} 478 479static volatile cvmx_debug_core_context_t *cvmx_debug_core_context(void) 480{ 481 return &cvmx_debug_globals->contextes[cvmx_get_core_num()]; 482} 483 484static volatile uint64_t *cvmx_debug_regnum_to_context_ref(int regnum, volatile cvmx_debug_core_context_t *context) 485{ 486 /* Must be kept in sync with mips_octeon_reg_names in gdb/mips-tdep.c. */ 487 if (regnum < 32) 488 return &context->regs[regnum]; 489 switch (regnum) 490 { 491 case 32: return &context->cop0.status; 492 case 33: return &context->lo; 493 case 34: return &context->hi; 494 case 35: return &context->cop0.badvaddr; 495 case 36: return &context->cop0.cause; 496 case 37: return &context->cop0.depc; 497 default: return NULL; 498 } 499} 500 501static int cvmx_debug_probe_load(unsigned char *ptr, unsigned char *result) 502{ 503 volatile unsigned char *p = ptr; 504 int ok; 505 unsigned char tem; 506 507 { 508 __cvmx_debug_mode_exception_ignore = 1; 509 __cvmx_debug_mode_exception_occured = 0; 510 /* We don't handle debug-mode exceptions in delay slots. Avoid them. */ 511 asm volatile (".set push \n\t" 512 ".set noreorder \n\t" 513 "nop \n\t" 514 "lbu %0, %1 \n\t" 515 "nop \n\t" 516 ".set pop" : "=r"(tem) : "m"(*p)); 517 ok = __cvmx_debug_mode_exception_occured == 0; 518 __cvmx_debug_mode_exception_ignore = 0; 519 __cvmx_debug_mode_exception_occured = 0; 520 *result = tem; 521 } 522 return ok; 523} 524 525static int cvmx_debug_probe_store(unsigned char *ptr) 526{ 527 volatile unsigned char *p = ptr; 528 int ok; 529 530 __cvmx_debug_mode_exception_ignore = 1; 531 __cvmx_debug_mode_exception_occured = 0; 532 /* We don't handle debug-mode exceptions in delay slots. Avoid them. */ 533 asm volatile (".set push \n\t" 534 ".set noreorder \n\t" 535 "nop \n\t" 536 "sb $0, %0 \n\t" 537 "nop \n\t" 538 ".set pop" : "=m"(*p)); 539 ok = __cvmx_debug_mode_exception_occured == 0; 540 541 __cvmx_debug_mode_exception_ignore = 0; 542 __cvmx_debug_mode_exception_occured = 0; 543 return ok; 544} 545 546 547/** 548 * Routines to handle hex data 549 * 550 * @param ch 551 * @return 552 */ 553static inline int cvmx_debug_hex(char ch) 554{ 555 if ((ch >= 'a') && (ch <= 'f')) 556 return(ch - 'a' + 10); 557 if ((ch >= '0') && (ch <= '9')) 558 return(ch - '0'); 559 if ((ch >= 'A') && (ch <= 'F')) 560 return(ch - 'A' + 10); 561 return(-1); 562} 563 564/** 565 * While we find nice hex chars, build an int. 566 * Return number of chars processed. 567 * 568 * @param ptr 569 * @param intValue 570 * @return 571 */ 572static int cvmx_debug_hexToLong(const char **ptr, uint64_t *intValue) 573{ 574 int numChars = 0; 575 long hexValue; 576 577 *intValue = 0; 578 while (**ptr) 579 { 580 hexValue = cvmx_debug_hex(**ptr); 581 if (hexValue < 0) 582 break; 583 584 *intValue = (*intValue << 4) | hexValue; 585 numChars ++; 586 587 (*ptr)++; 588 } 589 590 return(numChars); 591} 592 593/** 594 * Initialize the performance counter control registers. 595 * 596 */ 597static void cvmx_debug_set_perf_control_reg (volatile cvmx_debug_core_context_t *context, int perf_event, int perf_counter) 598{ 599 cvmx_core_perf_control_t control; 600 601 control.u32 = 0; 602 control.s.u = 1; 603 control.s.s = 1; 604 control.s.k = 1; 605 control.s.ex = 1; 606 control.s.w = 1; 607 control.s.m = 1 - perf_counter; 608 control.s.event = perf_event; 609 610 context->cop0.perfctrl[perf_counter] = control.u32; 611} 612 613static cvmx_debug_command_t cvmx_debug_process_packet(const char *packet) 614{ 615 const char *buf = packet; 616 cvmx_debug_command_t result = COMMAND_NOP; 617 cvmx_debug_state_t state = cvmx_debug_get_state(); 618 619 /* A one letter command code represents what to do. */ 620 switch (*buf++) 621 { 622 case '?': /* What protocol do I speak? */ 623 cvmx_debug_putpacket_noformat("S0A"); 624 break; 625 626 case '\003': /* Control-C */ 627 cvmx_debug_putpacket_noformat("T9"); 628 break; 629 630 case 'F': /* Change the focus core */ 631 { 632 uint64_t core; 633 if (!cvmx_debug_hexToLong(&buf, &core)) 634 { 635 cvmx_debug_putpacket_noformat("!Uknown core. Focus not changed."); 636 } 637 /* Only cores in the exception handler may become the focus. 638 If a core not in the exception handler got focus the 639 debugger would hang since nobody would talk to it. */ 640 else if (state.handler_cores & (1u << core)) 641 { 642 /* Focus change reply must be sent before the focus 643 changes. Otherwise the new focus core will eat our ACK 644 from the debugger. */ 645 cvmx_debug_putpacket_hexint("F", core); 646 cvmx_debug_comms[cvmx_debug_globals->comm_type]->change_core(state.focus_core, core); 647 state.focus_core = core; 648 cvmx_debug_update_state(state); 649 break; 650 } 651 else 652 cvmx_debug_putpacket_noformat("!Core is not in the exception handler. Focus not changed."); 653 /* Nothing changed, so we send back the old value */ 654 } 655 /* fall through */ 656 case 'f': /* Get the focus core */ 657 cvmx_debug_putpacket_hexint("F", state.focus_core); 658 break; 659 660 case 'J': /* Set the flag for skip-over-isr in Single-Stepping mode */ 661 { 662 if (*buf == '1') 663 state.step_isr = 1; /* Step in ISR */ 664 else 665 state.step_isr = 0; /* Step over ISR */ 666 cvmx_debug_update_state(state); 667 } 668 /* Fall through. The reply to the set step-isr command is the 669 same as the get step-isr command */ 670 671 case 'j': /* Reply with step_isr status */ 672 cvmx_debug_putpacket_hexint("J", (unsigned)state.step_isr); 673 break; 674 675 676 case 'I': /* Set the active cores */ 677 { 678 uint64_t active_cores; 679 if (!cvmx_debug_hexToLong(&buf, &active_cores)) 680 active_cores = 0; 681 /* Limit the active mask to the known to exist cores */ 682 state.active_cores = active_cores & state.known_cores; 683 684 /* Lazy user hack to have 0 be all cores */ 685 if (state.active_cores == 0) 686 state.active_cores = state.known_cores; 687 688 /* The focus core must be in the active_cores mask */ 689 if ((state.active_cores & (1u << state.focus_core)) == 0) 690 { 691 cvmx_debug_putpacket_noformat("!Focus core was added to the masked."); 692 state.active_cores |= 1u << state.focus_core; 693 } 694 695 cvmx_debug_update_state(state); 696 } 697 /* Fall through. The reply to the set active cores command is the 698 same as the get active cores command */ 699 700 case 'i': /* Get the active cores */ 701 cvmx_debug_putpacket_hexint("I", state.active_cores); 702 break; 703 704 case 'A': /* Setting the step mode all or one */ 705 { 706 if (*buf == '1') 707 state.step_all = 1; /* A step or continue will start all cores */ 708 else 709 state.step_all = 0; /* A step or continue only affects the focus core */ 710 cvmx_debug_update_state(state); 711 } 712 /* Fall through. The reply to the set step-all command is the 713 same as the get step-all command */ 714 715 case 'a': /* Getting the current step mode */ 716 cvmx_debug_putpacket_hexint("A", state.step_all); 717 break; 718 719 case 'g': /* read a register from global place. */ 720 { 721 volatile cvmx_debug_core_context_t *context = cvmx_debug_core_context(); 722 uint64_t regno; 723 volatile uint64_t *reg; 724 725 /* Get the register number to read */ 726 if (!cvmx_debug_hexToLong(&buf, ®no)) 727 { 728 cvmx_debug_printf("Register number cannot be read.\n"); 729 cvmx_debug_putpacket_hexint("", 0xDEADBEEF); 730 break; 731 } 732 733 reg = cvmx_debug_regnum_to_context_ref(regno, context); 734 if (!reg) 735 { 736 cvmx_debug_printf("Register #%d is not valid\n", (int)regno); 737 cvmx_debug_putpacket_hexint("", 0xDEADBEEF); 738 break; 739 } 740 cvmx_debug_putpacket_hexint("", *reg); 741 } 742 break; 743 744 case 'G': /* set the value of a register. */ 745 { 746 volatile cvmx_debug_core_context_t *context = cvmx_debug_core_context(); 747 uint64_t regno; 748 volatile uint64_t *reg; 749 uint64_t value; 750 751 /* Get the register number to write. It should be followed by 752 a comma */ 753 if (!cvmx_debug_hexToLong(&buf, ®no) 754 || (*buf++ != ',') 755 || !cvmx_debug_hexToLong(&buf, &value)) 756 { 757 cvmx_debug_printf("G packet corrupt: %s\n", buf); 758 goto error_packet; 759 } 760 761 reg = cvmx_debug_regnum_to_context_ref(regno, context); 762 if (!reg) 763 { 764 cvmx_debug_printf("Register #%d is not valid\n", (int)regno); 765 goto error_packet; 766 } 767 *reg = value; 768 } 769 break; 770 771 case 'm': /* Memory read. mAA..AA,LLLL Read LLLL bytes at address AA..AA */ 772 { 773 uint64_t addr, i, length; 774 unsigned char *ptr; 775 char *reply; 776 777 /* Get the memory address, a comma, and the length */ 778 if (!cvmx_debug_hexToLong(&buf, &addr) 779 || (*buf++ != ',') 780 || !cvmx_debug_hexToLong(&buf, &length)) 781 { 782 cvmx_debug_printf("m packet corrupt: %s\n", buf); 783 goto error_packet; 784 } 785 if (length >= 1024) 786 { 787 cvmx_debug_printf("m packet length out of range: %lld\n", (long long)length); 788 goto error_packet; 789 } 790 791 reply = __builtin_alloca(length * 2 + 1); 792 ptr = (unsigned char *)(long)addr; 793 for (i = 0; i < length; i++) 794 { 795 /* Probe memory. If not accessible fail. */ 796 unsigned char t; 797 if (!cvmx_debug_probe_load(&ptr[i], &t)) 798 goto error_packet; 799 cvmx_debug_int8_to_strhex(&reply[i * 2], t); 800 } 801 cvmx_debug_putpacket_noformat(reply); 802 } 803 break; 804 805 case 'M': /* Memory write. MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ 806 { 807 uint64_t addr, i, length; 808 unsigned char *ptr; 809 810 if (!cvmx_debug_hexToLong(&buf, &addr) 811 || *buf++ != ',' 812 || !cvmx_debug_hexToLong(&buf, &length) 813 || *buf++ != ':') 814 { 815 cvmx_debug_printf("M packet corrupt: %s\n", buf); 816 goto error_packet; 817 } 818 819 ptr = (unsigned char *)(long)addr; 820 for (i = 0; i < length; i++) 821 { 822 int n, n1; 823 unsigned char c; 824 825 n = cvmx_debug_hex(buf[i * 2]); 826 n1 = cvmx_debug_hex(buf[i * 2 + 1]); 827 c = (n << 4) | n1; 828 829 if (n == -1 || n1 == -1) 830 { 831 cvmx_debug_printf("M packet corrupt: %s\n", &buf[i * 2]); 832 goto error_packet; 833 } 834 /* Probe memory. If not accessible fail. */ 835 if (!cvmx_debug_probe_store(&ptr[i])) 836 { 837 cvmx_debug_printf("M cannot write: %p\n", &ptr[i]); 838 goto error_packet; 839 } 840 ptr[i] = c; 841 } 842 cvmx_debug_putpacket_noformat("+"); 843 } 844 break; 845 846 case 'e': /* Set/get performance counter events. e[1234]XX..X: [01] 847 is the performance counter to set X is the performance 848 event. [34] is to get the same thing. */ 849 { 850 uint64_t perf_event = 0; 851 char encoded_counter = *buf++; 852 uint64_t counter; 853 volatile cvmx_debug_core_context_t *context = cvmx_debug_core_context(); 854 855 /* Ignore errors from the packet. */ 856 cvmx_debug_hexToLong(&buf, &perf_event); 857 858 switch (encoded_counter) 859 { 860 case '1': /* Set performance counter0 event. */ 861 case '2': /* Set performance counter1 event. */ 862 863 counter = encoded_counter - '1'; 864 context->cop0.perfval[counter] = 0; 865 cvmx_debug_set_perf_control_reg(context, perf_event, counter); 866 break; 867 868 case '3': /* Get performance counter0 event. */ 869 case '4': /* Get performance counter1 event. */ 870 { 871 cvmx_core_perf_control_t c; 872 char outpacket[16*2 +2]; 873 counter = encoded_counter - '3'; 874 /* Pass performance counter0 event and counter to 875 the debugger. */ 876 c.u32 = context->cop0.perfctrl[counter]; 877 cvmx_debug_int64_to_strhex(outpacket, context->cop0.perfval[counter]); 878 outpacket[16] = ','; 879 cvmx_debug_int64_to_strhex(&outpacket[17], c.s.event); 880 outpacket[33] = 0; 881 cvmx_debug_putpacket_noformat(outpacket); 882 } 883 break; 884 } 885 } 886 break; 887 888#if 0 889 case 't': /* Return the trace buffer read data register contents. */ 890 { 891 uint64_t tra_data; 892 uint64_t tra_ctl; 893 char tmp[64]; 894 895 /* If trace buffer is disabled no trace data information is available. */ 896 if ((tra_ctl & 0x1) == 0) 897 { 898 cvmx_debug_putpacket_noformat("!Trace buffer not enabled\n"); 899 cvmx_debug_putpacket_noformat("t"); 900 } 901 else 902 { 903 cvmx_debug_putpacket_noformat("!Trace buffer is enabled\n"); 904 tra_data = cvmx_read_csr(OCTEON_TRA_READ_DATA); 905 mem2hex (&tra_data, tmp, 8); 906 strcpy (debug_output_buffer, "t"); 907 strcat (debug_output_buffer, tmp); 908 cvmx_debug_putpacket_noformat(debug_output_buffer); 909 } 910 } 911 break; 912#endif 913 914 case 'Z': /* Insert hardware breakpoint: Z[di]NN..N,AA.A, [di] data or 915 instruction, NN..Nth at address AA..A */ 916 { 917 enum type 918 { 919 WP_LOAD = 1, 920 WP_STORE = 2, 921 WP_ACCESS = 3 922 }; 923 924 uint64_t num, size; 925 uint64_t addr; 926 uint64_t type; 927 char bp_type = *buf++; 928 const int BE = 1, TE = 4; 929 volatile cvmx_debug_core_context_t *context = cvmx_debug_core_context(); 930 931 if (!cvmx_debug_hexToLong(&buf, &num) 932 || *buf++ != ',' 933 || !cvmx_debug_hexToLong(&buf, &addr)) 934 { 935 cvmx_debug_printf("Z packet corrupt: %s\n", &packet[1]); 936 goto error_packet; 937 } 938 939 switch (bp_type) 940 { 941 case 'i': // Instruction hardware breakpoint 942 if (num > 4) 943 { 944 cvmx_debug_printf("Z packet corrupt: %s\n", &packet[1]); 945 goto error_packet; 946 } 947 948 context->hw_ibp.address[num] = addr; 949 context->hw_ibp.address_mask[num] = 0; 950 context->hw_ibp.asid[num] = 0; 951 context->hw_ibp.control[num] = BE | TE; 952 break; 953 954 case 'd': // Data hardware breakpoint 955 { 956 uint64_t dbc = 0xff0 | BE | TE; 957 uint64_t dbm; 958 if (num > 4 959 || *buf++ != ',' 960 || !cvmx_debug_hexToLong(&buf, &size) 961 || *buf++ != ',' 962 || !cvmx_debug_hexToLong(&buf, &type) 963 || type > WP_ACCESS 964 || type < WP_LOAD) 965 { 966 cvmx_debug_printf("Z packet corrupt: %s\n", &packet[1]); 967 goto error_packet; 968 } 969 970 /* Set DBC[BE,TE,BLM]. */ 971 context->hw_dbp.address[num] = addr; 972 context->hw_dbp.asid[num] = 0; 973 974 dbc |= type == WP_STORE ? 0x1000 : type == WP_LOAD ? 0x2000 : 0; 975 /* Mask the bits depending on the size for 976 debugger to stop while accessing parts of the 977 memory location. */ 978 dbm = (size == 8) ? 0x7 : ((size == 4) ? 3 979 : (size == 2) ? 1 : 0); 980 context->hw_dbp.address_mask[num] = dbm; 981 context->hw_dbp.control[num] = dbc; 982 break; 983 } 984 default: 985 cvmx_debug_printf("Z packet corrupt: %s\n", &packet[1]); 986 goto error_packet; 987 } 988 } 989 break; 990 991 case 'z': /* Remove hardware breakpoint: z[di]NN..N remove NN..Nth 992breakpoint. */ 993 { 994 uint64_t num; 995 char bp_type = *buf++; 996 volatile cvmx_debug_core_context_t *context = cvmx_debug_core_context(); 997 998 if (!cvmx_debug_hexToLong(&buf, &num) || num > 4) 999 { 1000 cvmx_debug_printf("z packet corrupt: %s\n", buf); 1001 goto error_packet; 1002 } 1003 1004 switch (bp_type) 1005 { 1006 case 'i': // Instruction hardware breakpoint 1007 context->hw_ibp.address[num] = 0; 1008 context->hw_ibp.address_mask[num] = 0; 1009 context->hw_ibp.asid[num] = 0; 1010 context->hw_ibp.control[num] = 0; 1011 break; 1012 case 'd': // Data hardware breakpoint 1013 context->hw_dbp.address[num] = 0; 1014 context->hw_dbp.address_mask[num] = 0; 1015 context->hw_dbp.asid[num] = 0; 1016 context->hw_dbp.control[num] = 0; 1017 break; 1018 default: 1019 cvmx_debug_printf("z packet corrupt: %s\n", buf); 1020 goto error_packet; 1021 } 1022 } 1023 break; 1024 1025 case 's': /* Single step. sAA..AA Step one instruction from AA..AA (optional) */ 1026 result = COMMAND_STEP; 1027 break; 1028 1029 case 'c': /* Continue. cAA..AA Continue at address AA..AA (optional) */ 1030 result = COMMAND_CONTINUE; 1031 break; 1032 1033 case '+': /* Don't know. I think it is a communications sync */ 1034 /* Ignoring this command */ 1035 break; 1036 1037 default: 1038 cvmx_debug_printf("Unknown debug command: %s\n", buf - 1); 1039error_packet: 1040 cvmx_debug_putpacket_noformat("-"); 1041 break; 1042 } 1043 1044 return result; 1045} 1046 1047static cvmx_debug_command_t cvmx_debug_process_next_packet(void) 1048{ 1049 char packet[CVMX_DEBUG_MAX_REQUEST_SIZE]; 1050 if (cvmx_debug_comms[cvmx_debug_globals->comm_type]->getpacket(packet, CVMX_DEBUG_MAX_REQUEST_SIZE)) 1051 { 1052 cvmx_debug_printf("Request: %s\n", packet); 1053 return cvmx_debug_process_packet(packet); 1054 } 1055 return COMMAND_NOP; 1056} 1057 1058/* If a core isn't in the active core mask we need to start him up again. We 1059 can only do this if the core didn't hit a breakpoint or single step. If the 1060 core hit CVMX_CIU_DINT interrupt (generally happens when while executing 1061 _exit() at the end of the program). Remove the core from known cores so 1062 that when the cores in active core mask are done executing the program, the 1063 focus will not be transfered to this core. */ 1064 1065static int cvmx_debug_stop_core(cvmx_debug_state_t state, unsigned core, cvmx_debug_register_t *debug_reg, int proxy) 1066{ 1067 if (!cvmx_debug_active_core(state, core) && !debug_reg->s.dbp && !debug_reg->s.dss && (debug_reg->s.dint != 1)) 1068 { 1069 debug_reg->s.sst = 0; 1070 cvmx_debug_printf("Core #%d not in active cores, continuing.\n", core); 1071 return 0; 1072 } 1073 if ((state.core_finished & (1u<<core)) && proxy) 1074 return 0; 1075 return 1; 1076} 1077 1078/* check to see if current exc is single-stepped and that no other exc 1079 was also simultaneously noticed. */ 1080static int cvmx_debug_single_step_exc(cvmx_debug_register_t *debug_reg) 1081{ 1082 if (debug_reg->s.dss && !debug_reg->s.dib && !debug_reg->s.dbp && !debug_reg->s.ddbs && !debug_reg->s.ddbl) 1083 return 1; 1084 return 0; 1085} 1086 1087static void cvmx_debug_set_focus_core(cvmx_debug_state_t *state, int core) 1088{ 1089 if (state->ever_been_in_debug) 1090 cvmx_debug_putcorepacket("taking focus.", core); 1091 cvmx_debug_comms[cvmx_debug_globals->comm_type]->change_core (state->focus_core, core); 1092 state->focus_core = core; 1093} 1094 1095static void cvmx_debug_may_elect_as_focus_core(cvmx_debug_state_t *state, int core, cvmx_debug_register_t *debug_reg) 1096{ 1097 /* If another core has already elected itself as the focus core, we're late. */ 1098 if (state->handler_cores & (1u << state->focus_core)) 1099 return; 1100 1101 /* If we hit a breakpoint, elect ourselves. */ 1102 if (debug_reg->s.dib || debug_reg->s.dbp || debug_reg->s.ddbs || debug_reg->s.ddbl) 1103 cvmx_debug_set_focus_core(state, core); 1104 1105 /* It is possible the focus core has completed processing and exited the 1106 program. When this happens the focus core will not be in 1107 known_cores. If this is the case we need to elect a new focus. */ 1108 if ((state->known_cores & (1u << state->focus_core)) == 0) 1109 cvmx_debug_set_focus_core(state, core); 1110} 1111 1112static void cvmx_debug_send_stop_reason(cvmx_debug_register_t *debug_reg, volatile cvmx_debug_core_context_t *context) 1113{ 1114 /* Handle Debug Data Breakpoint Store/Load Exception. */ 1115 if (debug_reg->s.ddbs || debug_reg->s.ddbl) 1116 cvmx_debug_putpacket_hexint("T8:", (int) context->hw_dbp.status); 1117 else 1118 cvmx_debug_putpacket_noformat("T9"); 1119} 1120 1121 1122static void cvmx_debug_clear_status(volatile cvmx_debug_core_context_t *context) 1123{ 1124 /* SW needs to clear the BreakStatus bits after a watchpoint is hit or on 1125 reset. */ 1126 context->hw_dbp.status &= ~0x3fff; 1127 1128 /* Clear MCD0, which is write-1-to-clear. */ 1129 context->cop0.multicoredebug |= 1; 1130} 1131 1132static void cvmx_debug_sync_up_cores(void) 1133{ 1134 /* NOTE this reads directly from the state array for speed reasons 1135 and we don't change the array. */ 1136 do { 1137 asm("": : : "memory"); 1138 } while (cvmx_debug_globals->state[offsetof(cvmx_debug_state_t, step_all)/sizeof(uint32_t)] 1139 && cvmx_debug_globals->state[offsetof(cvmx_debug_state_t, handler_cores)/sizeof(uint32_t)] != 0); 1140} 1141 1142/* Delay the focus core a little if it is likely another core needs to steal 1143 focus. Once we enter the main loop focus can't be stolen */ 1144static void cvmx_debug_delay_focus_core(cvmx_debug_state_t state, unsigned core, cvmx_debug_register_t *debug_reg) 1145{ 1146 volatile int i; 1147 if (debug_reg->s.dss || debug_reg->s.dbp || core != state.focus_core) 1148 return; 1149 for (i = 0; i < 2400; i++) 1150 { 1151 asm volatile (".set push \n\t" 1152 ".set noreorder \n\t" 1153 "nop \n\t" 1154 "nop \n\t" 1155 "nop \n\t" 1156 "nop \n\t" 1157 ".set pop"); 1158 /* Spin giving the breakpoint core time to steal focus */ 1159 } 1160 1161} 1162 1163/* If this core was single-stepping in a group, 1164 && it was not the last focus-core, 1165 && last focus-core happens to be inside an ISR, blocking focus-switch 1166 then burn some cycles, to avoid unnecessary focus toggles. */ 1167static void cvmx_debug_delay_isr_core(unsigned core, uint32_t depc, int single_stepped_exc_only, 1168 cvmx_debug_state_t state) 1169{ 1170 volatile uint64_t i; 1171 if(!single_stepped_exc_only || state.step_isr || core == state.focus_core || state.focus_switch) 1172 return; 1173 1174 cvmx_debug_printf ("Core #%u spinning for focus at 0x%x\n", core, (unsigned int)depc); 1175 1176 for(i = ISR_DELAY_COUNTER; i > 0 ; i--) 1177 { 1178 state = cvmx_debug_get_state(); 1179 /* Spin giving the focus core time to service ISR */ 1180 /* But cut short the loop, if we can. Shrink down i, only once. */ 1181 if (i > 600000 && state.focus_switch) 1182 i = 500000; 1183 } 1184 1185} 1186 1187static int cvmx_debug_perform_proxy(cvmx_debug_register_t *debug_reg, volatile cvmx_debug_core_context_t *context) 1188{ 1189 unsigned core = cvmx_get_core_num(); 1190 cvmx_debug_state_t state = cvmx_debug_get_state(); 1191 cvmx_debug_command_t command = COMMAND_NOP; 1192 int single_stepped_exc_only = cvmx_debug_single_step_exc (debug_reg); 1193 1194 /* All cores should respect the focus core if it has to 1195 stop focus switching while servicing an interrupt. 1196 If the system is single-stepping, then the following 1197 code path is valid. If the current core tripped on a 1198 break-point or some other error while going through 1199 an ISR, then we shouldn't be returning unconditionally. 1200 In that case (non-single-step case) we must enter 1201 the debugger exception stub fully. */ 1202 if (!state.step_isr && (cvmx_interrupt_in_isr || (context->cop0.status & 0x2ULL)) && single_stepped_exc_only) 1203 { 1204 cvmx_spinlock_lock(&cvmx_debug_globals->lock); 1205 state = cvmx_debug_get_state(); 1206 /* If this is the focus core, switch off focus switching 1207 till ISR_DELAY_COUNTER. This will let focus core 1208 keep the focus until the ISR is completed. */ 1209 if(state.focus_switch && core == state.focus_core) 1210 { 1211 cvmx_debug_printf ("Core #%u stopped focus stealing at 0x%llx\n", core, (unsigned long long)context->cop0.depc); 1212 state.focus_switch = 0; 1213 } 1214 /* Alow other cores to steal focus. 1215 Focus core has completed ISR. */ 1216 if (*(uint32_t*)((__SIZE_TYPE__)context->cop0.depc) == ERET_INSN && core == state.focus_core) 1217 { 1218 cvmx_debug_printf ("Core #%u resumed focus stealing at 0x%llx\n", core, (unsigned long long)context->cop0.depc); 1219 state.focus_switch = 1; 1220 } 1221 cvmx_debug_update_state(state); 1222 cvmx_spinlock_unlock(&cvmx_debug_globals->lock); 1223 cvmx_debug_printf ("Core #%u resumed skipping isr.\n", core); 1224 return 0; 1225 } 1226 1227 /* Delay the focus core a little if it is likely another core needs to 1228 steal focus. Once we enter the main loop focus can't be stolen */ 1229 cvmx_debug_delay_focus_core(state, core, debug_reg); 1230 1231 cvmx_debug_delay_isr_core (core, context->cop0.depc, single_stepped_exc_only, state); 1232 1233 /* The following section of code does two critical things. First, it 1234 populates the handler_cores bitmask of all cores in the exception 1235 handler. Only one core at a time can update this field. Second it 1236 changes the focus core if needed. */ 1237 { 1238 cvmx_debug_printf("Core #%d stopped\n", core); 1239 cvmx_spinlock_lock(&cvmx_debug_globals->lock); 1240 state = cvmx_debug_get_state(); 1241 1242 state.handler_cores |= (1u << core); 1243 cvmx_debug_may_elect_as_focus_core(&state, core, debug_reg); 1244 1245/* Push all updates before exiting the critical section */ 1246 state.focus_switch = 1; 1247 cvmx_debug_update_state(state); 1248 cvmx_spinlock_unlock(&cvmx_debug_globals->lock); 1249 } 1250 if (__cvmx_debug_in_focus(state, core)) 1251 cvmx_debug_send_stop_reason(debug_reg, context); 1252 1253 do { 1254 unsigned oldfocus = state.focus_core; 1255 state = cvmx_debug_get_state(); 1256 /* Note the focus core can change in this loop. */ 1257 if (__cvmx_debug_in_focus(state, core)) 1258 { 1259 /* If the focus has changed and the old focus has exited, then send a signal 1260 that we should stop if step_all is off. */ 1261 if (oldfocus != state.focus_core && ((1u << oldfocus) & state.core_finished) 1262 && !state.step_all) 1263 cvmx_debug_send_stop_reason(debug_reg, context); 1264 1265 command = cvmx_debug_process_next_packet(); 1266 state = cvmx_debug_get_state(); 1267 /* When resuming let the other cores resume as well with 1268 step-all. */ 1269 if (command != COMMAND_NOP && state.step_all) 1270 { 1271 state.command = command; 1272 cvmx_debug_update_state(state); 1273 } 1274 } 1275 /* When steping all cores, update the non focus core's command too. */ 1276 else if (state.step_all) 1277 command = state.command; 1278 1279 /* If we did not get a command and the communication changed return, 1280 we are changing the communications. */ 1281 if (command == COMMAND_NOP && cvmx_debug_globals->comm_changed) 1282 { 1283 /* FIXME, this should a sync not based on cvmx_coremask_barrier_sync. */ 1284#ifndef CVMX_BUILD_FOR_LINUX_KERNEL 1285 /* Sync up. */ 1286 cvmx_coremask_barrier_sync(state.handler_cores); 1287#endif 1288 return 1; 1289 } 1290 } while (command == COMMAND_NOP); 1291 1292 debug_reg->s.sst = command == COMMAND_STEP; 1293 cvmx_debug_printf("Core #%d running\n", core); 1294 1295 { 1296 cvmx_spinlock_lock(&cvmx_debug_globals->lock); 1297 state = cvmx_debug_get_state(); 1298 state.handler_cores ^= (1u << core); 1299 cvmx_debug_update_state(state); 1300 cvmx_spinlock_unlock(&cvmx_debug_globals->lock); 1301 } 1302 1303 cvmx_debug_sync_up_cores(); 1304 /* Now that all cores are out, reset the command. */ 1305 if (__cvmx_debug_in_focus(state, core)) 1306 { 1307 cvmx_spinlock_lock(&cvmx_debug_globals->lock); 1308 state = cvmx_debug_get_state(); 1309 state.command = COMMAND_NOP; 1310 cvmx_debug_update_state(state); 1311 cvmx_spinlock_unlock(&cvmx_debug_globals->lock); 1312 } 1313 return 0; 1314} 1315 1316static void cvmx_debug_save_core_context(volatile cvmx_debug_core_context_t *context, uint64_t hi, uint64_t lo) 1317{ 1318 unsigned i; 1319 cvmx_debug_memcpy_align ((char *) context->regs, __cvmx_debug_save_regs_area, sizeof(context->regs)); 1320 context->lo = lo; 1321 context->hi = hi; 1322 CVMX_MF_COP0(context->cop0.index, COP0_INDEX); 1323 CVMX_MF_COP0(context->cop0.entrylo[0], COP0_ENTRYLO0); 1324 CVMX_MF_COP0(context->cop0.entrylo[1], COP0_ENTRYLO1); 1325 CVMX_MF_COP0(context->cop0.entryhi, COP0_ENTRYHI); 1326 CVMX_MF_COP0(context->cop0.pagemask, COP0_PAGEMASK); 1327 CVMX_MF_COP0(context->cop0.status, COP0_STATUS); 1328 CVMX_MF_COP0(context->cop0.cause, COP0_CAUSE); 1329 CVMX_MF_COP0(context->cop0.debug, COP0_DEBUG); 1330 CVMX_MF_COP0(context->cop0.multicoredebug, COP0_MULTICOREDEBUG); 1331 CVMX_MF_COP0(context->cop0.perfval[0], COP0_PERFVALUE0); 1332 CVMX_MF_COP0(context->cop0.perfval[1], COP0_PERFVALUE1); 1333 CVMX_MF_COP0(context->cop0.perfctrl[0], COP0_PERFCONTROL0); 1334 CVMX_MF_COP0(context->cop0.perfctrl[1], COP0_PERFCONTROL1); 1335 /* Save DEPC and DESAVE since debug-mode exceptions (see 1336 debug_probe_{load,store}) can clobber these. */ 1337 CVMX_MF_COP0(context->cop0.depc, COP0_DEPC); 1338 CVMX_MF_COP0(context->cop0.desave, COP0_DESAVE); 1339 1340 context->hw_ibp.status = cvmx_read_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_STATUS); 1341 for (i = 0; i < 4; i++) 1342 { 1343 context->hw_ibp.address[i] = cvmx_read_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ADDRESS(i)); 1344 context->hw_ibp.address_mask[i] = cvmx_read_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ADDRESS_MASK(i)); 1345 context->hw_ibp.asid[i] = cvmx_read_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ASID(i)); 1346 context->hw_ibp.control[i] = cvmx_read_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_CONTROL(i)); 1347 } 1348 1349 context->hw_dbp.status = cvmx_read_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_STATUS); 1350 for (i = 0; i < 4; i++) 1351 { 1352 context->hw_dbp.address[i] = cvmx_read_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_ADDRESS(i)); 1353 context->hw_dbp.address_mask[i] = cvmx_read_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_ADDRESS_MASK(i)); 1354 context->hw_dbp.asid[i] = cvmx_read_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_ASID(i)); 1355 context->hw_dbp.control[i] = cvmx_read_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_CONTROL(i)); 1356 } 1357 1358 for (i = 0; i < cvmx_debug_globals->tlb_entries; i++) 1359 { 1360 CVMX_MT_COP0(i, COP0_INDEX); 1361 asm volatile ("tlbr"); 1362 CVMX_MF_COP0(context->tlbs[i].entrylo[0], COP0_ENTRYLO0); 1363 CVMX_MF_COP0(context->tlbs[i].entrylo[1], COP0_ENTRYLO1); 1364 CVMX_MF_COP0(context->tlbs[i].entryhi, COP0_ENTRYHI); 1365 CVMX_MF_COP0(context->tlbs[i].pagemask, COP0_PAGEMASK); 1366 } 1367 CVMX_SYNCW; 1368} 1369 1370static void cvmx_debug_restore_core_context(volatile cvmx_debug_core_context_t *context) 1371{ 1372 uint64_t hi, lo; 1373 int i; 1374 cvmx_debug_memcpy_align (__cvmx_debug_save_regs_area, (char *) context->regs, sizeof(context->regs)); 1375 /* We don't change the TLB so no need to restore it. */ 1376 cvmx_write_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_STATUS, context->hw_dbp.status); 1377 for (i = 0; i < 4; i++) 1378 { 1379 cvmx_write_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_ADDRESS(i), context->hw_dbp.address[i]); 1380 cvmx_write_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_ADDRESS_MASK(i), context->hw_dbp.address_mask[i]); 1381 cvmx_write_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_ASID(i), context->hw_dbp.asid[i]); 1382 cvmx_write_csr(CVMX_DEBUG_HW_DATA_BREAKPOINT_CONTROL(i), context->hw_dbp.control[i]); 1383 } 1384 cvmx_write_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_STATUS, context->hw_ibp.status); 1385 for (i = 0; i < 4; i++) 1386 { 1387 cvmx_write_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ADDRESS(i), context->hw_ibp.address[i]); 1388 cvmx_write_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ADDRESS_MASK(i), context->hw_ibp.address_mask[i]); 1389 cvmx_write_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_ASID(i), context->hw_ibp.asid[i]); 1390 cvmx_write_csr(CVMX_DEBUG_HW_INSTRUCTION_BREAKPOINT_CONTROL(i), context->hw_ibp.control[i]); 1391 } 1392 CVMX_MT_COP0(context->cop0.index, COP0_INDEX); 1393 CVMX_MT_COP0(context->cop0.entrylo[0], COP0_ENTRYLO0); 1394 CVMX_MT_COP0(context->cop0.entrylo[1], COP0_ENTRYLO1); 1395 CVMX_MT_COP0(context->cop0.entryhi, COP0_ENTRYHI); 1396 CVMX_MT_COP0(context->cop0.pagemask, COP0_PAGEMASK); 1397 CVMX_MT_COP0(context->cop0.status, COP0_STATUS); 1398 CVMX_MT_COP0(context->cop0.cause, COP0_CAUSE); 1399 CVMX_MT_COP0(context->cop0.debug, COP0_DEBUG); 1400 CVMX_MT_COP0(context->cop0.multicoredebug, COP0_MULTICOREDEBUG); 1401 CVMX_MT_COP0(context->cop0.perfval[0], COP0_PERFVALUE0); 1402 CVMX_MT_COP0(context->cop0.perfval[1], COP0_PERFVALUE1); 1403 CVMX_MT_COP0(context->cop0.perfctrl[0], COP0_PERFCONTROL0); 1404 CVMX_MT_COP0(context->cop0.perfctrl[1], COP0_PERFCONTROL1); 1405 CVMX_MT_COP0(context->cop0.depc, COP0_DEPC); 1406 CVMX_MT_COP0(context->cop0.desave, COP0_DESAVE); 1407 lo = context->lo; 1408 hi = context->hi; 1409 asm("mtlo %0" :: "r"(lo)); 1410 asm("mthi %0" :: "r"(hi)); 1411} 1412 1413static inline void cvmx_debug_print_cause(volatile cvmx_debug_core_context_t *context) 1414{ 1415 if (!CVMX_DEBUG_LOGGING) 1416 return; 1417 if (context->cop0.multicoredebug & 1) 1418 cvmx_dprintf("MCD0 was pulsed\n"); 1419 if (context->cop0.multicoredebug & (1 << 16)) 1420 cvmx_dprintf("Exception %lld in Debug Mode\n", (long long)((context->cop0.debug >> 10) & 0x1f)); 1421 if (context->cop0.debug & (1 << 19)) 1422 cvmx_dprintf("DDBSImpr\n"); 1423 if (context->cop0.debug & (1 << 18)) 1424 cvmx_dprintf("DDBLImpr\n"); 1425 if (context->cop0.debug & (1 << 5)) 1426 cvmx_dprintf("DINT\n"); 1427 if (context->cop0.debug & (1 << 4)) 1428 cvmx_dprintf("Debug Instruction Breakpoint (DIB) exception\n"); 1429 if (context->cop0.debug & (1 << 3)) 1430 cvmx_dprintf("Debug Date Break Store (DDBS) exception\n"); 1431 if (context->cop0.debug & (1 << 2)) 1432 cvmx_dprintf("Debug Date Break Load (DDBL) exception\n"); 1433 if (context->cop0.debug & (1 << 1)) 1434 cvmx_dprintf("Debug Breakpoint (DBp) exception\n"); 1435 if (context->cop0.debug & (1 << 0)) 1436 cvmx_dprintf("Debug Single Step (DSS) exception\n"); 1437} 1438 1439void __cvmx_debug_handler_stage3 (uint64_t lo, uint64_t hi) 1440{ 1441 volatile cvmx_debug_core_context_t *context; 1442 int comms_changed = 0; 1443 1444 cvmx_debug_printf("Entering debug exception handler\n"); 1445 cvmx_debug_printf("Debug named block at %p\n", cvmx_debug_globals); 1446 if (__cvmx_debug_mode_exception_occured) 1447 { 1448 uint64_t depc; 1449 CVMX_MF_COP0(depc, COP0_DEPC); 1450 cvmx_dprintf("Unexpected debug-mode exception occured at 0x%llx, 0x%llx spinning\n", (long long) depc, (long long)(__cvmx_debug_mode_exception_occured)); 1451#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1452 panic("Unexpected debug-mode exception occured at 0x%llx, 0x%llx\n", (long long) depc, (long long)(__cvmx_debug_mode_exception_occured)); 1453#endif 1454 while (1) 1455 ; 1456 } 1457 1458 context = cvmx_debug_core_context(); 1459 cvmx_debug_save_core_context(context, hi, lo); 1460 1461 { 1462 cvmx_debug_state_t state; 1463 cvmx_spinlock_lock(&cvmx_debug_globals->lock); 1464 state = cvmx_debug_get_state(); 1465 state.ever_been_in_debug = 1; 1466 cvmx_debug_update_state (state); 1467 cvmx_spinlock_unlock(&cvmx_debug_globals->lock); 1468 } 1469 cvmx_debug_print_cause(context); 1470 1471 do 1472 { 1473 int needs_proxy; 1474 comms_changed = 0; 1475 /* If the communication changes, change it. */ 1476 cvmx_spinlock_lock(&cvmx_debug_globals->lock); 1477 if (cvmx_debug_globals->comm_changed) 1478 { 1479 cvmx_debug_printf("Communication changed: %d\n", (int)cvmx_debug_globals->comm_changed); 1480 if (cvmx_debug_globals->comm_changed > COMM_SIZE) 1481 { 1482 cvmx_dprintf("Unknown communication spinning: %lld > %d.\n", (long long)cvmx_debug_globals->comm_changed, (int)(COMM_SIZE)); 1483#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 1484 panic("Unknown communication.\n"); 1485#endif 1486 while (1) 1487 ; 1488 } 1489 cvmx_debug_globals->comm_type = cvmx_debug_globals->comm_changed - 1; 1490 cvmx_debug_globals->comm_changed = 0; 1491 } 1492 cvmx_spinlock_unlock(&cvmx_debug_globals->lock); 1493 needs_proxy = cvmx_debug_comms[cvmx_debug_globals->comm_type]->needs_proxy; 1494 1495 { 1496 cvmx_debug_register_t debug_reg; 1497 cvmx_debug_state_t state; 1498 unsigned core = cvmx_get_core_num(); 1499 1500 state = cvmx_debug_get_state(); 1501 debug_reg.u64 = context->cop0.debug; 1502 /* All cores stop on any exception. See if we want nothing from this and 1503 it should resume. This needs to be done for non proxy based debugging 1504 so that some non active-cores can control the other cores. */ 1505 if (!cvmx_debug_stop_core(state, core, &debug_reg, needs_proxy)) 1506 { 1507 context->cop0.debug = debug_reg.u64; 1508 break; 1509 } 1510 } 1511 1512 if (needs_proxy) 1513 { 1514 cvmx_debug_register_t debug_reg; 1515 debug_reg.u64 = context->cop0.debug; 1516 cvmx_debug_printf("Starting to proxy\n"); 1517 comms_changed = cvmx_debug_perform_proxy(&debug_reg, context); 1518 context->cop0.debug = debug_reg.u64; 1519 } 1520 else 1521 { 1522 cvmx_debug_printf("Starting to wait for remote host\n"); 1523 cvmx_debug_comms[cvmx_debug_globals->comm_type]->wait_for_resume(context, cvmx_debug_get_state()); 1524 } 1525 } while (comms_changed); 1526 1527 cvmx_debug_clear_status(context); 1528 1529 cvmx_debug_restore_core_context(context); 1530 cvmx_debug_printf("Exiting debug exception handler\n"); 1531} 1532 1533void cvmx_debug_trigger_exception(void) 1534{ 1535 /* Set CVMX_CIU_DINT to enter debug exception handler. */ 1536 cvmx_write_csr (CVMX_CIU_DINT, 1u << cvmx_get_core_num ()); 1537 /* Perform an immediate read after every write to an RSL register to force 1538 the write to complete. It doesn't matter what RSL read we do, so we 1539 choose CVMX_MIO_BOOT_BIST_STAT because it is fast and harmless */ 1540 cvmx_read_csr (CVMX_MIO_BOOT_BIST_STAT); 1541} 1542 1543/** 1544 * Inform debugger about the end of the program. This is 1545 * called from crt0 after all the C cleanup code finishes. 1546 * Our current stack is the C one, not the debug exception 1547 * stack. */ 1548void cvmx_debug_finish(void) 1549{ 1550 unsigned coreid = cvmx_get_core_num(); 1551 cvmx_debug_state_t state; 1552 1553 if (!cvmx_debug_globals) return; 1554 cvmx_debug_printf ("Debug _exit reached!, core %d, cvmx_debug_globals = %p\n", coreid, cvmx_debug_globals); 1555 1556#ifndef CVMX_BUILD_FOR_LINUX_KERNEL 1557 fflush (stdout); 1558 fflush (stderr); 1559#endif 1560 1561 cvmx_spinlock_lock(&cvmx_debug_globals->lock); 1562 state = cvmx_debug_get_state(); 1563 state.known_cores ^= (1u << coreid); 1564 state.core_finished |= (1u <<coreid); 1565 cvmx_debug_update_state(state); 1566 1567 /* Tell the user the core has finished. */ 1568 if (state.ever_been_in_debug) 1569 cvmx_debug_putcorepacket("finished.", coreid); 1570 1571 /* Notify the debugger if all cores have completed the program */ 1572 if ((cvmx_debug_core_mask () & state.core_finished) == cvmx_debug_core_mask ()) 1573 { 1574 cvmx_debug_printf("All cores done!\n"); 1575 if (state.ever_been_in_debug) 1576 cvmx_debug_putpacket_noformat("D0"); 1577 } 1578 if (state.focus_core == coreid && state.known_cores != 0) 1579 { 1580 /* Loop through cores looking for someone to handle interrupts. 1581 Since we already check that known_cores is non zero, this 1582 should always find a core */ 1583 unsigned newcore; 1584 for (newcore = 0; newcore < CVMX_MAX_CORES; newcore++) 1585 { 1586 if (state.known_cores & (1u<<newcore)) 1587 { 1588 cvmx_debug_printf("Routing uart interrupts to Core #%u.\n", newcore); 1589 cvmx_debug_set_focus_core(&state, newcore); 1590 cvmx_debug_update_state(state); 1591 break; 1592 } 1593 } 1594 } 1595 cvmx_spinlock_unlock(&cvmx_debug_globals->lock); 1596 1597 /* If we ever been in the debug, report to it that we have exited the core. */ 1598 if (state.ever_been_in_debug) 1599 cvmx_debug_trigger_exception(); 1600} 1601