Changes in kernel/arch/ia32/src/asm.S [b808660:b8230b9] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ia32/src/asm.S
rb808660 rb8230b9 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 39 40 #include <arch/pm.h> 41 #include <arch/mm/page.h> 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 42 34 43 35 .text 36 44 37 .global paging_on 45 38 .global enable_l_apic_in_msr 39 .global interrupt_handlers 46 40 .global memsetb 47 41 .global memsetw … … 51 45 .global memcpy_to_uspace 52 46 .global memcpy_to_uspace_failover_address 53 .global early_putchar 54 55 /* Wrapper for generic memsetb */ 47 48 49 # Wrapper for generic memsetb 56 50 memsetb: 57 51 jmp _memsetb 58 52 59 /* Wrapper for generic memsetw */ 53 # Wrapper for generic memsetw 60 54 memsetw: 61 55 jmp _memsetw 62 56 63 #define MEMCPY_DST 4 64 #define MEMCPY_SRC 8 65 #define MEMCPY_SIZE 12 57 58 #define MEMCPY_DST 4 59 #define MEMCPY_SRC 8 60 #define MEMCPY_SIZE 12 66 61 67 62 /** Copy memory to/from userspace. … … 73 68 * or copy_to_uspace(). 74 69 * 75 * @param MEMCPY_DST(%esp) 76 * @param MEMCPY_SRC(%esp) 77 * @param MEMCPY_SIZE(%esp) 70 * @param MEMCPY_DST(%esp) Destination address. 71 * @param MEMCPY_SRC(%esp) Source address. 72 * @param MEMCPY_SIZE(%esp) Size. 78 73 * 79 74 * @return MEMCPY_DST(%esp) on success and 0 on failure. 80 *81 75 */ 82 76 memcpy: 83 77 memcpy_from_uspace: 84 78 memcpy_to_uspace: 85 movl %edi, %edx 86 movl %esi, %eax 79 movl %edi, %edx /* save %edi */ 80 movl %esi, %eax /* save %esi */ 87 81 88 82 movl MEMCPY_SIZE(%esp), %ecx 89 shrl $2, %ecx 83 shrl $2, %ecx /* size / 4 */ 90 84 91 85 movl MEMCPY_DST(%esp), %edi 92 86 movl MEMCPY_SRC(%esp), %esi 93 87 94 /* Copy whole words */ 95 rep movsl 96 88 rep movsl /* copy whole words */ 89 97 90 movl MEMCPY_SIZE(%esp), %ecx 98 andl $3, %ecx 91 andl $3, %ecx /* size % 4 */ 99 92 jz 0f 100 93 101 /* Copy the rest byte by byte */ 102 rep movsb 103 104 0: 105 106 movl %edx, %edi 107 movl %eax, %esi 108 109 /* MEMCPY_DST(%esp), success */ 110 movl MEMCPY_DST(%esp), %eax 111 ret 112 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 113 102 /* 114 103 * We got here from as_page_fault() after the memory operations … … 119 108 movl %edx, %edi 120 109 movl %eax, %esi 121 122 /* Return 0, failure */ 123 xorl %eax, %eax 110 xorl %eax, %eax /* return 0, failure */ 124 111 ret 125 112 126 /** Turn paging on 127 * 128 * Enable paging and write-back caching in CR0. 129 * 130 */ 113 ## Turn paging on 114 # 115 # Enable paging and write-back caching in CR0. 116 # 131 117 paging_on: 132 118 movl %cr0, %edx 133 orl $(1 << 31), %edx /* paging on */ 134 135 /* Clear Cache Disable and not Write Though */ 119 orl $(1 << 31), %edx # paging on 120 # clear Cache Disable and not Write Though 136 121 andl $~((1 << 30) | (1 << 29)), %edx 137 movl %edx, 122 movl %edx,%cr0 138 123 jmp 0f 139 140 0: 141 ret 142 143 /** Enable local APIC 144 * 145 * Enable local APIC in MSR. 146 * 147 */ 124 0: 125 ret 126 127 128 ## Enable local APIC 129 # 130 # Enable local APIC in MSR. 131 # 148 132 enable_l_apic_in_msr: 149 133 movl $0x1b, %ecx … … 154 138 ret 155 139 156 /** Clear nested flag 157 * 158 */ 140 # Clear nested flag 141 # overwrites %ecx 159 142 .macro CLEAR_NT_FLAG 160 143 pushfl 161 andl $0xffffbfff, (%esp) 144 pop %ecx 145 and $0xffffbfff, %ecx 146 push %ecx 162 147 popfl 163 .endm 164 165 #define ISTATE_OFFSET_EDX 0 166 #define ISTATE_OFFSET_ECX 4 167 #define ISTATE_OFFSET_EBX 8 168 #define ISTATE_OFFSET_ESI 12 169 #define ISTATE_OFFSET_EDI 16 170 #define ISTATE_OFFSET_EBP 20 171 #define ISTATE_OFFSET_EAX 24 172 #define ISTATE_OFFSET_EBP_FRAME 28 173 #define ISTATE_OFFSET_EIP_FRAME 32 174 #define ISTATE_OFFSET_GS 36 175 #define ISTATE_OFFSET_FS 40 176 #define ISTATE_OFFSET_ES 44 177 #define ISTATE_OFFSET_DS 48 178 #define ISTATE_OFFSET_ERROR_WORD 52 179 #define ISTATE_OFFSET_EIP 56 180 #define ISTATE_OFFSET_CS 60 181 #define ISTATE_OFFSET_EFLAGS 64 182 #define ISTATE_OFFSET_ESP 68 183 #define ISTATE_OFFSET_SS 72 184 185 /* 186 * Size of the istate structure without the hardware-saved part 187 * and without the error word. 188 */ 189 #define ISTATE_SOFT_SIZE 52 190 191 /* 192 * Size of the entire istate structure including the error word and the 193 * hardware-saved part. 194 */ 195 #define ISTATE_REAL_SIZE (ISTATE_SOFT_SIZE + 24) 148 .endm 196 149 197 150 /* … … 207 160 sysenter_handler: 208 161 sti 209 subl $(ISTATE_REAL_SIZE), %esp 210 211 /* 212 * Save the return address and the userspace stack in the istate 213 * structure on locations that would normally be taken by them. 214 */ 215 movl %ebp, ISTATE_OFFSET_ESP(%esp) 216 movl %edi, ISTATE_OFFSET_EIP(%esp) 217 218 /* 219 * Push syscall arguments onto the stack 220 */ 221 movl %eax, ISTATE_OFFSET_EAX(%esp) 222 movl %ebx, ISTATE_OFFSET_EBX(%esp) 223 movl %ecx, ISTATE_OFFSET_ECX(%esp) 224 movl %edx, ISTATE_OFFSET_EDX(%esp) 225 movl %esi, ISTATE_OFFSET_ESI(%esp) 226 movl %edi, ISTATE_OFFSET_EDI(%esp) /* observability; not needed */ 227 movl %ebp, ISTATE_OFFSET_EBP(%esp) /* observability; not needed */ 228 229 /* 230 * Fake up the stack trace linkage. 231 */ 232 movl %edi, ISTATE_OFFSET_EIP_FRAME(%esp) 233 movl $0, ISTATE_OFFSET_EBP_FRAME(%esp) 234 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 235 236 /* 237 * Save TLS. 238 */ 239 movl %gs, %edx 240 movl %edx, ISTATE_OFFSET_GS(%esp) 241 242 /* 243 * Switch to kernel selectors. 244 */ 162 pushl %ebp # remember user stack 163 pushl %edi # remember return user address 164 165 pushl %gs # remember TLS 166 167 pushl %eax # syscall number 168 subl $8, %esp # unused sixth and fifth argument 169 pushl %esi # fourth argument 170 pushl %ebx # third argument 171 pushl %ecx # second argument 172 pushl %edx # first argument 173 245 174 movw $16, %ax 246 175 movw %ax, %ds 247 176 movw %ax, %es 248 177 249 178 cld 250 179 call syscall_handler 251 252 /* 253 * Restore TLS. 254 */ 255 movl ISTATE_OFFSET_GS(%esp), %edx 256 movl %edx, %gs 257 258 /* 259 * Prepare return address and userspace stack for SYSEXIT. 260 */ 261 movl ISTATE_OFFSET_EIP(%esp), %edx 262 movl ISTATE_OFFSET_ESP(%esp), %ecx 263 264 addl $(ISTATE_REAL_SIZE), %esp 265 266 sysexit /* return to userspace */ 267 268 /** Declare interrupt handlers 269 * 270 * Declare interrupt handlers for n interrupt 271 * vectors starting at vector i. 272 * 273 */ 274 275 .macro handler i 276 .global int_\i 277 int_\i: 278 .ifeq \i - 0x30 279 /* Syscall handler */ 280 subl $(ISTATE_SOFT_SIZE + 4), %esp 281 282 /* 283 * Push syscall arguments onto the stack 284 * 285 * NOTE: The idea behind the order of arguments passed 286 * in registers is to use all scratch registers 287 * first and preserved registers next. An optimized 288 * libc syscall wrapper can make use of this setup. 289 * The istate structure is arranged in the way to support 290 * this idea. 291 * 292 */ 293 movl %eax, ISTATE_OFFSET_EAX(%esp) 294 movl %ebx, ISTATE_OFFSET_EBX(%esp) 295 movl %ecx, ISTATE_OFFSET_ECX(%esp) 296 movl %edx, ISTATE_OFFSET_EDX(%esp) 297 movl %edi, ISTATE_OFFSET_EDI(%esp) 298 movl %esi, ISTATE_OFFSET_ESI(%esp) 299 movl %ebp, ISTATE_OFFSET_EBP(%esp) 300 301 /* 302 * Save the selector registers. 303 */ 304 movl %gs, %ecx 305 movl %fs, %edx 306 307 movl %ecx, ISTATE_OFFSET_GS(%esp) 308 movl %edx, ISTATE_OFFSET_FS(%esp) 309 310 movl %es, %ecx 311 movl %ds, %edx 312 313 movl %ecx, ISTATE_OFFSET_ES(%esp) 314 movl %edx, ISTATE_OFFSET_DS(%esp) 315 316 /* 317 * Switch to kernel selectors. 318 */ 319 movl $16, %eax 320 movl %eax, %ds 321 movl %eax, %es 322 323 movl $0, ISTATE_OFFSET_EBP_FRAME(%esp) 324 movl ISTATE_OFFSET_EIP(%esp), %eax 325 movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp) 326 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 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 ## Declare interrupt handlers 191 # 192 # Declare interrupt handlers for n interrupt 193 # vectors starting at vector i. 194 # 195 # The handlers setup data segment registers 196 # and call exc_dispatch(). 197 # 198 #define INTERRUPT_ALIGN 64 199 .macro handler i n 200 201 .ifeq \i - 0x30 # Syscall handler 202 pushl %ds 203 pushl %es 204 pushl %fs 205 pushl %gs 206 207 # 208 # Push syscall arguments onto the stack 209 # 210 # NOTE: The idea behind the order of arguments passed in registers is to 211 # use all scratch registers first and preserved registers next. 212 # An optimized libc syscall wrapper can make use of this setup. 213 # 214 pushl %eax 215 pushl %ebp 216 pushl %edi 217 pushl %esi 218 pushl %ebx 219 pushl %ecx 220 pushl %edx 221 222 # we must fill the data segment registers 223 movw $16, %ax 224 movw %ax, %ds 225 movw %ax, %es 327 226 328 227 cld 329 228 sti 330 331 /* Call syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) */ 229 # syscall_handler(edx, ecx, ebx, esi, edi, ebp, eax) 332 230 call syscall_handler 333 231 cli 232 addl $28, %esp # clean-up of parameters 233 234 popl %gs 235 popl %fs 236 popl %es 237 popl %ds 238 334 239 CLEAR_NT_FLAG 335 336 /*337 * Restore the selector registers.338 */339 movl ISTATE_OFFSET_GS(%esp), %ecx340 movl ISTATE_OFFSET_FS(%esp), %edx341 342 movl %ecx, %gs343 movl %edx, %fs344 345 movl ISTATE_OFFSET_ES(%esp), %ecx346 movl ISTATE_OFFSET_DS(%esp), %edx347 348 movl %ecx, %es349 movl %edx, %ds350 351 /*352 * Restore the preserved registers the handler cloberred itself353 * (i.e. EBP).354 */355 movl ISTATE_OFFSET_EBP(%esp), %ebp356 357 addl $(ISTATE_SOFT_SIZE + 4), %esp358 240 iret 359 360 241 .else 361 242 /* 362 * This macro distinguishes between two versions of ia32 363 * exceptions. One version has error word and the other 364 * does not have it. The latter version fakes the error 365 * word on the stack so that the handlers and istate_t 366 * can be the same for both types. 243 * This macro distinguishes between two versions of ia32 exceptions. 244 * One version has error word and the other does not have it. 245 * The latter version fakes the error word on the stack so that the 246 * handlers and istate_t can be the same for both types. 367 247 */ 368 248 .iflt \i - 32 369 249 .if (1 << \i) & ERROR_WORD_INTERRUPT_LIST 370 250 /* 371 * Exception with error word:do nothing251 * With error word, do nothing 372 252 */ 373 253 .else 374 254 /* 375 * Exception without error word: fake up one255 * Version without error word 376 256 */ 377 pushl $0257 subl $4, %esp 378 258 .endif 379 259 .else 380 260 /* 381 * Interrupt: fake up one261 * Version without error word 382 262 */ 383 pushl $0263 subl $4, %esp 384 264 .endif 385 265 386 subl $ISTATE_SOFT_SIZE, %esp 387 388 /* 389 * Save the general purpose registers. 390 */ 391 movl %eax, ISTATE_OFFSET_EAX(%esp) 392 movl %ebx, ISTATE_OFFSET_EBX(%esp) 393 movl %ecx, ISTATE_OFFSET_ECX(%esp) 394 movl %edx, ISTATE_OFFSET_EDX(%esp) 395 movl %edi, ISTATE_OFFSET_EDI(%esp) 396 movl %esi, ISTATE_OFFSET_ESI(%esp) 397 movl %ebp, ISTATE_OFFSET_EBP(%esp) 398 399 /* 400 * Save the selector registers. 401 */ 402 movl %gs, %eax 403 movl %fs, %ebx 404 movl %es, %ecx 405 movl %ds, %edx 406 407 movl %eax, ISTATE_OFFSET_GS(%esp) 408 movl %ebx, ISTATE_OFFSET_FS(%esp) 409 movl %ecx, ISTATE_OFFSET_ES(%esp) 410 movl %edx, ISTATE_OFFSET_DS(%esp) 411 412 /* 413 * Switch to kernel selectors. 414 */ 415 movl $16, %eax 416 movl %eax, %ds 417 movl %eax, %es 418 419 /* 420 * Imitate a regular stack frame linkage. 421 * Stop stack traces here if we came from userspace. 422 */ 423 cmpl $8, ISTATE_OFFSET_CS(%esp) 424 jz 0f 266 pushl %ds 267 pushl %es 268 pushl %fs 269 pushl %gs 270 271 pushl %ebp 272 pushl %edx 273 pushl %ecx 274 pushl %eax 275 276 # we must fill the data segment registers 277 278 movw $16, %ax 279 movw %ax, %ds 280 movw %ax, %es 281 282 # stop stack traces here 425 283 xorl %ebp, %ebp 426 284 427 0: 428 429 movl %ebp, ISTATE_OFFSET_EBP_FRAME(%esp) 430 movl ISTATE_OFFSET_EIP(%esp), %eax 431 movl %eax, ISTATE_OFFSET_EIP_FRAME(%esp) 432 leal ISTATE_OFFSET_EBP_FRAME(%esp), %ebp 433 434 cld 435 436 pushl %esp /* pass istate address */ 437 pushl $(\i) /* pass intnum */ 438 439 /* Call exc_dispatch(intnum, istate) */ 440 call exc_dispatch 441 442 addl $8, %esp /* clear arguments from the stack */ 443 444 CLEAR_NT_FLAG 445 446 /* 447 * Restore the selector registers. 448 */ 449 movl ISTATE_OFFSET_GS(%esp), %eax 450 movl ISTATE_OFFSET_FS(%esp), %ebx 451 movl ISTATE_OFFSET_ES(%esp), %ecx 452 movl ISTATE_OFFSET_DS(%esp), %edx 453 454 movl %eax, %gs 455 movl %ebx, %fs 456 movl %ecx, %es 457 movl %edx, %ds 458 459 /* 460 * Restore the scratch registers and the preserved 461 * registers the handler cloberred itself 462 * (i.e. EBX and EBP). 463 */ 464 movl ISTATE_OFFSET_EAX(%esp), %eax 465 movl ISTATE_OFFSET_EBX(%esp), %ebx 466 movl ISTATE_OFFSET_ECX(%esp), %ecx 467 movl ISTATE_OFFSET_EDX(%esp), %edx 468 movl ISTATE_OFFSET_EBP(%esp), %ebp 469 470 addl $(ISTATE_SOFT_SIZE + 4), %esp 471 iret 472 285 pushl %esp # *istate 286 pushl $(\i) # intnum 287 call exc_dispatch # exc_dispatch(intnum, *istate) 288 addl $8, %esp # Clear arguments from stack 289 290 CLEAR_NT_FLAG # Modifies %ecx 291 292 popl %eax 293 popl %ecx 294 popl %edx 295 popl %ebp 296 297 popl %gs 298 popl %fs 299 popl %es 300 popl %ds 301 302 # skip error word, no matter whether real or fake 303 addl $4, %esp 304 iret 305 .endif 306 307 .align INTERRUPT_ALIGN 308 .if (\n- \i) - 1 309 handler "(\i + 1)", \n 473 310 .endif 474 311 .endm 475 312 476 #define LIST_0_63 \ 477 0, 1, 2, 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,\ 478 28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,\ 479 53,54,55,56,57,58,59,60,61,62,63 480 313 # keep in sync with pm.h !!! 314 IDT_ITEMS = 64 315 .align INTERRUPT_ALIGN 481 316 interrupt_handlers: 482 .irp cnt, LIST_0_63 483 handler \cnt 484 .endr 485 486 /** Print Unicode character to EGA display. 487 * 488 * If CONFIG_EGA is undefined or CONFIG_FB is defined 489 * then this function does nothing. 490 * 491 * Since the EGA can only display Extended ASCII (usually 492 * ISO Latin 1) characters, some of the Unicode characters 493 * can be displayed in a wrong way. Only newline and backspace 494 * are interpreted, all other characters (even unprintable) are 495 * printed verbatim. 496 * 497 * @param %ebp+0x08 Unicode character to be printed. 498 * 499 */ 500 early_putchar: 501 502 #if ((defined(CONFIG_EGA)) && (!defined(CONFIG_FB))) 503 504 /* Prologue, save preserved registers */ 505 pushl %ebp 506 movl %esp, %ebp 507 pushl %ebx 508 pushl %esi 509 pushl %edi 510 511 movl $(PA2KA(0xb8000)), %edi /* base of EGA text mode memory */ 512 xorl %eax, %eax 513 514 /* Read bits 8 - 15 of the cursor address */ 515 movw $0x3d4, %dx 516 movb $0xe, %al 517 outb %al, %dx 518 519 movw $0x3d5, %dx 520 inb %dx, %al 521 shl $8, %ax 522 523 /* Read bits 0 - 7 of the cursor address */ 524 movw $0x3d4, %dx 525 movb $0xf, %al 526 outb %al, %dx 527 528 movw $0x3d5, %dx 529 inb %dx, %al 530 531 /* Sanity check for the cursor on screen */ 532 cmp $2000, %ax 533 jb early_putchar_cursor_ok 534 535 movw $1998, %ax 536 537 early_putchar_cursor_ok: 538 539 movw %ax, %bx 540 shl $1, %eax 541 addl %eax, %edi 542 543 movl 0x08(%ebp), %eax 544 545 cmp $0x0a, %al 546 jne early_putchar_backspace 547 548 /* Interpret newline */ 549 550 movw %bx, %ax /* %bx -> %dx:%ax */ 551 xorw %dx, %dx 552 553 movw $80, %cx 554 idivw %cx, %ax /* %dx = %bx % 80 */ 555 556 /* %bx <- %bx + 80 - (%bx % 80) */ 557 addw %cx, %bx 558 subw %dx, %bx 559 560 jmp early_putchar_skip 561 562 early_putchar_backspace: 563 564 cmp $0x08, %al 565 jne early_putchar_print 566 567 /* Interpret backspace */ 568 569 cmp $0x0000, %bx 570 je early_putchar_skip 571 572 dec %bx 573 jmp early_putchar_skip 574 575 early_putchar_print: 576 577 /* Print character */ 578 579 movb $0x0e, %ah /* black background, yellow foreground */ 580 stosw 581 inc %bx 582 583 early_putchar_skip: 584 585 /* Sanity check for the cursor on the last line */ 586 cmp $2000, %bx 587 jb early_putchar_no_scroll 588 589 /* Scroll the screen (24 rows) */ 590 movl $(PA2KA(0xb80a0)), %esi 591 movl $(PA2KA(0xb8000)), %edi 592 movl $960, %ecx 593 rep movsl 594 595 /* Clear the 24th row */ 596 xorl %eax, %eax 597 movl $40, %ecx 598 rep stosl 599 600 /* Go to row 24 */ 601 movw $1920, %bx 602 603 early_putchar_no_scroll: 604 605 /* Write bits 8 - 15 of the cursor address */ 606 movw $0x3d4, %dx 607 movb $0xe, %al 608 outb %al, %dx 609 610 movw $0x3d5, %dx 611 movb %bh, %al 612 outb %al, %dx 613 614 /* Write bits 0 - 7 of the cursor address */ 615 movw $0x3d4, %dx 616 movb $0xf, %al 617 outb %al, %dx 618 619 movw $0x3d5, %dx 620 movb %bl, %al 621 outb %al, %dx 622 623 /* Epilogue, restore preserved registers */ 624 popl %edi 625 popl %esi 626 popl %ebx 627 leave 628 629 #endif 630 631 ret 632 317 h_start: 318 handler 0 IDT_ITEMS 319 h_end: 320 321 .data 322 .global interrupt_handler_size 323 324 interrupt_handler_size: .long (h_end - h_start) / IDT_ITEMS
Note:
See TracChangeset
for help on using the changeset viewer.