1
0
Fork 0

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>
hifive-unleashed-5.1
Drew Schmitt 2018-08-20 10:32:16 -07:00 committed by Paolo Bonzini
parent 6fbbde9a19
commit 8b56ee91ff
5 changed files with 206 additions and 1 deletions

View File

@ -1,4 +1,5 @@
cr4_cpuid_sync_test
platform_info_test
set_sregs_test
sync_regs_test
vmx_tsc_adjust_test

View File

@ -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
TEST_GEN_PROGS_x86_64 += cr4_cpuid_sync_test

View File

@ -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);
@ -108,6 +109,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);

View File

@ -63,6 +63,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;
}
static void vm_open(struct kvm_vm *vm, int 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);
}
/* 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:

View 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;
}