cidet-appA.asm revision 694eb5fb2b25736d37902333e059a149f78c563c
; $Id$
;; @file
; CPU Instruction Decoding & Execution Tests - Ring-3 Driver Application, Assembly Code.
;
;
; Copyright (C) 2009-2014 Oracle Corporation
;
; This file is part of VirtualBox Open Source Edition (OSE), as
; available from http://www.virtualbox.org. This file is free software;
; you can redistribute it and/or modify it under the terms of the GNU
; General Public License (GPL) as published by the Free Software
; Foundation, in version 2 as it comes in the "COPYING" file of the
; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
;
; The contents of this file may alternatively be used under the terms
; of the Common Development and Distribution License Version 1.0
; (CDDL) only, as it comes in the "COPYING.CDDL" file of the
; VirtualBox OSE distribution, in which case the provisions of the
; CDDL are applicable instead of those of the GPL.
;
; You may elect to license modified versions of this file under the
; terms and conditions of either the GPL or the CDDL or both.
;
;*******************************************************************************
;* Header Files *
;*******************************************************************************
%include "iprt/asmdefs.mac"
%include "iprt/x86.mac"
%include "cidet.mac"
;*******************************************************************************
;* Global Variables *
;*******************************************************************************
%ifdef RT_ARCH_X86
;; Used by CidetAppSaveAndRestoreCtx when we have a tricky target stack.
g_uTargetEip dd 0
g_uTargetCs dw 0
%endif
;;
; ASSUMES that it's called and the EIP/RIP is found on the stack.
;
; @param pSaveCtx ds:xCX The context to save; DS, xDX and xCX have
; already been saved by the caller.
; @param pRestoreCtx ds:xDX The context to restore.
;
BEGINPROC CidetAppSaveAndRestoreCtx
;
; Save the stack pointer and program counter first so we can later
; bypass this step if we need to.
;
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xAX * 8], xAX ; need scratch register.
lea xAX, [xSP + xCB]
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xSP * 8], xAX
mov word [xCX + CIDETCPUCTX.aSRegs + X86_SREG_SS * 2], ss
mov word [xCX + CIDETCPUCTX.aSRegs + X86_SREG_CS * 2], cs
mov xAX, [xSP]
mov [xCX + CIDETCPUCTX.rip], xAX
jmp CidetAppSaveAndRestoreCtx_1
GLOBALNAME CidetAppSaveAndRestoreCtx_NoSsSpCsIp
mov [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xAX * 8], xAX
CidetAppSaveAndRestoreCtx_1:
; Flags.
%ifdef RT_ARCH_AMD64
pushfq
%else
pushfd
%endif
pop xAX
mov [xCX + CIDETCPUCTX.rfl], xAX
; Segment registers.
mov word [xCX + CIDETCPUCTX.aSRegs + X86_SREG_ES * 2], es
mov word [xCX + CIDETCPUCTX.aSRegs + X86_SREG_FS * 2], fs
mov word [xCX + CIDETCPUCTX.aSRegs + X86_SREG_GS * 2], gs
; Remaining GPRs.
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xBX * 8], xBX
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xBP * 8], xBP
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xSI * 8], xSI
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xDI * 8], xDI
%ifdef RT_ARCH_AMD64
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x8 * 8], r8
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x9 * 8], r9
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x10 * 8], r10
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x11 * 8], r11
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x12 * 8], r12
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x13 * 8], r13
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x14 * 8], r14
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x15 * 8], r15
xor eax, eax
mov [xCX + CIDETCPUCTX.cr0], rax
mov [xCX + CIDETCPUCTX.cr2], rax
mov [xCX + CIDETCPUCTX.cr3], rax
mov [xCX + CIDETCPUCTX.cr4], rax
mov [xCX + CIDETCPUCTX.cr8], rax
%else
xor eax, eax
mov [xCX + CIDETCPUCTX.rfl + 4], eax
mov [xCX + CIDETCPUCTX.rip + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xAX * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xCX * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xDX * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xBX * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xSP * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xBP * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xSI * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xDI * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x8 * 8 ], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x8 * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x9 * 8 ], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x9 * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x10 * 8 ], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x10 * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x11 * 8 ], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x11 * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x12 * 8 ], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x12 * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x13 * 8 ], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x13 * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x14 * 8 ], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x14 * 8 + 4], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x15 * 8 ], eax
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_x15 * 8 + 4], eax
mov [xCX + CIDETCPUCTX.cr0 ], eax
mov [xCX + CIDETCPUCTX.cr0 + 4], eax
mov [xCX + CIDETCPUCTX.cr2 ], eax
mov [xCX + CIDETCPUCTX.cr2 + 4], eax
mov [xCX + CIDETCPUCTX.cr3 ], eax
mov [xCX + CIDETCPUCTX.cr3 + 4], eax
mov [xCX + CIDETCPUCTX.cr4 ], eax
mov [xCX + CIDETCPUCTX.cr4 + 4], eax
mov [xCX + CIDETCPUCTX.cr8 ], eax
mov [xCX + CIDETCPUCTX.cr8 + 4], eax
%endif
mov [xCX + CIDETCPUCTX.tr], ax
mov [xCX + CIDETCPUCTX.ldtr], ax
;
; Restore the other state (pointer in xDX).
;
NAME(CidetAppSaveAndRestoreCtx_Restore):
; Restore ES, FS, and GS.
mov es, [xDX + CIDETCPUCTX.aSRegs + X86_SREG_ES * 2]
mov fs, [xDX + CIDETCPUCTX.aSRegs + X86_SREG_FS * 2]
mov gs, [xDX + CIDETCPUCTX.aSRegs + X86_SREG_GS * 2]
; Restore most GPRs (except xCX, xAX and xSP).
mov xCX, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xCX * 8]
mov xBX, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xBX * 8]
mov xBP, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xBP * 8]
mov xSI, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xSI * 8]
mov xDI, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xDI * 8]
%ifdef RT_ARCH_AMD64
mov r8, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_x8 * 8]
mov r9, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_x9 * 8]
mov r10, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_x10 * 8]
mov r11, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_x11 * 8]
mov r12, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_x12 * 8]
mov r13, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_x13 * 8]
mov r14, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_x14 * 8]
mov r15, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_x15 * 8]
%endif
%ifdef RT_ARCH_AMD64
; Create an iret frame which restores SS:RSP, RFLAGS, and CS:RIP.
movzx eax, word [xDX + CIDETCPUCTX.aSRegs + X86_SREG_SS * 2]
push xAX
push qword [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xSP * 8]
push qword [xDX + CIDETCPUCTX.rfl]
movzx eax, word [xDX + CIDETCPUCTX.aSRegs + X86_SREG_CS * 2]
push xAX
push qword [xDX + CIDETCPUCTX.rip]
; Restore DS, xAX and xDX then do the iret.
mov ds, [xDX + CIDETCPUCTX.aSRegs + X86_SREG_DS * 2]
mov xAX, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xAX * 8]
mov xDX, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xDX * 8]
iretq
%else
; In 32-bit mode iret doesn't restore CS:ESP for us, so we have to
; make a choice whether the SS:ESP is more important than EFLAGS.
cmp byte [xDX + CIDETCPUCTX.fTrickyStack], 0
jne .tricky_stack
mov ss, [xDX + CIDETCPUCTX.aSRegs + X86_SREG_SS * 2]
mov xSP, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xSP * 8]
push dword [xDX + CIDETCPUCTX.rfl] ; iret frame
movzx eax, word [xDX + CIDETCPUCTX.aSRegs + X86_SREG_CS * 2] ; iret frame
push xAX ; iret frame
push dword [xDX + CIDETCPUCTX.rip] ; iret frame
mov xAX, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xAX * 8]
mov ds, [xDX + CIDETCPUCTX.aSRegs + X86_SREG_DS * 2]
mov xDX, [cs:xDX + CIDETCPUCTX.aGRegs + X86_GREG_xDX * 8]
iretd
.tricky_stack:
mov xAX, [xDX + CIDETCPUCTX.rip]
mov [g_uTargetEip], xAX
mov ax, [xDX + CIDETCPUCTX.aSRegs + X86_SREG_CS * 2]
mov [g_uTargetCs], ax
push dword [xDX + CIDETCPUCTX.rfl]
popfd
mov ss, [xDX + CIDETCPUCTX.aSRegs + X86_SREG_SS * 2]
mov xSP, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xSP * 8]
mov xAX, [xDX + CIDETCPUCTX.aGRegs + X86_GREG_xAX * 8]
mov ds, [xDX + CIDETCPUCTX.aSRegs + X86_SREG_DS * 2]
mov xDX, [cs:xDX + CIDETCPUCTX.aGRegs + X86_GREG_xDX * 8]
jmp far [cs:g_uTargetEip]
%endif
ENDPROC CidetAppSaveAndRestoreCtx
;;
; C callable version of CidetAppSaveAndRestoreCtx more or less.
;
; @param pSaveCtx x86:esp+4 gcc:rdi msc:rcx
; @param pRestoreCtx x86:esp+8 gcc:rsi msc:rdx
BEGINPROC CidetAppExecute
%ifdef RT_ARCH_X86
mov ecx, [esp + 4]
mov edx, [esp + 8]
%elifdef ASM_CALL64_GCC
mov rcx, rdi
mov rdx, rsi
%elifndef ASM_CALL64_MSC
%error "unsupport arch."
%endif
mov word [xCX + CIDETCPUCTX.aSRegs + X86_SREG_DS * 2], ds
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xDX * 8], xDX
mov [xCX + CIDETCPUCTX.aGRegs + X86_GREG_xCX * 8], xCX
jmp NAME(CidetAppSaveAndRestoreCtx)
ENDPROC CidetAppExecute
;;
; C callable restore function.
;
; @param pRestoreCtx x86:esp+4 gcc:rdi msc:rcx
BEGINPROC CidetAppRestoreCtx
%ifdef RT_ARCH_X86
mov edx, [esp + 4]
%elifdef ASM_CALL64_GCC
mov rdx, rdi
%elifdef ASM_CALL64_MSC
mov rdx, rcx
%else
%error "unsupport arch."
%endif
mov ds, [cs:xDX + CIDETCPUCTX.aSRegs + X86_SREG_DS * 2]
jmp NAME(CidetAppSaveAndRestoreCtx_Restore)
ENDPROC CidetAppRestoreCtx