headers/bsd: Add sys/queue.h.
[haiku.git] / src / system / kernel / arch / m68k / arch_exceptions.S
blobf49eab0607e4f61477ea563f3d3b1a0a71ee2c7c
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  */
9 #include <asm_defs.h>
11 #include "asm_offsets.h"
14 /*      General exception handling concept:
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.
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.
35         algorithm overview:
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
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.
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.
57         algorithm in detail:
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  */
85 /* exception vector definitions */
87 /* this one just returns */
88 FUNCTION(__m68k_exception_noop):
89         rte
90 FUNCTION_END(__m68k_exception_noop)
92 /* see arch_asm.S for ctx switch */
94 FUNCTION(__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
106 null_sav_1:
107         sub.l           #IFRAME_fpu-IFRAME_fp,%sp
108 null_sav_2:     
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
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
121 null_res_1:
122         add.l           #IFRAME_fpu-IFRAME_fp,%sp
123 null_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
131 FUNCTION_END(__m68k_exception_common)