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