diff options
Diffstat (limited to 'src/VBox/ValidationKit/utils/cpu/cidet-appA.asm')
-rw-r--r-- | src/VBox/ValidationKit/utils/cpu/cidet-appA.asm | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/src/VBox/ValidationKit/utils/cpu/cidet-appA.asm b/src/VBox/ValidationKit/utils/cpu/cidet-appA.asm new file mode 100644 index 00000000..1f1e8bd5 --- /dev/null +++ b/src/VBox/ValidationKit/utils/cpu/cidet-appA.asm @@ -0,0 +1,309 @@ +; $Id: cidet-appA.asm $ +;; @file +; CPU Instruction Decoding & Execution Tests - Ring-3 Driver Application, Assembly Code. +; + +; +; Copyright (C) 2009-2019 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 + + +;; +; Leave GS alone on 64-bit darwin (gs is 0, no ldt or gdt entry to load that'll +; restore the lower 32-bits of the base when saving and restoring the register). +%ifdef RT_OS_DARWIN + %ifdef RT_ARCH_AMD64 + %define CIDET_LEAVE_GS_ALONE + %endif +%endif + + + +BEGINCODE + +;; +; 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.cr2], rax + %ifndef CIDET_REDUCED_CTX + mov [xCX + CIDETCPUCTX.cr0], rax + mov [xCX + CIDETCPUCTX.cr3], rax + mov [xCX + CIDETCPUCTX.cr4], rax + mov [xCX + CIDETCPUCTX.cr8], rax + mov [xCX + CIDETCPUCTX.dr0], rax + mov [xCX + CIDETCPUCTX.dr1], rax + mov [xCX + CIDETCPUCTX.dr2], rax + mov [xCX + CIDETCPUCTX.dr3], rax + mov [xCX + CIDETCPUCTX.dr6], rax + mov [xCX + CIDETCPUCTX.dr7], rax + mov [xCX + CIDETCPUCTX.tr], ax + mov [xCX + CIDETCPUCTX.ldtr], ax + %endif +%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.cr2 ], eax + mov [xCX + CIDETCPUCTX.cr2 + 4], eax + %ifndef CIDET_REDUCED_CTX + mov [xCX + CIDETCPUCTX.cr0 ], eax + mov [xCX + CIDETCPUCTX.cr0 + 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 + mov [xCX + CIDETCPUCTX.dr0 ], eax + mov [xCX + CIDETCPUCTX.dr0 + 4], eax + mov [xCX + CIDETCPUCTX.dr1 ], eax + mov [xCX + CIDETCPUCTX.dr1 + 4], eax + mov [xCX + CIDETCPUCTX.dr2 ], eax + mov [xCX + CIDETCPUCTX.dr2 + 4], eax + mov [xCX + CIDETCPUCTX.dr3 ], eax + mov [xCX + CIDETCPUCTX.dr3 + 4], eax + mov [xCX + CIDETCPUCTX.dr6 ], eax + mov [xCX + CIDETCPUCTX.dr6 + 4], eax + mov [xCX + CIDETCPUCTX.dr7 ], eax + mov [xCX + CIDETCPUCTX.dr7 + 4], eax + mov [xCX + CIDETCPUCTX.tr], ax + mov [xCX + CIDETCPUCTX.ldtr], ax + %endif +%endif + dec xAX + mov [xCX + CIDETCPUCTX.uErr], xAX +%ifdef RT_ARCH_X86 + mov [xCX + CIDETCPUCTX.uErr + 4], eax +%endif + mov [xCX + CIDETCPUCTX.uXcpt], eax + + ; + ; 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] +%ifndef CIDET_LEAVE_GS_ALONE + mov gs, [xDX + CIDETCPUCTX.aSRegs + X86_SREG_GS * 2] +%endif + + ; 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 + |