mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 09:19:51 +00:00
kvm: selftests: Add platform_info_test
Test guest access to MSR_PLATFORM_INFO when the capability is enabled or disabled. Signed-off-by: Drew Schmitt <dasch@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
6fbbde9a19
commit
8b56ee91ff
5 changed files with 206 additions and 1 deletions
1
tools/testing/selftests/kvm/.gitignore
vendored
1
tools/testing/selftests/kvm/.gitignore
vendored
|
@ -1,4 +1,5 @@
|
||||||
cr4_cpuid_sync_test
|
cr4_cpuid_sync_test
|
||||||
|
platform_info_test
|
||||||
set_sregs_test
|
set_sregs_test
|
||||||
sync_regs_test
|
sync_regs_test
|
||||||
vmx_tsc_adjust_test
|
vmx_tsc_adjust_test
|
||||||
|
|
|
@ -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 = 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
|
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 += sync_regs_test
|
||||||
TEST_GEN_PROGS_x86_64 += vmx_tsc_adjust_test
|
TEST_GEN_PROGS_x86_64 += vmx_tsc_adjust_test
|
||||||
TEST_GEN_PROGS_x86_64 += cr4_cpuid_sync_test
|
TEST_GEN_PROGS_x86_64 += cr4_cpuid_sync_test
|
||||||
|
|
|
@ -50,6 +50,7 @@ enum vm_mem_backing_src_type {
|
||||||
};
|
};
|
||||||
|
|
||||||
int kvm_check_cap(long cap);
|
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);
|
struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm);
|
||||||
void kvm_vm_free(struct kvm_vm *vmp);
|
void kvm_vm_free(struct kvm_vm *vmp);
|
||||||
|
@ -108,6 +109,9 @@ void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,
|
||||||
struct kvm_vcpu_events *events);
|
struct kvm_vcpu_events *events);
|
||||||
void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
|
void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
|
||||||
struct kvm_vcpu_events *events);
|
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);
|
const char *exit_reason_str(unsigned int exit_reason);
|
||||||
|
|
||||||
|
|
|
@ -63,6 +63,29 @@ int kvm_check_cap(long cap)
|
||||||
return ret;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
static void vm_open(struct kvm_vm *vm, int perm)
|
static void vm_open(struct kvm_vm *vm, int perm)
|
||||||
{
|
{
|
||||||
vm->kvm_fd = open(KVM_DEV_PATH, perm);
|
vm->kvm_fd = open(KVM_DEV_PATH, perm);
|
||||||
|
@ -1220,6 +1243,72 @@ void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
|
||||||
ret, errno);
|
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
|
/* VM VCPU Args Set
|
||||||
*
|
*
|
||||||
* Input Args:
|
* Input Args:
|
||||||
|
|
110
tools/testing/selftests/kvm/platform_info_test.c
Normal file
110
tools/testing/selftests/kvm/platform_info_test.c
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
// 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 MSR_PLATFORM_INFO_MAX_TURBO_RATIO 0xff00
|
||||||
|
|
||||||
|
static void guest_code(void)
|
||||||
|
{
|
||||||
|
uint64_t msr_platform_info;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
msr_platform_info = rdmsr(MSR_PLATFORM_INFO);
|
||||||
|
GUEST_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 guest_args args;
|
||||||
|
|
||||||
|
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));
|
||||||
|
guest_args_read(vm, VCPU_ID, &args);
|
||||||
|
TEST_ASSERT(args.port == GUEST_PORT_SYNC,
|
||||||
|
"Received IO from port other than PORT_HOST_SYNC: %u\n",
|
||||||
|
run->io.port);
|
||||||
|
TEST_ASSERT((args.arg1 & 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, 0, 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;
|
||||||
|
}
|
Loading…
Reference in a new issue