Diff markup
001 /* Copyright (C) 2004 The KOS Team 001 /* Copyright (C) 2004 The KOS Team
002 002
003 This program is free software; you can redi 003 This program is free software; you can redistribute it and/or
004 modify it under the terms of the GNU Genera 004 modify it under the terms of the GNU General Public License
005 as published by the Free Software Foundatio 005 as published by the Free Software Foundation; either version 2
006 of the License, or (at your option) any lat 006 of the License, or (at your option) any later version.
007 007
008 This program is distributed in the hope tha 008 This program is distributed in the hope that it will be useful,
009 but WITHOUT ANY WARRANTY; without even the 009 but WITHOUT ANY WARRANTY; without even the implied warranty of
010 MERCHANTABILITY or FITNESS FOR A PARTICULAR 010 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011 GNU General Public License for more details 011 GNU General Public License for more details.
012 012
013 You should have received a copy of the GNU 013 You should have received a copy of the GNU General Public License
014 along with this program; if not, write to t 014 along with this program; if not, write to the Free Software
015 Foundation, Inc., 59 Temple Place - Suite 3 015 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016 USA. 016 USA.
017 */ 017 */
018 #include "exception.h" 018 #include "exception.h"
019 019
020 #include "segment.h" 020 #include "segment.h"
021 021
022 .file "exception_wrappers.S" 022 .file "exception_wrappers.S"
023 023
024 .text 024 .text
025 025
026 /* The address of the table of handlers (defin 026 /* The address of the table of handlers (defined in exception.c) */
027 .extern sos_exception_handler_array 027 .extern sos_exception_handler_array
028 028
029 /* The address of the table of wrappers (defin 029 /* The address of the table of wrappers (defined below, and shared
030 with exception.c */ 030 with exception.c */
031 .globl sos_exception_wrapper_array 031 .globl sos_exception_wrapper_array
032 032
033 /** Update the kernel TSS in case we are switc 033 /** Update the kernel TSS in case we are switching to a thread in user
034 mode in order to come back into the co 034 mode in order to come back into the correct kernel stack */
035 .extern sos_cpu_context_update_kernel_tss 035 .extern sos_cpu_context_update_kernel_tss
036 036
037 /* The address of the function to call to set 037 /* The address of the function to call to set back the user thread's
038 MMU configuration upon return to user conte 038 MMU configuration upon return to user context */
039 .extern sos_thread_prepare_exception_switch_ba 039 .extern sos_thread_prepare_exception_switch_back
040 040
041 /** 041 /**
042 * For exceptions with/without error code, ref 042 * For exceptions with/without error code, refer to Intel x86 doc vol 3,
043 * section 5.12 043 * section 5.12
044 */ 044 */
045 045
046 /* These wrappers are for exceptions without e 046 /* These wrappers are for exceptions without error code */
047 .irp id, \ 047 .irp id, \
048 SOS_EXCEPT_DIVIDE_ERROR, 048 SOS_EXCEPT_DIVIDE_ERROR, \
049 SOS_EXCEPT_DEBUG, 049 SOS_EXCEPT_DEBUG, \
050 SOS_EXCEPT_NMI_INTERRUPT, 050 SOS_EXCEPT_NMI_INTERRUPT, \
051 SOS_EXCEPT_BREAKPOINT, 051 SOS_EXCEPT_BREAKPOINT, \
052 SOS_EXCEPT_OVERFLOW, 052 SOS_EXCEPT_OVERFLOW, \
053 SOS_EXCEPT_BOUND_RANGE_EXCEDEED, 053 SOS_EXCEPT_BOUND_RANGE_EXCEDEED, \
054 SOS_EXCEPT_INVALID_OPCODE, 054 SOS_EXCEPT_INVALID_OPCODE, \
055 SOS_EXCEPT_DEVICE_NOT_AVAILABLE, 055 SOS_EXCEPT_DEVICE_NOT_AVAILABLE, \
056 SOS_EXCEPT_COPROCESSOR_SEGMENT_OVERRU 056 SOS_EXCEPT_COPROCESSOR_SEGMENT_OVERRUN, \
057 SOS_EXCEPT_INTEL_RESERVED_1, 057 SOS_EXCEPT_INTEL_RESERVED_1, \
058 SOS_EXCEPT_FLOATING_POINT_ERROR, 058 SOS_EXCEPT_FLOATING_POINT_ERROR, \
059 SOS_EXCEPT_MACHINE_CHECK, 059 SOS_EXCEPT_MACHINE_CHECK, \
060 SOS_EXCEPT_INTEL_RESERVED_2, 060 SOS_EXCEPT_INTEL_RESERVED_2, \
061 SOS_EXCEPT_INTEL_RESERVED_3, 061 SOS_EXCEPT_INTEL_RESERVED_3, \
062 SOS_EXCEPT_INTEL_RESERVED_4, 062 SOS_EXCEPT_INTEL_RESERVED_4, \
063 SOS_EXCEPT_INTEL_RESERVED_5, 063 SOS_EXCEPT_INTEL_RESERVED_5, \
064 SOS_EXCEPT_INTEL_RESERVED_6, 064 SOS_EXCEPT_INTEL_RESERVED_6, \
065 SOS_EXCEPT_INTEL_RESERVED_7, 065 SOS_EXCEPT_INTEL_RESERVED_7, \
066 SOS_EXCEPT_INTEL_RESERVED_8, 066 SOS_EXCEPT_INTEL_RESERVED_8, \
067 SOS_EXCEPT_INTEL_RESERVED_9, 067 SOS_EXCEPT_INTEL_RESERVED_9, \
068 SOS_EXCEPT_INTEL_RESERVED_10, 068 SOS_EXCEPT_INTEL_RESERVED_10, \
069 SOS_EXCEPT_INTEL_RESERVED_11, 069 SOS_EXCEPT_INTEL_RESERVED_11, \
070 SOS_EXCEPT_INTEL_RESERVED_12, 070 SOS_EXCEPT_INTEL_RESERVED_12, \
071 SOS_EXCEPT_INTEL_RESERVED_13, 071 SOS_EXCEPT_INTEL_RESERVED_13, \
072 SOS_EXCEPT_INTEL_RESERVED_14 072 SOS_EXCEPT_INTEL_RESERVED_14
073 073
074 .p2align 2, 0x90 074 .p2align 2, 0x90
075 sos_exception_wrapper_\id: 075 sos_exception_wrapper_\id:
076 .type sos_exception_wrapper_\id,@funct 076 .type sos_exception_wrapper_\id,@function
077 077
078 /* Fake error code */ 078 /* Fake error code */
079 pushl $0 079 pushl $0
080 /* Backup the context */ 080 /* Backup the context */
081 pushl %ebp 081 pushl %ebp
082 movl %esp, %ebp 082 movl %esp, %ebp
083 083
084 pushl %edi 084 pushl %edi
085 pushl %esi 085 pushl %esi
086 pushl %edx 086 pushl %edx
087 pushl %ecx 087 pushl %ecx
088 pushl %ebx 088 pushl %ebx
089 pushl %eax 089 pushl %eax
090 subl $2,%esp 090 subl $2,%esp
091 pushw %ss 091 pushw %ss
092 pushw %ds 092 pushw %ds
093 pushw %es 093 pushw %es
094 pushw %fs 094 pushw %fs
095 pushw %gs 095 pushw %gs
096 096
097 /* Set correct kernel segment 097 /* Set correct kernel segment descriptors' value */
098 movw $SOS_BUILD_SEGMENT_REG_VA 098 movw $SOS_BUILD_SEGMENT_REG_VALUE(0, 0, SOS_SEG_KDATA), %di
099 pushw %di ; popw %ds 099 pushw %di ; popw %ds
100 pushw %di ; popw %es 100 pushw %di ; popw %es
101 pushw %di ; popw %fs 101 pushw %di ; popw %fs
102 pushw %di ; popw %gs 102 pushw %di ; popw %gs
103 103
104 /* 104 /*
105 * Call the handler with the e 105 * Call the handler with the exception number and the
106 * address of the stored CPU c 106 * address of the stored CPU context as arguments
107 */ 107 */
108 pushl %esp 108 pushl %esp
109 pushl $\id 109 pushl $\id
110 leal sos_exception_handler_ar 110 leal sos_exception_handler_array,%edi
111 call *\id*4(%edi) 111 call *\id*4(%edi)
112 /* Unallocate the arguments pa 112 /* Unallocate the arguments passed to the handler */
113 addl $8, %esp 113 addl $8, %esp
114 114
115 /* Reconfigure the MMU if need 115 /* Reconfigure the MMU if needed */
116 pushl %esp /* cpu_ctxt */ 116 pushl %esp /* cpu_ctxt */
117 call sos_thread_prepare_except 117 call sos_thread_prepare_exception_switch_back
118 addl $4, %esp /* Unallocate t 118 addl $4, %esp /* Unallocate the stack */
119 119
120 /* Prepare kernel TSS in case 120 /* Prepare kernel TSS in case we are switching to a
121 user thread: we make sure t 121 user thread: we make sure that we will come back
122 into the kernel at a correc 122 into the kernel at a correct stack location */
123 pushl %esp /* Pass the locatio 123 pushl %esp /* Pass the location of the context we are
124 restoring to the 124 restoring to the function */
125 call sos_cpu_context_update_ke 125 call sos_cpu_context_update_kernel_tss
126 addl $4, %esp 126 addl $4, %esp
127 127
128 /* Restore the context */ 128 /* Restore the context */
129 popw %gs 129 popw %gs
130 popw %fs 130 popw %fs
131 popw %es 131 popw %es
132 popw %ds 132 popw %ds
133 popw %ss 133 popw %ss
134 addl $2,%esp 134 addl $2,%esp
135 popl %eax 135 popl %eax
136 popl %ebx 136 popl %ebx
137 popl %ecx 137 popl %ecx
138 popl %edx 138 popl %edx
139 popl %esi 139 popl %esi
140 popl %edi 140 popl %edi
141 141
142 popl %ebp 142 popl %ebp
143 /* Remove fake error code */ 143 /* Remove fake error code */
144 addl $4, %esp 144 addl $4, %esp
145 iret 145 iret
146 .endr 146 .endr
147 147
148 /* These wrappers are for exceptions w 148 /* These wrappers are for exceptions with error code */
149 .irp id, \ 149 .irp id, \
150 SOS_EXCEPT_INVALID_TSS, 150 SOS_EXCEPT_INVALID_TSS, \
151 SOS_EXCEPT_SEGMENT_NOT_PRESENT, 151 SOS_EXCEPT_SEGMENT_NOT_PRESENT, \
152 SOS_EXCEPT_STACK_SEGMENT_FAULT, 152 SOS_EXCEPT_STACK_SEGMENT_FAULT, \
153 SOS_EXCEPT_GENERAL_PROTECTION, 153 SOS_EXCEPT_GENERAL_PROTECTION, \
154 SOS_EXCEPT_PAGE_FAULT, 154 SOS_EXCEPT_PAGE_FAULT, \
155 SOS_EXCEPT_ALIGNEMENT_CHECK 155 SOS_EXCEPT_ALIGNEMENT_CHECK
156 156
157 .p2align 2, 0x90 157 .p2align 2, 0x90
158 sos_exception_wrapper_\id: 158 sos_exception_wrapper_\id:
159 .type sos_exception_wrapper_\id,@funct 159 .type sos_exception_wrapper_\id,@function
160 160
161 /* ret eflags */ 161 /* ret eflags */
162 /* ret cs */ 162 /* ret cs */
163 /* ret eip */ 163 /* ret eip */
164 /* Error code */ 164 /* Error code */
165 165
166 /* Backup the context */ 166 /* Backup the context */
167 pushl %ebp 167 pushl %ebp
168 movl %esp, %ebp 168 movl %esp, %ebp
169 169
170 pushl %edi 170 pushl %edi
171 pushl %esi 171 pushl %esi
172 pushl %edx 172 pushl %edx
173 pushl %ecx 173 pushl %ecx
174 pushl %ebx 174 pushl %ebx
175 pushl %eax 175 pushl %eax
176 subl $2,%esp 176 subl $2,%esp
177 pushw %ss 177 pushw %ss
178 pushw %ds 178 pushw %ds
179 pushw %es 179 pushw %es
180 pushw %fs 180 pushw %fs
181 pushw %gs 181 pushw %gs
182 182
183 /* Set correct kernel segment 183 /* Set correct kernel segment descriptors' value */
184 movw $SOS_BUILD_SEGMENT_REG_VA 184 movw $SOS_BUILD_SEGMENT_REG_VALUE(0, 0, SOS_SEG_KDATA), %di
185 pushw %di ; popw %ds 185 pushw %di ; popw %ds
186 pushw %di ; popw %es 186 pushw %di ; popw %es
187 pushw %di ; popw %fs 187 pushw %di ; popw %fs
188 pushw %di ; popw %gs 188 pushw %di ; popw %gs
189 189
190 /* 190 /*
191 * Call the handler with the e 191 * Call the handler with the exception number and the
192 * address of the stored CPU c 192 * address of the stored CPU context as arguments
193 */ 193 */
194 pushl %esp 194 pushl %esp
195 pushl $\id 195 pushl $\id
196 leal sos_exception_handler_ar 196 leal sos_exception_handler_array,%edi
197 call *\id*4(%edi) 197 call *\id*4(%edi)
198 /* Unallocate the arguments pa 198 /* Unallocate the arguments passed to the handler */
199 addl $8, %esp 199 addl $8, %esp
200 200
201 /* Reconfigure the MMU if need 201 /* Reconfigure the MMU if needed */
202 pushl %esp /* cpu_ctxt */ 202 pushl %esp /* cpu_ctxt */
203 call sos_thread_prepare_except 203 call sos_thread_prepare_exception_switch_back
204 addl $4, %esp /* Unallocate t 204 addl $4, %esp /* Unallocate the stack */
205 205
206 /* Prepare kernel TSS in case 206 /* Prepare kernel TSS in case we are switching to a
207 user thread: we make sure t 207 user thread: we make sure that we will come back
208 into the kernel at a correc 208 into the kernel at a correct stack location */
209 pushl %esp /* Pass the locatio 209 pushl %esp /* Pass the location of the context we are
210 restoring to the 210 restoring to the function */
211 call sos_cpu_context_update_ke 211 call sos_cpu_context_update_kernel_tss
212 addl $4, %esp 212 addl $4, %esp
213 213
214 /* Restore the context */ 214 /* Restore the context */
215 popw %gs 215 popw %gs
216 popw %fs 216 popw %fs
217 popw %es 217 popw %es
218 popw %ds 218 popw %ds
219 popw %ss 219 popw %ss
220 addl $2,%esp 220 addl $2,%esp
221 popl %eax 221 popl %eax
222 popl %ebx 222 popl %ebx
223 popl %ecx 223 popl %ecx
224 popl %edx 224 popl %edx
225 popl %esi 225 popl %esi
226 popl %edi 226 popl %edi
227 popl %ebp 227 popl %ebp
228 228
229 /* Error code isn't compatible 229 /* Error code isn't compatible with iretd */
230 addl $4, %esp 230 addl $4, %esp
231 231
232 iret 232 iret
233 .endr 233 .endr
234 234
235 235
236 /* Double fault handler not supported. We must 236 /* Double fault handler not supported. We must define it since we
237 define an entry for it in the sos_exception 237 define an entry for it in the sos_exception_wrapper_array. It
238 simply uses an alternate stack to display a 238 simply uses an alternate stack to display a message and stop the
239 system. qemu won't handle it correctly (see 239 system. qemu won't handle it correctly (see comment in qemu's
240 sources). */ 240 sources). */
241 #define ALTERNATE_DOUBLE_FAULT_STACK_SIZE 512 241 #define ALTERNATE_DOUBLE_FAULT_STACK_SIZE 512
242 .irp id, SOS_EXCEPT_DOUBLE_FAULT 242 .irp id, SOS_EXCEPT_DOUBLE_FAULT
243 .p2align 2, 0x90 243 .p2align 2, 0x90
244 sos_exception_wrapper_\id: 244 sos_exception_wrapper_\id:
245 .type sos_exception_wrapper_\id,@function 245 .type sos_exception_wrapper_\id,@function
246 1: cli /* Not necessary */ 246 1: cli /* Not necessary */
247 movl $double_fault_alternate_stack, %e 247 movl $double_fault_alternate_stack, %eax
248 addl $ALTERNATE_DOUBLE_FAULT_STACK_SIZ 248 addl $ALTERNATE_DOUBLE_FAULT_STACK_SIZE, %eax
249 movl %eax, %esp 249 movl %eax, %esp
250 pushl $msg_double_fault_not_supported 250 pushl $msg_double_fault_not_supported
251 call sos_display_fatal_error ; jmp 1b 251 call sos_display_fatal_error ; jmp 1b /* Not necessary */
252 .endr 252 .endr
253 253
254 .section ".rodata" 254 .section ".rodata"
255 msg_double_fault_not_supported: 255 msg_double_fault_not_supported:
256 .string "exception_wrappers.S: Double 256 .string "exception_wrappers.S: Double fault detected ! NOT SUPPORTED yet. System Halted."
257 257
258 /* Build the sos_irq_wrapper_array, shared wit 258 /* Build the sos_irq_wrapper_array, shared with interrupt.c */
259 .p2align 5, 0x0 259 .p2align 5, 0x0
260 sos_exception_wrapper_array: 260 sos_exception_wrapper_array:
261 .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12, 261 .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15, \
262 16,17,18,19,20,21,22,23,24,25 262 16,17,18,19,20,21,22,23,24,25,26,27,29,30,31
263 .long (sos_exception_wrapper_\id) 263 .long (sos_exception_wrapper_\id)
264 .endr 264 .endr
265 265
266 /* Alternate stack for double fault handler */ 266 /* Alternate stack for double fault handler */
267 .bss 267 .bss
268 .p2align 2, 0x0 268 .p2align 2, 0x0
269 .size double_fault_alternate_stack, ALTERNATE_ 269 .size double_fault_alternate_stack, ALTERNATE_DOUBLE_FAULT_STACK_SIZE
270 double_fault_alternate_stack: 270 double_fault_alternate_stack:
271 .fill ALTERNATE_DOUBLE_FAULT_STACK_SIZ 271 .fill ALTERNATE_DOUBLE_FAULT_STACK_SIZE, 1, 0x0