X-Git-Url: https://gerrit.opnfv.org/gerrit/gitweb?a=blobdiff_plain;f=qemu%2Froms%2Fipxe%2Fsrc%2Farch%2Fi386%2Fcore%2Fvirtaddr.S;fp=qemu%2Froms%2Fipxe%2Fsrc%2Farch%2Fi386%2Fcore%2Fvirtaddr.S;h=5e5d7735247530743a6df3b8646670e604f1b096;hb=e44e3482bdb4d0ebde2d8b41830ac2cdb07948fb;hp=0000000000000000000000000000000000000000;hpb=9ca8dbcc65cfc63d6f5ef3312a33184e1d726e00;p=kvmfornfv.git 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