Diff markup
001 /* Copyright (C) 2004 The KOS Team 001 /* Copyright (C) 2004 The KOS Team
>> 002 Copyright (C) 1999 Free Software Foundation, Inc.
002 003
003 This program is free software; you can redi 004 This program is free software; you can redistribute it and/or
004 modify it under the terms of the GNU Genera 005 modify it under the terms of the GNU General Public License
005 as published by the Free Software Foundatio 006 as published by the Free Software Foundation; either version 2
006 of the License, or (at your option) any lat 007 of the License, or (at your option) any later version.
007 008
008 This program is distributed in the hope tha 009 This program is distributed in the hope that it will be useful,
009 but WITHOUT ANY WARRANTY; without even the 010 but WITHOUT ANY WARRANTY; without even the implied warranty of
010 MERCHANTABILITY or FITNESS FOR A PARTICULAR 011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
011 GNU General Public License for more details 012 GNU General Public License for more details.
012 013
013 You should have received a copy of the GNU 014 You should have received a copy of the GNU General Public License
014 along with this program; if not, write to t 015 along with this program; if not, write to the Free Software
015 Foundation, Inc., 59 Temple Place - Suite 3 016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
016 USA. 017 USA.
017 */ 018 */
018 !! 019 #define ASM_SOURCE 1
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 <<
036 Its prototype is: <<
037 sos_thread_prepare_irq_servicing(struct <<
038 */ <<
039 .extern sos_thread_prepare_irq_servicing <<
040 <<
041 /** Update the kernel TSS in case we are switc <<
042 mode in order to come back into the co <<
043 .extern sos_cpu_context_update_kernel_tss <<
044 <<
045 /** Select a thread to set on CPU (this enable <<
046 preemption) and configure the MMU to match <<
047 thread. <<
048 Its prototype is: <<
049 struct sos_cpu_state * // Selected CPU c <<
050 sos_thread_prepare_irq_switch_back(); <<
051 */ <<
052 .extern sos_thread_prepare_irq_switch_back <<
053 <<
054 /* These pre-handlers are for IRQ (Master PIC) 035 /* These pre-handlers are for IRQ (Master PIC) */
055 .irp id, 0,1,2,3,4,5,6,7 036 .irp id, 0,1,2,3,4,5,6,7
056 037
057 .p2align 2, 0x90 038 .p2align 2, 0x90
058 039
059 sos_irq_wrapper_\id: 040 sos_irq_wrapper_\id:
060 .type sos_irq_wrapper_\id,@function 041 .type sos_irq_wrapper_\id,@function
061 042
062 /* 043 /*
063 * Backup the CPU context 044 * Backup the CPU context
064 */ 045 */
065 046
066 /* Fake error code */ 047 /* Fake error code */
067 pushl $0 048 pushl $0
068 049
069 /* Backup the actual context * 050 /* Backup the actual context */
070 pushl %ebp 051 pushl %ebp
071 movl %esp, %ebp 052 movl %esp, %ebp
072 053
073 pushl %edi 054 pushl %edi
074 pushl %esi 055 pushl %esi
075 pushl %edx 056 pushl %edx
076 pushl %ecx 057 pushl %ecx
077 pushl %ebx 058 pushl %ebx
078 pushl %eax 059 pushl %eax
079 subl $2,%esp 060 subl $2,%esp
080 pushw %ss 061 pushw %ss
081 pushw %ds 062 pushw %ds
082 pushw %es 063 pushw %es
083 pushw %fs 064 pushw %fs
084 pushw %gs 065 pushw %gs
085 066
086 /* Set correct kernel segment <<
087 movw $SOS_BUILD_SEGMENT_REG_VA <<
088 pushw %di ; popw %ds <<
089 pushw %di ; popw %es <<
090 pushw %di ; popw %fs <<
091 pushw %di ; popw %gs <<
092 <<
093 /* 067 /*
094 * Increment IRQ nested level 068 * Increment IRQ nested level
095 */ 069 */
096 incl sos_irq_nested_level_coun 070 incl sos_irq_nested_level_counter
097 /* Outermost IRQ only: store t <<
098 of the current thread */ <<
099 cmpl $1, sos_irq_nested_level_ <<
100 jne 1f <<
101 pushl %esp <<
102 call sos_thread_prepare_irq_se <<
103 addl $4, %esp <<
104 <<
105 1: <<
106 071
107 /* Send EOI to PIC. See Intel 072 /* Send EOI to PIC. See Intel 8259 datasheet
108 available on Kos website */ 073 available on Kos website */
109 movb $0x20, %al 074 movb $0x20, %al
110 outb %al, $0x20 075 outb %al, $0x20
111 076
112 /* 077 /*
113 * Call the handler with IRQ n !! 078 * Call the handler with the IRQ number and the
>> 079 * address of the stored CPU context as arguments
114 */ 080 */
>> 081 pushl %esp
115 pushl $\id 082 pushl $\id
116 leal sos_irq_handler_array,%e 083 leal sos_irq_handler_array,%edi
117 call *\id*4(%edi) 084 call *\id*4(%edi)
118 addl $4, %esp !! 085 /* Unallocate the arguments passed to the handler */
>> 086 addl $8, %esp
119 087
120 /* 088 /*
121 * Decrement IRQ nested level 089 * Decrement IRQ nested level
122 */ 090 */
123 cli /* Just in case we messed 091 cli /* Just in case we messed up everything in the handler */
124 subl $1, sos_irq_nested_level_ 092 subl $1, sos_irq_nested_level_counter
125 093
126 /* sos_irq_nested_level_counte 094 /* sos_irq_nested_level_counter went below 0 ?! */
127 jnc 2f 095 jnc 2f
128 096
129 1: /* Yes: Print fatal error mess 097 1: /* Yes: Print fatal error message */
130 pushl $msg_nested_level_overfl 098 pushl $msg_nested_level_overflow
131 call sos_display_fatal_error 099 call sos_display_fatal_error
132 addl $4, %esp ; jmp 1b 100 addl $4, %esp ; jmp 1b
133 /* Never returns */ 101 /* Never returns */
134 102
135 2: /* No: all right ! */ 103 2: /* No: all right ! */
136 104
137 /* Was this the outermost IRQ <<
138 jnz 3f <<
139 <<
140 /* Yes: reschedule */ <<
141 call sos_thread_prepare_irq_sw <<
142 /* Establish new context: cont <<
143 movl %eax, %esp <<
144 <<
145 /* Prepare kernel TSS in case <<
146 user thread: we make sure t <<
147 into the kernel at a correc <<
148 pushl %esp /* Pass the locatio <<
149 restoring to the <<
150 call sos_cpu_context_update_ke <<
151 addl $4, %esp <<
152 3: <<
153 /* Restore the context */ 105 /* Restore the context */
154 popw %gs 106 popw %gs
155 popw %fs 107 popw %fs
156 popw %es 108 popw %es
157 popw %ds 109 popw %ds
158 popw %ss 110 popw %ss
159 addl $2,%esp 111 addl $2,%esp
160 popl %eax 112 popl %eax
161 popl %ebx 113 popl %ebx
162 popl %ecx 114 popl %ecx
163 popl %edx 115 popl %edx
164 popl %esi 116 popl %esi
165 popl %edi 117 popl %edi
166 popl %ebp 118 popl %ebp
167 119
168 /* Remove fake error code */ 120 /* Remove fake error code */
169 addl $4, %esp 121 addl $4, %esp
170 122
171 iret 123 iret
172 .endr 124 .endr
173 125
174 126
175 /* These pre-handlers are for IRQ (Slave PIC) 127 /* These pre-handlers are for IRQ (Slave PIC) */
176 .irp id, 8,9,10,11,12,13,14,15 128 .irp id, 8,9,10,11,12,13,14,15
177 129
178 .p2align 2, 0x90 130 .p2align 2, 0x90
179 131
180 sos_irq_wrapper_\id: 132 sos_irq_wrapper_\id:
181 .type sos_irq_wrapper_\id,@function 133 .type sos_irq_wrapper_\id,@function
182 134
183 /* 135 /*
184 * Backup the CPU context 136 * Backup the CPU context
185 */ 137 */
186 138
187 /* Fake error code */ 139 /* Fake error code */
188 pushl $0 140 pushl $0
189 141
190 /* Backup the actual context * 142 /* Backup the actual context */
191 pushl %ebp 143 pushl %ebp
192 movl %esp, %ebp 144 movl %esp, %ebp
193 145
194 pushl %edi 146 pushl %edi
195 pushl %esi 147 pushl %esi
196 pushl %edx 148 pushl %edx
197 pushl %ecx 149 pushl %ecx
198 pushl %ebx 150 pushl %ebx
199 pushl %eax 151 pushl %eax
200 subl $2,%esp 152 subl $2,%esp
201 pushw %ss 153 pushw %ss
202 pushw %ds 154 pushw %ds
203 pushw %es 155 pushw %es
204 pushw %fs 156 pushw %fs
205 pushw %gs 157 pushw %gs
206 158
207 /* Set correct kernel segment <<
208 movw $SOS_BUILD_SEGMENT_REG_VA <<
209 pushw %di ; popw %ds <<
210 pushw %di ; popw %es <<
211 pushw %di ; popw %fs <<
212 pushw %di ; popw %gs <<
213 <<
214 /* 159 /*
215 * Increment IRQ nested level 160 * Increment IRQ nested level
216 */ 161 */
217 incl sos_irq_nested_level_coun 162 incl sos_irq_nested_level_counter
218 /* Outermost IRQ only: store t <<
219 of the current thread */ <<
220 cmpl $1, sos_irq_nested_level_ <<
221 jne 1f <<
222 pushl %esp <<
223 call sos_thread_prepare_irq_se <<
224 addl $4, %esp <<
225 <<
226 1: <<
227 163
228 /* Send EOI to PIC. See Intel 164 /* Send EOI to PIC. See Intel 8259 datasheet
229 available on Kos website */ 165 available on Kos website */
230 movb $0x20, %al 166 movb $0x20, %al
231 outb %al, $0xa0 167 outb %al, $0xa0
232 outb %al, $0x20 168 outb %al, $0x20
233 169
234 /* 170 /*
235 * Call the handler with IRQ n !! 171 * Call the handler with the IRQ number and the
>> 172 * address of the stored CPU context as arguments
236 */ 173 */
>> 174 pushl %esp
237 pushl $\id 175 pushl $\id
238 leal sos_irq_handler_array,%e 176 leal sos_irq_handler_array,%edi
239 call *\id*4(%edi) 177 call *\id*4(%edi)
240 addl $4, %esp !! 178 /* Unallocate the arguments passed to the handler */
>> 179 addl $8, %esp
241 180
242 /* 181 /*
243 * Decrement IRQ nested level 182 * Decrement IRQ nested level
244 */ 183 */
245 cli /* Just in case we messed 184 cli /* Just in case we messed up everything in the handler */
246 subl $1, sos_irq_nested_level_ 185 subl $1, sos_irq_nested_level_counter
247 186
248 /* sos_irq_nested_level_counte 187 /* sos_irq_nested_level_counter went below 0 ?! */
249 jnc 2f 188 jnc 2f
250 189
251 1: /* Yes: Print fatal error mess 190 1: /* Yes: Print fatal error message */
252 pushl $msg_nested_level_overfl 191 pushl $msg_nested_level_overflow
253 call sos_display_fatal_error 192 call sos_display_fatal_error
254 addl $4, %esp ; jmp 1b 193 addl $4, %esp ; jmp 1b
255 /* Never returns */ 194 /* Never returns */
256 195
257 2: /* No: all right ! */ 196 2: /* No: all right ! */
258 197
259 /* Was this the outermost IRQ <<
260 jnz 3f <<
261 <<
262 /* Yes: reschedule */ <<
263 call sos_thread_prepare_irq_sw <<
264 /* Establish new context: cont <<
265 movl %eax, %esp <<
266 <<
267 /* Prepare kernel TSS in case <<
268 user thread: we make sure t <<
269 into the kernel at a correc <<
270 pushl %esp /* Pass the locatio <<
271 restoring to the <<
272 call sos_cpu_context_update_ke <<
273 addl $4, %esp <<
274 3: <<
275 /* Restore the context */ 198 /* Restore the context */
276 popw %gs 199 popw %gs
277 popw %fs 200 popw %fs
278 popw %es 201 popw %es
279 popw %ds 202 popw %ds
280 popw %ss 203 popw %ss
281 addl $2,%esp 204 addl $2,%esp
282 popl %eax 205 popl %eax
283 popl %ebx 206 popl %ebx
284 popl %ecx 207 popl %ecx
285 popl %edx 208 popl %edx
286 popl %esi 209 popl %esi
287 popl %edi 210 popl %edi
288 popl %ebp 211 popl %ebp
289 212
290 /* Remove fake error code */ 213 /* Remove fake error code */
291 addl $4, %esp 214 addl $4, %esp
292 215
293 iret 216 iret
294 .endr 217 .endr
295 218
296 .section ".rodata" 219 .section ".rodata"
297 msg_nested_level_overflow: 220 msg_nested_level_overflow:
298 .string "irq_wrappers.S: IRQ Nested le 221 .string "irq_wrappers.S: IRQ Nested level overflow ! System halted."
299 222
300 /* Build the sos_irq_wrapper_array, shared wit 223 /* Build the sos_irq_wrapper_array, shared with irq.c */
301 .p2align 5, 0x0 224 .p2align 5, 0x0
302 sos_irq_wrapper_array: 225 sos_irq_wrapper_array:
303 .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12, 226 .irp id, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
304 .long (sos_irq_wrapper_\id) 227 .long (sos_irq_wrapper_\id)
305 .endr 228 .endr