|
@@ -501,6 +501,150 @@ rm_gdtr:
|
501
|
501
|
.word 0 /* Limit */
|
502
|
502
|
.long 0 /* Base */
|
503
|
503
|
|
|
504
|
+/****************************************************************************
|
|
505
|
+ * phys_to_prot (protected-mode near call, 32-bit physical return address)
|
|
506
|
+ *
|
|
507
|
+ * Switch from 32-bit protected mode with physical addresses to 32-bit
|
|
508
|
+ * protected mode with virtual addresses. %esp is adjusted to a
|
|
509
|
+ * virtual address. All other registers and flags are preserved.
|
|
510
|
+ *
|
|
511
|
+ * The return address for this function should be a 32-bit physical
|
|
512
|
+ * (sic) address.
|
|
513
|
+ *
|
|
514
|
+ ****************************************************************************
|
|
515
|
+ */
|
|
516
|
+ .section ".text.phys_to_prot", "ax", @progbits
|
|
517
|
+ .code32
|
|
518
|
+ .globl phys_to_prot
|
|
519
|
+phys_to_prot:
|
|
520
|
+ /* Preserve registers and flags */
|
|
521
|
+ pushfl
|
|
522
|
+ pushl %eax
|
|
523
|
+ pushl %ebp
|
|
524
|
+
|
|
525
|
+ /* Switch to virtual code segment */
|
|
526
|
+ cli
|
|
527
|
+ ljmp $VIRTUAL_CS, $VIRTUAL(1f)
|
|
528
|
+1:
|
|
529
|
+ /* Switch to virtual data segment and adjust %esp */
|
|
530
|
+ movw $VIRTUAL_DS, %ax
|
|
531
|
+ movw %ax, %ds
|
|
532
|
+ movw %ax, %es
|
|
533
|
+ movw %ax, %fs
|
|
534
|
+ movw %ax, %gs
|
|
535
|
+ movw %ax, %ss
|
|
536
|
+ movl VIRTUAL(virt_offset), %ebp
|
|
537
|
+ subl %ebp, %esp
|
|
538
|
+
|
|
539
|
+ /* Adjust return address to a virtual address */
|
|
540
|
+ subl %ebp, 12(%esp)
|
|
541
|
+
|
|
542
|
+ /* Restore registers and flags, and return */
|
|
543
|
+ popl %ebp
|
|
544
|
+ popl %eax
|
|
545
|
+ popfl
|
|
546
|
+ ret
|
|
547
|
+
|
|
548
|
+ /* Expose as _phys_to_virt for use by COMBOOT */
|
|
549
|
+ .globl _phys_to_virt
|
|
550
|
+ .equ _phys_to_virt, phys_to_prot
|
|
551
|
+
|
|
552
|
+/****************************************************************************
|
|
553
|
+ * prot_to_phys (protected-mode near call, 32-bit virtual return address)
|
|
554
|
+ *
|
|
555
|
+ * Switch from 32-bit protected mode with virtual addresses to 32-bit
|
|
556
|
+ * protected mode with physical addresses. %esp is adjusted to a
|
|
557
|
+ * physical address. All other registers and flags are preserved.
|
|
558
|
+ *
|
|
559
|
+ * The return address for this function should be a 32-bit virtual
|
|
560
|
+ * (sic) address.
|
|
561
|
+ *
|
|
562
|
+ ****************************************************************************
|
|
563
|
+ */
|
|
564
|
+ .section ".text.prot_to_phys", "ax", @progbits
|
|
565
|
+ .code32
|
|
566
|
+prot_to_phys:
|
|
567
|
+ /* Preserve registers and flags */
|
|
568
|
+ pushfl
|
|
569
|
+ pushl %eax
|
|
570
|
+ pushl %ebp
|
|
571
|
+
|
|
572
|
+ /* Adjust return address to a physical address */
|
|
573
|
+ movl VIRTUAL(virt_offset), %ebp
|
|
574
|
+ addl %ebp, 12(%esp)
|
|
575
|
+
|
|
576
|
+ /* Switch to physical code segment */
|
|
577
|
+ cli
|
|
578
|
+ pushl $PHYSICAL_CS
|
|
579
|
+ leal VIRTUAL(1f)(%ebp), %eax
|
|
580
|
+ pushl %eax
|
|
581
|
+ lret
|
|
582
|
+1:
|
|
583
|
+ /* Switch to physical data segment and adjust %esp */
|
|
584
|
+ movw $PHYSICAL_DS, %ax
|
|
585
|
+ movw %ax, %ds
|
|
586
|
+ movw %ax, %es
|
|
587
|
+ movw %ax, %fs
|
|
588
|
+ movw %ax, %gs
|
|
589
|
+ movw %ax, %ss
|
|
590
|
+ addl %ebp, %esp
|
|
591
|
+
|
|
592
|
+ /* Restore registers and flags, and return */
|
|
593
|
+ popl %ebp
|
|
594
|
+ popl %eax
|
|
595
|
+ popfl
|
|
596
|
+ ret
|
|
597
|
+
|
|
598
|
+ /* Expose as _virt_to_phys for use by COMBOOT */
|
|
599
|
+ .globl _virt_to_phys
|
|
600
|
+ .equ _virt_to_phys, prot_to_phys
|
|
601
|
+
|
|
602
|
+/****************************************************************************
|
|
603
|
+ * intr_to_prot (protected-mode near call, 32-bit virtual return address)
|
|
604
|
+ *
|
|
605
|
+ * Switch from 32-bit protected mode with a virtual code segment and
|
|
606
|
+ * either a physical or virtual stack segment to 32-bit protected mode
|
|
607
|
+ * with normal virtual addresses. %esp is adjusted if necessary to a
|
|
608
|
+ * virtual address. All other registers and flags are preserved.
|
|
609
|
+ *
|
|
610
|
+ * The return address for this function should be a 32-bit virtual
|
|
611
|
+ * address.
|
|
612
|
+ *
|
|
613
|
+ ****************************************************************************
|
|
614
|
+ */
|
|
615
|
+ .section ".text.intr_to_prot", "ax", @progbits
|
|
616
|
+ .code32
|
|
617
|
+ .globl intr_to_prot
|
|
618
|
+intr_to_prot:
|
|
619
|
+ /* Preserve registers and flags */
|
|
620
|
+ pushfl
|
|
621
|
+ pushl %eax
|
|
622
|
+
|
|
623
|
+ /* Check whether stack segment is physical or virtual */
|
|
624
|
+ movw %ss, %ax
|
|
625
|
+ cmpw $VIRTUAL_DS, %ax
|
|
626
|
+ movw $VIRTUAL_DS, %ax
|
|
627
|
+
|
|
628
|
+ /* Reload data segment registers */
|
|
629
|
+ movw %ax, %ds
|
|
630
|
+ movw %ax, %es
|
|
631
|
+ movw %ax, %fs
|
|
632
|
+ movw %ax, %gs
|
|
633
|
+
|
|
634
|
+ /* Reload stack segment and adjust %esp if necessary */
|
|
635
|
+ je 1f
|
|
636
|
+ movw %ax, %ss
|
|
637
|
+ subl VIRTUAL(virt_offset), %esp
|
|
638
|
+1:
|
|
639
|
+ /* Restore registers and flags, and return */
|
|
640
|
+ popl %eax
|
|
641
|
+ popfl
|
|
642
|
+ ret
|
|
643
|
+
|
|
644
|
+ /* Expose as _intr_to_virt for use by GDB */
|
|
645
|
+ .globl _intr_to_virt
|
|
646
|
+ .equ _intr_to_virt, intr_to_prot
|
|
647
|
+
|
504
|
648
|
/****************************************************************************
|
505
|
649
|
* prot_call (real-mode near call, 16-bit real-mode near return address)
|
506
|
650
|
*
|
|
@@ -539,6 +683,7 @@ PC_OFFSET_IDT: .space 6
|
539
|
683
|
PC_OFFSET_IX86: .space SIZEOF_I386_ALL_REGS
|
540
|
684
|
PC_OFFSET_PADDING: .space 2 /* for alignment */
|
541
|
685
|
PC_OFFSET_RETADDR: .space 2
|
|
686
|
+PC_OFFSET_PARAMS:
|
542
|
687
|
PC_OFFSET_FUNCTION: .space 4
|
543
|
688
|
PC_OFFSET_END:
|
544
|
689
|
.previous
|
|
@@ -601,7 +746,9 @@ pc_rmode:
|
601
|
746
|
addr32 movl -20(%esp), %esp
|
602
|
747
|
popfl
|
603
|
748
|
popfw /* padding */
|
604
|
|
- ret $4
|
|
749
|
+
|
|
750
|
+ /* Return and discard function parameters */
|
|
751
|
+ ret $( PC_OFFSET_END - PC_OFFSET_PARAMS )
|
605
|
752
|
|
606
|
753
|
/****************************************************************************
|
607
|
754
|
* real_call (protected-mode near call, 32-bit virtual return address)
|
|
@@ -620,7 +767,7 @@ pc_rmode:
|
620
|
767
|
* See librm.h and realmode.h for details and examples.
|
621
|
768
|
*
|
622
|
769
|
* Parameters:
|
623
|
|
- * (32-bit) near pointer to real-mode function to call
|
|
770
|
+ * function : offset within .text16 of real-mode function to call
|
624
|
771
|
*
|
625
|
772
|
* Returns: none
|
626
|
773
|
****************************************************************************
|
|
@@ -629,6 +776,7 @@ pc_rmode:
|
629
|
776
|
RC_OFFSET_REGS: .space SIZEOF_I386_REGS
|
630
|
777
|
RC_OFFSET_REGS_END:
|
631
|
778
|
RC_OFFSET_RETADDR: .space 4
|
|
779
|
+RC_OFFSET_PARAMS:
|
632
|
780
|
RC_OFFSET_FUNCTION: .space 4
|
633
|
781
|
RC_OFFSET_END:
|
634
|
782
|
.previous
|
|
@@ -665,9 +813,11 @@ rc_rmode:
|
665
|
813
|
.section ".text.real_call", "ax", @progbits
|
666
|
814
|
.code32
|
667
|
815
|
rc_pmode:
|
668
|
|
- /* Restore registers and return */
|
|
816
|
+ /* Restore registers */
|
669
|
817
|
popal
|
670
|
|
- ret $4
|
|
818
|
+
|
|
819
|
+ /* Return and discard function parameters */
|
|
820
|
+ ret $( RC_OFFSET_END - RC_OFFSET_PARAMS )
|
671
|
821
|
|
672
|
822
|
|
673
|
823
|
/* Function vector, used because "call xx(%sp)" is not a valid
|
|
@@ -684,6 +834,55 @@ rm_default_gdtr_idtr:
|
684
|
834
|
.word 0x03ff /* Interrupt descriptor table limit */
|
685
|
835
|
.long 0 /* Interrupt descriptor table base */
|
686
|
836
|
|
|
837
|
+/****************************************************************************
|
|
838
|
+ * phys_call (protected-mode near call, 32-bit virtual return address)
|
|
839
|
+ *
|
|
840
|
+ * Call a function with flat 32-bit physical addressing
|
|
841
|
+ *
|
|
842
|
+ * The non-segment register values will be passed directly to the
|
|
843
|
+ * function. The segment registers will be set for flat 32-bit
|
|
844
|
+ * physical addressing. The non-segment register values set by the
|
|
845
|
+ * function will be passed back to the caller.
|
|
846
|
+ *
|
|
847
|
+ * librm.h defines a convenient macro PHYS_CODE() for using phys_call.
|
|
848
|
+ *
|
|
849
|
+ * Parameters:
|
|
850
|
+ * function : virtual (sic) address of function to call
|
|
851
|
+ *
|
|
852
|
+ ****************************************************************************
|
|
853
|
+ */
|
|
854
|
+ .struct 0
|
|
855
|
+PHC_OFFSET_RETADDR: .space 4
|
|
856
|
+PHC_OFFSET_PARAMS:
|
|
857
|
+PHC_OFFSET_FUNCTION: .space 4
|
|
858
|
+PHC_OFFSET_END:
|
|
859
|
+ .previous
|
|
860
|
+
|
|
861
|
+ .section ".text.phys_call", "ax", @progbits
|
|
862
|
+ .code32
|
|
863
|
+ .globl phys_call
|
|
864
|
+phys_call:
|
|
865
|
+ /* Adjust function pointer to a physical address */
|
|
866
|
+ pushl %ebp
|
|
867
|
+ movl VIRTUAL(virt_offset), %ebp
|
|
868
|
+ addl %ebp, ( PHC_OFFSET_FUNCTION + 4 /* saved %ebp */ )(%esp)
|
|
869
|
+ popl %ebp
|
|
870
|
+
|
|
871
|
+ /* Switch to physical addresses */
|
|
872
|
+ call prot_to_phys
|
|
873
|
+
|
|
874
|
+ /* Call function */
|
|
875
|
+ call *PHC_OFFSET_FUNCTION(%esp)
|
|
876
|
+
|
|
877
|
+ /* For sanity's sake, clear the direction flag as soon as possible */
|
|
878
|
+ cld
|
|
879
|
+
|
|
880
|
+ /* Switch to virtual addresses */
|
|
881
|
+ call phys_to_prot
|
|
882
|
+
|
|
883
|
+ /* Return and discard function parameters */
|
|
884
|
+ ret $( PHC_OFFSET_END - PHC_OFFSET_PARAMS )
|
|
885
|
+
|
687
|
886
|
/****************************************************************************
|
688
|
887
|
* flatten_real_mode (real-mode near call)
|
689
|
888
|
*
|
|
@@ -733,7 +932,7 @@ interrupt_wrapper:
|
733
|
932
|
pushl %esp
|
734
|
933
|
|
735
|
934
|
/* Switch to virtual addressing */
|
736
|
|
- call _intr_to_virt
|
|
935
|
+ call intr_to_prot
|
737
|
936
|
|
738
|
937
|
/* Expand IRQ number to whole %eax register */
|
739
|
938
|
movzbl %al, %eax
|