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: %lu\n", uc.cmd);
  62        TEST_ASSERT((uc.args[1] & MSR_PLATFORM_INFO_MAX_TURBO_RATIO) ==
  63                MSR_PLATFORM_INFO_MAX_TURBO_RATIO,
  64                "Expected MSR_PLATFORM_INFO to have max turbo ratio mask: %i.",
  65                MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
  66}
  67
  68static void test_msr_platform_info_disabled(struct kvm_vm *vm)
  69{
  70        struct kvm_run *run = vcpu_state(vm, VCPU_ID);
  71
  72        set_msr_platform_info_enabled(vm, false);
  73        vcpu_run(vm, VCPU_ID);
  74        TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
  75                        "Exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n",
  76                        run->exit_reason,
  77                        exit_reason_str(run->exit_reason));
  78}
  79
  80int main(int argc, char *argv[])
  81{
  82        struct kvm_vm *vm;
  83        int rv;
  84        uint64_t msr_platform_info;
  85
  86        /* Tell stdout not to buffer its content */
  87        setbuf(stdout, NULL);
  88
  89        rv = kvm_check_cap(KVM_CAP_MSR_PLATFORM_INFO);
  90        if (!rv) {
  91                print_skip("KVM_CAP_MSR_PLATFORM_INFO not supported");
  92                exit(KSFT_SKIP);
  93        }
  94
  95        vm = vm_create_default(VCPU_ID, 0, guest_code);
  96
  97        msr_platform_info = vcpu_get_msr(vm, VCPU_ID, MSR_PLATFORM_INFO);
  98        vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO,
  99                msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
 100        test_msr_platform_info_enabled(vm);
 101        test_msr_platform_info_disabled(vm);
 102        vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO, msr_platform_info);
 103
 104        kvm_vm_free(vm);
 105
 106        return 0;
 107}
 108