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