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 018
019 #include "segment.h" 019 #include "segment.h"
020 020
021 .file "irq_wrappers.S" 021 .file "irq_wrappers.S"
022 022
023 .text 023 .text
024 024
025 /** The address of the table of handlers (defi 025 /** The address of the table of handlers (defined in irq.c) */
026 .extern sos_irq_handler_array 026 .extern sos_irq_handler_array
027 027
028 /** The address of the table of wrappers (defi 028 /** The address of the table of wrappers (defined below, and shared
029 with irq.c */ 029 with irq.c */
030 .globl sos_irq_wrapper_array 030 .globl sos_irq_wrapper_array
031 031
032 /** The variable holding the nested level of t 032 /** The variable holding the nested level of the IRQ handlers */
033 .extern sos_irq_nested_level_counter 033 .extern sos_irq_nested_level_counter
034 034
035 /** Update the interrupted current thread's CP 035 /** Update the interrupted current thread's CPU context
036 Its prototype is: 036 Its prototype is:
037 sos_thread_prepare_irq_servicing(struct 037 sos_thread_prepare_irq_servicing(struct sos_cpu_state *);
038 */ 038 */
039 .extern sos_thread_prepare_irq_servicing 039 .extern sos_thread_prepare_irq_servicing
040 040
041 /** Update the kernel TSS in case we are switc 041 /** Update the kernel TSS in case we are switching to a thread in user
042 mode in order to come back into the co 042 mode in order to come back into the correct kernel stack */
043 .extern sos_cpu_context_update_kernel_tss 043 .extern sos_cpu_context_update_kernel_tss
044 044
045 /** Select a thread to set on CPU (this enable 045 /** Select a thread to set on CPU (this enables user-threads
046 preemption) and configure the MMU to match 046 preemption) and configure the MMU to match that of the destination
047 thread. 047 thread.
048 Its prototype is: 048 Its prototype is:
049 struct sos_cpu_state * // Selected CPU c 049 struct sos_cpu_state * // Selected CPU context
050 sos_thread_prepare_irq_switch_back(); 050 sos_thread_prepare_irq_switch_back();
051 */ 051 */
052 .extern sos_thread_prepare_irq_switch_back 052 .extern sos_thread_prepare_irq_switch_back
053 053
054 /* These pre-handlers are for IRQ (Master PIC) 054 /* These pre-handlers are for IRQ (Master PIC) */
055 .irp id, 0,1,2,3,4,5,6,7 055 .irp id, 0,1,2,3,4,5,6,7
056 056
057 .p2align 2, 0x90 057 .p2align 2, 0x90
058 058
059 sos_irq_wrapper_\id: 059 sos_irq_wrapper_\id:
060 .type sos_irq_wrapper_\id,@function 060 .type sos_irq_wrapper_\id,@function
061 061
062 /* 062 /*
063 * Backup the CPU context 063 * Backup the CPU context
064 */ 064 */
065 065
066 /* Fake error code */ 066 /* Fake error code */
067 pushl $0 067 pushl $0
068 068
069 /* Backup the actual context * 069 /* Backup the actual context */
070 pushl %ebp 070 pushl %ebp
071 movl %esp, %ebp 071 movl %esp, %ebp
072 072
073 pushl %edi 073 pushl %edi
074 pushl %esi 074 pushl %esi
075 pushl %edx 075 pushl %edx
076 pushl %ecx 076 pushl %ecx
077 pushl %ebx 077 pushl %ebx
078 pushl %eax 078 pushl %eax
079 subl $2,%esp 079 subl $2,%esp
080 pushw %ss 080 pushw %ss
081 pushw %ds 081 pushw %ds
082 pushw %es 082 pushw %es
083 pushw %fs 083 pushw %fs
084 pushw %gs 084 pushw %gs
085 085
086 /* Set correct kernel segment 086 /* Set correct kernel segment descriptors' value */
087 movw $SOS_BUILD_SEGMENT_REG_VA 087 movw $SOS_BUILD_SEGMENT_REG_VALUE(0, 0, SOS_SEG_KDATA), %di
088 pushw %di ; popw %ds 088 pushw %di ; popw %ds
089 pushw %di ; popw %es 089 pushw %di ; popw %es
090 pushw %di ; popw %fs 090 pushw %di ; popw %fs
091 pushw %di ; popw %gs 091 pushw %di ; popw %gs
092 092
093 /* 093 /*
094 * Increment IRQ nested level 094 * Increment IRQ nested level
095 */ 095 */
096 incl sos_irq_nested_level_coun 096 incl sos_irq_nested_level_counter
097 /* Outermost IRQ only: store t 097 /* Outermost IRQ only: store the interrupted context
098 of the current thread */ 098 of the current thread */
099 cmpl $1, sos_irq_nested_level_ 099 cmpl $1, sos_irq_nested_level_counter
100 jne 1f 100 jne 1f
101 pushl %esp 101 pushl %esp
102 call sos_thread_prepare_irq_se 102 call sos_thread_prepare_irq_servicing
103 addl $4, %esp 103 addl $4, %esp
104 104
105 1: 105 1:
106 106
107 /* Send EOI to PIC. See Intel 107 /* Send EOI to PIC. See Intel 8259 datasheet
108 available on Kos website */ 108 available on Kos website */
109 movb $0x20, %al 109 movb $0x20, %al
110 outb %al, $0x20 110 outb %al, $0x20
111 111
112 /* 112 /*
113 * Call the handler with IRQ n 113 * Call the handler with IRQ number as argument
114 */ 114 */
115 pushl $\id 115 pushl $\id
116 leal sos_irq_handler_array,%e 116 leal sos_irq_handler_array,%edi
117 call *\id*4(%edi) 117 call *\id*4(%edi)
118 addl $4, %esp 118 addl $4, %esp
119 119
120 /* 120 /*
121 * Decrement IRQ nested level 121 * Decrement IRQ nested level
122 */ 122 */
123 cli /* Just in case we messed 123 cli /* Just in case we messed up everything in the handler */
124 subl $1, sos_irq_nested_level_ 124 subl $1, sos_irq_nested_level_counter
125 125
126 /* sos_irq_nested_level_counte 126 /* sos_irq_nested_level_counter went below 0 ?! */
127 jnc 2f 127 jnc 2f
128 128
129 1: /* Yes: Print fatal error mess 129 1: /* Yes: Print fatal error message */
130 pushl $msg_nested_level_overfl 130 pushl $msg_nested_level_overflow
131 call sos_display_fatal_error 131 call sos_display_fatal_error
132 addl $4, %esp ; jmp 1b 132 addl $4, %esp ; jmp 1b
133 /* Never returns */ 133 /* Never returns */
134 134
135 2: /* No: all right ! */ 135 2: /* No: all right ! */
136 136
137 /* Was this the outermost IRQ 137 /* Was this the outermost IRQ handler ? */
138 jnz 3f 138 jnz 3f
139 139
140 /* Yes: reschedule */ 140 /* Yes: reschedule */
141 call sos_thread_prepare_irq_sw 141 call sos_thread_prepare_irq_switch_back
142 /* Establish new context: cont 142 /* Establish new context: context switch ! */
143 movl %eax, %esp 143 movl %eax, %esp
144 144
145 /* Prepare kernel TSS in case 145 /* Prepare kernel TSS in case we are switching to a
146 user thread: we make sure t 146 user thread: we make sure that we will come back
147 into the kernel at a correc 147 into the kernel at a correct stack location */
148 pushl %esp /* Pass the locatio 148 pushl %esp /* Pass the location of the context we are
149 restoring to the 149 restoring to the function */
150 call sos_cpu_context_update_ke 150 call sos_cpu_context_update_kernel_tss
151 addl $4, %esp 151 addl $4, %esp
152 3: 152 3:
153 /* Restore the context */ 153 /* Restore the context */
154 popw %gs 154 popw %gs
155 popw %fs 155 popw %fs
156 popw %es 156 popw %es
157 popw %ds 157 popw %ds
158 popw %ss 158 popw %ss
159 addl $2,%esp 159 addl $2,%esp
160 popl %eax 160 popl %eax
161 popl %ebx 161 popl %ebx
162 popl %ecx 162 popl %ecx
163 popl %edx 163 popl %edx
164 popl %esi 164 popl %esi
165 popl %edi 165 popl %edi
166 popl %ebp 166 popl %ebp
167 167
168 /* Remove fake error code */ 168 /* Remove fake error code */
169 addl $4, %esp 169 addl $4, %esp
170 170
171 iret 171 iret
172 .endr 172 .endr
173 173
174 174
175 /* These pre-handlers are for IRQ (Slave PIC) 175 /* These pre-handlers are for IRQ (Slave PIC) */
176 .irp id, 8,9,10,11,12,13,14,15 176 .irp id, 8,9,10,11,12,13,14,15
177 177
178 .p2align 2, 0x90 178 .p2align 2, 0x90
179 179
180 sos_irq_wrapper_\id: 180 sos_irq_wrapper_\id:
181 .type sos_irq_wrapper_\id,@function 181 .type sos_irq_wrapper_\id,@function
182 182
183 /* 183 /*
184 * Backup the CPU context 184 * Backup the CPU context
185 */ 185 */
186 186
187 /* Fake error code */ 187 /* Fake error code */
188 pushl $0 188 pushl $0
189 189
190 /* Backup the actual context * 190 /* Backup the actual context */
191 pushl %ebp 191 pushl %ebp
192 movl %esp, %ebp 192 movl %esp, %ebp
193 193
194 pushl %edi 194 pushl %edi
195 pushl %esi 195 pushl %esi
196 pushl %edx 196 pushl %edx
197 pushl %ecx 197 pushl %ecx
198 pushl %ebx 198 pushl %ebx
199 pushl %eax 199 pushl %eax
200 subl $2,%esp 200 subl $2,%esp
201 pushw %ss 201 pushw %ss
202 pushw %ds 202 pushw %ds
203 pushw %es 203 pushw %es
204 pushw %fs 204 pushw %fs
205 pushw %gs 205 pushw %gs
206 206
207 /* Set correct kernel segment 207 /* Set correct kernel segment descriptors' value */
208 movw $SOS_BUILD_SEGMENT_REG_VA 208 movw $SOS_BUILD_SEGMENT_REG_VALUE(0, 0, SOS_SEG_KDATA), %di
209 pushw %di ; popw %ds 209 pushw %di ; popw %ds
210 pushw %di ; popw %es 210 pushw %di ; popw %es
211 pushw %di ; popw %fs 211 pushw %di ; popw %fs
212 pushw %di ; popw %gs 212 pushw %di ; popw %gs
213 213
214 /* 214 /*
215 * Increment IRQ nested level 215 * Increment IRQ nested level
216 */ 216 */
217 incl sos_irq_nested_level_coun 217 incl sos_irq_nested_level_counter
218 /* Outermost IRQ only: store t 218 /* Outermost IRQ only: store the interrupted context
219 of the current thread */ 219 of the current thread */
220 cmpl $1, sos_irq_nested_level_ 220 cmpl $1, sos_irq_nested_level_counter
221 jne 1f 221 jne 1f
222 pushl %esp 222 pushl %esp
223 call sos_thread_prepare_irq_se 223 call sos_thread_prepare_irq_servicing
224 addl $4, %esp 224 addl $4, %esp
225 225
226 1: 226 1:
227 227
228 /* Send EOI to PIC. See Intel 228 /* Send EOI to PIC. See Intel 8259 datasheet
229 available on Kos website */ 229 available on Kos website */
230 movb $0x20, %al 230 movb $0x20, %al
231 outb %al, $0xa0 231 outb %al, $0xa0
232 outb %al, $0x20 232 outb %al, $0x20
233 233
234 /* 234 /*
235 * Call the handler with IRQ n 235 * Call the handler with IRQ number as argument
236 */ 236 */
237 pushl $\id 237 pushl $\id
238 leal sos_irq_handler_array,%e 238 leal sos_irq_handler_array,%edi
239 call *\id*4(%edi) 239 call *\id*4(%edi)
240 addl $4, %esp 240 addl $4, %esp
241 241
242 /* 242 /*
243 * Decrement IRQ nested level 243 * Decrement IRQ nested level
244 */ 244 */
245 cli /* Just in case we messed 245 cli /* Just in case we messed up everything in the handler */
246 subl $1, sos_irq_nested_level_ 246 subl $1, sos_irq_nested_level_counter
247 247
248 /* sos_irq_nested_level_counte 248 /* sos_irq_nested_level_counter went below 0 ?! */
249 jnc 2f 249 jnc 2f
250 250
251 1: /* Yes: Print fatal error mess 251 1: /* Yes: Print fatal error message */
252 pushl $msg_nested_level_overfl 252 pushl $msg_nested_level_overflow
253 call sos_display_fatal_error 253 call sos_display_fatal_error
254 addl $4, %esp ; jmp 1b 254 addl $4, %esp ; jmp 1b
255 /* Never returns */ 255 /* Never returns */
256 256
257 2: /* No: all right ! */ 257 2: /* No: all right ! */
258 258
259 /* Was this the outermost IRQ 259 /* Was this the outermost IRQ handler ? */
260 jnz 3f 260 jnz 3f
261 261
262 /* Yes: reschedule */ 262 /* Yes: reschedule */
263 call sos_thread_prepare_irq_sw 263 call sos_thread_prepare_irq_switch_back
264 /* Establish new context: cont 264 /* Establish new context: context switch ! */
265 movl %eax, %esp 265 movl %eax, %esp
266 266
267 /* Prepare kernel TSS in case 267 /* Prepare kernel TSS in case we are switching to a
268 user thread: we make sure t 268 user thread: we make sure that we will come back
269 into the kernel at a correc 269 into the kernel at a correct stack location */
270 pushl %esp /* Pass the locatio 270 pushl %esp /* Pass the location of the context we are
271 restoring to the 271 restoring to the function */
272 call sos_cpu_context_update_ke 272 call sos_cpu_context_update_kernel_tss
273 addl $4, %esp 273 addl $4, %esp
274 3: 274 3:
275 /* Restore the context */ 275 /* Restore the context */
276 popw %gs 276 popw %gs
277 popw %fs 277 popw %fs
278 popw %es 278 popw %es
279 popw %ds 279 popw %ds
280 popw %ss 280 popw %ss
281 addl $2,%esp 281 addl $2,%esp
282 popl %eax 282 popl %eax
283 popl %ebx 283 popl %ebx
284 popl %ecx 284 popl %ecx
285 popl %edx 285 popl %edx
286 popl %esi 286 popl %esi
287 popl %edi 287 popl %edi
288 popl %ebp 288 popl %ebp
289 289
290 /* Remove fake error code */ 290 /* Remove fake error code */
291 addl $4, %esp 291 addl $4, %esp
292 292
293 iret 293 iret
294 .endr 294 .endr
295 295
296 .section ".rodata" 296 .section ".rodata"
297 msg_nested_level_overflow: 297 msg_nested_level_overflow:
298 .string "irq_wrappers.S: IRQ Nested le 298 .string "irq_wrappers.S: IRQ Nested level overflow ! System halted."
299 299
300 /* Build the sos_irq_wrapper_array, shared wit 300 /* Build the sos_irq_wrapper_array, shared with irq.c */
301 .p2align 5, 0x0 301 .p2align 5, 0x0
302 sos_irq_wrapper_array: 302 sos_irq_wrapper_array:
303 .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12, 303 .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
304 .long (sos_irq_wrapper_\id) 304 .long (sos_irq_wrapper_\id)
305 .endr 305 .endr