linux/tools/testing/selftests/kvm/x86_64/platform_info_test.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Test for x86 KVM_CAP_MSR_PLATFORM_INFO
   4 *
   5 * Copyright (C) 2018, Google LLC.
   6 *
   7 * This work is licensed under the terms of the GNU GPL, version 2.
   8 *
   9 * Verifies expected behavior of controlling guest access to
  10 * MSR_PLATFORM_INFO.
  11 */
  12
  13#define _GNU_SOURCE /* for program_invocation_short_name */
  14#include <fcntl.h>
  15#include <stdio.h>
  16#include <stdlib.h>
  17#include <string.h>
  18#include <sys/ioctl.h>
  19
  20#include "test_util.h"
  21#include "kvm_util.h"
  22#include "processor.h"
  23
  24#define VCPU_ID 0
  25#define MSR_PLATFORM_INFO_MAX_TURBO_RATIO 0xff00
  26
  27static void guest_code(void)
  28{
  29        uint64_t msr_platform_info;
  30
  31        for (;;) {
  32                msr_platform_info = rdmsr(MSR_PLATFORM_INFO);
  33                GUEST_SYNC(msr_platform_info);
  34                asm volatile ("inc %r11");
  35        }
  36}
  37
  38static void set_msr_platform_info_enabled(struct kvm_vm *vm, bool enable)
  39{
  40        struct kvm_enable_cap cap = {};
  41
  42        cap.cap = KVM_CAP_MSR_PLATFORM_INFO;
  43        cap.flags = 0;
  44        cap.args[0] = (int)enable;
  45        vm_enable_cap(vm, &cap);
  46}
  47
  48static void test_msr_platform_info_enabled(struct kvm_vm *vm)
  49{
  50        struct kvm_run *run = vcpu_state(vm, VCPU_ID);
  51        struct ucall uc;
  52
  53        set_msr_platform_info_enabled(vm, true);
  54        vcpu_run(vm, VCPU_ID);
  55        TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
  56                        "Exit_reason other than KVM_EXIT_IO: %u (%s),\n",
  57                        run->exit_reason,
  58                        exit_reason_str(run->exit_reason));
  59        get_ucall(vm, VCPU_ID, &uc);
  60        TEST_ASSERT(uc.cmd == UCALL_SYNC,
  61                        "Received ucall other than UCALL_SYNC: %u\n",
  62                        ucall);
  63        TEST_ASSERT((uc.args[1] & MSR_PLATFORM_INFO_MAX_TURBO_RATIO) ==
  64                MSR_PLATFORM_INFO_MAX_TURBO_RATIO,
  65                "Expected MSR_PLATFORM_INFO to have max turbo ratio mask: %i.",
  66                MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
  67}
  68
  69static void test_msr_platform_info_disabled(struct kvm_vm *vm)
  70{
  71        struct kvm_run *run = vcpu_state(vm, VCPU_ID);
  72
  73        set_msr_platform_info_enabled(vm, false);
  74        vcpu_run(vm, VCPU_ID);
  75        TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
  76                        "Exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n",
  77                        run->exit_reason,
  78                        exit_reason_str(run->exit_reason));
  79}
  80
  81int main(int argc, char *argv[])
  82{
  83        struct kvm_vm *vm;
  84        int rv;
  85        uint64_t msr_platform_info;
  86
  87        /* Tell stdout not to buffer its content */
  88        setbuf(stdout, NULL);
  89
  90        rv = kvm_check_cap(KVM_CAP_MSR_PLATFORM_INFO);
  91        if (!rv) {
  92                fprintf(stderr,
  93                        "KVM_CAP_MSR_PLATFORM_INFO not supported, skip test\n");
  94                exit(KSFT_SKIP);
  95        }
  96
  97        vm = vm_create_default(VCPU_ID, 0, guest_code);
  98
  99        msr_platform_info = vcpu_get_msr(vm, VCPU_ID, MSR_PLATFORM_INFO);
 100        vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO,
 101                msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
 102        test_msr_platform_info_enabled(vm);
 103        test_msr_platform_info_disabled(vm);
 104        vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO, msr_platform_info);
 105
 106        kvm_vm_free(vm);
 107
 108        return 0;
 109}
 110