瀏覽代碼

[librm] Add phys_call() wrapper for calling code with physical addressing

Add a phys_call() wrapper function (analogous to the existing
real_call() wrapper function) for calling code with flat physical
addressing, and use this wrapper within the PHYS_CODE() macro.

Move the relevant functionality inside librm.S, where it more
naturally belongs.

The COMBOOT code currently uses explicit calls to _virt_to_phys and
_phys_to_virt.  These will need to be rewritten if our COMBOOT support
is ever generalised to be able to run in a 64-bit build.
Specifically:

  - com32_exec_loop() should be restructured to use PHYS_CODE()

  - com32_wrapper.S should be restructured to use an equivalent of
    prot_call(), passing parameters via a struct i386_all_regs

  - there appears to be no need for com32_wrapper.S to switch between
    external and internal stacks; this could be omitted to simplify
    the design.

For now, librm.S continues to expose _virt_to_phys and _phys_to_virt
for use by com32.c and com32_wrapper.S.  Similarly, librm.S continues
to expose _intr_to_virt for use by gdbidt.S.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 8 年之前
父節點
當前提交
ea203e4fe1
共有 3 個檔案被更改,包括 212 行新增153 行删除
  1. 0
    145
      src/arch/x86/core/virtaddr.S
  2. 8
    3
      src/arch/x86/include/librm.h
  3. 204
    5
      src/arch/x86/transitions/librm.S

+ 0
- 145
src/arch/x86/core/virtaddr.S 查看文件

@@ -1,145 +0,0 @@
1
-/*
2
- * Functions to support the virtual addressing method of relocation
3
- * that Etherboot uses.
4
- *
5
- */
6
-
7
-FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
8
-
9
-#include "librm.h"
10
-		
11
-	.arch i386
12
-	.text
13
-	.code32
14
-	
15
-/****************************************************************************
16
- * _virt_to_phys (virtual addressing)
17
- *
18
- * Switch from virtual to flat physical addresses.  %esp is adjusted
19
- * to a physical value.  Segment registers are set to flat physical
20
- * selectors.  All other registers are preserved.  Flags are
21
- * preserved.
22
- *
23
- * Parameters: none
24
- * Returns: none
25
- ****************************************************************************
26
- */
27
-	.globl _virt_to_phys
28
-_virt_to_phys:
29
-	/* Preserve registers and flags */
30
-	pushfl
31
-	pushl	%eax
32
-	pushl	%ebp
33
-
34
-	/* Change return address to a physical address */
35
-	movl	VIRTUAL(virt_offset), %ebp
36
-	addl	%ebp, 12(%esp)
37
-
38
-	/* Switch to physical code segment */
39
-	cli
40
-	pushl	$PHYSICAL_CS
41
-	leal	VIRTUAL(1f)(%ebp), %eax
42
-	pushl	%eax
43
-	lret
44
-1:
45
-	/* Reload other segment registers and adjust %esp */
46
-	movl	$PHYSICAL_DS, %eax
47
-	movl	%eax, %ds
48
-	movl	%eax, %es
49
-	movl	%eax, %fs
50
-	movl	%eax, %gs
51
-	movl	%eax, %ss
52
-	addl	%ebp, %esp
53
-
54
-	/* Restore registers and flags, and return */
55
-	popl	%ebp
56
-	popl	%eax
57
-	popfl
58
-	ret
59
-
60
-/****************************************************************************
61
- * _phys_to_virt (flat physical addressing)
62
- *
63
- * Switch from flat physical to virtual addresses.  %esp is adjusted
64
- * to a virtual value.  Segment registers are set to virtual
65
- * selectors.  All other registers are preserved.  Flags are
66
- * preserved.
67
- *
68
- * Parameters: none
69
- * Returns: none
70
- ****************************************************************************
71
- */
72
-	.globl _phys_to_virt
73
-_phys_to_virt:
74
-	/* Preserve registers and flags */
75
-	pushfl
76
-	pushl	%eax
77
-	pushl	%ebp
78
-
79
-	/* Switch to virtual code segment */
80
-	cli
81
-	ljmp	$VIRTUAL_CS, $VIRTUAL(1f)
82
-1:
83
-	/* Reload data segment registers */
84
-	movl	$VIRTUAL_DS, %eax
85
-	movl	%eax, %ds
86
-	movl	%eax, %es
87
-	movl	%eax, %fs
88
-	movl	%eax, %gs
89
-
90
-	/* Reload stack segment and adjust %esp */
91
-	movl	VIRTUAL(virt_offset), %ebp
92
-	movl	%eax, %ss
93
-	subl	%ebp, %esp
94
-
95
-	/* Change the return address to a virtual address */
96
-	subl	%ebp, 12(%esp)
97
-
98
-	/* Restore registers and flags, and return */
99
-	popl	%ebp
100
-	popl	%eax
101
-	popfl
102
-	ret
103
-
104
-/****************************************************************************
105
- * _intr_to_virt (virtual code segment, virtual or physical stack segment)
106
- *
107
- * Switch from virtual code segment with either a virtual or physical
108
- * stack segment to using virtual addressing.  %esp is adjusted if
109
- * necessary to a virtual value.  Segment registers are set to virtual
110
- * selectors.  All other registers are preserved.  Flags are
111
- * preserved.
112
- *
113
- * Parameters: none
114
- * Returns: none
115
- ****************************************************************************
116
- */
117
-	.globl _intr_to_virt
118
-_intr_to_virt:
119
-	/* Preserve registers and flags */
120
-	pushfl
121
-	pushl	%eax
122
-	pushl	%ebp
123
-
124
-	/* Check whether stack segment is physical or virtual */
125
-	movl	%ss, %eax
126
-	cmpw	$VIRTUAL_DS, %ax
127
-	movl	$VIRTUAL_DS, %eax
128
-
129
-	/* Reload data segment registers */
130
-	movl	%eax, %ds
131
-	movl	%eax, %es
132
-	movl	%eax, %fs
133
-	movl	%eax, %gs
134
-
135
-	/* Reload stack segment and adjust %esp if necessary */
136
-	je	1f
137
-	movl	VIRTUAL(virt_offset), %ebp
138
-	movl	%eax, %ss
139
-	subl	%ebp, %esp
140
-1:
141
-	/* Restore registers and flags, and return */
142
-	popl	%ebp
143
-	popl	%eax
144
-	popfl
145
-	ret

+ 8
- 3
src/arch/x86/include/librm.h 查看文件

@@ -250,11 +250,16 @@ extern void remove_user_from_rm_stack ( userptr_t data, size_t size );
250 250
 
251 251
 /* PHYS_CODE: declare a fragment of code that executes in flat physical mode */
252 252
 #define PHYS_CODE( asm_code_str )			\
253
-	"call _virt_to_phys\n\t"			\
253
+	"push $1f\n\t"					\
254
+	"call phys_call\n\t"				\
255
+	".section \".text.phys\", \"ax\", @progbits\n\t"\
254 256
 	".code32\n\t"					\
257
+	"\n1:\n\t"					\
255 258
 	asm_code_str					\
256
-	"call _phys_to_virt\n\t"			\
257
-	CODE_DEFAULT "\n\t"
259
+	"\n\t"						\
260
+	"ret\n\t"					\
261
+	CODE_DEFAULT "\n\t"				\
262
+	".previous\n\t"
258 263
 
259 264
 /** Number of interrupts */
260 265
 #define NUM_INT 256

+ 204
- 5
src/arch/x86/transitions/librm.S 查看文件

@@ -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

Loading…
取消
儲存