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