Skip to content

Commit 920541b

Browse files
committed
Merge tag 'for-linus-6.0' of git://git.kernel.org/pub/scm/virt/kvm/kvm
Pull kvm fixes from Paolo Bonzini: "A small fix to the reported set of supported CPUID bits, and selftests fixes: - Skip tests that require EPT when it is not available - Do not hang when a test fails with an empty stack trace - avoid spurious failure when running access_tracking_perf_test in a KVM guest - work around GCC's tendency to optimize loops into mem*() functions, which breaks because the guest code in selftests cannot call into PLTs - fix -Warray-bounds error in fix_hypercall_test" * tag 'for-linus-6.0' of git://git.kernel.org/pub/scm/virt/kvm/kvm: KVM: selftests: Compare insn opcodes directly in fix_hypercall_test KVM: selftests: Implement memcmp(), memcpy(), and memset() for guest use KVM: x86: Hide IA32_PLATFORM_DCA_CAP[31:0] from the guest KVM: selftests: Gracefully handle empty stack traces KVM: selftests: replace assertion with warning in access_tracking_perf_test KVM: selftests: Skip tests that require EPT when it is not available
2 parents 70575e7 + 3942650 commit 920541b

File tree

8 files changed

+115
-37
lines changed

8 files changed

+115
-37
lines changed

arch/x86/kvm/cpuid.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -902,8 +902,6 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
902902
entry->edx = 0;
903903
}
904904
break;
905-
case 9:
906-
break;
907905
case 0xa: { /* Architectural Performance Monitoring */
908906
union cpuid10_eax eax;
909907
union cpuid10_edx edx;

tools/testing/selftests/kvm/Makefile

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ LIBKVM += lib/rbtree.c
4848
LIBKVM += lib/sparsebit.c
4949
LIBKVM += lib/test_util.c
5050

51+
LIBKVM_STRING += lib/string_override.c
52+
5153
LIBKVM_x86_64 += lib/x86_64/apic.c
5254
LIBKVM_x86_64 += lib/x86_64/handlers.S
5355
LIBKVM_x86_64 += lib/x86_64/perf_test_util.c
@@ -220,7 +222,8 @@ LIBKVM_C := $(filter %.c,$(LIBKVM))
220222
LIBKVM_S := $(filter %.S,$(LIBKVM))
221223
LIBKVM_C_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM_C))
222224
LIBKVM_S_OBJ := $(patsubst %.S, $(OUTPUT)/%.o, $(LIBKVM_S))
223-
LIBKVM_OBJS = $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ)
225+
LIBKVM_STRING_OBJ := $(patsubst %.c, $(OUTPUT)/%.o, $(LIBKVM_STRING))
226+
LIBKVM_OBJS = $(LIBKVM_C_OBJ) $(LIBKVM_S_OBJ) $(LIBKVM_STRING_OBJ)
224227

225228
EXTRA_CLEAN += $(LIBKVM_OBJS) cscope.*
226229

@@ -231,6 +234,12 @@ $(LIBKVM_C_OBJ): $(OUTPUT)/%.o: %.c
231234
$(LIBKVM_S_OBJ): $(OUTPUT)/%.o: %.S
232235
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@
233236

237+
# Compile the string overrides as freestanding to prevent the compiler from
238+
# generating self-referential code, e.g. without "freestanding" the compiler may
239+
# "optimize" memcmp() by invoking memcmp(), thus causing infinite recursion.
240+
$(LIBKVM_STRING_OBJ): $(OUTPUT)/%.o: %.c
241+
$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c -ffreestanding $< -o $@
242+
234243
x := $(shell mkdir -p $(sort $(dir $(TEST_GEN_PROGS))))
235244
$(TEST_GEN_PROGS): $(LIBKVM_OBJS)
236245
$(TEST_GEN_PROGS_EXTENDED): $(LIBKVM_OBJS)

tools/testing/selftests/kvm/access_tracking_perf_test.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,9 @@
3131
* These limitations are worked around in this test by using a large enough
3232
* region of memory for each vCPU such that the number of translations cached in
3333
* the TLB and the number of pages held in pagevecs are a small fraction of the
34-
* overall workload. And if either of those conditions are not true this test
35-
* will fail rather than silently passing.
34+
* overall workload. And if either of those conditions are not true (for example
35+
* in nesting, where TLB size is unlimited) this test will print a warning
36+
* rather than silently passing.
3637
*/
3738
#include <inttypes.h>
3839
#include <limits.h>
@@ -172,17 +173,23 @@ static void mark_vcpu_memory_idle(struct kvm_vm *vm,
172173
vcpu_idx, no_pfn, pages);
173174

174175
/*
175-
* Test that at least 90% of memory has been marked idle (the rest might
176-
* not be marked idle because the pages have not yet made it to an LRU
177-
* list or the translations are still cached in the TLB). 90% is
176+
* Check that at least 90% of memory has been marked idle (the rest
177+
* might not be marked idle because the pages have not yet made it to an
178+
* LRU list or the translations are still cached in the TLB). 90% is
178179
* arbitrary; high enough that we ensure most memory access went through
179180
* access tracking but low enough as to not make the test too brittle
180181
* over time and across architectures.
182+
*
183+
* Note that when run in nested virtualization, this check will trigger
184+
* much more frequently because TLB size is unlimited and since no flush
185+
* happens, much more pages are cached there and guest won't see the
186+
* "idle" bit cleared.
181187
*/
182-
TEST_ASSERT(still_idle < pages / 10,
183-
"vCPU%d: Too many pages still idle (%"PRIu64 " out of %"
184-
PRIu64 ").\n",
185-
vcpu_idx, still_idle, pages);
188+
if (still_idle < pages / 10)
189+
printf("WARNING: vCPU%d: Too many pages still idle (%" PRIu64
190+
"out of %" PRIu64 "), this will affect performance results"
191+
".\n",
192+
vcpu_idx, still_idle, pages);
186193

187194
close(page_idle_fd);
188195
close(pagemap_fd);

tools/testing/selftests/kvm/include/x86_64/vmx.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,7 @@ void nested_map_memslot(struct vmx_pages *vmx, struct kvm_vm *vm,
617617
uint32_t memslot);
618618
void nested_identity_map_1g(struct vmx_pages *vmx, struct kvm_vm *vm,
619619
uint64_t addr, uint64_t size);
620+
bool kvm_vm_has_ept(struct kvm_vm *vm);
620621
void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm,
621622
uint32_t eptp_memslot);
622623
void prepare_virtualize_apic_accesses(struct vmx_pages *vmx, struct kvm_vm *vm);

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ static void test_dump_stack(void)
2222
* Build and run this command:
2323
*
2424
* addr2line -s -e /proc/$PPID/exe -fpai {backtrace addresses} | \
25-
* grep -v test_dump_stack | cat -n 1>&2
25+
* cat -n 1>&2
2626
*
2727
* Note that the spacing is different and there's no newline.
2828
*/
@@ -36,18 +36,24 @@ static void test_dump_stack(void)
3636
n * (((sizeof(void *)) * 2) + 1) +
3737
/* Null terminator: */
3838
1];
39-
char *c;
39+
char *c = cmd;
4040

4141
n = backtrace(stack, n);
42-
c = &cmd[0];
43-
c += sprintf(c, "%s", addr2line);
4442
/*
45-
* Skip the first 3 frames: backtrace, test_dump_stack, and
46-
* test_assert. We hope that backtrace isn't inlined and the other two
47-
* we've declared noinline.
43+
* Skip the first 2 frames, which should be test_dump_stack() and
44+
* test_assert(); both of which are declared noinline. Bail if the
45+
* resulting stack trace would be empty. Otherwise, addr2line will block
46+
* waiting for addresses to be passed in via stdin.
4847
*/
48+
if (n <= 2) {
49+
fputs(" (stack trace empty)\n", stderr);
50+
return;
51+
}
52+
53+
c += sprintf(c, "%s", addr2line);
4954
for (i = 2; i < n; i++)
5055
c += sprintf(c, " %lx", ((unsigned long) stack[i]) - 1);
56+
5157
c += sprintf(c, "%s", pipeline);
5258
#pragma GCC diagnostic push
5359
#pragma GCC diagnostic ignored "-Wunused-result"
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
#include <stddef.h>
3+
4+
/*
5+
* Override the "basic" built-in string helpers so that they can be used in
6+
* guest code. KVM selftests don't support dynamic loading in guest code and
7+
* will jump into the weeds if the compiler decides to insert an out-of-line
8+
* call via the PLT.
9+
*/
10+
int memcmp(const void *cs, const void *ct, size_t count)
11+
{
12+
const unsigned char *su1, *su2;
13+
int res = 0;
14+
15+
for (su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) {
16+
if ((res = *su1 - *su2) != 0)
17+
break;
18+
}
19+
return res;
20+
}
21+
22+
void *memcpy(void *dest, const void *src, size_t count)
23+
{
24+
char *tmp = dest;
25+
const char *s = src;
26+
27+
while (count--)
28+
*tmp++ = *s++;
29+
return dest;
30+
}
31+
32+
void *memset(void *s, int c, size_t count)
33+
{
34+
char *xs = s;
35+
36+
while (count--)
37+
*xs++ = c;
38+
return s;
39+
}

tools/testing/selftests/kvm/lib/x86_64/vmx.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
* Copyright (C) 2018, Google LLC.
66
*/
77

8+
#include <asm/msr-index.h>
9+
810
#include "test_util.h"
911
#include "kvm_util.h"
1012
#include "processor.h"
@@ -542,9 +544,27 @@ void nested_identity_map_1g(struct vmx_pages *vmx, struct kvm_vm *vm,
542544
__nested_map(vmx, vm, addr, addr, size, PG_LEVEL_1G);
543545
}
544546

547+
bool kvm_vm_has_ept(struct kvm_vm *vm)
548+
{
549+
struct kvm_vcpu *vcpu;
550+
uint64_t ctrl;
551+
552+
vcpu = list_first_entry(&vm->vcpus, struct kvm_vcpu, list);
553+
TEST_ASSERT(vcpu, "Cannot determine EPT support without vCPUs.\n");
554+
555+
ctrl = vcpu_get_msr(vcpu, MSR_IA32_VMX_TRUE_PROCBASED_CTLS) >> 32;
556+
if (!(ctrl & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS))
557+
return false;
558+
559+
ctrl = vcpu_get_msr(vcpu, MSR_IA32_VMX_PROCBASED_CTLS2) >> 32;
560+
return ctrl & SECONDARY_EXEC_ENABLE_EPT;
561+
}
562+
545563
void prepare_eptp(struct vmx_pages *vmx, struct kvm_vm *vm,
546564
uint32_t eptp_memslot)
547565
{
566+
TEST_REQUIRE(kvm_vm_has_ept(vm));
567+
548568
vmx->eptp = (void *)vm_vaddr_alloc_page(vm);
549569
vmx->eptp_hva = addr_gva2hva(vm, (uintptr_t)vmx->eptp);
550570
vmx->eptp_gpa = addr_gva2gpa(vm, (uintptr_t)vmx->eptp);

tools/testing/selftests/kvm/x86_64/fix_hypercall_test.c

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@
1414
#include "kvm_util.h"
1515
#include "processor.h"
1616

17+
/* VMCALL and VMMCALL are both 3-byte opcodes. */
18+
#define HYPERCALL_INSN_SIZE 3
19+
1720
static bool ud_expected;
1821

1922
static void guest_ud_handler(struct ex_regs *regs)
@@ -22,7 +25,7 @@ static void guest_ud_handler(struct ex_regs *regs)
2225
GUEST_DONE();
2326
}
2427

25-
extern unsigned char svm_hypercall_insn;
28+
extern uint8_t svm_hypercall_insn[HYPERCALL_INSN_SIZE];
2629
static uint64_t svm_do_sched_yield(uint8_t apic_id)
2730
{
2831
uint64_t ret;
@@ -39,7 +42,7 @@ static uint64_t svm_do_sched_yield(uint8_t apic_id)
3942
return ret;
4043
}
4144

42-
extern unsigned char vmx_hypercall_insn;
45+
extern uint8_t vmx_hypercall_insn[HYPERCALL_INSN_SIZE];
4346
static uint64_t vmx_do_sched_yield(uint8_t apic_id)
4447
{
4548
uint64_t ret;
@@ -56,39 +59,34 @@ static uint64_t vmx_do_sched_yield(uint8_t apic_id)
5659
return ret;
5760
}
5861

59-
static void assert_hypercall_insn(unsigned char *exp_insn, unsigned char *obs_insn)
60-
{
61-
uint32_t exp = 0, obs = 0;
62-
63-
memcpy(&exp, exp_insn, sizeof(exp));
64-
memcpy(&obs, obs_insn, sizeof(obs));
65-
66-
GUEST_ASSERT_EQ(exp, obs);
67-
}
68-
6962
static void guest_main(void)
7063
{
71-
unsigned char *native_hypercall_insn, *hypercall_insn;
64+
uint8_t *native_hypercall_insn, *hypercall_insn;
7265
uint8_t apic_id;
7366

7467
apic_id = GET_APIC_ID_FIELD(xapic_read_reg(APIC_ID));
7568

7669
if (is_intel_cpu()) {
77-
native_hypercall_insn = &vmx_hypercall_insn;
78-
hypercall_insn = &svm_hypercall_insn;
70+
native_hypercall_insn = vmx_hypercall_insn;
71+
hypercall_insn = svm_hypercall_insn;
7972
svm_do_sched_yield(apic_id);
8073
} else if (is_amd_cpu()) {
81-
native_hypercall_insn = &svm_hypercall_insn;
82-
hypercall_insn = &vmx_hypercall_insn;
74+
native_hypercall_insn = svm_hypercall_insn;
75+
hypercall_insn = vmx_hypercall_insn;
8376
vmx_do_sched_yield(apic_id);
8477
} else {
8578
GUEST_ASSERT(0);
8679
/* unreachable */
8780
return;
8881
}
8982

83+
/*
84+
* The hypercall didn't #UD (guest_ud_handler() signals "done" if a #UD
85+
* occurs). Verify that a #UD is NOT expected and that KVM patched in
86+
* the native hypercall.
87+
*/
9088
GUEST_ASSERT(!ud_expected);
91-
assert_hypercall_insn(native_hypercall_insn, hypercall_insn);
89+
GUEST_ASSERT(!memcmp(native_hypercall_insn, hypercall_insn, HYPERCALL_INSN_SIZE));
9290
GUEST_DONE();
9391
}
9492

0 commit comments

Comments
 (0)