338N/A; Copyright (C) 2006-2007 Oracle Corporation
338N/A; This file is part of VirtualBox Open Source Edition (OSE), as
338N/A; you can redistribute it
and/or modify it under the terms of the GNU
338N/A; General Public License (GPL) as published by the Free Software
338N/A; Foundation, in version 2 as it comes in the "COPYING" file of the
338N/A; VirtualBox OSE distribution. VirtualBox OSE is distributed in the
338N/A; hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
338N/A;*******************************************************************************
338N/A;*******************************************************************************
338N/A;*******************************************************************************
338N/A;* Defined Constants And Macros *
4134N/A;*******************************************************************************
338N/A; Function prolog which saves everything and loads the first parameter into ebx.
2095N/A; Function epilog which saves everything and loads the first parameter into ebx.
338N/A; Does an rdtsc (trashing edx:eax) and move the result to edi:esi.
338N/A; Does an rdtsc (trashing edx:eax) and move the result to ecx:ebp.
338N/A; Saves the result of an instruction profiling operation.
338N/A; Input is in edi:esi (start) and [ebp + 8] points to TSTMICRO.
338N/A%macro STORE_INSTR_PRF_RESULT 0
338N/A; Samples the end time of an instruction profiling operation and
338N/A; Saves the result of an instruction profiling operation.
338N/A; Input is in edi:esi (start) and [ebp + 8] points to TSTMICRO.
338N/A%macro RDTSC_STORE_INSTR_PRF_RESULT 0
338N/A; copies the stack to gabStackCopy and saves ESP and EBP in gpESP and gpEBP.
338N/A; @param %1 The resume label.
338N/A; @param ebx TSTMICRO pointer.
338N/A; @uses ecx, edi, esi, flags.
338N/A%macro COPY_STACK_ESP_EBP_RESUME 1
mov dword [gEIPResume], %1
;*******************************************************************************
;*******************************************************************************
EXPORTEDNAME tstMicroRCAsmStart
; Check the overhead of doing rdtsc + two xchg operations.
RDTSC_STORE_INSTR_PRF_RESULT
RDTSC_STORE_INSTR_PRF_RESULT
; Invalidate the current code page.
invlpg [NAME(tstInvlpgEIP)]
RDTSC_STORE_INSTR_PRF_RESULT
RDTSC_STORE_INSTR_PRF_RESULT
RDTSC_STORE_INSTR_PRF_RESULT
or ebx, X86_CR0_WRITE_PROTECT
; disabled it now or we'll die...
and ebx, ~X86_CR0_WRITE_PROTECT
or ebx, X86_CR0_WRITE_PROTECT
; just wast a bit of space and time to try avoid the enable bit tainting the results of the disable.
and ebx, ~X86_CR0_WRITE_PROTECT
RDTSC_STORE_INSTR_PRF_RESULT
; Generate a #PF accessing page 0 in
COPY_STACK_ESP_EBP_RESUME tstPFR0_Resume
xor ebx, ebx ; The NULL pointer.
xor ebp, ebp ; ebp:ecx - Rx enter time (0:0).
RDTSC_EDI_ESI ; edi:esi - Before trap.
mov [ebx], ebx ; traps - 2 bytes
RDTSC_EDI_ESI ; edi:esi - Rx entry time.
; Generate a #PF accessing page 0 in ring-1
BEGINPROC_EXPORTED tstPFR1
COPY_STACK_ESP_EBP_RESUME tstPFR1_Resume
; Setup iret to execute r1 code.
mov eax, 02069h ; load ds and es with R1 selectors.
push dword 0000h ; eflags
RDTSC_ECX_EBP ; ebp:ecx - Rx enter time (0:0).
RDTSC_EDI_ESI ; edi:esi - Before trap.
mov [ebx], ebx ; traps - 2 bytes
RDTSC_EDI_ESI ; edi:esi - Rx entry time.
; Generate a #PF accessing page 0 in ring-2
BEGINPROC_EXPORTED tstPFR2
COPY_STACK_ESP_EBP_RESUME tstPFR2_Resume
; Setup iret to execute r2 code.
mov eax, 0206ah ; load ds and es with R2 selectors.
push dword 0000h ; eflags
RDTSC_ECX_EBP ; ebp:ecx - Rx enter time (0:0).
RDTSC_EDI_ESI ; edi:esi - Before trap.
mov [ebx], ebx ; traps - 2 bytes
RDTSC_EDI_ESI ; edi:esi - Rx entry time.
; Generate a #PF accessing page 0 in ring-3
BEGINPROC_EXPORTED tstPFR3
COPY_STACK_ESP_EBP_RESUME tstPFR3_Resume
; Setup iret to execute r3 code.
mov eax, 0306bh ; load ds and es with R3 selectors.
push dword 0000h ; eflags
RDTSC_ECX_EBP ; ebp:ecx - Rx enter time (0:0).
RDTSC_EDI_ESI ; edi:esi - Before trap.
mov [ebx], ebx ; traps - 2 bytes
RDTSC_EDI_ESI ; edi:esi - Rx entry time.
; Trap handler with error code - share code with tstTrapHandler.
BEGINPROC_EXPORTED tstTrapHandlerNoErr
jmp tstTrapHandler_Common
; Trap handler with error code.
; 14 SS (only if ring transition.)
; 10 ESP (only if ring transition.)
; 0 Error code. (~0 for vectors which don't take an error code.)
;; @todo This is a bit of a mess - clean up!
mov eax, -1 ; return code
and ebx, ~X86_CR0_WRITE_PROTECT
; first hit, or final hit?
jne near tstTrapHandler_Fault
; save the results - edx:ecx == r0 enter time, edi:esi == before trap, ecx:ebp == Rx enter time.
; Advance the EIP and resume.
add [esp + 4], ecx ; return eip + offEIPAdd
add esp, byte 4 ; skip the err code
; take the timestamp before resuming.
%if 0 ; this has been broken for quite some time
; Setup CPUMCTXCORE frame
push dword [esp + 4h + 0h] ; 3ch - eip
push dword [esp + 0ch + 4h] ; 38h - eflags
;;;;push dword [esp + 08h + 8h] ; 34h - cs
push dword [esp + 14h + 1ch] ; 20h - ss
push dword [esp + 10h + 20h] ; 1ch - esp
test byte [esp + 0ch + 4h], 3h ; check CPL of the cs selector
jmp short tstTrapHandler_Fault_Hyper ;; @todo
jz short tstTrapHandler_Fault_Hyper
tstTrapHandler_Fault_Guest:
mov eax, VERR_TRPM_DONT_PANIC
jmp short tstTrapHandler_Fault_Guest
tstTrapHandler_Fault_Hyper:
lea ebx, [esp + 14h + 040h] ; calc esp at trap
mov eax, VERR_TRPM_DONT_PANIC
jmp short tstTrapHandler_Fault_Hyper
xor eax, eax ; return code.
; save the results - edx:ecx == r0 end time, edi:esi == Rx end time.
; Restore the IDT and stack, and resume the testcase code.
EXPORTEDNAME tstMicroRCAsmEnd