1/***********************license start***************
2 * Copyright (c) 2003-2010  Cavium Inc. (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 Inc. 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 INC. 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
41
42
43
44
45
46
47
48
49#include <machine/asm.h>
50#include <machine/regdef.h>
51
52.set noreorder
53.set noat
54
55LEAF(cvmx_interrupt_stage1)
56	dla     k0, cvmx_interrupt_stage2
57	jalr 	k1, k0   // Save our address in k1, so we can tell which
58                         // vector we are coming from.
59	nop
60END(cvmx_interrupt_stage1)
61
62#define STACK_SIZE  (36*8)
63LEAF(cvmx_interrupt_stage2)
64	dsubu	sp, sp, STACK_SIZE
65	sd	zero, 0(sp)	// Just a place holder
66	sd	$1, 8(sp)	// start saving registers
67	sd	$2, 16(sp)
68	sd 	$3, 24(sp)
69	sd 	$4, 32(sp)
70	sd	$5, 40(sp)
71	sd	$6, 48(sp)
72	sd	$7, 56(sp)
73	sd	$8, 64(sp)
74	sd	$9, 72(sp)
75	sd	$10, 80(sp)
76	sd	$11, 88(sp)
77	sd	$12, 96(sp)
78	sd	$13, 104(sp)
79	sd	$14, 112(sp)
80	sd	$15, 120(sp)
81	sd	$16, 128(sp)
82	sd	$17, 136(sp)
83	sd	$18, 144(sp)
84	sd	$19, 152(sp)
85	sd	$20, 160(sp)
86	sd	$21, 168(sp)
87	sd	$22, 176(sp)
88	sd	$23, 184(sp)
89	sd	$24, 192(sp)
90	sd	$25, 200(sp)
91	sd	$26, 208(sp)
92	sd	$27, 216(sp)
93	mfhi	k0		// Reading lo and high takes multiple cycles
94	mflo	k1		// Do it here so it completes by the time we need it
95	sd	$28, 224(sp)
96	daddu	$1, sp, STACK_SIZE // Correct the SP for the space we used
97	sd	$1, 232(sp)
98	sd	$30, 240(sp)
99	sd	$31, 248(sp)	// saved all general purpose registers
100	sd	k0, 256(sp)	// save hi
101	sd	k1, 264(sp)	// save lo
102        /* Save DCACHE error register early, since any non-errored DCACHE accesses will clear
103        ** error bit */
104        dmfc0   k0, $27, 1
105        sd      k0, 272(sp)
106        /* Store EPC for GCC's frame unwinder. */
107        dmfc0   k0, $14
108        sd      k0, 280(sp)
109
110	dla	k0, cvmx_interrupt_in_isr
111	li	k1, 1
112	sw	k1, 0(k0)
113
114	dla     k0, cvmx_interrupt_do_irq
115	jal 	k0
116	dadd	a0, sp, 0	// First argument is array of registers
117
118	dla	k0, cvmx_interrupt_in_isr
119	sw	$0, 0(k0)
120
121	ld	k0, 256(sp)	// read hi
122	ld	k1, 264(sp)	// read lo
123	mthi	k0		// restore hi
124	mtlo	k1		// restore lo
125
126	ld	$1, 8(sp)	// start restoring registers
127	ld	$2, 16(sp)
128	ld 	$3, 24(sp)
129	ld 	$4, 32(sp)
130	ld	$5, 40(sp)
131	ld	$6, 48(sp)
132	ld	$7, 56(sp)
133	ld	$8, 64(sp)
134	ld	$9, 72(sp)
135	ld	$10, 80(sp)
136	ld	$11, 88(sp)
137	ld	$12, 96(sp)
138	ld	$13, 104(sp)
139	ld	$14, 112(sp)
140	ld	$15, 120(sp)
141	ld	$16, 128(sp)
142	ld	$17, 136(sp)
143	ld	$18, 144(sp)
144	ld	$19, 152(sp)
145	ld	$20, 160(sp)
146	ld	$21, 168(sp)
147	ld	$22, 176(sp)
148	ld	$23, 184(sp)
149	ld	$24, 192(sp)
150	ld	$25, 200(sp)
151	ld	$26, 208(sp)
152	ld	$28, 224(sp)
153	ld	$30, 240(sp)
154	ld	$31, 248(sp)	// restored all general purpose registers
155	ld	$29, 232(sp)	// No need to correct for STACK_SIZE
156	eret
157	nop
158END(cvmx_interrupt_stage2)
159
160// Icache and Dcache exception handler. This code is executed
161// with ERL set so we can't us virtual addresses. We save and restore
162// K0 to a global memory location so we can handle cache errors from exception
163// context. This means that if two cores get a cache exception at the same time
164// the K0 might be corrupted. This entire handler MUST fit in 128 bytes.
165#define K0_STORE_LOCATION	8
166#define DCACHE_ERROR_COUNT	16
167#define ICACHE_ERROR_COUNT	24
168LEAF(cvmx_interrupt_cache_error)
169	.set push
170	.set noreorder
171	sd	k0, K0_STORE_LOCATION($0)	// Store K0 into global loc in case we're in an exception
172	dmfc0	k0, $27, 1			// Get Dcache error status before any loads
173	bbit0	k0, 0, not_dcache_error		// Skip dcache count if no error
174	 dmtc0	k0, $27, 1			// Clear any Dcache errors
175	ld	k0, DCACHE_ERROR_COUNT($0)	// Load the dcache error count
176	daddu	k0, 1				// Increment the dcache error count
177	sd	k0, DCACHE_ERROR_COUNT($0)	// Store the dcache error count
178not_dcache_error:
179	dmfc0	k0, $27, 0			// Get the Icache error status
180	bbit0	k0, 0, not_icache_error		// Skip Icache count if no error
181	 dmtc0	k0, $27, 0			// Clear any Icache errors
182	ld	k0, ICACHE_ERROR_COUNT($0)	// Load the icache error count
183	daddu	k0, 1				// Increment the icache error count
184	sd	k0, ICACHE_ERROR_COUNT($0)	// Store the icache error count
185not_icache_error:
186	ld	k0, K0_STORE_LOCATION($0)	// Restore K0 since we might have been in an exception
187	nop
188	nop
189	nop
190	nop
191	nop
192	nop					// Keep the ERET 8 instructions away
193	nop					// from a branch target.
194	eret					// Return from the Icache exception
195	.set pop
196END(cvmx_interrupt_cache_error)
197
198