Changeset 6dce6af in mainline
- Timestamp:
- 2010-07-01T21:29:43Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 54171e8
- Parents:
- c685fc8
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ia32/src/asm.S
rc685fc8 r6dce6af 1 # 2 # Copyright (c) 2001-2004 Jakub Jermar 3 # All rights reserved. 4 # 5 # Redistribution and use in source and binary forms, with or without 6 # modification, are permitted provided that the following conditions 7 # are met: 8 # 9 # - Redistributions of source code must retain the above copyright 10 # notice, this list of conditions and the following disclaimer. 11 # - Redistributions in binary form must reproduce the above copyright 12 # notice, this list of conditions and the following disclaimer in the 13 # documentation and/or other materials provided with the distribution. 14 # - The name of the author may not be used to endorse or promote products 15 # derived from this software without specific prior written permission. 16 # 17 # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 # 28 29 ## very low and hardware-level functions 30 31 # Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int has no error 32 # word and 1 means interrupt with error word 33 #define ERROR_WORD_INTERRUPT_LIST 0x00027d00 1 /* 2 * Copyright (c) 2001 Jakub Jermar 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * - The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /** Very low and hardware-level functions 30 * 31 */ 32 33 /** 34 * Mask for interrupts 0 - 31 (bits 0 - 31) where 0 means that int 35 * has no error word and 1 means interrupt with error word 36 * 37 */ 38 #define ERROR_WORD_INTERRUPT_LIST 0x00027d00 34 39 35 40 .text … … 47 52 48 53 49 # Wrapper for generic memsetb 54 /* Wrapper for generic memsetb */ 50 55 memsetb: 51 56 jmp _memsetb 52 57 53 # Wrapper for generic memsetw 58 /* Wrapper for generic memsetw */ 54 59 memsetw: 55 60 jmp _memsetw 56 61 57 58 #define MEMCPY_DST 4 59 #define MEMCPY_SRC 8 60 #define MEMCPY_SIZE 12 62 #define MEMCPY_DST 4 63 #define MEMCPY_SRC 8 64 #define MEMCPY_SIZE 12 61 65 62 66 /** Copy memory to/from userspace. … … 68 72 * or copy_to_uspace(). 69 73 * 70 * @param MEMCPY_DST(%esp) 71 * @param MEMCPY_SRC(%esp) 72 * @param MEMCPY_SIZE(%esp) 74 * @param MEMCPY_DST(%esp) Destination address. 75 * @param MEMCPY_SRC(%esp) Source address. 76 * @param MEMCPY_SIZE(%esp) Size. 73 77 * 74 78 * @return MEMCPY_DST(%esp) on success and 0 on failure. 79 * 75 80 */ 76 81 memcpy: 77 82 memcpy_from_uspace: 78 83 memcpy_to_uspace: 79 movl %edi, %edx 80 movl %esi, %eax 84 movl %edi, %edx /* save %edi */ 85 movl %esi, %eax /* save %esi */ 81 86 82 87 movl MEMCPY_SIZE(%esp), %ecx 83 shrl $2, %ecx 88 shrl $2, %ecx /* size / 4 */ 84 89 85 90 movl MEMCPY_DST(%esp), %edi 86 91 movl MEMCPY_SRC(%esp), %esi 87 92 88 rep movsl /* copy whole words */ 89 93 /* Copy whole words */ 94 rep movsl 95 90 96 movl MEMCPY_SIZE(%esp), %ecx 91 andl $3, %ecx 97 andl $3, %ecx /* size % 4 */ 92 98 jz 0f 93 99 94 rep movsb /* copy the rest byte by byte */ 95 96 0: 97 movl %edx, %edi 98 movl %eax, %esi 99 movl MEMCPY_DST(%esp), %eax /* MEMCPY_DST(%esp), success */ 100 ret 101 100 /* Copy the rest byte by byte */ 101 rep movsb 102 103 0: 104 105 movl %edx, %edi 106 movl %eax, %esi 107 108 /* MEMCPY_DST(%esp), success */ 109 movl MEMCPY_DST(%esp), %eax 110 ret 111 102 112 /* 103 113 * We got here from as_page_fault() after the memory operations … … 108 118 movl %edx, %edi 109 119 movl %eax, %esi 110 xorl %eax, %eax /* return 0, failure */ 120 121 /* Return 0, failure */ 122 xorl %eax, %eax 111 123 ret 112 124 113 ## Turn paging on 114 # 115 # Enable paging and write-back caching in CR0. 116 # 125 /** Turn paging on 126 * 127 * Enable paging and write-back caching in CR0. 128 * 129 */ 117 130 paging_on: 118 131 movl %cr0, %edx 119 orl $(1 << 31), %edx # paging on 120 # clear Cache Disable and not Write Though 132 orl $(1 << 31), %edx /* paging on */ 133 134 /* Clear Cache Disable and not Write Though */ 121 135 andl $~((1 << 30) | (1 << 29)), %edx 122 movl %edx, %cr0136 movl %edx, %cr0 123 137 jmp 0f 124 0: 125 ret 126 127 128 ## Enable local APIC 129 # 130 # Enable local APIC in MSR. 131 # 138 139 0: 140 ret 141 142 /** Enable local APIC 143 * 144 * Enable local APIC in MSR. 145 * 146 */ 132 147 enable_l_apic_in_msr: 133 148 movl $0x1b, %ecx … … 138 153 ret 139 154 140 # Clear nested flag 141 # overwrites %ecx 155 /** Clear nested flag 156 * 157 */ 142 158 .macro CLEAR_NT_FLAG 143 159 pushfl 144 160 andl $0xffffbfff, (%esp) 145 161 popfl 146 .endm 162 .endm 147 163 148 164 /* … … 158 174 sysenter_handler: 159 175 sti 160 pushl %ebp # remember user stack161 pushl %edi # remember return user address162 163 xorl %ebp, %ebp # stop stack traces here164 165 pushl %gs # remember TLS166 167 pushl %eax # syscall number168 subl $8, %esp # unused sixth and fifth argument169 pushl %esi # fourth argument170 pushl %ebx # third argument171 pushl %ecx # second argument172 pushl %edx # first argument173 176 pushl %ebp /* remember user stack */ 177 pushl %edi /* remember return user address */ 178 179 xorl %ebp, %ebp /* stop stack traces here */ 180 181 pushl %gs /* remember TLS */ 182 183 pushl %eax /* syscall number */ 184 subl $8, %esp /* unused sixth and fifth argument */ 185 pushl %esi /* fourth argument */ 186 pushl %ebx /* third argument */ 187 pushl %ecx /* second argument */ 188 pushl %edx /* first argument */ 189 174 190 movw $16, %ax 175 191 movw %ax, %ds 176 192 movw %ax, %es 177 193 178 194 cld 179 195 call syscall_handler 180 addl $28, %esp # remove arguments from stack 181 182 pop %gs # restore TLS 183 184 pop %edx # prepare return EIP for SYSEXIT 185 pop %ecx # prepare userspace ESP for SYSEXIT 186 187 sysexit # return to userspace 188 189 190 #define ISTATE_OFFSET_EAX 0 191 #define ISTATE_OFFSET_EBX 4 192 #define ISTATE_OFFSET_ECX 8 193 #define ISTATE_OFFSET_EDX 12 194 #define ISTATE_OFFSET_EDI 16 195 #define ISTATE_OFFSET_ESI 20 196 #define ISTATE_OFFSET_EBP 24 197 #define ISTATE_OFFSET_EBP_FRAME 28 198 #define ISTATE_OFFSET_EIP_FRAME 32 199 #define ISTATE_OFFSET_GS 36 200 #define ISTATE_OFFSET_FS 40 201 #define ISTATE_OFFSET_ES 44 202 #define ISTATE_OFFSET_DS 48 203 #define ISTATE_OFFSET_ERROR_WORD 52 204 #define ISTATE_OFFSET_EIP 56 205 #define ISTATE_OFFSET_CS 60 206 #define ISTATE_OFFSET_EFLAGS 64 207 #define ISTATE_OFFSET_ESP 68 208 #define ISTATE_OFFSET_SS 72 196 addl $28, %esp /* remove arguments from stack */ 197 198 pop %gs /* restore TLS */ 199 200 pop %edx /* prepare return EIP for SYSEXIT */ 201 pop %ecx /* prepare userspace ESP for SYSEXIT */ 202 203 sysexit /* return to userspace */ 204 205 #define ISTATE_OFFSET_EAX 0 206 #define ISTATE_OFFSET_EBX 4 207 #define ISTATE_OFFSET_ECX 8 208 #define ISTATE_OFFSET_EDX 12 209 #define ISTATE_OFFSET_EDI 16 210 #define ISTATE_OFFSET_ESI 20 211 #define ISTATE_OFFSET_EBP 24 212 #define ISTATE_OFFSET_EBP_FRAME 28 213 #define ISTATE_OFFSET_EIP_FRAME 32 214 #define ISTATE_OFFSET_GS 36 215 #define ISTATE_OFFSET_FS 40 216 #define ISTATE_OFFSET_ES 44 217 #define ISTATE_OFFSET_DS 48 218 #define ISTATE_OFFSET_ERROR_WORD 52 219 #define ISTATE_OFFSET_EIP 56 220 #define ISTATE_OFFSET_CS 60 221 #define ISTATE_OFFSET_EFLAGS 64 222 #define ISTATE_OFFSET_ESP 68 223 #define ISTATE_OFFSET_SS 72 209 224 210 225 /* 211 * Size of the istate structure without the hardware-saved part and without the 212 * error word. 213 */ 214 #define ISTATE_SOFT_SIZE 52 215 216 ## Declare interrupt handlers 217 # 218 # Declare interrupt handlers for n interrupt 219 # vectors starting at vector i. 220 # 221 # The handlers setup data segment registers 222 # and call exc_dispatch(). 223 # 224 #define INTERRUPT_ALIGN 256 226 * Size of the istate structure without the hardware-saved part 227 * and without the error word. 228 */ 229 #define ISTATE_SOFT_SIZE 52 230 231 /** Declare interrupt handlers 232 * 233 * Declare interrupt handlers for n interrupt 234 * vectors starting at vector i. 235 * 236 * The handlers setup data segment registers 237 * and call exc_dispatch(). 238 * 239 */ 240 #define INTERRUPT_ALIGN 256 241 225 242 .macro handler i n 226 227 .ifeq \i - 0x30 # Syscall handler 228 pushl %ds 229 pushl %es 230 pushl %fs 231 pushl %gs 232 233 # 234 # Push syscall arguments onto the stack 235 # 236 # NOTE: The idea behind the order of arguments passed in registers is to 237 # use all scratch registers first and preserved registers next. 238 # An optimized libc syscall wrapper can make use of this setup. 239 # 240 pushl %eax 241 pushl %ebp 242 pushl %edi 243 pushl %esi 244 pushl %ebx 245 pushl %ecx 246 pushl %edx 247 248 # we must fill the data segment registers 249 movw $16, %ax 250 movw %ax, %ds 251 movw %ax, %es 252 253 xorl %ebp, %ebp 254 255 cld 256 sti 257 # syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) 258 call syscall_handler 259 cli 260 261 movl 20(%esp), %ebp # restore EBP 262 addl $28, %esp # clean-up of parameters 263 264 popl %gs 265 popl %fs 266 popl %es 267 popl %ds 268 269 CLEAR_NT_FLAG 270 iret 271 .else 272 /* 273 * This macro distinguishes between two versions of ia32 exceptions. 274 * One version has error word and the other does not have it. 275 * The latter version fakes the error word on the stack so that the 276 * handlers and istate_t can be the same for both types. 277 */ 278 .iflt \i - 32 279 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST 280 # 281 # Exception with error word: do nothing 282 # 283 .else 284 # 285 # Exception without error word: fake up one 286 # 287 pushl $0 288 .endif 289 .else 290 # 291 # Interrupt: fake up one 292 # 293 pushl $0 294 .endif 295 296 subl $ISTATE_SOFT_SIZE, %esp 297 298 # 299 # Save the general purpose registers. 300 # 301 movl %eax, ISTATE_OFFSET_EAX(%esp) 302 movl %ebx, ISTATE_OFFSET_EBX(%esp) 303 movl %ecx, ISTATE_OFFSET_ECX(%esp) 304 movl %edx, ISTATE_OFFSET_EDX(%esp) 305 movl %edi, ISTATE_OFFSET_EDI(%esp) 306 movl %esi, ISTATE_OFFSET_ESI(%esp) 307 movl %ebp, ISTATE_OFFSET_EBP(%esp) 308 309 # 310 # Save the selector registers. 311 # 312 movl %gs, %eax 313 movl %fs, %ebx 314 movl %es, %ecx 315 movl %ds, %edx 316 317 movl %eax, ISTATE_OFFSET_GS(%esp) 318 movl %ebx, ISTATE_OFFSET_FS(%esp) 319 movl %ecx, ISTATE_OFFSET_ES(%esp) 320 movl %edx, ISTATE_OFFSET_DS(%esp) 321 322 # 323 # Switch to kernel selectors. 324 # 325 movl $16, %eax 326 movl %eax, %ds 327 movl %eax, %es 328 329 # 330 # Imitate a regular stack frame linkage. 331 # Stop stack traces here if we came from userspace. 332 # 333 cmpl $8, ISTATE_OFFSET_CS(%esp) 334 jz 0f 335 xorl %ebp, %ebp 336 0: movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp) 337 movl ISTATE_OFFSET_EIP(%esp), %eax 338 movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp) 339 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 340 341 cld 342 343 pushl %esp # pass istate address 344 pushl $(\i) # pass intnum 345 call exc_dispatch # exc_dispatch(intnum, istate) 346 addl $8, %esp # Clear arguments from the stack 347 348 CLEAR_NT_FLAG 349 350 # 351 # Restore the selector registers. 352 # 353 movl ISTATE_OFFSET_GS(%esp), %eax 354 movl ISTATE_OFFSET_FS(%esp), %ebx 355 movl ISTATE_OFFSET_ES(%esp), %ecx 356 movl ISTATE_OFFSET_DS(%esp), %edx 357 358 movl %eax, %gs 359 movl %ebx, %fs 360 movl %ecx, %es 361 movl %edx, %ds 362 363 # 364 # Restore the scratch registers and the preserved registers the handler 365 # cloberred itself (i.e. EBX and EBP). 366 # 367 movl ISTATE_OFFSET_EAX(%esp), %eax 368 movl ISTATE_OFFSET_EBX(%esp), %ebx 369 movl ISTATE_OFFSET_ECX(%esp), %ecx 370 movl ISTATE_OFFSET_EDX(%esp), %edx 371 movl ISTATE_OFFSET_EBP(%esp), %ebp 372 373 addl $(ISTATE_SOFT_SIZE + 4), %esp 374 iret 375 .endif 376 377 .align INTERRUPT_ALIGN 378 .if (\n- \i) - 1 379 handler "(\i + 1)", \n 380 .endif 243 .ifeq \i - 0x30 244 /* Syscall handler */ 245 pushl %ds 246 pushl %es 247 pushl %fs 248 pushl %gs 249 250 /* 251 * Push syscall arguments onto the stack 252 * 253 * NOTE: The idea behind the order of arguments passed 254 * in registers is to use all scratch registers 255 * first and preserved registers next. An optimized 256 * libc syscall wrapper can make use of this setup. 257 * 258 */ 259 pushl %eax 260 pushl %ebp 261 pushl %edi 262 pushl %esi 263 pushl %ebx 264 pushl %ecx 265 pushl %edx 266 267 /* We must fill the data segment registers */ 268 movw $16, %ax 269 movw %ax, %ds 270 movw %ax, %es 271 272 xorl %ebp, %ebp 273 274 cld 275 sti 276 277 /* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */ 278 call syscall_handler 279 cli 280 281 movl 20(%esp), %ebp /* restore EBP */ 282 addl $28, %esp /* clean-up of parameters */ 283 284 popl %gs 285 popl %fs 286 popl %es 287 popl %ds 288 289 CLEAR_NT_FLAG 290 iret 291 .else 292 /* 293 * This macro distinguishes between two versions of ia32 294 * exceptions. One version has error word and the other 295 * does not have it. The latter version fakes the error 296 * word on the stack so that the handlers and istate_t 297 * can be the same for both types. 298 */ 299 .iflt \i - 32 300 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST 301 /* 302 * Exception with error word: do nothing 303 */ 304 .else 305 /* 306 * Exception without error word: fake up one 307 */ 308 pushl $0 309 .endif 310 .else 311 /* 312 * Interrupt: fake up one 313 */ 314 pushl $0 315 .endif 316 317 subl $ISTATE_SOFT_SIZE, %esp 318 319 /* 320 * Save the general purpose registers. 321 */ 322 movl %eax, ISTATE_OFFSET_EAX(%esp) 323 movl %ebx, ISTATE_OFFSET_EBX(%esp) 324 movl %ecx, ISTATE_OFFSET_ECX(%esp) 325 movl %edx, ISTATE_OFFSET_EDX(%esp) 326 movl %edi, ISTATE_OFFSET_EDI(%esp) 327 movl %esi, ISTATE_OFFSET_ESI(%esp) 328 movl %ebp, ISTATE_OFFSET_EBP(%esp) 329 330 /* 331 * Save the selector registers. 332 */ 333 movl %gs, %eax 334 movl %fs, %ebx 335 movl %es, %ecx 336 movl %ds, %edx 337 338 movl %eax, ISTATE_OFFSET_GS(%esp) 339 movl %ebx, ISTATE_OFFSET_FS(%esp) 340 movl %ecx, ISTATE_OFFSET_ES(%esp) 341 movl %edx, ISTATE_OFFSET_DS(%esp) 342 343 /* 344 * Switch to kernel selectors. 345 */ 346 movl $16, %eax 347 movl %eax, %ds 348 movl %eax, %es 349 350 /* 351 * Imitate a regular stack frame linkage. 352 * Stop stack traces here if we came from userspace. 353 */ 354 cmpl $8, ISTATE_OFFSET_CS(%esp) 355 jz 0f 356 xorl %ebp, %ebp 357 358 0: 359 360 movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp) 361 movl ISTATE_OFFSET_EIP(%esp), %eax 362 movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp) 363 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 364 365 cld 366 367 pushl %esp /* pass istate address */ 368 pushl $(\i) /* pass intnum */ 369 370 /* Call exc_dispatch(intnum, istate) */ 371 call exc_dispatch 372 373 addl $8, %esp /* clear arguments from the stack */ 374 375 CLEAR_NT_FLAG 376 377 /* 378 * Restore the selector registers. 379 */ 380 movl ISTATE_OFFSET_GS(%esp), %eax 381 movl ISTATE_OFFSET_FS(%esp), %ebx 382 movl ISTATE_OFFSET_ES(%esp), %ecx 383 movl ISTATE_OFFSET_DS(%esp), %edx 384 385 movl %eax, %gs 386 movl %ebx, %fs 387 movl %ecx, %es 388 movl %edx, %ds 389 390 /* 391 * Restore the scratch registers and the preserved 392 * registers the handler cloberred itself 393 * (i.e. EBX and EBP). 394 */ 395 movl ISTATE_OFFSET_EAX(%esp), %eax 396 movl ISTATE_OFFSET_EBX(%esp), %ebx 397 movl ISTATE_OFFSET_ECX(%esp), %ecx 398 movl ISTATE_OFFSET_EDX(%esp), %edx 399 movl ISTATE_OFFSET_EBP(%esp), %ebp 400 401 addl $(ISTATE_SOFT_SIZE + 4), %esp 402 iret 403 404 .endif 405 406 .align INTERRUPT_ALIGN 407 .if (\n- \i) - 1 408 handler "(\i + 1)", \n 409 .endif 381 410 .endm 382 411 383 # keep in sync with pm.h !!! 412 /* Keep in sync with pm.h! */ 384 413 IDT_ITEMS = 64 414 385 415 .align INTERRUPT_ALIGN 386 416 interrupt_handlers: 387 h_start:388 handler 0 IDT_ITEMS389 h_end:417 h_start: 418 handler 0 IDT_ITEMS 419 h_end: 390 420 391 421 .data
Note:
See TracChangeset
for help on using the changeset viewer.