cvmx-debug-handler.S revision 232812
1215976Sjmallett/***********************license start*************** 2232812Sjmallett * Copyright (c) 2003-2010 Cavium Inc. (support@cavium.com). All rights 3215976Sjmallett * reserved. 4215976Sjmallett * 5215976Sjmallett * 6215976Sjmallett * Redistribution and use in source and binary forms, with or without 7215976Sjmallett * modification, are permitted provided that the following conditions are 8215976Sjmallett * met: 9215976Sjmallett * 10215976Sjmallett * * Redistributions of source code must retain the above copyright 11215976Sjmallett * notice, this list of conditions and the following disclaimer. 12215976Sjmallett * 13215976Sjmallett * * Redistributions in binary form must reproduce the above 14215976Sjmallett * copyright notice, this list of conditions and the following 15215976Sjmallett * disclaimer in the documentation and/or other materials provided 16215976Sjmallett * with the distribution. 17215976Sjmallett 18232812Sjmallett * * Neither the name of Cavium Inc. nor the names of 19215976Sjmallett * its contributors may be used to endorse or promote products 20215976Sjmallett * derived from this software without specific prior written 21215976Sjmallett * permission. 22215976Sjmallett 23215976Sjmallett * This Software, including technical data, may be subject to U.S. export control 24215976Sjmallett * laws, including the U.S. Export Administration Act and its associated 25215976Sjmallett * regulations, and may be subject to export or import regulations in other 26215976Sjmallett * countries. 27215976Sjmallett 28215976Sjmallett * TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" 29232812Sjmallett * AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR 30215976Sjmallett * WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO 31215976Sjmallett * THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR 32215976Sjmallett * DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM 33215976Sjmallett * SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE, 34215976Sjmallett * MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF 35215976Sjmallett * VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 36215976Sjmallett * CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR 37215976Sjmallett * PERFORMANCE OF THE SOFTWARE LIES WITH YOU. 38215976Sjmallett ***********************license end**************************************/ 39215976Sjmallett 40215976Sjmallett#undef __ASSEMBLY__ 41215976Sjmallett#define __ASSEMBLY__ 42215976Sjmallett 43215976Sjmallett#ifdef __linux__ 44215976Sjmallett#include <asm/asm.h> 45215976Sjmallett#include <asm/regdef.h> 46215976Sjmallett#else 47215976Sjmallett#include <machine/asm.h> 48215976Sjmallett#include <machine/regdef.h> 49215976Sjmallett#endif 50215976Sjmallett 51215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 52215976Sjmallett#include <asm/octeon/cvmx-asm.h> 53215976Sjmallett#include <asm/octeon/octeon-boot-info.h> 54215976Sjmallett#else 55232812Sjmallett 56215976Sjmallett#include "cvmx-asm.h" 57215976Sjmallett 58232812Sjmallett#ifndef _OCTEON_TOOLCHAIN_RUNTIME 59232812Sjmallett#include <octeon_mem_map.h> 60215976Sjmallett#else 61232812Sjmallett#include "cvmx-platform.h" 62215976Sjmallett#include "octeon-boot-info.h" 63215976Sjmallett#endif 64215976Sjmallett 65215976Sjmallett#endif 66215976Sjmallett 67215976Sjmallett/* The registers saving/restoring is split into two because k0 is stored in the COP0_DESAVE register. */ 68215976Sjmallett#define REGS0 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25 69215976Sjmallett#define REGS1 27,28,29,30,31 70215976Sjmallett 71215976Sjmallett#define SAVE_REGISTER(reg) \ 72215976Sjmallett sd reg, 0(k0); \ 73215976Sjmallett addi k0, 8 74215976Sjmallett 75215976Sjmallett#define RESTORE_REGISTER(reg) \ 76215976Sjmallett ld reg, -8(k0); \ 77215976Sjmallett addi k0, -8 78215976Sjmallett 79215976Sjmallett#define SAVE_COP0(reg) \ 80215976Sjmallett dmfc0 k1,reg; \ 81215976Sjmallett sd k1, 0(k0); \ 82215976Sjmallett addi k0, 8 83215976Sjmallett 84215976Sjmallett#define RESTORE_COP0(reg) \ 85215976Sjmallett ld k1, -8(k0); \ 86215976Sjmallett addi k0, -8; \ 87215976Sjmallett dmtc0 k1,reg 88215976Sjmallett 89215976Sjmallett#define SAVE_ADDRESS(addr) \ 90215976Sjmallett dli k1, addr; \ 91215976Sjmallett ld k1, 0(k1); \ 92215976Sjmallett sd k1, 0(k0); \ 93215976Sjmallett addi k0, 8 94215976Sjmallett 95215976Sjmallett#define RESTORE_ADDRESS(addr) \ 96215976Sjmallett dli t0, addr; \ 97215976Sjmallett ld k1, -8(k0); \ 98215976Sjmallett sd k1, 0(t0); \ 99215976Sjmallett addi k0, -8 100215976Sjmallett 101232812Sjmallett#define REG_SAVE_BASE_DIV_8 (BOOTLOADER_DEBUG_REG_SAVE_BASE >> 3) 102215976Sjmallett 103215976Sjmallett 104215976Sjmallett#define HW_INSTRUCTION_BREAKPOINT_STATUS (0xFFFFFFFFFF301000) 105215976Sjmallett#define HW_INSTRUCTION_BREAKPOINT_ADDRESS(num) (0xFFFFFFFFFF301100 + 0x100 * (num)) 106215976Sjmallett#define HW_INSTRUCTION_BREAKPOINT_ADDRESS_MASK(num) (0xFFFFFFFFFF301108 + 0x100 * (num)) 107215976Sjmallett#define HW_INSTRUCTION_BREAKPOINT_ASID(num) (0xFFFFFFFFFF301110 + 0x100 * (num)) 108215976Sjmallett#define HW_INSTRUCTION_BREAKPOINT_CONTROL(num) (0xFFFFFFFFFF301118 + 0x100 * (num)) 109215976Sjmallett 110215976Sjmallett#define HW_DATA_BREAKPOINT_STATUS (0xFFFFFFFFFF302000) 111215976Sjmallett#define HW_DATA_BREAKPOINT_ADDRESS(num) (0xFFFFFFFFFF302100 + 0x100 * (num)) 112215976Sjmallett#define HW_DATA_BREAKPOINT_ADDRESS_MASK(num) (0xFFFFFFFFFF302108 + 0x100 * (num)) 113215976Sjmallett#define HW_DATA_BREAKPOINT_ASID(num) (0xFFFFFFFFFF302110 + 0x100 * (num)) 114215976Sjmallett#define HW_DATA_BREAKPOINT_CONTROL(num) (0xFFFFFFFFFF302118 + 0x100 * (num)) 115215976Sjmallett 116215976Sjmallett 117215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL 118215976Sjmallett#define loadaddr(reg, addr, shift) \ 119215976Sjmallett dla reg, addr##_all; \ 120215976Sjmallett mfc0 $1, $15, 1; \ 121215976Sjmallett andi $1, 0xff; \ 122215976Sjmallett sll $1, shift; \ 123215976Sjmallett add reg, reg, $1 124215976Sjmallett#else 125215976Sjmallett#define loadaddr(reg, addr, shift) \ 126215976Sjmallett dla reg, addr 127215976Sjmallett#endif 128215976Sjmallett 129215976Sjmallett 130215976Sjmallett .set noreorder 131215976Sjmallett .set noat 132215976Sjmallett 133215976Sjmallett .text 134215976Sjmallett 135215976Sjmallett// Detect debug-mode exception, save all registers, create a stack and then 136215976Sjmallett// call the stage3 C function. 137215976Sjmallett 138215976Sjmallett .ent __cvmx_debug_handler_stage2 139215976Sjmallett .globl __cvmx_debug_handler_stage2 140215976Sjmallett__cvmx_debug_handler_stage2: 141215976Sjmallett // Save off k0 in COP0_DESAVE 142215976Sjmallett dmtc0 k0, COP0_DESAVE 143215976Sjmallett 144215976Sjmallett // Use reserved space in kseg0 to save off some temp regs 145215976Sjmallett mfc0 k0, $15, 1 // read exception base reg. 146215976Sjmallett andi k0, 0xff // mask off core ID 147215976Sjmallett sll k0, 12 // multiply by 4096 (512 dwords) DEBUG_NUMREGS 148215976Sjmallett 149232812Sjmallett addiu k0, REG_SAVE_BASE_DIV_8 150232812Sjmallett addiu k0, REG_SAVE_BASE_DIV_8 151232812Sjmallett addiu k0, REG_SAVE_BASE_DIV_8 152232812Sjmallett addiu k0, REG_SAVE_BASE_DIV_8 153232812Sjmallett addiu k0, REG_SAVE_BASE_DIV_8 154232812Sjmallett addiu k0, REG_SAVE_BASE_DIV_8 155232812Sjmallett addiu k0, REG_SAVE_BASE_DIV_8 156232812Sjmallett addiu k0, REG_SAVE_BASE_DIV_8 157215976Sjmallett // add base offset - after exeption vectors for all cores 158215976Sjmallett 159215976Sjmallett rotr k0, k0, 31 // set bit 31 for kseg0 access 160215976Sjmallett addi k0, 1 161215976Sjmallett rotr k0, k0, 1 162215976Sjmallett 163215976Sjmallett // save off k1 and at ($1) off to the bootloader reg save area 164215976Sjmallett // at is used by dla 165215976Sjmallett sd $1, 8(k0) // save at for temp usage 166215976Sjmallett sd k1, 216(k0) // save k1 for temp usage 167215976Sjmallett 168215976Sjmallett 169215976Sjmallett // Detect debug-mode exception. 170215976Sjmallett // If COP0_MULTICOREDEBUG[DExecC] is set, 171215976Sjmallett dmfc0 k1, COP0_MULTICOREDEBUG 172215976Sjmallett bbit0 k1, 16, noexc 173215976Sjmallett nop 174215976Sjmallett 175215976Sjmallett // COP0_DEBUG[DINT,DIB,DDBS,DBp,DSS] are not set and 176215976Sjmallett dmfc0 k1, COP0_DEBUG 177215976Sjmallett andi k1, 0x3f 178215976Sjmallett bnez k1, noexc 179215976Sjmallett nop 180215976Sjmallett 181215976Sjmallett // COP0_DEBUG[DExecC] is set. 182215976Sjmallett dmfc0 k1, COP0_DEBUG 183215976Sjmallett dext k1,k1,10,5 184215976Sjmallett beqz k1,noexc 185215976Sjmallett nop 186215976Sjmallett 187215976Sjmallett // We don't handle debug-mode exceptions in delay-slots so DEBUG[DBD] 188215976Sjmallett // should not be set. If yes spin forever. 189215976Sjmallett dmfc0 k1, COP0_DEBUG 190215976Sjmallett1: 191215976Sjmallett bbit1 k1, 31, 1b 192215976Sjmallett nop 193215976Sjmallett 194215976Sjmallett // It's a debug-mode exception. Flag the occurence. Also if it's 195215976Sjmallett // expected just ignore it but returning the subsequent instruction 196215976Sjmallett // after the fault. 197215976Sjmallett 198215976Sjmallett loadaddr (k1, __cvmx_debug_mode_exception_occured, 3) 199215976Sjmallett sd k1, 0(k1) 200215976Sjmallett 201215976Sjmallett loadaddr (k1, __cvmx_debug_mode_exception_ignore, 3) 202215976Sjmallett ld k1, 0(k1) 203215976Sjmallett beqz k1, noexc 204215976Sjmallett nop 205215976Sjmallett 206215976Sjmallett // Restore k1 and at from the bootloader reg save area 207215976Sjmallett ld $1, 8(k0) // save at for temp usage 208215976Sjmallett ld k1, 216(k0) // save k1 for temp usage 209215976Sjmallett 210215976Sjmallett dmfc0 k0, COP0_DEPC 211215976Sjmallett // Skip the faulting instruction. 212215976Sjmallett daddiu k0, 4 213215976Sjmallett jr k0 214215976Sjmallett dmfc0 k0, COP0_DESAVE 215215976Sjmallett 216215976Sjmallettnoexc: 217215976Sjmallett 218215976Sjmallett loadaddr (k1, __cvmx_debug_save_regs_area, 8) 219215976Sjmallett 220215976Sjmallett // Restore at 221215976Sjmallett ld $1, 8(k0) // restore at for temp usage 222215976Sjmallett 223215976Sjmallett .irp n, REGS0 224215976Sjmallett sd $\n, 0(k1) 225215976Sjmallett addiu k1, 8 226215976Sjmallett .endr 227215976Sjmallett 228215976Sjmallett move $25, k1 229215976Sjmallett ld k1, 216(k0) // restore k1 for temp usage 230215976Sjmallett move k0, $25 231215976Sjmallett 232215976Sjmallett // Store out k0, we can use $25 here because we just saved it 233215976Sjmallett dmfc0 $25, COP0_DESAVE 234215976Sjmallett sd $25, 0(k0) 235215976Sjmallett addiu k0, 8 236215976Sjmallett 237215976Sjmallett .irp n, REGS1 238215976Sjmallett sd $\n, 0(k0) 239215976Sjmallett addiu k0, 8 240215976Sjmallett .endr 241215976Sjmallett 242215976Sjmallett loadaddr(sp, __cvmx_debug_stack_top, 3) 243215976Sjmallett // Load the stack pointer as a pointer size. 244215976Sjmallett#ifdef _ABIN32 245215976Sjmallett lw sp,0(sp) 246215976Sjmallett#else 247215976Sjmallett ld sp,0(sp) 248215976Sjmallett#endif 249232812Sjmallett mflo $4 250232812Sjmallett mfhi $5 251215976Sjmallett jal __cvmx_debug_handler_stage3 252215976Sjmallett nop 253215976Sjmallett 254215976Sjmallett loadaddr(k0, __cvmx_debug_save_regs_area, 8) 255215976Sjmallett 256215976Sjmallett .irp n, REGS0 257215976Sjmallett ld $\n, 0(k0) 258215976Sjmallett addiu k0, 8 259215976Sjmallett .endr 260215976Sjmallett 261215976Sjmallett // Restore k0 to COP0_DESAVE via k1 262215976Sjmallett ld k1, 0(k0) 263215976Sjmallett addiu k0, 8 264215976Sjmallett dmtc0 k1, COP0_DESAVE 265215976Sjmallett 266215976Sjmallett .irp n, REGS1 267215976Sjmallett ld $\n, 0(k0) 268215976Sjmallett addiu k0, 8 269215976Sjmallett .endr 270215976Sjmallett 271215976Sjmallett dmfc0 k0, COP0_DESAVE 272215976Sjmallett // Flush the icache; by adding and removing SW breakpoints we change 273215976Sjmallett // the instruction stream. 274215976Sjmallett synci 0($0) 275215976Sjmallett deret 276215976Sjmallett nop 277215976Sjmallett 278215976Sjmallett .end __cvmx_debug_handler_stage2 279