272 lines
7.3 KiB
ArmAsm
272 lines
7.3 KiB
ArmAsm
|
/***********************license start***************
|
||
|
* Copyright (c) 2003-2010 Cavium Networks (support@cavium.com). All rights
|
||
|
* reserved.
|
||
|
*
|
||
|
*
|
||
|
* Redistribution and use in source and binary forms, with or without
|
||
|
* modification, are permitted provided that the following conditions are
|
||
|
* met:
|
||
|
*
|
||
|
* * Redistributions of source code must retain the above copyright
|
||
|
* notice, this list of conditions and the following disclaimer.
|
||
|
*
|
||
|
* * Redistributions in binary form must reproduce the above
|
||
|
* copyright notice, this list of conditions and the following
|
||
|
* disclaimer in the documentation and/or other materials provided
|
||
|
* with the distribution.
|
||
|
|
||
|
* * Neither the name of Cavium Networks nor the names of
|
||
|
* its contributors may be used to endorse or promote products
|
||
|
* derived from this software without specific prior written
|
||
|
* permission.
|
||
|
|
||
|
* This Software, including technical data, may be subject to U.S. export control
|
||
|
* laws, including the U.S. Export Administration Act and its associated
|
||
|
* regulations, and may be subject to export or import regulations in other
|
||
|
* countries.
|
||
|
|
||
|
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
|
||
|
* AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
|
||
|
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
|
||
|
* THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
|
||
|
* DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
|
||
|
* SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
|
||
|
* MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
|
||
|
* VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
|
||
|
* CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
|
||
|
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||
|
***********************license end**************************************/
|
||
|
|
||
|
#undef __ASSEMBLY__
|
||
|
#define __ASSEMBLY__
|
||
|
|
||
|
#ifdef __linux__
|
||
|
#include <asm/asm.h>
|
||
|
#include <asm/regdef.h>
|
||
|
#else
|
||
|
#include <machine/asm.h>
|
||
|
#include <machine/regdef.h>
|
||
|
#endif
|
||
|
|
||
|
#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
|
||
|
#include <asm/octeon/cvmx-asm.h>
|
||
|
#include <asm/octeon/octeon-boot-info.h>
|
||
|
#else
|
||
|
#include "executive-config.h"
|
||
|
#include "cvmx-asm.h"
|
||
|
|
||
|
#ifndef __OCTEON_NEWLIB__
|
||
|
#include "../../bootloader/u-boot/include/octeon_mem_map.h"
|
||
|
#else
|
||
|
#include "octeon-boot-info.h"
|
||
|
#endif
|
||
|
|
||
|
#endif
|
||
|
|
||
|
/* The registers saving/restoring is split into two because k0 is stored in the COP0_DESAVE register. */
|
||
|
#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
|
||
|
#define REGS1 27,28,29,30,31
|
||
|
|
||
|
#define SAVE_REGISTER(reg) \
|
||
|
sd reg, 0(k0); \
|
||
|
addi k0, 8
|
||
|
|
||
|
#define RESTORE_REGISTER(reg) \
|
||
|
ld reg, -8(k0); \
|
||
|
addi k0, -8
|
||
|
|
||
|
#define SAVE_COP0(reg) \
|
||
|
dmfc0 k1,reg; \
|
||
|
sd k1, 0(k0); \
|
||
|
addi k0, 8
|
||
|
|
||
|
#define RESTORE_COP0(reg) \
|
||
|
ld k1, -8(k0); \
|
||
|
addi k0, -8; \
|
||
|
dmtc0 k1,reg
|
||
|
|
||
|
#define SAVE_ADDRESS(addr) \
|
||
|
dli k1, addr; \
|
||
|
ld k1, 0(k1); \
|
||
|
sd k1, 0(k0); \
|
||
|
addi k0, 8
|
||
|
|
||
|
#define RESTORE_ADDRESS(addr) \
|
||
|
dli t0, addr; \
|
||
|
ld k1, -8(k0); \
|
||
|
sd k1, 0(t0); \
|
||
|
addi k0, -8
|
||
|
|
||
|
#define REG_SAVE_BASE_DIV_4 (BOOTLOADER_DEBUG_REG_SAVE_BASE >> 2)
|
||
|
|
||
|
|
||
|
#define HW_INSTRUCTION_BREAKPOINT_STATUS (0xFFFFFFFFFF301000)
|
||
|
#define HW_INSTRUCTION_BREAKPOINT_ADDRESS(num) (0xFFFFFFFFFF301100 + 0x100 * (num))
|
||
|
#define HW_INSTRUCTION_BREAKPOINT_ADDRESS_MASK(num) (0xFFFFFFFFFF301108 + 0x100 * (num))
|
||
|
#define HW_INSTRUCTION_BREAKPOINT_ASID(num) (0xFFFFFFFFFF301110 + 0x100 * (num))
|
||
|
#define HW_INSTRUCTION_BREAKPOINT_CONTROL(num) (0xFFFFFFFFFF301118 + 0x100 * (num))
|
||
|
|
||
|
#define HW_DATA_BREAKPOINT_STATUS (0xFFFFFFFFFF302000)
|
||
|
#define HW_DATA_BREAKPOINT_ADDRESS(num) (0xFFFFFFFFFF302100 + 0x100 * (num))
|
||
|
#define HW_DATA_BREAKPOINT_ADDRESS_MASK(num) (0xFFFFFFFFFF302108 + 0x100 * (num))
|
||
|
#define HW_DATA_BREAKPOINT_ASID(num) (0xFFFFFFFFFF302110 + 0x100 * (num))
|
||
|
#define HW_DATA_BREAKPOINT_CONTROL(num) (0xFFFFFFFFFF302118 + 0x100 * (num))
|
||
|
|
||
|
|
||
|
#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
|
||
|
#define loadaddr(reg, addr, shift) \
|
||
|
dla reg, addr##_all; \
|
||
|
mfc0 $1, $15, 1; \
|
||
|
andi $1, 0xff; \
|
||
|
sll $1, shift; \
|
||
|
add reg, reg, $1
|
||
|
#else
|
||
|
#define loadaddr(reg, addr, shift) \
|
||
|
dla reg, addr
|
||
|
#endif
|
||
|
|
||
|
|
||
|
.set noreorder
|
||
|
.set noat
|
||
|
|
||
|
.text
|
||
|
|
||
|
// Detect debug-mode exception, save all registers, create a stack and then
|
||
|
// call the stage3 C function.
|
||
|
|
||
|
.ent __cvmx_debug_handler_stage2
|
||
|
.globl __cvmx_debug_handler_stage2
|
||
|
__cvmx_debug_handler_stage2:
|
||
|
// Save off k0 in COP0_DESAVE
|
||
|
dmtc0 k0, COP0_DESAVE
|
||
|
|
||
|
// Use reserved space in kseg0 to save off some temp regs
|
||
|
mfc0 k0, $15, 1 // read exception base reg.
|
||
|
andi k0, 0xff // mask off core ID
|
||
|
sll k0, 12 // multiply by 4096 (512 dwords) DEBUG_NUMREGS
|
||
|
|
||
|
addiu k0, REG_SAVE_BASE_DIV_4
|
||
|
addiu k0, REG_SAVE_BASE_DIV_4
|
||
|
addiu k0, REG_SAVE_BASE_DIV_4
|
||
|
addiu k0, REG_SAVE_BASE_DIV_4
|
||
|
// add base offset - after exeption vectors for all cores
|
||
|
|
||
|
rotr k0, k0, 31 // set bit 31 for kseg0 access
|
||
|
addi k0, 1
|
||
|
rotr k0, k0, 1
|
||
|
|
||
|
// save off k1 and at ($1) off to the bootloader reg save area
|
||
|
// at is used by dla
|
||
|
sd $1, 8(k0) // save at for temp usage
|
||
|
sd k1, 216(k0) // save k1 for temp usage
|
||
|
|
||
|
|
||
|
// Detect debug-mode exception.
|
||
|
// If COP0_MULTICOREDEBUG[DExecC] is set,
|
||
|
dmfc0 k1, COP0_MULTICOREDEBUG
|
||
|
bbit0 k1, 16, noexc
|
||
|
nop
|
||
|
|
||
|
// COP0_DEBUG[DINT,DIB,DDBS,DBp,DSS] are not set and
|
||
|
dmfc0 k1, COP0_DEBUG
|
||
|
andi k1, 0x3f
|
||
|
bnez k1, noexc
|
||
|
nop
|
||
|
|
||
|
// COP0_DEBUG[DExecC] is set.
|
||
|
dmfc0 k1, COP0_DEBUG
|
||
|
dext k1,k1,10,5
|
||
|
beqz k1,noexc
|
||
|
nop
|
||
|
|
||
|
// We don't handle debug-mode exceptions in delay-slots so DEBUG[DBD]
|
||
|
// should not be set. If yes spin forever.
|
||
|
dmfc0 k1, COP0_DEBUG
|
||
|
1:
|
||
|
bbit1 k1, 31, 1b
|
||
|
nop
|
||
|
|
||
|
// It's a debug-mode exception. Flag the occurence. Also if it's
|
||
|
// expected just ignore it but returning the subsequent instruction
|
||
|
// after the fault.
|
||
|
|
||
|
loadaddr (k1, __cvmx_debug_mode_exception_occured, 3)
|
||
|
sd k1, 0(k1)
|
||
|
|
||
|
loadaddr (k1, __cvmx_debug_mode_exception_ignore, 3)
|
||
|
ld k1, 0(k1)
|
||
|
beqz k1, noexc
|
||
|
nop
|
||
|
|
||
|
// Restore k1 and at from the bootloader reg save area
|
||
|
ld $1, 8(k0) // save at for temp usage
|
||
|
ld k1, 216(k0) // save k1 for temp usage
|
||
|
|
||
|
dmfc0 k0, COP0_DEPC
|
||
|
// Skip the faulting instruction.
|
||
|
daddiu k0, 4
|
||
|
jr k0
|
||
|
dmfc0 k0, COP0_DESAVE
|
||
|
|
||
|
noexc:
|
||
|
|
||
|
loadaddr (k1, __cvmx_debug_save_regs_area, 8)
|
||
|
|
||
|
// Restore at
|
||
|
ld $1, 8(k0) // restore at for temp usage
|
||
|
|
||
|
.irp n, REGS0
|
||
|
sd $\n, 0(k1)
|
||
|
addiu k1, 8
|
||
|
.endr
|
||
|
|
||
|
move $25, k1
|
||
|
ld k1, 216(k0) // restore k1 for temp usage
|
||
|
move k0, $25
|
||
|
|
||
|
// Store out k0, we can use $25 here because we just saved it
|
||
|
dmfc0 $25, COP0_DESAVE
|
||
|
sd $25, 0(k0)
|
||
|
addiu k0, 8
|
||
|
|
||
|
.irp n, REGS1
|
||
|
sd $\n, 0(k0)
|
||
|
addiu k0, 8
|
||
|
.endr
|
||
|
|
||
|
loadaddr(sp, __cvmx_debug_stack_top, 3)
|
||
|
// Load the stack pointer as a pointer size.
|
||
|
#ifdef _ABIN32
|
||
|
lw sp,0(sp)
|
||
|
#else
|
||
|
ld sp,0(sp)
|
||
|
#endif
|
||
|
jal __cvmx_debug_handler_stage3
|
||
|
nop
|
||
|
|
||
|
loadaddr(k0, __cvmx_debug_save_regs_area, 8)
|
||
|
|
||
|
.irp n, REGS0
|
||
|
ld $\n, 0(k0)
|
||
|
addiu k0, 8
|
||
|
.endr
|
||
|
|
||
|
// Restore k0 to COP0_DESAVE via k1
|
||
|
ld k1, 0(k0)
|
||
|
addiu k0, 8
|
||
|
dmtc0 k1, COP0_DESAVE
|
||
|
|
||
|
.irp n, REGS1
|
||
|
ld $\n, 0(k0)
|
||
|
addiu k0, 8
|
||
|
.endr
|
||
|
|
||
|
dmfc0 k0, COP0_DESAVE
|
||
|
// Flush the icache; by adding and removing SW breakpoints we change
|
||
|
// the instruction stream.
|
||
|
synci 0($0)
|
||
|
deret
|
||
|
nop
|
||
|
|
||
|
.end __cvmx_debug_handler_stage2
|