btx.S (181433) | btx.S (189017) |
---|---|
1/* 2 * Copyright (c) 1998 Robert Nordier 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are freely 6 * permitted provided that the above copyright notice and this 7 * paragraph and the following disclaimer are duplicated in all 8 * such forms. 9 * 10 * This software is provided "AS IS" and without any express or 11 * implied warranties, including, without limitation, the implied 12 * warranties of merchantability and fitness for a particular 13 * purpose. 14 * | 1/* 2 * Copyright (c) 1998 Robert Nordier 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are freely 6 * permitted provided that the above copyright notice and this 7 * paragraph and the following disclaimer are duplicated in all 8 * such forms. 9 * 10 * This software is provided "AS IS" and without any express or 11 * implied warranties, including, without limitation, the implied 12 * warranties of merchantability and fitness for a particular 13 * purpose. 14 * |
15 * $FreeBSD: head/sys/boot/i386/btx/btx/btx.S 181433 2008-08-08 19:39:11Z jhb $ | 15 * $FreeBSD: head/sys/boot/i386/btx/btx/btx.S 189017 2009-02-24 23:11:15Z jhb $ |
16 */ 17 18/* 19 * Memory layout. 20 */ 21 .set MEM_BTX,0x1000 # Start of BTX memory 22 .set MEM_ESP0,0x1800 # Supervisor stack 23 .set MEM_BUF,0x1800 # Scratch buffer --- 7 unchanged lines hidden (view full) --- 31/* 32 * Paging control. 33 */ 34 .set PAG_SIZ,0x1000 # Page size 35 .set PAG_CNT,0x1000 # Pages to map 36/* 37 * Fields in %eflags. 38 */ | 16 */ 17 18/* 19 * Memory layout. 20 */ 21 .set MEM_BTX,0x1000 # Start of BTX memory 22 .set MEM_ESP0,0x1800 # Supervisor stack 23 .set MEM_BUF,0x1800 # Scratch buffer --- 7 unchanged lines hidden (view full) --- 31/* 32 * Paging control. 33 */ 34 .set PAG_SIZ,0x1000 # Page size 35 .set PAG_CNT,0x1000 # Pages to map 36/* 37 * Fields in %eflags. 38 */ |
39 .set PSL_RESERVED_DEFAULT,0x00000002 |
|
39 .set PSL_T,0x00000100 # Trap flag 40 .set PSL_I,0x00000200 # Interrupt enable flag 41 .set PSL_VM,0x00020000 # Virtual 8086 mode flag 42 .set PSL_AC,0x00040000 # Alignment check flag 43/* 44 * Segment selectors. 45 */ 46 .set SEL_SCODE,0x8 # Supervisor code --- 403 unchanged lines hidden (view full) --- 450 * -0x28 %esp 451 * -0x2c %ebp 452 * -0x30 %esi 453 * -0x34 %edi 454 * -0x38 %gs 455 * -0x3c %fs 456 * -0x40 %ds 457 * -0x44 %es | 40 .set PSL_T,0x00000100 # Trap flag 41 .set PSL_I,0x00000200 # Interrupt enable flag 42 .set PSL_VM,0x00020000 # Virtual 8086 mode flag 43 .set PSL_AC,0x00040000 # Alignment check flag 44/* 45 * Segment selectors. 46 */ 47 .set SEL_SCODE,0x8 # Supervisor code --- 403 unchanged lines hidden (view full) --- 451 * -0x28 %esp 452 * -0x2c %ebp 453 * -0x30 %esi 454 * -0x34 %edi 455 * -0x38 %gs 456 * -0x3c %fs 457 * -0x40 %ds 458 * -0x44 %es |
459 * -0x48 zero %eax (hardware int only) 460 * -0x4c zero %ecx (hardware int only) 461 * -0x50 zero %edx (hardware int only) 462 * -0x54 zero %ebx (hardware int only) 463 * -0x58 zero %esp (hardware int only) 464 * -0x5c zero %ebp (hardware int only) 465 * -0x60 zero %esi (hardware int only) 466 * -0x64 zero %edi (hardware int only) 467 * -0x68 zero %gs (hardware int only) 468 * -0x6c zero %fs (hardware int only) 469 * -0x70 zero %ds (hardware int only) 470 * -0x74 zero %es (hardware int only) |
|
458 */ 459int_hw: cld # String ops inc 460 pusha # Save gp regs 461 pushl %gs # Save 462 pushl %fs # seg 463 pushl %ds # regs 464 pushl %es 465 push $SEL_SDATA # Set up 466 popl %ds # to 467 pushl %ds # address 468 popl %es # data 469 leal 0x44(%esp,1),%esi # Base of frame | 471 */ 472int_hw: cld # String ops inc 473 pusha # Save gp regs 474 pushl %gs # Save 475 pushl %fs # seg 476 pushl %ds # regs 477 pushl %es 478 push $SEL_SDATA # Set up 479 popl %ds # to 480 pushl %ds # address 481 popl %es # data 482 leal 0x44(%esp,1),%esi # Base of frame |
483 movl %esp,MEM_ESPR-0x04 # Save kernel stack pointer |
|
470 movl -0x14(%esi),%eax # Get Int no 471 cmpl $-1,%eax # Hardware interrupt? | 484 movl -0x14(%esi),%eax # Get Int no 485 cmpl $-1,%eax # Hardware interrupt? |
472 jne intusr.2 # Yes | 486 jne intusr.1 # Yes |
473/* | 487/* |
474 * v86 calls save the btx_v86 pointer on the real mode stack and read the 475 * address and flags from the btx_v86 structure. | 488 * v86 calls save the btx_v86 pointer on the real mode stack and read 489 * the address and flags from the btx_v86 structure. For interrupt 490 * handler invocations (VM86 INTx requests), disable interrupts, 491 * tracing, and alignment checking while the handler runs. |
476 */ 477 movl $MEM_USR,%ebx # User base 478 movl %ebx,%edx # address 479 addl -0x4(%esi),%ebx # User ESP 480 movl (%ebx),%ebp # btx_v86 pointer 481 addl %ebp,%edx # Flatten btx_v86 ptr 482 movl %edx,MEM_ESPR-0x08 # Save btx_v86 ptr 483 movl V86_ADDR(%edx),%eax # Get int no/address 484 movl V86_CTL(%edx),%edx # Get control flags | 492 */ 493 movl $MEM_USR,%ebx # User base 494 movl %ebx,%edx # address 495 addl -0x4(%esi),%ebx # User ESP 496 movl (%ebx),%ebp # btx_v86 pointer 497 addl %ebp,%edx # Flatten btx_v86 ptr 498 movl %edx,MEM_ESPR-0x08 # Save btx_v86 ptr 499 movl V86_ADDR(%edx),%eax # Get int no/address 500 movl V86_CTL(%edx),%edx # Get control flags |
501 movl -0x08(%esi),%ebx # Save user flags in %ebx 502 testl $V86F_ADDR,%edx # Segment:offset? 503 jnz intusr.4 # Yes 504 andl $~(PSL_I|PSL_T|PSL_AC),%ebx # Disable interrupts, tracing, 505 # and alignment checking for 506 # interrupt handler |
|
485 jmp intusr.3 # Skip hardware interrupt 486/* | 507 jmp intusr.3 # Skip hardware interrupt 508/* |
487 * Hardware interrupts store a NULL btx_v86 pointer and use the address 488 * (interrupt number) from the stack with empty flags. Also, we clear 489 * the segment registers for the interrupt handler. | 509 * Hardware interrupts store a NULL btx_v86 pointer and use the 510 * address (interrupt number) from the stack with empty flags. Also, 511 * push a dummy frame of zeros onto the stack for all the general 512 * purpose and segment registers and clear %eflags. This gives the 513 * hardware interrupt handler a clean slate. |
490 */ | 514 */ |
491intusr.2: xorl %edx,%edx # Control flags | 515intusr.1: xorl %edx,%edx # Control flags |
492 movl %edx,MEM_ESPR-0x08 # NULL btx_v86 ptr | 516 movl %edx,MEM_ESPR-0x08 # NULL btx_v86 ptr |
493 movl %edx,-0x38(%esi) # Real mode %gs of 0 494 movl %edx,-0x3c(%esi) # Real mode %fs of 0 495 movl %edx,-0x40(%esi) # Real mode %ds of 0 496 movl %edx,-0x44(%esi) # Real mode %es of 0 | 517 movl $12,%ecx # Frame is 12 dwords 518intusr.2: pushl $0x0 # Fill frame 519 loop intusr.2 # with zeros 520 movl $PSL_RESERVED_DEFAULT,%ebx # Set clean %eflags |
497/* | 521/* |
498 * %eax now holds either the interrupt number or segment:offset of function. 499 * %edx now holds the V86F_* flags. 500 * 501 * For interrupt handler invocations (either hardware interrupts or VM86 502 * INTx requests) we also disable interrupts, tracing, and alignment checking 503 * while the handler runs. | 522 * Look up real mode IDT entry for hardware interrupts and VM86 INTx 523 * requests. |
504 */ | 524 */ |
505intusr.3: movl -0x08(%esi),%ebx # Save user flags in %ebx 506 testl $V86F_ADDR,%edx # Segment:offset? 507 jnz intusr.4 # Yes 508 shll $0x2,%eax # Scale | 525intusr.3: shll $0x2,%eax # Scale |
509 movl (%eax),%eax # Load int vector | 526 movl (%eax),%eax # Load int vector |
510 andl $~(PSL_I|PSL_T|PSL_AC),%ebx # Disable interrupts, tracing, 511 # and alignment checking for 512 # interrupt handler | |
513 jmp intusr.5 # Skip CALLF test | 527 jmp intusr.5 # Skip CALLF test |
528/* 529 * Panic if V86F_CALLF isn't set with V86F_ADDR. 530 */ |
|
514intusr.4: testl $V86F_CALLF,%edx # Far call? 515 jnz intusr.5 # Ok 516 movl %edx,0x30(%esp,1) # Place VM86 flags in int no 517 movl $badvm86,%esi # Display bad 518 call putstr # VM86 call 519 popl %es # Restore 520 popl %ds # seg 521 popl %fs # regs 522 popl %gs 523 popal # Restore gp regs 524 jmp ex_noc # Panic | 531intusr.4: testl $V86F_CALLF,%edx # Far call? 532 jnz intusr.5 # Ok 533 movl %edx,0x30(%esp,1) # Place VM86 flags in int no 534 movl $badvm86,%esi # Display bad 535 call putstr # VM86 call 536 popl %es # Restore 537 popl %ds # seg 538 popl %fs # regs 539 popl %gs 540 popal # Restore gp regs 541 jmp ex_noc # Panic |
542/* 543 * %eax now holds the segment:offset of the function. 544 * %ebx now holds the %eflags to pass to real mode. 545 * %edx now holds the V86F_* flags. 546 */ |
|
525intusr.5: movw %bx,MEM_ESPR-0x12 # Pass user flags to real mode 526 # target 527/* 528 * If this is a v86 call, copy the seg regs out of the btx_v86 structure. 529 */ 530 movl MEM_ESPR-0x08,%ecx # Get btx_v86 ptr 531 jecxz intusr.6 # Skip for hardware ints 532 leal -0x44(%esi),%edi # %edi => kernel stack seg regs 533 pushl %esi # Save 534 leal V86_ES(%ecx),%esi # %esi => btx_v86 seg regs 535 movl $4,%ecx # Copy seg regs 536 rep # from btx_v86 537 movsl # to kernel stack 538 popl %esi # Restore | 547intusr.5: movw %bx,MEM_ESPR-0x12 # Pass user flags to real mode 548 # target 549/* 550 * If this is a v86 call, copy the seg regs out of the btx_v86 structure. 551 */ 552 movl MEM_ESPR-0x08,%ecx # Get btx_v86 ptr 553 jecxz intusr.6 # Skip for hardware ints 554 leal -0x44(%esi),%edi # %edi => kernel stack seg regs 555 pushl %esi # Save 556 leal V86_ES(%ecx),%esi # %esi => btx_v86 seg regs 557 movl $4,%ecx # Copy seg regs 558 rep # from btx_v86 559 movsl # to kernel stack 560 popl %esi # Restore |
539intusr.6: movl %esp,MEM_ESPR-0x04 # Save kernel stack pointer 540 movl -0x08(%esi),%ebx # Copy user flags to real | 561intusr.6: movl -0x08(%esi),%ebx # Copy user flags to real |
541 movl %ebx,MEM_ESPR-0x0c # mode return trampoline 542 movl $rret_tramp,%ebx # Set return trampoline 543 movl %ebx,MEM_ESPR-0x10 # CS:IP 544 movl %eax,MEM_ESPR-0x16 # Real mode target CS:IP 545 ljmpw $SEL_RCODE,$intusr.7 # Change to 16-bit segment 546 .code16 547intusr.7: movl %cr0,%eax # Leave 548 dec %al # protected --- 57 unchanged lines hidden (view full) --- 606 movw %cx,%ds # seg 607 movw %cx,%es # regs 608 movl MEM_ESPR-0x04,%esp # Switch to kernel stack 609 leal 0x44(%esp,1),%esi # Base of frame 610 andb $~0x2,tss_desc+0x5 # Clear TSS busy 611 movb $SEL_TSS,%cl # Set task 612 ltr %cx # register 613/* | 562 movl %ebx,MEM_ESPR-0x0c # mode return trampoline 563 movl $rret_tramp,%ebx # Set return trampoline 564 movl %ebx,MEM_ESPR-0x10 # CS:IP 565 movl %eax,MEM_ESPR-0x16 # Real mode target CS:IP 566 ljmpw $SEL_RCODE,$intusr.7 # Change to 16-bit segment 567 .code16 568intusr.7: movl %cr0,%eax # Leave 569 dec %al # protected --- 57 unchanged lines hidden (view full) --- 627 movw %cx,%ds # seg 628 movw %cx,%es # regs 629 movl MEM_ESPR-0x04,%esp # Switch to kernel stack 630 leal 0x44(%esp,1),%esi # Base of frame 631 andb $~0x2,tss_desc+0x5 # Clear TSS busy 632 movb $SEL_TSS,%cl # Set task 633 ltr %cx # register 634/* |
614 * Now we are back in protected mode. Copy the registers off of the real 615 * mode stack onto the kernel stack. Also, initialize all the seg regs on 616 * the kernel stack. | 635 * Now we are back in protected mode. The kernel stack frame set up 636 * before entering real mode is still intact. For hardware interrupts, 637 * leave the frame unchanged. 638 */ 639 cmpl $0,MEM_ESPR-0x08 # Leave saved regs unchanged 640 jz rret_tramp.3 # for hardware ints 641/* 642 * For V86 calls, copy the registers off of the real mode stack onto 643 * the kernel stack as we want their updated values. Also, initialize 644 * the segment registers on the kernel stack. |
617 * 618 * Note that the %esp in the kernel stack after this is garbage, but popa 619 * ignores it, so we don't have to fix it up. 620 */ 621 leal -0x18(%esi),%edi # Kernel stack GP regs 622 pushl %esi # Save 623 movl $MEM_ESPR-0x0c,%esi # Real mode stack GP regs 624 movl $8,%ecx # Copy GP regs from 625 rep # real mode stack 626 movsl # to kernel stack | 645 * 646 * Note that the %esp in the kernel stack after this is garbage, but popa 647 * ignores it, so we don't have to fix it up. 648 */ 649 leal -0x18(%esi),%edi # Kernel stack GP regs 650 pushl %esi # Save 651 movl $MEM_ESPR-0x0c,%esi # Real mode stack GP regs 652 movl $8,%ecx # Copy GP regs from 653 rep # real mode stack 654 movsl # to kernel stack |
627 popl %esi # Restore | |
628 movl $SEL_UDATA,%eax # Selector for data seg regs 629 movl $4,%ecx # Initialize %ds, 630 rep # %es, %fs, and 631 stosl # %gs 632/* | 655 movl $SEL_UDATA,%eax # Selector for data seg regs 656 movl $4,%ecx # Initialize %ds, 657 rep # %es, %fs, and 658 stosl # %gs 659/* |
633 * If this was a V86 call, copy the saved seg regs on the real mode stack 634 * back over to the btx_v86 structure. Also, conditionally update the saved 635 * eflags on the kernel stack based on the flags from the user. | 660 * For V86 calls, copy the saved seg regs on the real mode stack back 661 * over to the btx_v86 structure. Also, conditionally update the 662 * saved eflags on the kernel stack based on the flags from the user. |
636 */ 637 movl MEM_ESPR-0x08,%ecx # Get btx_v86 ptr | 663 */ 664 movl MEM_ESPR-0x08,%ecx # Get btx_v86 ptr |
638 jecxz rret_tramp.3 # Skip for hardware ints | |
639 leal V86_GS(%ecx),%edi # %edi => btx_v86 seg regs | 665 leal V86_GS(%ecx),%edi # %edi => btx_v86 seg regs |
640 pushl %esi # Save | |
641 leal MEM_ESPR-0x2c,%esi # %esi => real mode seg regs 642 xchgl %ecx,%edx # Save btx_v86 ptr 643 movl $4,%ecx # Copy seg regs 644 rep # from real mode stack 645 movsl # to btx_v86 646 popl %esi # Restore 647 movl V86_CTL(%edx),%edx # Read V86 control flags 648 testl $V86F_FLAGS,%edx # User wants flags? --- 399 unchanged lines hidden --- | 666 leal MEM_ESPR-0x2c,%esi # %esi => real mode seg regs 667 xchgl %ecx,%edx # Save btx_v86 ptr 668 movl $4,%ecx # Copy seg regs 669 rep # from real mode stack 670 movsl # to btx_v86 671 popl %esi # Restore 672 movl V86_CTL(%edx),%edx # Read V86 control flags 673 testl $V86F_FLAGS,%edx # User wants flags? --- 399 unchanged lines hidden --- |