tstMicroGC.cpp revision c97989161fbe75bc14cea477a5443bbf474dd3ad
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/* $Id$ */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Micro Testcase, profiling special CPU operations - GC Code (hacks).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Copyright (C) 2006-2007 innotek GmbH
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * available from http://www.virtualbox.org. This file is free software;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * you can redistribute it and/or modify it under the terms of the GNU
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * General Public License as published by the Free Software Foundation,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * distribution. VirtualBox OSE is distributed in the hope that it will
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * be useful, but WITHOUT ANY WARRANTY of any kind.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * If you received this file as part of a commercial VirtualBox
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * distribution, then only the terms of your commercial VirtualBox
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * license agreement apply instead of the previous paragraph.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync* Header Files *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/vm.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/vmm.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/selm.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "tstMicro.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/err.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/asm.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <VBox/log.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/assert.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <iprt/string.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/*******************************************************************************
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync* Internal Functions *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync*******************************************************************************/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync__BEGIN_DECLS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncDECLEXPORT(int) tstMicroGC(PTSTMICRO pTst, unsigned uTestcase);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync__END_DECLS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * Save and load our IDT.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param pTst Pointer to the instance data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync * @param iIDT The index of the IDT entry which should be hooked.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync */
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncvoid idtInstall(PTSTMICRO pTst, int iIDT)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync RTIDTR Idtr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASMGetIDTR(&Idtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Idtr.pIdt == (uintptr_t)&pTst->aIDT[0])
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return;
pTst->OriginalIDTR.cbIdt = Idtr.cbIdt;
pTst->OriginalIDTR.pIdt = Idtr.pIdt;
/*
* Copy the IDT.
*/
if (Idtr.cbIdt >= sizeof(pTst->aIDT))
Idtr.cbIdt = sizeof(pTst->aIDT) - 1;
memcpy(&pTst->aIDT[0], (void *)Idtr.pIdt, Idtr.cbIdt + 1);
/* Hook up IDT entry. */
if (iIDT >= 0)
{
uintptr_t uHandler = (uintptr_t)tstTrapHandlerNoErr;
if ( iIDT == 8
|| iIDT == 0xa
|| iIDT == 0xb
|| iIDT == 0xc
|| iIDT == 0xd
|| iIDT == 0xe
|| iIDT == 0x11)
uHandler = (uintptr_t)tstTrapHandler;
pTst->aIDT[iIDT].Int.u16OffsetHigh = uHandler >> 16;
pTst->aIDT[iIDT].Int.u16OffsetLow = uHandler & 0xffff;
pTst->aIDT[iIDT].Int.u16SegSel = SELMGetHyperCS(&g_VM);
pTst->aIDT[iIDT].Int.u2DPL = 3;
pTst->aIDT[iIDT].Int.u1Present = 1;
pTst->aIDT[iIDT].Int.u1Fixed0 = 0;
pTst->aIDT[iIDT].Int.u1Fixed1 = 0;
pTst->aIDT[iIDT].Int.u1Fixed2 = 0;
pTst->aIDT[iIDT].Int.u1Fixed3 = 0;
pTst->aIDT[iIDT].Int.u1Fixed4 = 1;
pTst->aIDT[iIDT].Int.u1Fixed5 = 1;
pTst->aIDT[iIDT].Int.u132BitGate = 1;
pTst->aIDT[iIDT].Int.u1Fixed6 = 0;
pTst->aIDT[iIDT].Int.u5Reserved2 = 0;
}
/* Install int 42h, R3 gate */
pTst->aIDT[0x42].Int.u16OffsetHigh = (uintptr_t)tstInterrupt42 >> 16;
pTst->aIDT[0x42].Int.u16OffsetLow = (uintptr_t)tstInterrupt42 & 0xffff;
pTst->aIDT[0x42].Int.u16SegSel = SELMGetHyperCS(&g_VM);
pTst->aIDT[0x42].Int.u2DPL = 3;
pTst->aIDT[0x42].Int.u1Present = 1;
pTst->aIDT[0x42].Int.u1Fixed0 = 0;
pTst->aIDT[0x42].Int.u1Fixed1 = 0;
pTst->aIDT[0x42].Int.u1Fixed2 = 0;
pTst->aIDT[0x42].Int.u1Fixed3 = 0;
pTst->aIDT[0x42].Int.u1Fixed4 = 1;
pTst->aIDT[0x42].Int.u1Fixed5 = 1;
pTst->aIDT[0x42].Int.u132BitGate = 1;
pTst->aIDT[0x42].Int.u1Fixed6 = 0;
pTst->aIDT[0x42].Int.u5Reserved2 = 0;
/*
* Load our IDT.
*/
Idtr.pIdt = (uintptr_t)&pTst->aIDT[0];
ASMSetIDTR(&Idtr);
RTIDTR Idtr2;
ASMGetIDTR(&Idtr2);
Assert(Idtr2.pIdt == (uintptr_t)&pTst->aIDT[0]);
}
/**
* Removes all trap overrides except for gate 42.
*/
DECLASM(void) idtOnly42(PTSTMICRO pTst)
{
if (pTst->OriginalIDTR.pIdt)
memcpy(&pTst->aIDT[0], (void *)pTst->OriginalIDTR.pIdt, sizeof(VBOXIDTE) * 32);
}
DECLEXPORT(int) tstMicroGC(PTSTMICRO pTst, unsigned uTestcase)
{
RTLogPrintf("pTst=%p uTestcase=%d\n", pTst, uTestcase);
/*
* Validate input.
*/
if (uTestcase >= TSTMICROTEST_MAX)
return VERR_INVALID_PARAMETER;
/*
* Clear the results.
*/
pTst->u64TSCR0Start = 0;
pTst->u64TSCRxStart = 0;
pTst->u64TSCR0Enter = 0;
pTst->u64TSCR0Exit = 0;
pTst->u64TSCRxEnd = 0;
pTst->u64TSCR0End = 0;
pTst->cHits = 0;
pTst->offEIPAdd = 0;
pTst->u32CR2 = 0;
pTst->u32EIP = 0;
pTst->u32ErrCd = 0;
PTSTMICRORESULT pRes = &pTst->aResults[uTestcase];
memset(&pTst->aResults[uTestcase], 0, sizeof(pTst->aResults[uTestcase]));
/*
* Do the testcase.
*/
int rc = VINF_SUCCESS;
switch (uTestcase)
{
case TSTMICROTEST_OVERHEAD:
{
tstOverhead(pTst);
break;
}
case TSTMICROTEST_INVLPG_0:
{
tstInvlpg0(pTst);
break;
}
case TSTMICROTEST_INVLPG_EIP:
{
tstInvlpgEIP(pTst);
break;
}
case TSTMICROTEST_INVLPG_ESP:
{
tstInvlpgESP(pTst);
break;
}
case TSTMICROTEST_CR3_RELOAD:
{
tstCR3Reload(pTst);
break;
}
case TSTMICROTEST_WP_DISABLE:
{
tstWPDisable(pTst);
break;
}
case TSTMICROTEST_WP_ENABLE:
{
tstWPEnable(pTst);
break;
}
case TSTMICROTEST_PF_R0:
{
idtInstall(pTst, 0xe);
pTst->offEIPAdd = 2;
rc = tstPFR0(pTst);
break;
}
case TSTMICROTEST_PF_R1:
{
idtInstall(pTst, 0xe);
pTst->offEIPAdd = 2;
rc = tstPFR1(pTst);
break;
}
case TSTMICROTEST_PF_R2:
{
idtInstall(pTst, 0xe);
pTst->offEIPAdd = 2;
rc = tstPFR2(pTst);
break;
}
case TSTMICROTEST_PF_R3:
{
idtInstall(pTst, 0xe);
pTst->offEIPAdd = 2;
rc = tstPFR3(pTst);
break;
}
}
/*
* Compute the results.
*/
if (pTst->u64TSCR0End && pTst->u64TSCR0Start)
pRes->cTotalTicks = pTst->u64TSCR0End - pTst->u64TSCR0Start - pTst->u64Overhead;
if (pTst->u64TSCRxStart && pTst->u64TSCR0Start)
pRes->cToRxFirstTicks = pTst->u64TSCRxStart - pTst->u64TSCR0Start - pTst->u64Overhead;
if (pTst->u64TSCR0Enter && pTst->u64TSCRxStart)
pRes->cTrapTicks = pTst->u64TSCR0Enter - pTst->u64TSCRxStart - pTst->u64Overhead;
if (pTst->u64TSCRxEnd && pTst->u64TSCR0Exit)
pRes->cToRxTrapTicks = pTst->u64TSCRxEnd - pTst->u64TSCR0Exit - pTst->u64Overhead;
if (pTst->u64TSCR0End && pTst->u64TSCRxEnd)
pRes->cToR0Ticks = pTst->u64TSCR0End - pTst->u64TSCRxEnd - pTst->u64Overhead;
return rc;
}