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