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