summaryrefslogtreecommitdiffstats
path: root/qemu/roms/ipxe/src/arch/i386/core/virtaddr.S
diff options
context:
space:
mode:
Diffstat (limited to 'qemu/roms/ipxe/src/arch/i386/core/virtaddr.S')
-rw-r--r--qemu/roms/ipxe/src/arch/i386/core/virtaddr.S145
1 files changed, 145 insertions, 0 deletions
diff --git a/qemu/roms/ipxe/src/arch/i386/core/virtaddr.S b/qemu/roms/ipxe/src/arch/i386/core/virtaddr.S
new file mode 100644
index 000000000..5e5d77352
--- /dev/null
+++ b/qemu/roms/ipxe/src/arch/i386/core/virtaddr.S
@@ -0,0 +1,145 @@
+/*
+ * Functions to support the virtual addressing method of relocation
+ * that Etherboot uses.
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER )
+
+#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 virt_offset, %ebp
+ addl %ebp, 12(%esp)
+
+ /* Switch to physical code segment */
+ cli
+ pushl $PHYSICAL_CS
+ leal 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, $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 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 virt_offset, %ebp
+ movl %eax, %ss
+ subl %ebp, %esp
+1:
+ /* Restore registers and flags, and return */
+ popl %ebp
+ popl %eax
+ popfl
+ ret