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
41215976Sjmallett
42215976Sjmallett
43215976Sjmallett
44215976Sjmallett
45215976Sjmallett
46215976Sjmallett
47215976Sjmallett
48215976Sjmallett
49215976Sjmallett#include <machine/asm.h>
50215976Sjmallett#include <machine/regdef.h>
51215976Sjmallett
52215976Sjmallett.set noreorder
53215976Sjmallett.set noat
54215976Sjmallett
55215976SjmallettLEAF(cvmx_interrupt_stage1)
56215976Sjmallett	dla     k0, cvmx_interrupt_stage2
57215976Sjmallett	jalr 	k1, k0   // Save our address in k1, so we can tell which
58215976Sjmallett                         // vector we are coming from.
59215976Sjmallett	nop
60215976SjmallettEND(cvmx_interrupt_stage1)
61215976Sjmallett
62215976Sjmallett#define STACK_SIZE  (36*8)
63215976SjmallettLEAF(cvmx_interrupt_stage2)
64215976Sjmallett	dsubu	sp, sp, STACK_SIZE
65215976Sjmallett	sd	zero, 0(sp)	// Just a place holder
66215976Sjmallett	sd	$1, 8(sp)	// start saving registers
67215976Sjmallett	sd	$2, 16(sp)
68215976Sjmallett	sd 	$3, 24(sp)
69215976Sjmallett	sd 	$4, 32(sp)
70215976Sjmallett	sd	$5, 40(sp)
71215976Sjmallett	sd	$6, 48(sp)
72215976Sjmallett	sd	$7, 56(sp)
73215976Sjmallett	sd	$8, 64(sp)
74215976Sjmallett	sd	$9, 72(sp)
75215976Sjmallett	sd	$10, 80(sp)
76215976Sjmallett	sd	$11, 88(sp)
77215976Sjmallett	sd	$12, 96(sp)
78215976Sjmallett	sd	$13, 104(sp)
79215976Sjmallett	sd	$14, 112(sp)
80215976Sjmallett	sd	$15, 120(sp)
81215976Sjmallett	sd	$16, 128(sp)
82215976Sjmallett	sd	$17, 136(sp)
83215976Sjmallett	sd	$18, 144(sp)
84215976Sjmallett	sd	$19, 152(sp)
85215976Sjmallett	sd	$20, 160(sp)
86215976Sjmallett	sd	$21, 168(sp)
87215976Sjmallett	sd	$22, 176(sp)
88215976Sjmallett	sd	$23, 184(sp)
89215976Sjmallett	sd	$24, 192(sp)
90215976Sjmallett	sd	$25, 200(sp)
91215976Sjmallett	sd	$26, 208(sp)
92215976Sjmallett	sd	$27, 216(sp)
93215976Sjmallett	mfhi	k0		// Reading lo and high takes multiple cycles
94215976Sjmallett	mflo	k1		// Do it here so it completes by the time we need it
95215976Sjmallett	sd	$28, 224(sp)
96215976Sjmallett	daddu	$1, sp, STACK_SIZE // Correct the SP for the space we used
97215976Sjmallett	sd	$1, 232(sp)
98215976Sjmallett	sd	$30, 240(sp)
99215976Sjmallett	sd	$31, 248(sp)	// saved all general purpose registers
100215976Sjmallett	sd	k0, 256(sp)	// save hi
101215976Sjmallett	sd	k1, 264(sp)	// save lo
102215976Sjmallett        /* Save DCACHE error register early, since any non-errored DCACHE accesses will clear
103215976Sjmallett        ** error bit */
104215976Sjmallett        dmfc0   k0, $27, 1
105215976Sjmallett        sd      k0, 272(sp)
106232812Sjmallett        /* Store EPC for GCC's frame unwinder. */
107215976Sjmallett        dmfc0   k0, $14
108215976Sjmallett        sd      k0, 280(sp)
109215976Sjmallett
110215976Sjmallett	dla	k0, cvmx_interrupt_in_isr
111215976Sjmallett	li	k1, 1
112215976Sjmallett	sw	k1, 0(k0)
113215976Sjmallett
114215976Sjmallett	dla     k0, cvmx_interrupt_do_irq
115215976Sjmallett	jal 	k0
116215976Sjmallett	dadd	a0, sp, 0	// First argument is array of registers
117215976Sjmallett
118215976Sjmallett	dla	k0, cvmx_interrupt_in_isr
119215976Sjmallett	sw	$0, 0(k0)
120215976Sjmallett
121215976Sjmallett	ld	k0, 256(sp)	// read hi
122215976Sjmallett	ld	k1, 264(sp)	// read lo
123215976Sjmallett	mthi	k0		// restore hi
124215976Sjmallett	mtlo	k1		// restore lo
125215976Sjmallett
126215976Sjmallett	ld	$1, 8(sp)	// start restoring registers
127215976Sjmallett	ld	$2, 16(sp)
128215976Sjmallett	ld 	$3, 24(sp)
129215976Sjmallett	ld 	$4, 32(sp)
130215976Sjmallett	ld	$5, 40(sp)
131215976Sjmallett	ld	$6, 48(sp)
132215976Sjmallett	ld	$7, 56(sp)
133215976Sjmallett	ld	$8, 64(sp)
134215976Sjmallett	ld	$9, 72(sp)
135215976Sjmallett	ld	$10, 80(sp)
136215976Sjmallett	ld	$11, 88(sp)
137215976Sjmallett	ld	$12, 96(sp)
138215976Sjmallett	ld	$13, 104(sp)
139215976Sjmallett	ld	$14, 112(sp)
140215976Sjmallett	ld	$15, 120(sp)
141215976Sjmallett	ld	$16, 128(sp)
142215976Sjmallett	ld	$17, 136(sp)
143215976Sjmallett	ld	$18, 144(sp)
144215976Sjmallett	ld	$19, 152(sp)
145215976Sjmallett	ld	$20, 160(sp)
146215976Sjmallett	ld	$21, 168(sp)
147215976Sjmallett	ld	$22, 176(sp)
148215976Sjmallett	ld	$23, 184(sp)
149215976Sjmallett	ld	$24, 192(sp)
150215976Sjmallett	ld	$25, 200(sp)
151215976Sjmallett	ld	$26, 208(sp)
152215976Sjmallett	ld	$28, 224(sp)
153215976Sjmallett	ld	$30, 240(sp)
154215976Sjmallett	ld	$31, 248(sp)	// restored all general purpose registers
155215976Sjmallett	ld	$29, 232(sp)	// No need to correct for STACK_SIZE
156215976Sjmallett	eret
157215976Sjmallett	nop
158215976SjmallettEND(cvmx_interrupt_stage2)
159215976Sjmallett
160215976Sjmallett// Icache and Dcache exception handler. This code is executed
161215976Sjmallett// with ERL set so we can't us virtual addresses. We save and restore
162215976Sjmallett// K0 to a global memory location so we can handle cache errors from exception
163215976Sjmallett// context. This means that if two cores get a cache exception at the same time
164215976Sjmallett// the K0 might be corrupted. This entire handler MUST fit in 128 bytes.
165215976Sjmallett#define K0_STORE_LOCATION	8
166215976Sjmallett#define DCACHE_ERROR_COUNT	16
167215976Sjmallett#define ICACHE_ERROR_COUNT	24
168215976SjmallettLEAF(cvmx_interrupt_cache_error)
169215976Sjmallett	.set push
170215976Sjmallett	.set noreorder
171215976Sjmallett	sd	k0, K0_STORE_LOCATION($0)	// Store K0 into global loc in case we're in an exception
172215976Sjmallett	dmfc0	k0, $27, 1			// Get Dcache error status before any loads
173215976Sjmallett	bbit0	k0, 0, not_dcache_error		// Skip dcache count if no error
174215976Sjmallett	 dmtc0	k0, $27, 1			// Clear any Dcache errors
175215976Sjmallett	ld	k0, DCACHE_ERROR_COUNT($0)	// Load the dcache error count
176215976Sjmallett	daddu	k0, 1				// Increment the dcache error count
177215976Sjmallett	sd	k0, DCACHE_ERROR_COUNT($0)	// Store the dcache error count
178215976Sjmallettnot_dcache_error:
179215976Sjmallett	dmfc0	k0, $27, 0			// Get the Icache error status
180215976Sjmallett	bbit0	k0, 0, not_icache_error		// Skip Icache count if no error
181215976Sjmallett	 dmtc0	k0, $27, 0			// Clear any Icache errors
182215976Sjmallett	ld	k0, ICACHE_ERROR_COUNT($0)	// Load the icache error count
183215976Sjmallett	daddu	k0, 1				// Increment the icache error count
184215976Sjmallett	sd	k0, ICACHE_ERROR_COUNT($0)	// Store the icache error count
185215976Sjmallettnot_icache_error:
186215976Sjmallett	ld	k0, K0_STORE_LOCATION($0)	// Restore K0 since we might have been in an exception
187232812Sjmallett	nop
188232812Sjmallett	nop
189232812Sjmallett	nop
190232812Sjmallett	nop
191232812Sjmallett	nop
192232812Sjmallett	nop					// Keep the ERET 8 instructions away
193232812Sjmallett	nop					// from a branch target.
194215976Sjmallett	eret					// Return from the Icache exception
195215976Sjmallett	.set pop
196215976SjmallettEND(cvmx_interrupt_cache_error)
197215976Sjmallett
198