1/*
2 * Copyright 2006, Ingo Weinhold <bonefish@cs.tu-berlin.de>.
3 * All rights reserved. Distributed under the terms of the MIT License.
4 *
5 * Copyright 2003, Travis Geiselbrecht. All rights reserved.
6 * Distributed under the terms of the NewOS License.
7 */
8
9#include <asm_defs.h>
10
11#include "asm_offsets.h"
12
13
14/*	General exception handling concept:
15
16	Starting with 68020 the vector offset (=vector number * 4) is part
17	of the all exception frame types, so we can easily have a common
18	asm stub for all of them, which calls m68k_exception_entry in
19	arch_int.cpp.
20	Also, m68k doesn't disable the mmu on interrupt as ppc does,
21	which makes things simpler.
22
23	----ppc
24
25	The PPC architecture specifies entry point offsets for the various
26	exceptions in the first two physical pages. We put a short piece of code
27	(VEC_ENTRY()) into each exception vector. It calls exception_vector_common,
28	which is defined in the unused space at the beginning of the first physical
29	page. It re-enables address translation and calls ppc_exception_tail which
30	lies in the kernel. It dumps an iframe and invokes ppc_exception_entry()
31	(arch_int.cpp), which handles the exception and returns eventually.
32	The registers are restored from the iframe and we return from the
33	interrupt.
34
35	algorithm overview:
36
37	* VEC_ENTRY
38	* exception_vector_common
39	* ppc_exception_tail
40		- dump iframe
41		- ppc_exception_entry()
42		- restore registers and return from interrupt
43
44	Here we use the following SPRG registers, which are at the disposal of the
45	operating system:
46	* SPRG0: Physical address pointer to a struct cpu_exception_context
47			 for the current CPU. The structure contains helpful pointers
48			 as well as some scratch memory for temporarily saving registers.
49	* SPRG1: Scratch.
50
51	struct cpu_exception_context (defined in arch_int.h):
52	offset 0:  virtual address of the exception handler routine in the kernel
53	offset 4:  virtual address of the exception context
54	offset 8:  kernel stack for the current thread
55	offset 12: start of scratch memory for saving registers etc.
56
57	algorithm in detail:
58
59	* VEC_ENTRY
60		- save r1 in SPRG1 and load cpu_exception_context into r1
61		- save r0, save LR in r0
62	* exception_vector_common
63		- params:
64			. r0: old LR
65			. r1: exception context (physical address)
66			. SPRG1: original r1
67		- save r0-3
68		- load virtual exception context address to r1
69		- turn on BAT for exception vector code
70		- turn on address translation
71		- get exception vector offset from LR
72	* ppc_exception_tail
73		- params:
74			. r1: exception context (virtual address)
75			. r3: exception vector offset
76			. SPRG1: original r1
77		- turn off BAT
78		- get kernel stack pointer
79		- dump iframe
80		- ppc_exception_entry()
81		- restore registers and return from interrupt
82 */
83
84
85/* exception vector definitions */
86
87/* this one just returns */
88FUNCTION(__m68k_exception_noop):
89	rte
90FUNCTION_END(__m68k_exception_noop)
91
92/* see arch_asm.S for ctx switch */
93
94FUNCTION(__m68k_exception_common):
95	/* save regs */
96	movem.l		%d0-%d7/%a0-%a6,-(%sp)	/* push the iframe address */
97	/* save fp */
98	sub.l		#FPU_STATE_sizeof,%sp
99	fsave		(%sp)
100	tst.b		(%sp)			/* check for a null state */
101	beq		null_sav_1		/* yes */
102
103	fmovem		%fpcr/%fpsr/%fpiar,-(%sp)
104	fmovem		%fp0-%fp7,-(%sp)
105	bra		null_sav_2
106null_sav_1:
107	sub.l		#IFRAME_fpu-IFRAME_fp,%sp
108null_sav_2:
109
110	move.l		%sp,%fp			/* have stack_trace() find the iframe */
111	move.l		%sp,-(%sp)		/* push address of iframe */
112	bsr		m68k_exception_entry	/* call C entry */
113	add.l		#4,%sp
114
115	/* restore fp */
116	tst.b		IFRAME_fpu-IFRAME_fp(%sp) /* check for a null state */
117	beq		null_res_1		/* yes */
118	fmovem		(%sp)+,%fp0-%fp7
119	fmovem		(%sp)+,%fpcr/%fpsr/%fpiar
120	bra		null_res_2
121null_res_1:
122	add.l		#IFRAME_fpu-IFRAME_fp,%sp
123null_res_2:
124	/* restore fp */
125	frestore	(%sp)
126	add.l		#FPU_STATE_sizeof,%sp
127	/* restore regs */
128	movem.l		(%sp)+,%d0-%d7/%a0-%a6
129
130	rte
131FUNCTION_END(__m68k_exception_common)
132
133
134