Skip to content

Commit 8b56ee9

Browse files
dasch-1bonzini
authored andcommitted
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>
1 parent 6fbbde9 commit 8b56ee9

File tree

5 files changed

+206
-1
lines changed

5 files changed

+206
-1
lines changed

tools/testing/selftests/kvm/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
cr4_cpuid_sync_test
2+
platform_info_test
23
set_sregs_test
34
sync_regs_test
45
vmx_tsc_adjust_test

tools/testing/selftests/kvm/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ UNAME_M := $(shell uname -m)
66
LIBKVM = lib/assert.c lib/elf.c lib/io.c lib/kvm_util.c lib/sparsebit.c
77
LIBKVM_x86_64 = lib/x86.c lib/vmx.c
88

9-
TEST_GEN_PROGS_x86_64 = set_sregs_test
9+
TEST_GEN_PROGS_x86_64 = platform_info_test
10+
TEST_GEN_PROGS_x86_64 += set_sregs_test
1011
TEST_GEN_PROGS_x86_64 += sync_regs_test
1112
TEST_GEN_PROGS_x86_64 += vmx_tsc_adjust_test
1213
TEST_GEN_PROGS_x86_64 += cr4_cpuid_sync_test

tools/testing/selftests/kvm/include/kvm_util.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ enum vm_mem_backing_src_type {
5050
};
5151

5252
int kvm_check_cap(long cap);
53+
int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap);
5354

5455
struct kvm_vm *vm_create(enum vm_guest_mode mode, uint64_t phy_pages, int perm);
5556
void kvm_vm_free(struct kvm_vm *vmp);
@@ -108,6 +109,9 @@ void vcpu_events_get(struct kvm_vm *vm, uint32_t vcpuid,
108109
struct kvm_vcpu_events *events);
109110
void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
110111
struct kvm_vcpu_events *events);
112+
uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index);
113+
void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
114+
uint64_t msr_value);
111115

112116
const char *exit_reason_str(unsigned int exit_reason);
113117

tools/testing/selftests/kvm/lib/kvm_util.c

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,29 @@ int kvm_check_cap(long cap)
6363
return ret;
6464
}
6565

66+
/* VM Enable Capability
67+
*
68+
* Input Args:
69+
* vm - Virtual Machine
70+
* cap - Capability
71+
*
72+
* Output Args: None
73+
*
74+
* Return: On success, 0. On failure a TEST_ASSERT failure is produced.
75+
*
76+
* Enables a capability (KVM_CAP_*) on the VM.
77+
*/
78+
int vm_enable_cap(struct kvm_vm *vm, struct kvm_enable_cap *cap)
79+
{
80+
int ret;
81+
82+
ret = ioctl(vm->fd, KVM_ENABLE_CAP, cap);
83+
TEST_ASSERT(ret == 0, "KVM_ENABLE_CAP IOCTL failed,\n"
84+
" rc: %i errno: %i", ret, errno);
85+
86+
return ret;
87+
}
88+
6689
static void vm_open(struct kvm_vm *vm, int perm)
6790
{
6891
vm->kvm_fd = open(KVM_DEV_PATH, perm);
@@ -1220,6 +1243,72 @@ void vcpu_events_set(struct kvm_vm *vm, uint32_t vcpuid,
12201243
ret, errno);
12211244
}
12221245

1246+
/* VCPU Get MSR
1247+
*
1248+
* Input Args:
1249+
* vm - Virtual Machine
1250+
* vcpuid - VCPU ID
1251+
* msr_index - Index of MSR
1252+
*
1253+
* Output Args: None
1254+
*
1255+
* Return: On success, value of the MSR. On failure a TEST_ASSERT is produced.
1256+
*
1257+
* Get value of MSR for VCPU.
1258+
*/
1259+
uint64_t vcpu_get_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index)
1260+
{
1261+
struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1262+
struct {
1263+
struct kvm_msrs header;
1264+
struct kvm_msr_entry entry;
1265+
} buffer = {};
1266+
int r;
1267+
1268+
TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1269+
buffer.header.nmsrs = 1;
1270+
buffer.entry.index = msr_index;
1271+
r = ioctl(vcpu->fd, KVM_GET_MSRS, &buffer.header);
1272+
TEST_ASSERT(r == 1, "KVM_GET_MSRS IOCTL failed,\n"
1273+
" rc: %i errno: %i", r, errno);
1274+
1275+
return buffer.entry.data;
1276+
}
1277+
1278+
/* VCPU Set MSR
1279+
*
1280+
* Input Args:
1281+
* vm - Virtual Machine
1282+
* vcpuid - VCPU ID
1283+
* msr_index - Index of MSR
1284+
* msr_value - New value of MSR
1285+
*
1286+
* Output Args: None
1287+
*
1288+
* Return: On success, nothing. On failure a TEST_ASSERT is produced.
1289+
*
1290+
* Set value of MSR for VCPU.
1291+
*/
1292+
void vcpu_set_msr(struct kvm_vm *vm, uint32_t vcpuid, uint64_t msr_index,
1293+
uint64_t msr_value)
1294+
{
1295+
struct vcpu *vcpu = vcpu_find(vm, vcpuid);
1296+
struct {
1297+
struct kvm_msrs header;
1298+
struct kvm_msr_entry entry;
1299+
} buffer = {};
1300+
int r;
1301+
1302+
TEST_ASSERT(vcpu != NULL, "vcpu not found, vcpuid: %u", vcpuid);
1303+
memset(&buffer, 0, sizeof(buffer));
1304+
buffer.header.nmsrs = 1;
1305+
buffer.entry.index = msr_index;
1306+
buffer.entry.data = msr_value;
1307+
r = ioctl(vcpu->fd, KVM_SET_MSRS, &buffer.header);
1308+
TEST_ASSERT(r == 1, "KVM_SET_MSRS IOCTL failed,\n"
1309+
" rc: %i errno: %i", r, errno);
1310+
}
1311+
12231312
/* VM VCPU Args Set
12241313
*
12251314
* Input Args:
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
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 "x86.h"
23+
24+
#define VCPU_ID 0
25+
#define MSR_PLATFORM_INFO_MAX_TURBO_RATIO 0xff00
26+
27+
static 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+
38+
static 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+
48+
static void test_msr_platform_info_enabled(struct kvm_vm *vm)
49+
{
50+
struct kvm_run *run = vcpu_state(vm, VCPU_ID);
51+
struct guest_args args;
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+
guest_args_read(vm, VCPU_ID, &args);
60+
TEST_ASSERT(args.port == GUEST_PORT_SYNC,
61+
"Received IO from port other than PORT_HOST_SYNC: %u\n",
62+
run->io.port);
63+
TEST_ASSERT((args.arg1 & MSR_PLATFORM_INFO_MAX_TURBO_RATIO) ==
64+
MSR_PLATFORM_INFO_MAX_TURBO_RATIO,
65+
"Expected MSR_PLATFORM_INFO to have max turbo ratio mask: %i.",
66+
MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
67+
}
68+
69+
static void test_msr_platform_info_disabled(struct kvm_vm *vm)
70+
{
71+
struct kvm_run *run = vcpu_state(vm, VCPU_ID);
72+
73+
set_msr_platform_info_enabled(vm, false);
74+
vcpu_run(vm, VCPU_ID);
75+
TEST_ASSERT(run->exit_reason == KVM_EXIT_SHUTDOWN,
76+
"Exit_reason other than KVM_EXIT_SHUTDOWN: %u (%s)\n",
77+
run->exit_reason,
78+
exit_reason_str(run->exit_reason));
79+
}
80+
81+
int main(int argc, char *argv[])
82+
{
83+
struct kvm_vm *vm;
84+
struct kvm_run *state;
85+
int rv;
86+
uint64_t msr_platform_info;
87+
88+
/* Tell stdout not to buffer its content */
89+
setbuf(stdout, NULL);
90+
91+
rv = kvm_check_cap(KVM_CAP_MSR_PLATFORM_INFO);
92+
if (!rv) {
93+
fprintf(stderr,
94+
"KVM_CAP_MSR_PLATFORM_INFO not supported, skip test\n");
95+
exit(KSFT_SKIP);
96+
}
97+
98+
vm = vm_create_default(VCPU_ID, 0, guest_code);
99+
100+
msr_platform_info = vcpu_get_msr(vm, VCPU_ID, MSR_PLATFORM_INFO);
101+
vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO,
102+
msr_platform_info | MSR_PLATFORM_INFO_MAX_TURBO_RATIO);
103+
test_msr_platform_info_disabled(vm);
104+
test_msr_platform_info_enabled(vm);
105+
vcpu_set_msr(vm, VCPU_ID, MSR_PLATFORM_INFO, msr_platform_info);
106+
107+
kvm_vm_free(vm);
108+
109+
return 0;
110+
}

0 commit comments

Comments
 (0)