VirtualBox

Changeset 74533 in vbox


Ignore:
Timestamp:
Sep 30, 2018 2:50:51 PM (6 years ago)
Author:
vboxsync
Message:

VMM/testcase: Ported NemRawBench-1 to darwin. bugref:9044

Location:
trunk/src/VBox/VMM/testcase
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/testcase/Makefile.kmk

    r74529 r74533  
    411411# Special NEM host testcase.
    412412#
    413 if1of ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH), $(if-expr "$(USERNAME)" == "bird",linux.amd64,) win.amd64)
     413if1of ($(KBUILD_TARGET).$(KBUILD_TARGET_ARCH), $(if-expr "$(USERNAME)" == "bird",darwin.amd64 linux.amd64,) win.amd64)
    414414 PROGRAMS += NemRawBench-1
    415415 NemRawBench-1_TEMPLATE = VBoxR3Static
    416416 NemRawBench-1_SOURCES = NemRawBench-1.cpp
    417  #NemRawBench-1_BLD_TYPE = release
     417 NemRawBench-1_BLD_TYPE = release
    418418 NemRawBench-1_INCS.win = \
    419         $(KBUILD_DEVTOOLS)/win.x86/sdk/v10.0.17134.0/include/10.0.17134.0/um \
    420         $(KBUILD_DEVTOOLS)/win.x86/sdk/v10.0.17134.0/include/10.0.17134.0/shared
     419        $(KBUILD_DEVTOOLS)/win.x86/sdk/v10.0.17134.0/include/10.0.17134.0/um \
     420        $(KBUILD_DEVTOOLS)/win.x86/sdk/v10.0.17134.0/include/10.0.17134.0/shared
     421 NemRawBench-1_CXXFLAGS.darwin = \
     422        -F/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform//Developer/SDKs/MacOSX10.13.sdk/System/Library/Frameworks
     423 #NemRawBench-1_LDFLAGS.darwin =  \
     424 #      -F/System/Library/Frameworks \
     425 #      -framework Hypervisor
     426 NemRawBench-1_LDFLAGS.darwin = \
     427        /System/Library/Frameworks/Hypervisor.framework/Hypervisor
    421428endif
    422429
  • trunk/src/VBox/VMM/testcase/NemRawBench-1.cpp

    r74531 r74533  
     1/* $Id$ */
     2/** @file
     3 * NEM Benchmark.
     4 */
     5
     6/*
     7 * Copyright (C) 2018 Oracle Corporation
     8 *
     9 * This file is part of VirtualBox Open Source Edition (OSE), as
     10 * available from http://www.virtualbox.org. This file is free software;
     11 * you can redistribute it and/or modify it under the terms of the GNU
     12 * General Public License (GPL) as published by the Free Software
     13 * Foundation, in version 2 as it comes in the "COPYING" file of the
     14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
     15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
     16 */
     17
    118
    219/*********************************************************************************************************************************
     
    1128# include <linux/kvm.h>
    1229# include <errno.h>
    13 # include <stdint.h>
    1430# include <sys/fcntl.h>
    1531# include <sys/ioctl.h>
     
    1834# include <time.h>
    1935
     36#elif defined(RT_OS_DARWIN)
     37# include <Availability.h>
     38# if 1 /* header mix hack */
     39#  undef __OSX_AVAILABLE_STARTING
     40#  define __OSX_AVAILABLE_STARTING(_osx, _ios)
     41# endif
     42# include <Hypervisor/hv.h>
     43# include <Hypervisor/hv_arch_x86.h>
     44# include <Hypervisor/hv_arch_vmx.h>
     45# include <Hypervisor/hv_vmx.h>
     46# include <mach/mach_time.h>
     47# include <mach/kern_return.h>
     48# include <sys/time.h>
     49# include <time.h>
     50# include <sys/mman.h>
     51# include <errno.h>
     52
    2053#else
    2154# error "port me"
     
    2356
    2457#include <stdarg.h>
     58#include <stdint.h>
    2559#include <stdio.h>
    2660#include <stdlib.h>
     
    4276/** The no-op test port number. */
    4377#define MY_NOP_PORT             0x7f
     78
     79#define MY_TEST_F_NOP_IO        (1U<<0)
     80#define MY_TEST_F_CPUID         (1U<<1)
     81#define MY_TEST_F_NOP_MMIO      (1U<<2)
    4482
    4583
     
    78116/** The size of the g_pVCpuRun mapping. */
    79117static ssize_t                  g_cbVCpuRun;
     118
     119#elif defined(RT_OS_DARWIN)
     120/** The VCpu ID. */
     121static hv_vcpuid_t              g_idVCpu;
    80122#endif
    81123
     
    96138#ifdef RT_OS_WINDOWS
    97139    return g_pfnRtlGetSystemTimePrecise() * 100;
     140
    98141#elif defined(RT_OS_LINUX)
    99142    struct timespec ts;
    100143    clock_gettime(CLOCK_MONOTONIC, &ts);
    101144    return (uint64_t)ts.tv_sec * UINT64_C(1000000000) + ts.tv_nsec;
     145
     146#elif defined(RT_OS_DARWIN)
     147    static struct mach_timebase_info    s_Info = { 0, 0 };
     148    static double                       s_rdFactor = 0.0;
     149    /* Lazy init. */
     150    if (s_Info.denom != 0)
     151    { /* likely */ }
     152    else if (mach_timebase_info(&s_Info) == KERN_SUCCESS)
     153        s_rdFactor = (double)s_Info.numer / (double)s_Info.denom;
     154    else
     155    {
     156        error("mach_timebase_info(&Info) failed\n");
     157        exit(1);
     158    }
     159    if (s_Info.denom == 1 && s_Info.numer == 1) /* special case: absolute time is in nanoseconds */
     160        return mach_absolute_time();
     161    return mach_absolute_time() * s_rdFactor;
    102162#else
    103 # error "port me"
     163    struct timeval tv;
     164    gettimeofday(&tv, NULL);
     165    return (uint64_t)tv.tv_sec * UINT64_C(1000000000)
     166         + (tv.tv_usec * UINT32_C(1000));
    104167#endif
     168}
     169
     170
     171char *formatNum(uint64_t uNum, int cchWidth, char *pszDst, size_t cbDst)
     172{
     173    char szTmp[64 + 22];
     174#ifdef _MSC_VER
     175    size_t cchTmp = snprintf(szTmp, sizeof(szTmp) - 22, "%I64u", uNum);
     176#else
     177    size_t cchTmp = snprintf(szTmp, sizeof(szTmp) - 22, "%llu", uNum);
     178#endif
     179    size_t cSeps  = (cchTmp - 1) / 3;
     180    if (cSeps)
     181    {
     182        szTmp[cchTmp + cSeps] = '\0';
     183        for (size_t iSrc = cchTmp, iDst = cchTmp + cSeps; cSeps > 0; cSeps--)
     184        {
     185            szTmp[--iDst] = szTmp[--iSrc];
     186            szTmp[--iDst] = szTmp[--iSrc];
     187            szTmp[--iDst] = szTmp[--iSrc];
     188            szTmp[--iDst] = ' ';
     189        }
     190    }
     191    snprintf(pszDst, cbDst, "%*s", cchWidth, szTmp);
     192    return pszDst;
    105193}
    106194
     
    236324        { "cr3",    WHvX64RegisterCr3, 64 },
    237325        { "cr4",    WHvX64RegisterCr4, 64 },
    238    };
     326    };
    239327    for (unsigned i = 0; i < sizeof(s_aRegs) / sizeof(s_aRegs[0]); i++)
    240328    {
     
    261349
    262350
    263 static int runRealModeTest(unsigned cInstructions, const char *pszInstruction,
     351static int runRealModeTest(unsigned cInstructions, const char *pszInstruction, unsigned fTest,
    264352                           unsigned uEax, unsigned uEcx, unsigned uEdx, unsigned uEbx,
    265353                           unsigned uEsp, unsigned uEbp, unsigned uEsi, unsigned uEdi)
    266354{
     355    (void)fTest;
     356
    267357    /*
    268358     * Initialize the real mode context.
     
    295385    ADD_REG64(WHvX64RegisterRdi, uEdi);
    296386    ADD_REG64(WHvX64RegisterRip, MY_TEST_RIP);
    297     ADD_REG64(WHvX64RegisterRflags, 1);
     387    ADD_REG64(WHvX64RegisterRflags, 2);
    298388    ADD_SEG(WHvX64RegisterEs, 0x00000, 0xffff, 0x0000, 0);
    299389    ADD_SEG(WHvX64RegisterCs, 0x00000, 0xffff, 0x0000, 1);
     
    515605}
    516606
    517 static int runRealModeTest(unsigned cInstructions, const char *pszInstruction,
     607static int runRealModeTest(unsigned cInstructions, const char *pszInstruction, unsigned fTest,
    518608                           unsigned uEax, unsigned uEcx, unsigned uEdx, unsigned uEbx,
    519609                           unsigned uEsp, unsigned uEbp, unsigned uEsi, unsigned uEdi)
    520610{
     611    (void)fTest;
     612
    521613    /*
    522614     * Setup real mode context.
     
    549641    Regs.rdi = uEdi;
    550642    Regs.rip = MY_TEST_RIP;
    551     Regs.rflags = 1;
     643    Regs.rflags = 2;
    552644    int rc = ioctl(g_fdVCpu, KVM_SET_REGS, &Regs);
    553645    if (rc != 0)
     
    614706
    615707#elif defined(RT_OS_DARWIN)
    616 # error "port me"
     708
     709/*
     710 * Mac OS X - Hypervisor API.
     711 */
     712
     713static int createVM(void)
     714{
     715    /* VM and VCpu */
     716    hv_return_t rcHv = hv_vm_create(HV_VM_DEFAULT);
     717    if (rcHv != HV_SUCCESS)
     718        return error("hv_vm_create failed: %#x\n", rcHv);
     719
     720    g_idVCpu = -1;
     721    rcHv = hv_vcpu_create(&g_idVCpu, HV_VCPU_DEFAULT);
     722    if (rcHv != HV_SUCCESS)
     723        return error("hv_vcpu_create failed: %#x\n", rcHv);
     724
     725    /* Memory. */
     726    g_pbMem = (unsigned char *)mmap(NULL, g_cbMem, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0);
     727    if ((void *)g_pbMem == MAP_FAILED)
     728        return error("mmap RAM failed: %d\n", errno);
     729    memset(g_pbMem, 0xf4, g_cbMem);
     730
     731    rcHv = hv_vm_map(g_pbMem, MY_MEM_BASE, g_cbMem, HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC);
     732    if (rcHv != HV_SUCCESS)
     733        return error("hv_vm_map failed: %#x\n", rcHv);
     734
     735    rcHv = hv_vm_protect(0x2000, 0x1000, HV_MEMORY_READ | HV_MEMORY_WRITE | HV_MEMORY_EXEC);
     736    if (rcHv != HV_SUCCESS)
     737        return error("hv_vm_protect failed: %#x\n", rcHv);
     738    return 0;
     739}
     740
     741
     742static int runtimeError(const char *pszFormat, ...)
     743{
     744    fprintf(stderr, "runtime error: ");
     745    va_list va;
     746    va_start(va, pszFormat);
     747    vfprintf(stderr, pszFormat, va);
     748    va_end(va);
     749
     750    static struct { const char *pszName; uint32_t uField; uint32_t uFmt : 31; uint32_t fIsReg : 1; } const s_aFields[] =
     751    {
     752        { "VMCS_RO_EXIT_REASON",        VMCS_RO_EXIT_REASON,        64, 0 },
     753        { "VMCS_RO_EXIT_QUALIFIC",      VMCS_RO_EXIT_QUALIFIC,      64, 0 },
     754        { "VMCS_RO_INSTR_ERROR",        VMCS_RO_INSTR_ERROR,        64, 0 },
     755        { "VMCS_RO_VMEXIT_IRQ_INFO",    VMCS_RO_VMEXIT_IRQ_INFO,    64, 0 },
     756        { "VMCS_RO_VMEXIT_IRQ_ERROR",   VMCS_RO_VMEXIT_IRQ_ERROR,   64, 0 },
     757        { "VMCS_RO_VMEXIT_INSTR_LEN",   VMCS_RO_VMEXIT_INSTR_LEN,   64, 0 },
     758        { "VMCS_RO_VMX_INSTR_INFO",     VMCS_RO_VMX_INSTR_INFO,     64, 0 },
     759        { "VMCS_RO_GUEST_LIN_ADDR",     VMCS_RO_GUEST_LIN_ADDR,     64, 0 },
     760        { "VMCS_GUEST_PHYSICAL_ADDRESS",VMCS_GUEST_PHYSICAL_ADDRESS,64, 0 },
     761        { "VMCS_RO_IO_RCX",             VMCS_RO_IO_RCX,             64, 0 },
     762        { "VMCS_RO_IO_RSI",             VMCS_RO_IO_RSI,             64, 0 },
     763        { "VMCS_RO_IO_RDI",             VMCS_RO_IO_RDI,             64, 0 },
     764        { "VMCS_RO_IO_RIP",             VMCS_RO_IO_RIP,             64, 0 },
     765        { "rip",                        HV_X86_RIP,                 64, 1 },
     766        { "rip (vmcs)",                 VMCS_GUEST_RIP,             64, 0 },
     767        { "cs",                         HV_X86_CS,                  16, 1 },
     768        { "cs (vmcs)",                  VMCS_GUEST_CS,              16, 0 },
     769        { "cs.base",                    VMCS_GUEST_CS_BASE,         64, 0 },
     770        { "cs.limit",                   VMCS_GUEST_CS_LIMIT,        32, 0 },
     771        { "cs.attr",                    VMCS_GUEST_CS_AR,           32, 0 },
     772        { "rflags",                     HV_X86_RFLAGS,              32, 1 },
     773        { "rax",                        HV_X86_RAX,                 64, 1 },
     774        { "rcx",                        HV_X86_RCX,                 64, 1 },
     775        { "rdx",                        HV_X86_RDX,                 64, 1 },
     776        { "rbx",                        HV_X86_RBX,                 64, 1 },
     777        { "rsp",                        HV_X86_RSP,                 64, 1 },
     778        { "rsp (vmcs)",                 VMCS_GUEST_RSP,             64, 0 },
     779        { "ss",                         HV_X86_SS,                  16, 1 },
     780        { "ss (vmcs)",                  VMCS_GUEST_SS,              16, 0 },
     781        { "ss.base",                    VMCS_GUEST_SS_BASE,         64, 0 },
     782        { "ss.limit",                   VMCS_GUEST_SS_LIMIT,        32, 0 },
     783        { "ss.attr",                    VMCS_GUEST_SS_AR,           32, 0 },
     784        { "rbp",                        HV_X86_RBP,                 64, 1 },
     785        { "rsi",                        HV_X86_RSI,                 64, 1 },
     786        { "rdi",                        HV_X86_RDI,                 64, 1 },
     787        { "ds",                         HV_X86_DS,                  16, 1 },
     788        { "ds (vmcs)",                  VMCS_GUEST_DS,              16, 0 },
     789        { "ds.base",                    VMCS_GUEST_DS_BASE,         64, 0 },
     790        { "ds.limit",                   VMCS_GUEST_DS_LIMIT,        32, 0 },
     791        { "ds.attr",                    VMCS_GUEST_DS_AR,           32, 0 },
     792        { "es",                         HV_X86_ES,                  16, 1 },
     793        { "es (vmcs)",                  VMCS_GUEST_ES,              16, 0 },
     794        { "es.base",                    VMCS_GUEST_ES_BASE,         64, 0 },
     795        { "es.limit",                   VMCS_GUEST_ES_LIMIT,        32, 0 },
     796        { "es.attr",                    VMCS_GUEST_ES_AR,           32, 0 },
     797        { "fs",                         HV_X86_FS,                  16, 1 },
     798        { "fs (vmcs)",                  VMCS_GUEST_FS,              16, 0 },
     799        { "fs.base",                    VMCS_GUEST_FS_BASE,         64, 0 },
     800        { "fs.limit",                   VMCS_GUEST_FS_LIMIT,        32, 0 },
     801        { "fs.attr",                    VMCS_GUEST_FS_AR,           32, 0 },
     802        { "gs",                         HV_X86_GS,                  16, 1 },
     803        { "gs (vmcs)",                  VMCS_GUEST_GS,              16, 0 },
     804        { "gs.base",                    VMCS_GUEST_GS_BASE,         64, 0 },
     805        { "gs.limit",                   VMCS_GUEST_GS_LIMIT,        32, 0 },
     806        { "gs.attr",                    VMCS_GUEST_GS_AR,           32, 0 },
     807        { "cr0",                        HV_X86_CR0,                 64, 1 },
     808        { "cr0 (vmcs)",                 VMCS_GUEST_CR0,             64, 0 },
     809        { "cr2",                        HV_X86_CR2,                 64, 1 },
     810        { "cr3",                        HV_X86_CR3,                 64, 1 },
     811        { "cr3 (vmcs)",                 VMCS_GUEST_CR3,             64, 0 },
     812        { "cr4",                        HV_X86_CR4,                 64, 1 },
     813        { "cr4 (vmcs)",                 VMCS_GUEST_CR4,             64, 0 },
     814        { "idtr.base",                  VMCS_GUEST_IDTR_BASE,       64, 0 },
     815        { "idtr.limit",                 VMCS_GUEST_IDTR_LIMIT,      32, 0 },
     816        { "gdtr.base",                  VMCS_GUEST_GDTR_BASE,       64, 0 },
     817        { "gdtr.limit",                 VMCS_GUEST_GDTR_LIMIT,      32, 0 },
     818
     819        { "VMCS_CTRL_PIN_BASED",        VMCS_CTRL_PIN_BASED,        64, 0 },
     820        { "VMCS_CTRL_CPU_BASED",        VMCS_CTRL_CPU_BASED,        64, 0 },
     821        { "VMCS_CTRL_CPU_BASED2",       VMCS_CTRL_CPU_BASED2,       64, 0 },
     822        { "VMCS_CTRL_VMENTRY_CONTROLS", VMCS_CTRL_VMENTRY_CONTROLS, 64, 0 },
     823        { "VMCS_CTRL_VMEXIT_CONTROLS",  VMCS_CTRL_VMEXIT_CONTROLS,  64, 0 },
     824        { "VMCS_CTRL_EXC_BITMAP",       VMCS_CTRL_EXC_BITMAP,       64, 0 },
     825        { "VMCS_CTRL_CR0_MASK",         VMCS_CTRL_CR0_MASK,         64, 0 },
     826        { "VMCS_CTRL_CR0_SHADOW",       VMCS_CTRL_CR0_SHADOW,       64, 0 },
     827        { "VMCS_CTRL_CR4_MASK",         VMCS_CTRL_CR4_MASK,         64, 0 },
     828        { "VMCS_CTRL_CR4_SHADOW",       VMCS_CTRL_CR4_SHADOW,       64, 0 },
     829    };
     830    for (unsigned i = 0; i < sizeof(s_aFields) / sizeof(s_aFields[0]); i++)
     831    {
     832        uint64_t uValue = UINT64_MAX;
     833        hv_return_t rcHv;
     834        if (s_aFields[i].fIsReg)
     835            rcHv = hv_vcpu_read_register(g_idVCpu, (hv_x86_reg_t)s_aFields[i].uField, &uValue);
     836        else
     837            rcHv = hv_vmx_vcpu_read_vmcs(g_idVCpu, s_aFields[i].uField, &uValue);
     838        if (rcHv == HV_SUCCESS)
     839        {
     840            if (s_aFields[i].uFmt == 16)
     841                fprintf(stderr, "%28s=%04llx\n", s_aFields[i].pszName, uValue);
     842            else if (s_aFields[i].uFmt == 32)
     843                fprintf(stderr, "%28s=%08llx\n", s_aFields[i].pszName, uValue);
     844            else
     845                fprintf(stderr, "%28s=%08x'%08x\n", s_aFields[i].pszName, (uint32_t)(uValue >> 32), (uint32_t)uValue);
     846        }
     847        else
     848            fprintf(stderr, "%28s=<%s failed %#x>\n", s_aFields[i].pszName,
     849                    s_aFields[i].fIsReg ? "hv_vcpu_read_register" : "hv_vmx_vcpu_read_vmcs", rcHv);
     850    }
     851    return 1;
     852}
     853
     854
     855static int runRealModeTest(unsigned cInstructions, const char *pszInstruction, unsigned fTest,
     856                           unsigned uEax, unsigned uEcx, unsigned uEdx, unsigned uEbx,
     857                           unsigned uEsp, unsigned uEbp, unsigned uEsi, unsigned uEdi)
     858{
     859    /*
     860     * Setup real mode context.
     861     */
     862#define WRITE_REG_RET(a_enmReg, a_uValue) \
     863        do { \
     864            hv_return_t rcHvX = hv_vcpu_write_register(g_idVCpu, a_enmReg, a_uValue); \
     865            if (rcHvX == HV_SUCCESS) { /* likely */ } \
     866            else return error("hv_vcpu_write_register(%#x, %s, %#llx) -> %#x\n", g_idVCpu, #a_enmReg, (uint64_t)(a_uValue), rcHvX); \
     867        } while (0)
     868#define READ_REG_RET(a_enmReg, a_puValue) \
     869        do { \
     870            hv_return_t rcHvX = hv_vcpu_read_register(g_idVCpu, a_enmReg, a_puValue); \
     871            if (rcHvX == HV_SUCCESS) { /* likely */ } \
     872            else return error("hv_vcpu_read_register(%#x, %s,) -> %#x\n", g_idVCpu, #a_enmReg, rcHvX); \
     873        } while (0)
     874#define WRITE_VMCS_RET(a_enmField, a_uValue) \
     875        do { \
     876            hv_return_t rcHvX = hv_vmx_vcpu_write_vmcs(g_idVCpu, a_enmField, a_uValue); \
     877            if (rcHvX == HV_SUCCESS) { /* likely */ } \
     878            else return error("hv_vmx_vcpu_write_vmcs(%#x, %s, %#llx) -> %#x\n", g_idVCpu, #a_enmField, (uint64_t)(a_uValue), rcHvX); \
     879        } while (0)
     880#define READ_VMCS_RET(a_enmField, a_puValue) \
     881        do { \
     882            hv_return_t rcHvX = hv_vmx_vcpu_read_vmcs(g_idVCpu, a_enmField, a_puValue); \
     883            if (rcHvX == HV_SUCCESS) { /* likely */ } \
     884            else return error("hv_vmx_vcpu_read_vmcs(%#x, %s,) -> %#x\n", g_idVCpu, #a_enmField, rcHvX); \
     885        } while (0)
     886#define READ_CAP_RET(a_enmCap, a_puValue) \
     887        do { \
     888            hv_return_t rcHvX = hv_vmx_read_capability(a_enmCap, a_puValue); \
     889            if (rcHvX == HV_SUCCESS) { /* likely */ } \
     890            else return error("hv_vmx_read_capability(%s) -> %#x\n", #a_enmCap); \
     891        } while (0)
     892#define CAP_2_CTRL(a_uCap, a_fWanted) ( ((a_fWanted) | (uint32_t)(a_uCap)) & (uint32_t)((a_uCap) >> 32) )
     893#if 1
     894    uint64_t uCap;
     895    READ_CAP_RET(HV_VMX_CAP_PINBASED, &uCap);
     896    WRITE_VMCS_RET(VMCS_CTRL_PIN_BASED, CAP_2_CTRL(uCap, PIN_BASED_INTR | PIN_BASED_NMI | PIN_BASED_VIRTUAL_NMI));
     897    READ_CAP_RET(HV_VMX_CAP_PROCBASED, &uCap);
     898    WRITE_VMCS_RET(VMCS_CTRL_CPU_BASED, CAP_2_CTRL(uCap, CPU_BASED_HLT
     899                                                       | CPU_BASED_INVLPG
     900                                                       | CPU_BASED_MWAIT
     901                                                       | CPU_BASED_RDPMC
     902                                                       | CPU_BASED_RDTSC
     903                                                       | CPU_BASED_CR3_LOAD
     904                                                       | CPU_BASED_CR3_STORE
     905                                                       | CPU_BASED_CR8_LOAD
     906                                                       | CPU_BASED_CR8_STORE
     907                                                       | CPU_BASED_MOV_DR
     908                                                       | CPU_BASED_UNCOND_IO
     909                                                       | CPU_BASED_MONITOR
     910                                                       | CPU_BASED_PAUSE
     911                                                       ));
     912    READ_CAP_RET(HV_VMX_CAP_PROCBASED2, &uCap);
     913    WRITE_VMCS_RET(VMCS_CTRL_CPU_BASED2, CAP_2_CTRL(uCap, 0));
     914    READ_CAP_RET(HV_VMX_CAP_ENTRY, &uCap);
     915    WRITE_VMCS_RET(VMCS_CTRL_VMENTRY_CONTROLS, CAP_2_CTRL(uCap, 0));
     916#endif
     917    WRITE_VMCS_RET(VMCS_CTRL_EXC_BITMAP, UINT32_MAX);
     918    WRITE_VMCS_RET(VMCS_CTRL_CR0_MASK,   0x60000000);
     919    WRITE_VMCS_RET(VMCS_CTRL_CR0_SHADOW, 0x00000000);
     920    WRITE_VMCS_RET(VMCS_CTRL_CR4_MASK,   0x00000000);
     921    WRITE_VMCS_RET(VMCS_CTRL_CR4_SHADOW, 0x00000000);
     922
     923    WRITE_REG_RET(HV_X86_RAX, uEax);
     924    WRITE_REG_RET(HV_X86_RCX, uEcx);
     925    WRITE_REG_RET(HV_X86_RDX, uEdx);
     926    WRITE_REG_RET(HV_X86_RBX, uEbx);
     927    WRITE_REG_RET(HV_X86_RSP, uEsp);
     928    WRITE_REG_RET(HV_X86_RBP, uEbp);
     929    WRITE_REG_RET(HV_X86_RSI, uEsi);
     930    WRITE_REG_RET(HV_X86_RDI, uEdi);
     931    WRITE_REG_RET(HV_X86_RIP, MY_TEST_RIP);
     932    WRITE_REG_RET(HV_X86_RFLAGS, 2);
     933    WRITE_REG_RET(HV_X86_ES, 0x0000);
     934    WRITE_VMCS_RET(VMCS_GUEST_ES_BASE, 0x0000000);
     935    WRITE_VMCS_RET(VMCS_GUEST_ES_LIMIT,   0xffff);
     936    WRITE_VMCS_RET(VMCS_GUEST_ES_AR,        0x93);
     937    WRITE_REG_RET(HV_X86_CS, 0x0000);
     938    WRITE_VMCS_RET(VMCS_GUEST_CS_BASE, 0x0000000);
     939    WRITE_VMCS_RET(VMCS_GUEST_CS_LIMIT,   0xffff);
     940    WRITE_VMCS_RET(VMCS_GUEST_CS_AR,        0x9b);
     941    WRITE_REG_RET(HV_X86_SS, 0x0000);
     942    WRITE_VMCS_RET(VMCS_GUEST_SS_BASE, 0x0000000);
     943    WRITE_VMCS_RET(VMCS_GUEST_SS_LIMIT,   0xffff);
     944    WRITE_VMCS_RET(VMCS_GUEST_SS_AR,        0x93);
     945    WRITE_REG_RET(HV_X86_DS, 0x0000);
     946    WRITE_VMCS_RET(VMCS_GUEST_DS_BASE, 0x0000000);
     947    WRITE_VMCS_RET(VMCS_GUEST_DS_LIMIT,  0xffff);
     948    WRITE_VMCS_RET(VMCS_GUEST_DS_AR,        0x93);
     949    WRITE_REG_RET(HV_X86_FS, 0x0000);
     950    WRITE_VMCS_RET(VMCS_GUEST_FS_BASE, 0x0000000);
     951    WRITE_VMCS_RET(VMCS_GUEST_FS_LIMIT,   0xffff);
     952    WRITE_VMCS_RET(VMCS_GUEST_FS_AR,        0x93);
     953    WRITE_REG_RET(HV_X86_GS, 0x0000);
     954    WRITE_VMCS_RET(VMCS_GUEST_GS_BASE, 0x0000000);
     955    WRITE_VMCS_RET(VMCS_GUEST_GS_LIMIT,   0xffff);
     956    WRITE_VMCS_RET(VMCS_GUEST_GS_AR,        0x93);
     957    //WRITE_REG_RET(HV_X86_CR0, 0x10030 /*WP+NE+ET*/);
     958    WRITE_VMCS_RET(VMCS_GUEST_CR0,        0x10030 /*WP+NE+ET*/);
     959    //WRITE_REG_RET(HV_X86_CR2, 0);
     960    //WRITE_REG_RET(HV_X86_CR3, 0);
     961    WRITE_VMCS_RET(VMCS_GUEST_CR3,             0);
     962    //WRITE_REG_RET(HV_X86_CR4, 0x2000);
     963    WRITE_VMCS_RET(VMCS_GUEST_CR4,        0x2000);
     964    WRITE_VMCS_RET(VMCS_GUEST_LDTR,          0x0000);
     965    WRITE_VMCS_RET(VMCS_GUEST_LDTR_BASE, 0x00000000);
     966    WRITE_VMCS_RET(VMCS_GUEST_LDTR_LIMIT,    0x0000);
     967    WRITE_VMCS_RET(VMCS_GUEST_LDTR_AR,      0x10000);
     968    WRITE_VMCS_RET(VMCS_GUEST_TR,            0x0000);
     969    WRITE_VMCS_RET(VMCS_GUEST_TR_BASE,   0x00000000);
     970    WRITE_VMCS_RET(VMCS_GUEST_TR_LIMIT,      0x0000);
     971    WRITE_VMCS_RET(VMCS_GUEST_TR_AR,        0x00083);
     972    hv_vcpu_flush(g_idVCpu);
     973    hv_vcpu_invalidate_tlb(g_idVCpu);
     974
     975    /*
     976     * Run the test.
     977     */
     978    uint32_t cExits = 0;
     979    uint64_t const nsStart = getNanoTS();
     980    for (;; cExits++)
     981    {
     982        hv_return_t rcHv = hv_vcpu_run(g_idVCpu);
     983        if (rcHv == HV_SUCCESS)
     984        {
     985            uint64_t uExitReason = UINT64_MAX;
     986            READ_VMCS_RET(VMCS_RO_EXIT_REASON, &uExitReason);
     987            if (!(uExitReason & UINT64_C(0x80000000)))
     988            {
     989                if (uExitReason == VMX_REASON_IO)
     990                {
     991                    uint64_t uIoQual = UINT64_MAX;
     992                    READ_VMCS_RET(VMCS_RO_EXIT_QUALIFIC, &uIoQual);
     993                    if ((uint16_t)(uIoQual >> 16) == MY_NOP_PORT && (fTest & MY_TEST_F_NOP_IO))
     994                    { /* likely: nop instruction */ }
     995                    else if ((uint16_t)(uIoQual >> 16) == MY_TERM_PORT)
     996                        break;
     997                    else
     998                        return runtimeError("Unexpected I/O port access (for %s): %#x\n", pszInstruction, (uint16_t)(uIoQual >> 16));
     999
     1000                    /* Advance RIP. */
     1001                    uint64_t cbInstr = UINT64_MAX;
     1002                    READ_VMCS_RET(VMCS_RO_VMEXIT_INSTR_LEN, &cbInstr);
     1003                    if (cbInstr < 1 || cbInstr > 15)
     1004                        return runtimeError("Bad instr len: %#llx\n", cbInstr);
     1005                    uint64_t uRip = UINT64_MAX;
     1006                    READ_REG_RET(HV_X86_RIP, &uRip);
     1007                    WRITE_REG_RET(HV_X86_RIP, uRip + cbInstr);
     1008                }
     1009                else if (uExitReason == VMX_REASON_CPUID && (fTest & MY_TEST_F_CPUID))
     1010                {
     1011                    /* Set registers and advance RIP. */
     1012                    WRITE_REG_RET(HV_X86_RAX, 0x42424242);
     1013                    WRITE_REG_RET(HV_X86_RCX, 0x04242424);
     1014                    WRITE_REG_RET(HV_X86_RDX, 0x00424242);
     1015                    WRITE_REG_RET(HV_X86_RBX, 0x00024242);
     1016
     1017                    uint64_t cbInstr = UINT64_MAX;
     1018                    READ_VMCS_RET(VMCS_RO_VMEXIT_INSTR_LEN, &cbInstr);
     1019                    if (cbInstr < 1 || cbInstr > 15)
     1020                        return runtimeError("Bad instr len: %#llx\n", cbInstr);
     1021                    uint64_t uRip = UINT64_MAX;
     1022                    READ_REG_RET(HV_X86_RIP, &uRip);
     1023                    WRITE_REG_RET(HV_X86_RIP, uRip + cbInstr);
     1024                }
     1025                else if (uExitReason == VMX_REASON_EPT_VIOLATION)
     1026                {
     1027                    uint64_t uEptQual = UINT64_MAX;
     1028                    READ_VMCS_RET(VMCS_RO_EXIT_QUALIFIC, &uEptQual);
     1029                    uint64_t GCPhys = UINT64_MAX;
     1030                    READ_VMCS_RET(VMCS_GUEST_PHYSICAL_ADDRESS, &GCPhys);
     1031                    if (GCPhys == MY_NOP_MMIO && (fTest & MY_TEST_F_NOP_MMIO))
     1032                    { /* likely */ }
     1033                    else if (GCPhys == MY_TEST_RIP)
     1034                        continue; /* dunno why we get this, but restarting it works */
     1035                    else
     1036                        return runtimeError("Unexpected EPT viotaion at %#llx\n", GCPhys);
     1037
     1038                    /* Set RAX and advance RIP. */
     1039                    WRITE_REG_RET(HV_X86_RAX, 42);
     1040
     1041                    uint64_t cbInstr = UINT64_MAX;
     1042                    READ_VMCS_RET(VMCS_RO_VMEXIT_INSTR_LEN, &cbInstr);
     1043                    if (cbInstr < 1 || cbInstr > 15)
     1044                        return runtimeError("Bad instr len: %#llx\n", cbInstr);
     1045                    uint64_t uRip = UINT64_MAX;
     1046                    READ_REG_RET(HV_X86_RIP, &uRip);
     1047                    WRITE_REG_RET(HV_X86_RIP, uRip + cbInstr);
     1048                }
     1049                else if (uExitReason == VMX_REASON_IRQ)
     1050                { /* ignore */ }
     1051                else
     1052                    return runtimeError("Unexpected exit reason: %#x\n", uExitReason);
     1053            }
     1054            else
     1055                return runtimeError("VM entry failure: %#x\n", uExitReason);
     1056        }
     1057        else
     1058            return runtimeError("hv_vcpu_run failed (for %s): %#x\n", pszInstruction, rcHv);
     1059    }
     1060    uint64_t const nsElapsed = getNanoTS() - nsStart;
     1061
     1062    /* Report the results. */
     1063    char szTmp1[64], szTmp2[64], szTmp3[64];
     1064    uint64_t const cInstrPerSec = nsElapsed ? (uint64_t)cInstructions * 1000000000 / nsElapsed : 0;
     1065    printf("%s %7s instructions per second (%s exits in %s ns)\n",
     1066           formatNum(cInstrPerSec, 10, szTmp1, sizeof(szTmp1)), pszInstruction,
     1067           formatNum(cExits, 0, szTmp2, sizeof(szTmp2)),
     1068           formatNum(nsElapsed, 0, szTmp3, sizeof(szTmp3)));
     1069    return 0;
     1070}
     1071
    6171072#else
    6181073# error "port me"
    6191074#endif
     1075
     1076void dumpCode(uint8_t const *pb, uint8_t *pbEnd)
     1077{
     1078    printf("testing:");
     1079    for (; pb != pbEnd; pb++)
     1080        printf(" %02x", *pb);
     1081    printf("\n");
     1082}
    6201083
    6211084
     
    6351098    /* JNZ MY_TEST_RIP */
    6361099    *pb++ = 0x75;
    637     *pb   = (signed char)(pbStart - pb + 1);
     1100    *pb   = (signed char)(pbStart - pb - 1);
    6381101    pb++;
    6391102    /* OUT 1, AL -  Temination port call. */
     
    6431106    *pb++ = 0xeb;
    6441107    *pb++ = 0xfc;
    645 
    646     return runRealModeTest(100000 * cFactor, "OUT", 42 /*eax*/, 10000 * cFactor /*ecx*/, MY_NOP_PORT /*edx*/, 0 /*ebx*/,
     1108    dumpCode(pbStart, pb);
     1109
     1110    return runRealModeTest(100000 * cFactor, "OUT", MY_TEST_F_NOP_IO,
     1111                           42 /*eax*/, 10000 * cFactor /*ecx*/, MY_NOP_PORT /*edx*/, 0 /*ebx*/,
    6471112                           0 /*esp*/, 0 /*ebp*/, 0 /*esi*/, 0 /*uEdi*/);
    6481113}
     
    6591124    {
    6601125        /* XOR EAX,EAX */
    661 #ifndef RT_OS_LINUX /* Broken on 4.18.0, probably wrong rip advance (2 instead of 3 bytes). */
    6621126        *pb++ = 0x66;
    663 #endif
    6641127        *pb++ = 0x33;
    6651128        *pb++ = 0xc0;
     
    6741137    /* JNZ MY_TEST_RIP */
    6751138    *pb++ = 0x75;
    676     *pb   = (signed char)(pbStart - pb + 1);
     1139    *pb   = (signed char)(pbStart - pb - 1);
    6771140    pb++;
    6781141    /* OUT 1, AL -  Temination port call. */
     
    6821145    *pb++ = 0xeb;
    6831146    *pb++ = 0xfc;
    684 
    685     return runRealModeTest(100000 * cFactor, "CPUID", 0 /*eax*/, 0 /*ecx*/, 0 /*edx*/, 0 /*ebx*/,
     1147    dumpCode(pbStart, pb);
     1148
     1149    return runRealModeTest(100000 * cFactor, "CPUID", MY_TEST_F_CPUID,
     1150                           0 /*eax*/, 0 /*ecx*/, 0 /*edx*/, 0 /*ebx*/,
    6861151                           0 /*esp*/, 0 /*ebp*/, 10000 * cFactor /*esi*/, 0 /*uEdi*/);
    6871152}
     
    7061171    /* JNZ MY_TEST_RIP */
    7071172    *pb++ = 0x75;
    708     *pb   = (signed char)(pbStart - pb + 1);
     1173    *pb   = (signed char)(pbStart - pb - 1);
    7091174    pb++;
    7101175    /* OUT 1, AL -  Temination port call. */
     
    7141179    *pb++ = 0xeb;
    7151180    *pb++ = 0xfc;
    716 
    717     return runRealModeTest(100000 * cFactor, "MMIO/r1" , 0 /*eax*/, 0 /*ecx*/, 0 /*edx*/, MY_NOP_MMIO /*ebx*/,
     1181    dumpCode(pbStart, pb);
     1182
     1183    return runRealModeTest(100000 * cFactor, "MMIO/r1", MY_TEST_F_NOP_MMIO,
     1184                           0 /*eax*/, 0 /*ecx*/, 0 /*edx*/, MY_NOP_MMIO /*ebx*/,
    7181185                           0 /*esp*/, 0 /*ebp*/, 10000 * cFactor /*esi*/, 0 /*uEdi*/);
    7191186}
     
    7281195#ifdef RT_OS_WINDOWS
    7291196    unsigned const  cFactorDefault = 4;
     1197#elif RT_OS_DARWIN
     1198    unsigned const  cFactorDefault = 32;
    7301199#else
    731     unsigned const  cFactorDefault = 10;
     1200    unsigned const  cFactorDefault = 24;
    7321201#endif
    7331202    unsigned        cFactor = cFactorDefault;
     
    7881257        mmioTest(cFactor);
    7891258
     1259
    7901260        printf("tstNemMini-1: done\n");
    7911261    }
     
    8051275 *      39088 MMIO/r1 instructions per second
    8061276 *
     1277 * - Darwin/xnu 10.12.6/16.7.0; 3.1GHz Core i7-7920HQ (Kaby Lake):
     1278 *    925 845     OUT instructions per second (3 200 307 exits in 3 456 301 621 ns)
     1279 *    949 278   CPUID instructions per second (3 200 222 exits in 3 370 980 173 ns)
     1280 *    871 499 MMIO/r1 instructions per second (3 200 223 exits in 3 671 834 221 ns)
    8071281 */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette