summaryrefslogtreecommitdiffstats
path: root/src/VBox/ValidationKit/utils/cpu/cidet-appA.asm
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/ValidationKit/utils/cpu/cidet-appA.asm')
-rw-r--r--src/VBox/ValidationKit/utils/cpu/cidet-appA.asm319
1 files changed, 319 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..55feb013
--- /dev/null
+++ b/src/VBox/ValidationKit/utils/cpu/cidet-appA.asm
@@ -0,0 +1,319 @@
+; $Id: cidet-appA.asm $
+;; @file
+; CPU Instruction Decoding & Execution Tests - Ring-3 Driver Application, Assembly Code.
+;
+
+;
+; Copyright (C) 2009-2023 Oracle and/or its affiliates.
+;
+; This file is part of VirtualBox base platform packages, as
+; available from https://www.virtualbox.org.
+;
+; This program is free software; you can redistribute it and/or
+; modify it under the terms of the GNU General Public License
+; as published by the Free Software Foundation, in version 3 of the
+; License.
+;
+; This program is distributed in the hope that it will be useful, but
+; WITHOUT ANY WARRANTY; without even the implied warranty of
+; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+; General Public License for more details.
+;
+; You should have received a copy of the GNU General Public License
+; along with this program; if not, see <https://www.gnu.org/licenses>.
+;
+; The contents of this file may alternatively be used under the terms
+; of the Common Development and Distribution License Version 1.0
+; (CDDL), a copy of it is provided in the "COPYING.CDDL" file included
+; in the VirtualBox 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.
+;
+; SPDX-License-Identifier: GPL-3.0-only OR CDDL-1.0
+;
+
+
+;*******************************************************************************
+;* 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
+