cvmx-debug-handler.S revision 215976
1215976Sjmallett/***********************license start***************
2215976Sjmallett * Copyright (c) 2003-2010  Cavium Networks (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
18215976Sjmallett *   * Neither the name of Cavium Networks 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"
29215976Sjmallett * AND WITH ALL FAULTS AND CAVIUM  NETWORKS 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
55215976Sjmallett#include "executive-config.h"
56215976Sjmallett#include "cvmx-asm.h"
57215976Sjmallett
58215976Sjmallett#ifndef __OCTEON_NEWLIB__
59215976Sjmallett#include "../../bootloader/u-boot/include/octeon_mem_map.h"
60215976Sjmallett#else
61215976Sjmallett#include "octeon-boot-info.h"
62215976Sjmallett#endif
63215976Sjmallett
64215976Sjmallett#endif
65215976Sjmallett
66215976Sjmallett/* The registers saving/restoring is split into two because k0 is stored in the COP0_DESAVE register.  */
67215976Sjmallett#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
68215976Sjmallett#define REGS1 27,28,29,30,31
69215976Sjmallett
70215976Sjmallett#define SAVE_REGISTER(reg)	\
71215976Sjmallett	sd reg, 0(k0);		\
72215976Sjmallett	addi k0, 8
73215976Sjmallett
74215976Sjmallett#define RESTORE_REGISTER(reg)	\
75215976Sjmallett	ld reg, -8(k0);		\
76215976Sjmallett	addi k0, -8
77215976Sjmallett
78215976Sjmallett#define SAVE_COP0(reg)		\
79215976Sjmallett	dmfc0 k1,reg;		\
80215976Sjmallett	sd k1, 0(k0);		\
81215976Sjmallett	addi k0, 8
82215976Sjmallett
83215976Sjmallett#define RESTORE_COP0(reg)	\
84215976Sjmallett	ld k1, -8(k0);		\
85215976Sjmallett	addi k0, -8;		\
86215976Sjmallett	dmtc0 k1,reg
87215976Sjmallett
88215976Sjmallett#define SAVE_ADDRESS(addr)	\
89215976Sjmallett	dli k1, addr;		\
90215976Sjmallett	ld k1, 0(k1);		\
91215976Sjmallett	sd k1, 0(k0);		\
92215976Sjmallett	addi k0, 8
93215976Sjmallett
94215976Sjmallett#define RESTORE_ADDRESS(addr)	\
95215976Sjmallett	dli t0, addr;		\
96215976Sjmallett	ld k1, -8(k0);		\
97215976Sjmallett	sd k1, 0(t0);		\
98215976Sjmallett	addi k0, -8
99215976Sjmallett
100215976Sjmallett#define REG_SAVE_BASE_DIV_4  (BOOTLOADER_DEBUG_REG_SAVE_BASE >> 2)
101215976Sjmallett
102215976Sjmallett
103215976Sjmallett#define HW_INSTRUCTION_BREAKPOINT_STATUS            (0xFFFFFFFFFF301000)
104215976Sjmallett#define HW_INSTRUCTION_BREAKPOINT_ADDRESS(num)      (0xFFFFFFFFFF301100 + 0x100 * (num))
105215976Sjmallett#define HW_INSTRUCTION_BREAKPOINT_ADDRESS_MASK(num) (0xFFFFFFFFFF301108 + 0x100 * (num))
106215976Sjmallett#define HW_INSTRUCTION_BREAKPOINT_ASID(num)         (0xFFFFFFFFFF301110 + 0x100 * (num))
107215976Sjmallett#define HW_INSTRUCTION_BREAKPOINT_CONTROL(num)      (0xFFFFFFFFFF301118 + 0x100 * (num))
108215976Sjmallett
109215976Sjmallett#define HW_DATA_BREAKPOINT_STATUS                   (0xFFFFFFFFFF302000)
110215976Sjmallett#define HW_DATA_BREAKPOINT_ADDRESS(num)             (0xFFFFFFFFFF302100 + 0x100 * (num))
111215976Sjmallett#define HW_DATA_BREAKPOINT_ADDRESS_MASK(num)        (0xFFFFFFFFFF302108 + 0x100 * (num))
112215976Sjmallett#define HW_DATA_BREAKPOINT_ASID(num)                (0xFFFFFFFFFF302110 + 0x100 * (num))
113215976Sjmallett#define HW_DATA_BREAKPOINT_CONTROL(num)             (0xFFFFFFFFFF302118 + 0x100 * (num))
114215976Sjmallett
115215976Sjmallett
116215976Sjmallett#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
117215976Sjmallett#define loadaddr(reg, addr, shift) \
118215976Sjmallett	dla	reg, addr##_all; \
119215976Sjmallett        mfc0    $1, $15, 1; \
120215976Sjmallett        andi    $1, 0xff; \
121215976Sjmallett        sll     $1, shift; \
122215976Sjmallett	add	reg, reg, $1
123215976Sjmallett#else
124215976Sjmallett#define loadaddr(reg, addr, shift) \
125215976Sjmallett	dla	reg, addr
126215976Sjmallett#endif
127215976Sjmallett
128215976Sjmallett
129215976Sjmallett	.set	noreorder
130215976Sjmallett	.set	noat
131215976Sjmallett
132215976Sjmallett	.text
133215976Sjmallett
134215976Sjmallett// Detect debug-mode exception, save all registers, create a stack and then
135215976Sjmallett// call the stage3 C function.
136215976Sjmallett
137215976Sjmallett	.ent	__cvmx_debug_handler_stage2
138215976Sjmallett	.globl	__cvmx_debug_handler_stage2
139215976Sjmallett__cvmx_debug_handler_stage2:
140215976Sjmallett	// Save off k0 in COP0_DESAVE
141215976Sjmallett	dmtc0	k0, COP0_DESAVE
142215976Sjmallett
143215976Sjmallett	// Use reserved space in kseg0 to save off some temp regs
144215976Sjmallett        mfc0    k0, $15, 1  // read exception base reg.
145215976Sjmallett        andi    k0, 0xff    // mask off core ID
146215976Sjmallett        sll     k0, 12      // multiply by 4096 (512 dwords) DEBUG_NUMREGS
147215976Sjmallett
148215976Sjmallett        addiu   k0,  REG_SAVE_BASE_DIV_4
149215976Sjmallett        addiu   k0,  REG_SAVE_BASE_DIV_4
150215976Sjmallett        addiu   k0,  REG_SAVE_BASE_DIV_4
151215976Sjmallett        addiu   k0,  REG_SAVE_BASE_DIV_4
152215976Sjmallett		// add base offset - after exeption vectors for all cores
153215976Sjmallett
154215976Sjmallett        rotr    k0, k0, 31   // set bit 31 for kseg0 access
155215976Sjmallett        addi    k0, 1
156215976Sjmallett        rotr    k0, k0, 1
157215976Sjmallett
158215976Sjmallett	// save off k1 and at ($1) off to the bootloader reg save area
159215976Sjmallett	// at is used by dla
160215976Sjmallett	sd      $1, 8(k0)	// save at for temp usage
161215976Sjmallett	sd      k1, 216(k0)	// save k1 for temp usage
162215976Sjmallett
163215976Sjmallett
164215976Sjmallett	// Detect debug-mode exception.
165215976Sjmallett	// If COP0_MULTICOREDEBUG[DExecC] is set,
166215976Sjmallett	dmfc0	k1, COP0_MULTICOREDEBUG
167215976Sjmallett	bbit0	k1, 16, noexc
168215976Sjmallett	nop
169215976Sjmallett
170215976Sjmallett	// COP0_DEBUG[DINT,DIB,DDBS,DBp,DSS] are not set and
171215976Sjmallett	dmfc0	k1, COP0_DEBUG
172215976Sjmallett	andi	k1, 0x3f
173215976Sjmallett	bnez	k1, noexc
174215976Sjmallett	nop
175215976Sjmallett
176215976Sjmallett	// COP0_DEBUG[DExecC] is set.
177215976Sjmallett	dmfc0	k1, COP0_DEBUG
178215976Sjmallett	dext	k1,k1,10,5
179215976Sjmallett	beqz	k1,noexc
180215976Sjmallett	nop
181215976Sjmallett
182215976Sjmallett	// We don't handle debug-mode exceptions in delay-slots so DEBUG[DBD]
183215976Sjmallett	// should not be set.  If yes spin forever.
184215976Sjmallett	dmfc0	k1, COP0_DEBUG
185215976Sjmallett1:
186215976Sjmallett	bbit1	k1, 31, 1b
187215976Sjmallett	nop
188215976Sjmallett
189215976Sjmallett	// It's a debug-mode exception.  Flag the occurence.  Also if it's
190215976Sjmallett	// expected just ignore it but returning the subsequent instruction
191215976Sjmallett	// after the fault.
192215976Sjmallett
193215976Sjmallett	loadaddr (k1, __cvmx_debug_mode_exception_occured, 3)
194215976Sjmallett	sd	k1, 0(k1)
195215976Sjmallett
196215976Sjmallett	loadaddr (k1, __cvmx_debug_mode_exception_ignore, 3)
197215976Sjmallett	ld	k1, 0(k1)
198215976Sjmallett	beqz	k1, noexc
199215976Sjmallett	nop
200215976Sjmallett
201215976Sjmallett	// Restore k1 and at from the bootloader reg save area
202215976Sjmallett	ld      $1, 8(k0)	// save at for temp usage
203215976Sjmallett	ld      k1, 216(k0)	// save k1 for temp usage
204215976Sjmallett
205215976Sjmallett	dmfc0	k0, COP0_DEPC
206215976Sjmallett	// Skip the faulting instruction.
207215976Sjmallett	daddiu	k0, 4
208215976Sjmallett	jr	k0
209215976Sjmallett	dmfc0	k0, COP0_DESAVE
210215976Sjmallett
211215976Sjmallettnoexc:
212215976Sjmallett
213215976Sjmallett	loadaddr (k1, __cvmx_debug_save_regs_area, 8)
214215976Sjmallett
215215976Sjmallett	// Restore at
216215976Sjmallett	ld      $1, 8(k0)	// restore at for temp usage
217215976Sjmallett
218215976Sjmallett	.irp	n, REGS0
219215976Sjmallett	sd	$\n, 0(k1)
220215976Sjmallett	addiu	k1, 8
221215976Sjmallett	.endr
222215976Sjmallett
223215976Sjmallett	move	$25, k1
224215976Sjmallett	ld      k1, 216(k0)	// restore k1 for temp usage
225215976Sjmallett	move	k0, $25
226215976Sjmallett
227215976Sjmallett	// Store out k0, we can use $25 here because we just saved it
228215976Sjmallett	dmfc0	$25, COP0_DESAVE
229215976Sjmallett	sd	$25, 0(k0)
230215976Sjmallett	addiu	k0, 8
231215976Sjmallett
232215976Sjmallett	.irp	n, REGS1
233215976Sjmallett	sd	$\n, 0(k0)
234215976Sjmallett	addiu	k0, 8
235215976Sjmallett	.endr
236215976Sjmallett
237215976Sjmallett	loadaddr(sp, __cvmx_debug_stack_top, 3)
238215976Sjmallett	// Load the stack pointer as a pointer size.
239215976Sjmallett#ifdef _ABIN32
240215976Sjmallett	lw	sp,0(sp)
241215976Sjmallett#else
242215976Sjmallett	ld	sp,0(sp)
243215976Sjmallett#endif
244215976Sjmallett	jal	__cvmx_debug_handler_stage3
245215976Sjmallett	nop
246215976Sjmallett
247215976Sjmallett	loadaddr(k0, __cvmx_debug_save_regs_area, 8)
248215976Sjmallett
249215976Sjmallett	.irp	n, REGS0
250215976Sjmallett	ld	$\n, 0(k0)
251215976Sjmallett	addiu	k0, 8
252215976Sjmallett	.endr
253215976Sjmallett
254215976Sjmallett	// Restore k0 to COP0_DESAVE via k1
255215976Sjmallett	ld	k1, 0(k0)
256215976Sjmallett	addiu	k0, 8
257215976Sjmallett	dmtc0	k1, COP0_DESAVE
258215976Sjmallett
259215976Sjmallett	.irp	n, REGS1
260215976Sjmallett	ld	$\n, 0(k0)
261215976Sjmallett	addiu	k0, 8
262215976Sjmallett	.endr
263215976Sjmallett
264215976Sjmallett	dmfc0	k0, COP0_DESAVE
265215976Sjmallett	// Flush the icache; by adding and removing SW breakpoints we change
266215976Sjmallett	// the instruction stream.
267215976Sjmallett	synci 	0($0)
268215976Sjmallett	deret
269215976Sjmallett	nop
270215976Sjmallett
271215976Sjmallett	.end	__cvmx_debug_handler_stage2
272