1/***********************license start***************
2 * Copyright (c) 2003-2010  Cavium Networks (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 Networks 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  NETWORKS 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#undef __ASSEMBLY__
41#define __ASSEMBLY__
42
43#ifdef __linux__
44#include <asm/asm.h>
45#include <asm/regdef.h>
46#else
47#include <machine/asm.h>
48#include <machine/regdef.h>
49#endif
50
51#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
52#include <asm/octeon/cvmx-asm.h>
53#include <asm/octeon/octeon-boot-info.h>
54#else
55#include "executive-config.h"
56#include "cvmx-asm.h"
57
58#ifndef __OCTEON_NEWLIB__
59#include "../../bootloader/u-boot/include/octeon_mem_map.h"
60#else
61#include "octeon-boot-info.h"
62#endif
63
64#endif
65
66/* The registers saving/restoring is split into two because k0 is stored in the COP0_DESAVE register.  */
67#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
68#define REGS1 27,28,29,30,31
69
70#define SAVE_REGISTER(reg)	\
71	sd reg, 0(k0);		\
72	addi k0, 8
73
74#define RESTORE_REGISTER(reg)	\
75	ld reg, -8(k0);		\
76	addi k0, -8
77
78#define SAVE_COP0(reg)		\
79	dmfc0 k1,reg;		\
80	sd k1, 0(k0);		\
81	addi k0, 8
82
83#define RESTORE_COP0(reg)	\
84	ld k1, -8(k0);		\
85	addi k0, -8;		\
86	dmtc0 k1,reg
87
88#define SAVE_ADDRESS(addr)	\
89	dli k1, addr;		\
90	ld k1, 0(k1);		\
91	sd k1, 0(k0);		\
92	addi k0, 8
93
94#define RESTORE_ADDRESS(addr)	\
95	dli t0, addr;		\
96	ld k1, -8(k0);		\
97	sd k1, 0(t0);		\
98	addi k0, -8
99
100#define REG_SAVE_BASE_DIV_4  (BOOTLOADER_DEBUG_REG_SAVE_BASE >> 2)
101
102
103#define HW_INSTRUCTION_BREAKPOINT_STATUS            (0xFFFFFFFFFF301000)
104#define HW_INSTRUCTION_BREAKPOINT_ADDRESS(num)      (0xFFFFFFFFFF301100 + 0x100 * (num))
105#define HW_INSTRUCTION_BREAKPOINT_ADDRESS_MASK(num) (0xFFFFFFFFFF301108 + 0x100 * (num))
106#define HW_INSTRUCTION_BREAKPOINT_ASID(num)         (0xFFFFFFFFFF301110 + 0x100 * (num))
107#define HW_INSTRUCTION_BREAKPOINT_CONTROL(num)      (0xFFFFFFFFFF301118 + 0x100 * (num))
108
109#define HW_DATA_BREAKPOINT_STATUS                   (0xFFFFFFFFFF302000)
110#define HW_DATA_BREAKPOINT_ADDRESS(num)             (0xFFFFFFFFFF302100 + 0x100 * (num))
111#define HW_DATA_BREAKPOINT_ADDRESS_MASK(num)        (0xFFFFFFFFFF302108 + 0x100 * (num))
112#define HW_DATA_BREAKPOINT_ASID(num)                (0xFFFFFFFFFF302110 + 0x100 * (num))
113#define HW_DATA_BREAKPOINT_CONTROL(num)             (0xFFFFFFFFFF302118 + 0x100 * (num))
114
115
116#ifdef CVMX_BUILD_FOR_LINUX_KERNEL
117#define loadaddr(reg, addr, shift) \
118	dla	reg, addr##_all; \
119        mfc0    $1, $15, 1; \
120        andi    $1, 0xff; \
121        sll     $1, shift; \
122	add	reg, reg, $1
123#else
124#define loadaddr(reg, addr, shift) \
125	dla	reg, addr
126#endif
127
128
129	.set	noreorder
130	.set	noat
131
132	.text
133
134// Detect debug-mode exception, save all registers, create a stack and then
135// call the stage3 C function.
136
137	.ent	__cvmx_debug_handler_stage2
138	.globl	__cvmx_debug_handler_stage2
139__cvmx_debug_handler_stage2:
140	// Save off k0 in COP0_DESAVE
141	dmtc0	k0, COP0_DESAVE
142
143	// Use reserved space in kseg0 to save off some temp regs
144        mfc0    k0, $15, 1  // read exception base reg.
145        andi    k0, 0xff    // mask off core ID
146        sll     k0, 12      // multiply by 4096 (512 dwords) DEBUG_NUMREGS
147
148        addiu   k0,  REG_SAVE_BASE_DIV_4
149        addiu   k0,  REG_SAVE_BASE_DIV_4
150        addiu   k0,  REG_SAVE_BASE_DIV_4
151        addiu   k0,  REG_SAVE_BASE_DIV_4
152		// add base offset - after exeption vectors for all cores
153
154        rotr    k0, k0, 31   // set bit 31 for kseg0 access
155        addi    k0, 1
156        rotr    k0, k0, 1
157
158	// save off k1 and at ($1) off to the bootloader reg save area
159	// at is used by dla
160	sd      $1, 8(k0)	// save at for temp usage
161	sd      k1, 216(k0)	// save k1 for temp usage
162
163
164	// Detect debug-mode exception.
165	// If COP0_MULTICOREDEBUG[DExecC] is set,
166	dmfc0	k1, COP0_MULTICOREDEBUG
167	bbit0	k1, 16, noexc
168	nop
169
170	// COP0_DEBUG[DINT,DIB,DDBS,DBp,DSS] are not set and
171	dmfc0	k1, COP0_DEBUG
172	andi	k1, 0x3f
173	bnez	k1, noexc
174	nop
175
176	// COP0_DEBUG[DExecC] is set.
177	dmfc0	k1, COP0_DEBUG
178	dext	k1,k1,10,5
179	beqz	k1,noexc
180	nop
181
182	// We don't handle debug-mode exceptions in delay-slots so DEBUG[DBD]
183	// should not be set.  If yes spin forever.
184	dmfc0	k1, COP0_DEBUG
1851:
186	bbit1	k1, 31, 1b
187	nop
188
189	// It's a debug-mode exception.  Flag the occurence.  Also if it's
190	// expected just ignore it but returning the subsequent instruction
191	// after the fault.
192
193	loadaddr (k1, __cvmx_debug_mode_exception_occured, 3)
194	sd	k1, 0(k1)
195
196	loadaddr (k1, __cvmx_debug_mode_exception_ignore, 3)
197	ld	k1, 0(k1)
198	beqz	k1, noexc
199	nop
200
201	// Restore k1 and at from the bootloader reg save area
202	ld      $1, 8(k0)	// save at for temp usage
203	ld      k1, 216(k0)	// save k1 for temp usage
204
205	dmfc0	k0, COP0_DEPC
206	// Skip the faulting instruction.
207	daddiu	k0, 4
208	jr	k0
209	dmfc0	k0, COP0_DESAVE
210
211noexc:
212
213	loadaddr (k1, __cvmx_debug_save_regs_area, 8)
214
215	// Restore at
216	ld      $1, 8(k0)	// restore at for temp usage
217
218	.irp	n, REGS0
219	sd	$\n, 0(k1)
220	addiu	k1, 8
221	.endr
222
223	move	$25, k1
224	ld      k1, 216(k0)	// restore k1 for temp usage
225	move	k0, $25
226
227	// Store out k0, we can use $25 here because we just saved it
228	dmfc0	$25, COP0_DESAVE
229	sd	$25, 0(k0)
230	addiu	k0, 8
231
232	.irp	n, REGS1
233	sd	$\n, 0(k0)
234	addiu	k0, 8
235	.endr
236
237	loadaddr(sp, __cvmx_debug_stack_top, 3)
238	// Load the stack pointer as a pointer size.
239#ifdef _ABIN32
240	lw	sp,0(sp)
241#else
242	ld	sp,0(sp)
243#endif
244	jal	__cvmx_debug_handler_stage3
245	nop
246
247	loadaddr(k0, __cvmx_debug_save_regs_area, 8)
248
249	.irp	n, REGS0
250	ld	$\n, 0(k0)
251	addiu	k0, 8
252	.endr
253
254	// Restore k0 to COP0_DESAVE via k1
255	ld	k1, 0(k0)
256	addiu	k0, 8
257	dmtc0	k1, COP0_DESAVE
258
259	.irp	n, REGS1
260	ld	$\n, 0(k0)
261	addiu	k0, 8
262	.endr
263
264	dmfc0	k0, COP0_DESAVE
265	// Flush the icache; by adding and removing SW breakpoints we change
266	// the instruction stream.
267	synci 	0($0)
268	deret
269	nop
270
271	.end	__cvmx_debug_handler_stage2
272