/* * VM exit benchmark using a hypercall * * Copyright (c) Siemens AG, 2015 * * Authors: * Jan Kiszka * * This work is licensed under the terms of the GNU GPL, version 2. See * the COPYING file in the top-level directory. */ #ifndef __x86_64__ #error only x86-64 supported #endif #include #include #define LOOPS 1000000 #define X86_FEATURE_VMX (1UL << 5) static inline unsigned long cpuid_ecx(void) { unsigned long val; asm volatile("cpuid" : "=c" (val) : "a" (1) : "ebx", "edx"); return val; } static inline __attribute__((always_inline)) unsigned long long read_tsc(void) { unsigned long long hi, lo; asm volatile("rdtsc" : "=a" (lo), "=d" (hi)); return (hi << 32) | lo; } int main(int argc, char *argv[]) { bool use_vmcall = !!(cpuid_ecx() & X86_FEATURE_VMX); unsigned long long start, sum = 0; unsigned int n; for (n = 0; n < LOOPS; n++) { if (use_vmcall) { start = read_tsc(); asm volatile("vmcall" : : "a" (-1)); sum += read_tsc() - start; } else { start = read_tsc(); asm volatile("vmmcall" : : "a" (-1)); sum += read_tsc() - start; } } printf("Null hypercall: %llu cycles\n", sum / LOOPS); return 0; }