Re: [PATCH v3 3/3] kvm: selftests: Add platform_info_test

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Ping. Are there any other changes I need to incorporate here?

Thanks,
Drew

On Mon, Aug 20, 2018 at 10:32 AM Drew Schmitt <dasch@xxxxxxxxxx> wrote:
>
> Test guest access to MSR_PLATFORM_INFO when the capability is enabled
> or disabled.
>
> Signed-off-by: Drew Schmitt <dasch@xxxxxxxxxx>
> ---
>  tools/testing/selftests/kvm/.gitignore        |   1 +
>  tools/testing/selftests/kvm/Makefile          |   3 +-
>  .../testing/selftests/kvm/include/kvm_util.h  |   4 +
>  tools/testing/selftests/kvm/lib/kvm_util.c    |  89 +++++++++++++
>  .../selftests/kvm/platform_info_test.c        | 121 ++++++++++++++++++
>  5 files changed, 217 insertions(+), 1 deletion(-)
>  create mode 100644 tools/testing/selftests/kvm/platform_info_test.c
>
> diff --git a/tools/testing/selftests/kvm/.gitignore b/tools/testing/selftests/kvm/.gitignore
> index 63fc1ab9248fa..8078891ded84a 100644
> --- a/tools/testing/selftests/kvm/.gitignore
> +++ b/tools/testing/selftests/kvm/.gitignore
> @@ -1,3 +1,4 @@
> +platform_info_test
>  set_sregs_test
>  sync_regs_test
>  vmx_tsc_adjust_test
> diff --git a/tools/testing/selftests/kvm/Makefile b/tools/testing/selftests/kvm/Makefile
> index d9d00319b07cd..85e3eb4108c28 100644
> --- a/tools/testing/selftests/kvm/Makefile
> +++ b/tools/testing/selftests/kvm/Makefile
> @@ -6,7 +6,8 @@ UNAME_M := $(shell uname -m)
>  LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/sparsebit.c
>  LIBKVM_x86_64 = lib/x86.c lib/vmx.c
>
> -TEST_GEN_PROGS_x86_64 = set_sregs_test
> +TEST_GEN_PROGS_x86_64 = platform_info_test
> +TEST_GEN_PROGS_x86_64 += set_sregs_test
>  TEST_GEN_PROGS_x86_64 += sync_regs_test
>  TEST_GEN_PROGS_x86_64 += vmx_tsc_adjust_test
>
> diff --git a/tools/testing/selftests/kvm/include/kvm_util.h b/tools/testing/selftests/kvm/include/kvm_util.h
> index 637b7017b6ee5..a7e34eaccadba 100644
> --- a/tools/testing/selftests/kvm/include/kvm_util.h
> +++ b/tools/testing/selftests/kvm/include/kvm_util.h
> @@ -50,6 +50,7 @@ enum vm_mem_backing_src_type {
>  };
>
>  int kvm_check_cap(long cap);
> +int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap);
>
>  struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm);
>  void kvm_vm_free(struct kvm_vm *vmp);
> @@ -103,6 +104,9 @@ void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,
>                           struct kvm_vcpu_events *events);
>  void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
>                           struct kvm_vcpu_events *events);
> +uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index);
> +void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
> +       uint64_t msr_value);
>
>  const char *exit_reason_str(unsigned int exit_reason);
>
> diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
> index 37e2a787d2fcc..2d13b26d32215 100644
> --- a/tools/testing/selftests/kvm/lib/kvm_util.c
> +++ b/tools/testing/selftests/kvm/lib/kvm_util.c
> @@ -62,6 +62,29 @@ int kvm_check_cap(long cap)
>         return ret;
>  }
>
> +/* VM Enable Capability
> + *
> + * Input Args:
> + *   vm - Virtual Machine
> + *   cap - Capability
> + *
> + * Output Args: None
> + *
> + * Return: On success, 0. On failure a TEST_ASSERT failure is produced.
> + *
> + * Enables a capability (KVM_CAP_*) on the VM.
> + */
> +int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap)
> +{
> +       int ret;
> +
> +       ret = ioctl(vm->fd, KVM_ENABLE_CAP, cap);
> +       TEST_ASSERT(ret == 0, "KVM_ENABLE_CAP IOCTL failed,\n"
> +               "  rc: %i errno: %i", ret, errno);
> +
> +       return ret;
> +}
> +
>  /* VM Create
>   *
>   * Input Args:
> @@ -1124,6 +1147,72 @@ void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
>                 ret, errno);
>  }
>
> +/* VCPU Get MSR
> + *
> + * Input Args:
> + *   vm - Virtual Machine
> + *   vcpuid - VCPU ID
> + *   msr_index - Index of MSR
> + *
> + * Output Args: None
> + *
> + * Return: On success, value of the MSR. On failure a TEST_ASSERT is produced.
> + *
> + * Get value of MSR for VCPU.
> + */
> +uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index)
> +{
> +       struct vcpu *vcpu = vcpu_find(vm, vcpuid);
> +       struct {
> +               struct kvm_msrs header;
> +               struct kvm_msr_entry entry;
> +       } buffer = {};
> +       int r;
> +
> +       TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
> +       buffer.header.nmsrs = 1;
> +       buffer.entry.index = msr_index;
> +       r = ioctl(vcpu->fd, KVM_GET_MSRS, &buffer.header);
> +       TEST_ASSERT(r == 1, "KVM_GET_MSRS IOCTL failed,\n"
> +               "  rc: %i errno: %i", r, errno);
> +
> +       return buffer.entry.data;
> +}
> +
> +/* VCPU Set MSR
> + *
> + * Input Args:
> + *   vm - Virtual Machine
> + *   vcpuid - VCPU ID
> + *   msr_index - Index of MSR
> + *   msr_value - New value of MSR
> + *
> + * Output Args: None
> + *
> + * Return: On success, nothing. On failure a TEST_ASSERT is produced.
> + *
> + * Set value of MSR for VCPU.
> + */
> +void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
> +       uint64_t msr_value)
> +{
> +       struct vcpu *vcpu = vcpu_find(vm, vcpuid);
> +       struct {
> +               struct kvm_msrs header;
> +               struct kvm_msr_entry entry;
> +       } buffer = {};
> +       int r;
> +
> +       TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
> +       memset(&buffer, 0, sizeof(buffer));
> +       buffer.header.nmsrs = 1;
> +       buffer.entry.index = msr_index;
> +       buffer.entry.data = msr_value;
> +       r = ioctl(vcpu->fd, KVM_SET_MSRS, &buffer.header);
> +       TEST_ASSERT(r == 1, "KVM_SET_MSRS IOCTL failed,\n"
> +               "  rc: %i errno: %i", r, errno);
> +}
> +
>  /* VM VCPU Args Set
>   *
>   * Input Args:
> diff --git a/tools/testing/selftests/kvm/platform_info_test.c b/tools/testing/selftests/kvm/platform_info_test.c
> new file mode 100644
> index 0000000000000..3c14959a09210
> --- /dev/null
> +++ b/tools/testing/selftests/kvm/platform_info_test.c
> @@ -0,0 +1,121 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * Test for x86 KVM_CAP_MSR_PLATFORM_INFO
> + *
> + * Copyright (C) 2018, Google LLC.
> + *
> + * This work is licensed under the terms of the GNU GPL, version 2.
> + *
> + * Verifies expected behavior of controlling guest access to
> + * MSR_PLATFORM_INFO.
> + */
> +
> +#define _GNU_SOURCE /* for program_invocation_short_name */
> +#include <fcntl.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/ioctl.h>
> +
> +#include "test_util.h"
> +#include "kvm_util.h"
> +#include "x86.h"
> +
> +#define VCPU_ID 0
> +#define PORT_HOST_SYNC 0x1000
> +#define MSR_PLATFORM_INFO_MAX_TURBO_RATIO 0xff00
> +
> +static void __exit_to_l0(uint16_t port, unsigned long arg)
> +{
> +       __asm__ __volatile__("in %[port], %%al"
> +               :
> +               : [port]"d"(port), "D"(arg)
> +               : "rax");
> +}
> +
> +#define exit_to_l0(_port, _arg) __exit_to_l0(_port, (unsigned long) (_arg))
> +
> +static void guest_code(void)
> +{
> +       uint64_t msr_platform_info;
> +
> +       for (;;) {
> +               msr_platform_info = rdmsr(MSR_PLATFORM_INFO);
> +               exit_to_l0(PORT_HOST_SYNC, msr_platform_info);
> +               asm volatile ("inc %r11");
> +       }
> +}
> +
> +static void set_msr_platform_info_enabled(struct kvm_vm *vm, bool enable)
> +{
> +       struct kvm_enable_cap cap = {};
> +
> +       cap.cap = KVM_CAP_MSR_PLATFORM_INFO;
> +       cap.flags = 0;
> +       cap.args[0] = (int)enable;
> +       vm_enable_cap(vm, &cap);
> +}
> +
> +static void test_msr_platform_info_enabled(struct kvm_vm *vm)
> +{
> +       struct kvm_run *run = vcpu_state(vm, VCPU_ID);
> +       struct kvm_regs regs;
> +
> +       set_msr_platform_info_enabled(vm, true);
> +       vcpu_run(vm, VCPU_ID);
> +       TEST_ASSERT(run->exit_reason == KVM_EXIT_IO,
> +                       "Exit_reason other than KVM_EXIT_IO: %u (%s),\n",
> +                       run->exit_reason,
> +                       exit_reason_str(run->exit_reason));
> +       TEST_ASSERT(run->io.port == PORT_HOST_SYNC,
> +                       "Received IO from port other than PORT_HOST_SYNC: %u\n",
> +                       run->io.port);
> +       vcpu_regs_get(vm, VCPU_ID, &regs);
> +       TEST_ASSERT((regs.rdi & MSR_PLATFORM_INFO_MAX_TURBO_RATIO) ==
> +               MSR_PLATFORM_INFO_MAX_TURBO_RATIO,
> +               "Expected MSR_PLATFORM_INFO to have max turbo ratio mask: %i.",
> +               MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
> +}
> +
> +static void test_msr_platform_info_disabled(struct kvm_vm *vm)
> +{
> +       struct kvm_run *run = vcpu_state(vm, VCPU_ID);
> +
> +       set_msr_platform_info_enabled(vm, false);
> +       vcpu_run(vm, VCPU_ID);
> +       TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
> +                       "Exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n",
> +                       run->exit_reason,
> +                       exit_reason_str(run->exit_reason));
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +       struct kvm_vm *vm;
> +       struct kvm_run *state;
> +       int rv;
> +       uint64_t msr_platform_info;
> +
> +       /* Tell stdout not to buffer its content */
> +       setbuf(stdout, NULL);
> +
> +       rv = kvm_check_cap(KVM_CAP_MSR_PLATFORM_INFO);
> +       if (!rv) {
> +               fprintf(stderr,
> +                       "KVM_CAP_MSR_PLATFORM_INFO not supported, skip test\n");
> +               exit(KSFT_SKIP);
> +       }
> +
> +       vm = vm_create_default(VCPU_ID, guest_code);
> +
> +       msr_platform_info = vcpu_get_msr(vm, VCPU_ID, MSR_PLATFORM_INFO);
> +       vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO,
> +               msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
> +       test_msr_platform_info_disabled(vm);
> +       test_msr_platform_info_enabled(vm);
> +       vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO, msr_platform_info);
> +
> +       kvm_vm_free(vm);
> +
> +       return 0;
> +}
> --
> 2.18.0.865.gffc8e1a3cd6-goog
>



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux