Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / arch / i386 / core / virtaddr.S
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 (file)
index 0000000..5e5d773
--- /dev/null
@@ -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