mirror of https://gitee.com/openkylin/linux.git
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
|
@ -1,4 +1,5 @@
|
|||
cr4_cpuid_sync_test
|
||||
platform_info_test
|
||||
set_sregs_test
|
||||
sync_regs_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_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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 New Issue