mirror of
https://github.com/ipxe/ipxe
synced 2026-01-06 20:21:47 +03:00
[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>
This commit is contained in:
@@ -1,145 +0,0 @@
|
||||
/*
|
||||
* Functions to support the virtual addressing method of relocation
|
||||
* that Etherboot uses.
|
||||
*
|
||||
*/
|
||||
|
||||
FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )
|
||||
|
||||
#include "librm.h"
|
||||
|
||||
.arch i386
|
||||
.text
|
||||
.code32
|
||||
|
||||
/****************************************************************************
|
||||
* _virt_to_phys (virtual addressing)
|
||||
*
|
||||
* Switch from virtual to flat physical addresses. %esp is adjusted
|
||||
* to a physical value. Segment registers are set to flat physical
|
||||
* selectors. All other registers are preserved. Flags are
|
||||
* preserved.
|
||||
*
|
||||
* Parameters: none
|
||||
* Returns: none
|
||||
****************************************************************************
|
||||
*/
|
||||
.globl _virt_to_phys
|
||||
_virt_to_phys:
|
||||
/* Preserve registers and flags */
|
||||
pushfl
|
||||
pushl %eax
|
||||
pushl %ebp
|
||||
|
||||
/* Change return address to a physical address */
|
||||
movl VIRTUAL(virt_offset), %ebp
|
||||
addl %ebp, 12(%esp)
|
||||
|
||||
/* Switch to physical code segment */
|
||||
cli
|
||||
pushl $PHYSICAL_CS
|
||||
leal VIRTUAL(1f)(%ebp), %eax
|
||||
pushl %eax
|
||||
lret
|
||||
1:
|
||||
/* Reload other segment registers and adjust %esp */
|
||||
movl $PHYSICAL_DS, %eax
|
||||
movl %eax, %ds
|
||||
movl %eax, %es
|
||||
movl %eax, %fs
|
||||
movl %eax, %gs
|
||||
movl %eax, %ss
|
||||
addl %ebp, %esp
|
||||
|
||||
/* Restore registers and flags, and return */
|
||||
popl %ebp
|
||||
popl %eax
|
||||
popfl
|
||||
ret
|
||||
|
||||
/****************************************************************************
|
||||
* _phys_to_virt (flat physical addressing)
|
||||
*
|
||||
* Switch from flat physical to virtual addresses. %esp is adjusted
|
||||
* to a virtual value. Segment registers are set to virtual
|
||||
* selectors. All other registers are preserved. Flags are
|
||||
* preserved.
|
||||
*
|
||||
* Parameters: none
|
||||
* Returns: none
|
||||
****************************************************************************
|
||||
*/
|
||||
.globl _phys_to_virt
|
||||
_phys_to_virt:
|
||||
/* Preserve registers and flags */
|
||||
pushfl
|
||||
pushl %eax
|
||||
pushl %ebp
|
||||
|
||||
/* Switch to virtual code segment */
|
||||
cli
|
||||
ljmp $VIRTUAL_CS, $VIRTUAL(1f)
|
||||
1:
|
||||
/* Reload data segment registers */
|
||||
movl $VIRTUAL_DS, %eax
|
||||
movl %eax, %ds
|
||||
movl %eax, %es
|
||||
movl %eax, %fs
|
||||
movl %eax, %gs
|
||||
|
||||
/* Reload stack segment and adjust %esp */
|
||||
movl VIRTUAL(virt_offset), %ebp
|
||||
movl %eax, %ss
|
||||
subl %ebp, %esp
|
||||
|
||||
/* Change the return address to a virtual address */
|
||||
subl %ebp, 12(%esp)
|
||||
|
||||
/* Restore registers and flags, and return */
|
||||
popl %ebp
|
||||
popl %eax
|
||||
popfl
|
||||
ret
|
||||
|
||||
/****************************************************************************
|
||||
* _intr_to_virt (virtual code segment, virtual or physical stack segment)
|
||||
*
|
||||
* Switch from virtual code segment with either a virtual or physical
|
||||
* stack segment to using virtual addressing. %esp is adjusted if
|
||||
* necessary to a virtual value. Segment registers are set to virtual
|
||||
* selectors. All other registers are preserved. Flags are
|
||||
* preserved.
|
||||
*
|
||||
* Parameters: none
|
||||
* Returns: none
|
||||
****************************************************************************
|
||||
*/
|
||||
.globl _intr_to_virt
|
||||
_intr_to_virt:
|
||||
/* Preserve registers and flags */
|
||||
pushfl
|
||||
pushl %eax
|
||||
pushl %ebp
|
||||
|
||||
/* Check whether stack segment is physical or virtual */
|
||||
movl %ss, %eax
|
||||
cmpw $VIRTUAL_DS, %ax
|
||||
movl $VIRTUAL_DS, %eax
|
||||
|
||||
/* Reload data segment registers */
|
||||
movl %eax, %ds
|
||||
movl %eax, %es
|
||||
movl %eax, %fs
|
||||
movl %eax, %gs
|
||||
|
||||
/* Reload stack segment and adjust %esp if necessary */
|
||||
je 1f
|
||||
movl VIRTUAL(virt_offset), %ebp
|
||||
movl %eax, %ss
|
||||
subl %ebp, %esp
|
||||
1:
|
||||
/* Restore registers and flags, and return */
|
||||
popl %ebp
|
||||
popl %eax
|
||||
popfl
|
||||
ret
|
||||
Reference in New Issue
Block a user