exception_vector.S revision 1.8
1/*	$NetBSD: exception_vector.S,v 1.8 2002/04/28 17:10:38 uch Exp $	*/
2
3/*-
4 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *        This product includes software developed by the NetBSD
18 *        Foundation, Inc. and its contributors.
19 * 4. Neither the name of The NetBSD Foundation nor the names of its
20 *    contributors may be used to endorse or promote products derived
21 *    from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
25 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
26 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
27 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
28 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
29 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
30 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
31 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
34 */
35
36#include "assym.h"
37#include "opt_cputype.h"
38
39#include <sh3/param.h>
40#include <sh3/asm.h>
41#include <sh3/locore.h>
42#include <sh3/exception.h>
43#include <sh3/ubcreg.h>
44#include <sh3/mmu_sh3.h>
45#include <sh3/mmu_sh4.h>
46
47/*
48 * Exception vectors. following routines are copied to vector addreses.
49 *	sh_vector_generic:	VBR + 0x100
50	 *	sh_vector_tlbmiss:	VBR + 0x400
51 *	sh_vector_interrupt:	VBR + 0x600
52 */
53
54/*
55 * void sh_vector_generic(void) __attribute__((__noreturn__)):
56 *	copied to VBR+0x100. This code should be relocatable and max 384
57 *	instructions.
58 *		0x40 TLB miss (load)
59 *		0x60 TLB miss (store)
60 *		0xc0	TLB protection (store)
61 *		  -> tlbmiss_exp()
62 *		0xa0 TLB protection (load)
63 *		0x80 Initial page write.
64 *		 and other...
65 *		  -> trap()
66 */
67	.globl	_C_LABEL(sh_vector_generic), _C_LABEL(sh_vector_generic_end)
68	.text
69	.align	2
70_C_LABEL(sh_vector_generic):
71	__EXCEPTION_ENTRY
72	/* Identify exception cause */
73	MOV	(EXPEVT, r0)
74	mov.l	@r0,	r0
75	/*
76	 * TLB exception.
77	 */
78	cmp/eq	#0x40,	r0		/* T_TLBINVALIDR */
79	bf	1f
803:
81	__INTR_MASK(r0, r1)
82	__EXCEPTION_UNBLOCK(r0, r1)
83	mov.l	_L.tlb_handler, r0
84	jsr	@r0
85	 mov	r14,	r6
86	bra	4f
87	 nop
881:
89	cmp/eq	#0x60,	r0		/* T_TLBINVALIDW */
90	bt	3b
91
92	mov.l	_L.TLBPROTWR, r1	/* T_TLBPRIVW */
93	cmp/eq	r0,	r1
94	bt	3b
95
96	/*
97	 * General exception.
98	 */
99#ifdef DDB
100	mov	#0,	r2
101	MOV	(BBRA, r1)
102	mov.w	r2,	@r1	/* disable UBC */
103	mov.l	r2,	@(TF_UBC, r14)	/* clear trapframe->tf_ubc */
104#endif /* DDB */
105
106	mov.l	r0,	@(TF_TRAPNO, r14) /* trapframe->tf_trapno = EXPEVT */
107	__INTR_UNMASK(r0, r1)
108	__EXCEPTION_UNBLOCK(r0, r1)
109	mov.l	_L.trap, r0
110	jsr	@r0
111	 mov	r14,	r6
112
113	/* Check for ASTs on exit to user mode. */
114	mov.l	_L.ast,	r0
115	jsr	@r0
116	 mov	r14,	r4
117
118#ifdef DDB	/* BBRA = trapframe->tf_ubc */
119	__EXCEPTION_BLOCK(r0, r1)
120	mov.l	@(TF_UBC, r14), r0
121	MOV	(BBRA, r1)
122	mov.w	r0,	@r1
123#endif /* DDB */
1244:
125	__EXCEPTION_RETURN
126	/* NOTREACHED */
127	.align	2
128REG_SYMBOL(EXPEVT)
129REG_SYMBOL(BBRA)
130_L.TLBPROTWR:	.long	0x000000c0
131_L.trap:	.long	_C_LABEL(trap)
132_L.ast:		.long	_C_LABEL(ast)
133_L.tlb_handler:	.long	_C_LABEL(tlb_handler)
134_C_LABEL(sh_vector_generic_end):	.long	0
135
136#ifdef SH3
137/*
138 * void sh3_vector_tlbmiss(void) __attribute__((__noreturn__)):
139 *	copied to VBR+0x400. This code should be relocatable and max 256
140 *	instructions.
141 */
142	.globl	_C_LABEL(sh3_vector_tlbmiss), _C_LABEL(sh3_vector_tlbmiss_end)
143	.text
144	.align	2
145_C_LABEL(sh3_vector_tlbmiss):
146	__EXCEPTION_ENTRY
147	__INTR_MASK(r0, r1)
148	__EXCEPTION_UNBLOCK(r0, r1)
149#if !defined(P1_STACK)
150	/* Load kernel stack */
151	mov.l	_L.TEA, r1
152	mov.l	@r1,	r0	/* r0 = va */
153	mov.l	_L.VPN_MASK, r1
154	and	r1,	r0	/* va = trunc_page(va) */
155	mov.l	_L.CURUPTE, r1
156	mov	#UPAGES,r3
157	mov	#1,	r2
1584:	mov.l	@r1+,	r6
159	cmp/eq	r6,	r0	/* md_upte.addr: u-area VPN */
160	bt	5f
161	add	#4,	r1	/* skip md_upte.data */
162	cmp/eq	r2,	r3
163	bf/s	4b
164	 add	#1,	r2
165	bra	6f
166	 nop
1675:	mov.l	@r1,	r2	/* md_upte.data: u-area PTE */
168	mov.l	_L.PTEL, r1
169	mov.l	r2,	@r1
170	ldtlb
171	bra	3f
172	 nop
173#endif /* !P1_STACK */
1746:	mov	r0,	r2
175	mov	#-22,	r1
176	shld	r1,	r2	/* r2 = va >> 22 */
177	shll2	r2		/* r2 *= sizeof(pt_entry_t) */
178	mov.l	_L.TTB, r1
179	mov.l	@r1,	r1
180	add	r1,	r2	/* r2 = page directory entry address */
181	mov	#1	r1
182	swap.b	r1,	r1	/* 0x100 (PG_V) */
183	mov.l	@r2,	r2	/* r2 = pde */
184	and	r2,	r1
185	tst	r1,	r1
186	bt	2f		/* (pde & PG_V) == 0 -> tlb_handler */
187	mov.l	_L.VPN_MASK, r1
188	and	r1,	r2	/* zero attribute bits */
189	mov.l	_L.PT_MASK, r1
190	mov	r0,	r3
191	and	r1,	r3	/* r3 = va & 0x003ff000 */
192	mov	#-12	r1
193	shld	r1,	r3	/* r3 = (va & 0x003ff000) >> 12 */
194	shll2	r3		/* r3 *= sizeof(pt_entry_t) */
195	add	r2,	r3	/* r3 = page table entry address */
196	mov.l	@r3,	r3	/* r3 = page table entry */
197	mov	#1,	r1
198	swap.b	r1,	r1	/* r1 = PG_V */
199	and	r3,	r1
200	tst	r1,	r1
201	bt	2f		/* (pte & PG_V) == 0 -> tlb_handler */
202	mov.l	_L.PTE_HW_BITS, r2
203	and	r2,	r3
204	mov.l	_L.PTEL, r1
205	mov.l	r3,	@r1	/* PTEL = (pte & PG_HW_BITS) */
206	ldtlb
207	bra	3f
208	 nop
2092:
210	mov.l	1f,	r0
211	jsr	@r0
212	 mov	r14,	r6
2133:
214	__EXCEPTION_RETURN
215	.align	2
2161:		.long	_C_LABEL(tlb_handler)
217_L.TEA:		.long	SH3_TEA
218_L.TTB:		.long	SH3_TTB
219_L.PTEL:	.long	SH3_PTEL
220_L.PTE_HW_BITS:	.long	0x1ffff17e
221_L.PT_MASK:	.long	0x003ff000
222_L.VPN_MASK:	.long	0xfffff000
223_L.CURUPTE:	.long	_C_LABEL(curupte)
224	.align	2
225_C_LABEL(sh3_vector_tlbmiss_end):	.long	0
226#endif /* SH3 */
227
228#ifdef SH4
229/*
230 * void sh4_vector_tlbmiss(void) __attribute__((__noreturn__)):
231 *	copied to VBR+0x400. This code should be relocatable and max 256
232 *	instructions.
233 */
234	.globl	_C_LABEL(sh4_vector_tlbmiss), _C_LABEL(sh4_vector_tlbmiss_end)
235	.text
236	.align	2
237_C_LABEL(sh4_vector_tlbmiss):
238	__EXCEPTION_ENTRY
239	__INTR_MASK(r0, r1)
240	__EXCEPTION_UNBLOCK(r0, r1)
241	mov	#0x20,	r7
242	swap.b	r7,	r7
243	swap.w	r7,	r7	/* r7 = 0x20000000 */
244	mov.l	__L.TEA, r1
245	mov.l	@r1,	r0	/* r0 = va */
246	mov	r0,	r2
247	mov	#-22,	r1
248	shld	r1,	r2	/* r2 = va >> 22 */
249	shll2	r2		/* r2 *= sizeof(pt_entry_t) */
250	mov.l	__L.TTB, r1
251	mov.l	@r1,	r1
252	or	r7,	r1	/* XXX P2 access */
253	add	r1,	r2	/* r2 = page directory entry address */
254	mov	#1	r1
255	swap.b	r1,	r1	/* 0x100 (PG_V) */
256	mov.l	@r2,	r2	/* r2 = pde */
257	and	r2,	r1
258	tst	r1,	r1
259	bt	2f		/* (pde & PG_V) == 0 -> tlb_handler */
260	mov.l	__L.VPN_MASK, r1
261	and	r1,	r2	/* zero attribute bits */
262	mov.l	__L.PT_MASK, r1
263	mov	r0,	r3
264	and	r1,	r3	/* r3 = va & 0x003ff000 */
265	mov	#-12	r1
266	shld	r1,	r3	/* r3 = (va & 0x003ff000) >> 12 */
267	shll2	r3		/* r3 *= sizeof(pt_entry_t) */
268	add	r2,	r3	/* r3 = page table entry address */
269	or	r7,	r3	/* XXX P2 access */
270	mov.l	@r3,	r3	/* r3 = page table entry */
271	mov	#1,	r1
272	swap.b	r1,	r1	/* r1 = PG_V */
273	and	r3,	r1
274	tst	r1,	r1
275	bt	2f		/* (pte & PG_V) == 0 -> tlb_handler */
276	mov	#0xe,	r1
277	swap.b	r1,	r1	/* r1 = _PG_PCMCIA (0x0e00) */
278	and	r3,	r1
279	tst	r1,	r1
280	bt	4f
281	mov	r3,	r2
282	mov	#-9	r1
283	shld	r1,	r2
284	mov	#7,	r1
285	and	r1,	r2	/* r2 = (pte >> 9) & 0x7 */
286	mov.l	__L.PTEA, r1
287	mov.l	r2,	@r1
288	mov.l	__L.PTE_HW_BITS, r1
289	and	r3,	r1
290	mov	#-9,	r2
291	and	r2,	r3	/* pte &= ~PG_N XXX */
292	mov.l	__L.PTEL, r1
293	mov.l	r3,	@r1
294	bra	6f
295	 nop
2964:
297	mov.l	__L.PTE_HW_BITS, r1
298	and	r1,	r3
299	mov.l	__L.P3SEGBASE, r1
300	cmp/hs	r1,	r0	/* va >= 0xc0000000 ? T = 1 */
301	bf	5f
302	mov	#1,	r1
303	or	r1,	r3	/* PG_WT  P3 write-through XXX */
3045:
305	mov.l	__L.PTEA, r1
306	xor	r0,	r0
307	mov.l	r0,	@r1
308	mov.l	__L.PTEL, r1
309	mov.l	r3,	@r1
310	nop
3116:	ldtlb
312	bra	3f
313	 nop
3142:
315	mov.l	1f,	r0
316	jsr	@r0
317	 mov	r14,	r6
3183:
319	__EXCEPTION_RETURN
320	.align	2
3211:		.long	_C_LABEL(tlb_handler)
322__L.TEA:	.long	SH4_TEA
323__L.TTB:	.long	SH4_TTB
324__L.PTEL:	.long	SH4_PTEL
325__L.PTEA:	.long	SH4_PTEA
326__L.P3SEGBASE:	.long	0xc0000000
327__L.PTE_HW_BITS:.long	0x1ffff17e
328__L.PT_MASK:	.long	0x003ff000
329__L.VPN_MASK:	.long	0xfffff000
330_C_LABEL(sh4_vector_tlbmiss_end):	.long	0
331#endif /* SH4 */
332
333/*
334 * void sh_vector_interrupt(void) __attribute__((__noreturn__)):
335 *	copied to VBR+0x600. This code should be relocatable.
336 */
337	.globl	_C_LABEL(sh_vector_interrupt), _C_LABEL(sh_vector_interrupt_end)
338	.align	2
339	.text
340_C_LABEL(sh_vector_interrupt):
341	__EXCEPTION_ENTRY
342	stc	r0_bank,r6	/* ssp */
343	/* Enable exception for P3 access */
344	__INTR_MASK(r0, r1)
345	__EXCEPTION_UNBLOCK(r0, r1)
346	/* uvmexp.intrs++ */
347	mov.l	__L.uvmexp.intrs, r0
348	mov.l	@r0,	r1
349	add	#1	r1
350	mov.l	r1,	@r0
351	/* Dispatch interrupt handler */
352	mov.l	__L.intc_intr, r0
353	jsr	@r0		/* intc_intr(ssr, spc, ssp) */
354	 nop
355	/* Check for ASTs on exit to user mode. */
356	mov.l	__L.ast, r0
357	jsr	@r0
358	 mov	r14,	r4
359	__EXCEPTION_RETURN
360	.align	2
361__L.intc_intr:		.long	_C_LABEL(intc_intr)
362__L.ast:		.long	_C_LABEL(ast)
363__L.uvmexp.intrs:	.long	_C_LABEL(uvmexp) + UVMEXP_INTRS
364_C_LABEL(sh_vector_interrupt_end):	.long	0
365