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