Skip to content

Commit 473badf

Browse files
committed
Merge tag 'kvm-x86-selftests-6.18' of https://github.com/kvm-x86/linux into HEAD
KVM selftests changes for 6.18 - Add #DE coverage in the fastops test (the only exception that's guest- triggerable in fastop-emulated instructions). - Fix PMU selftests errors encountered on Granite Rapids (GNR), Sierra Forest (SRF) and Clearwater Forest (CWF). - Minor cleanups and improvements
2 parents 6a13749 + df1f294 commit 473badf

File tree

16 files changed

+303
-109
lines changed

16 files changed

+303
-109
lines changed

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

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -263,13 +263,18 @@ int __open_path_or_exit(const char *path, int flags, const char *enoent_help);
263263
int open_path_or_exit(const char *path, int flags);
264264
int open_kvm_dev_path_or_exit(void);
265265

266-
bool get_kvm_param_bool(const char *param);
267-
bool get_kvm_intel_param_bool(const char *param);
268-
bool get_kvm_amd_param_bool(const char *param);
266+
int kvm_get_module_param_integer(const char *module_name, const char *param);
267+
bool kvm_get_module_param_bool(const char *module_name, const char *param);
269268

270-
int get_kvm_param_integer(const char *param);
271-
int get_kvm_intel_param_integer(const char *param);
272-
int get_kvm_amd_param_integer(const char *param);
269+
static inline bool get_kvm_param_bool(const char *param)
270+
{
271+
return kvm_get_module_param_bool("kvm", param);
272+
}
273+
274+
static inline int get_kvm_param_integer(const char *param)
275+
{
276+
return kvm_get_module_param_integer("kvm", param);
277+
}
273278

274279
unsigned int kvm_check_cap(long cap);
275280

tools/testing/selftests/kvm/include/x86/pmu.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
#ifndef SELFTEST_KVM_PMU_H
66
#define SELFTEST_KVM_PMU_H
77

8+
#include <stdbool.h>
89
#include <stdint.h>
910

11+
#include <linux/bits.h>
12+
1013
#define KVM_PMU_EVENT_FILTER_MAX_EVENTS 300
1114

1215
/*
@@ -61,6 +64,11 @@
6164
#define INTEL_ARCH_BRANCHES_RETIRED RAW_EVENT(0xc4, 0x00)
6265
#define INTEL_ARCH_BRANCHES_MISPREDICTED RAW_EVENT(0xc5, 0x00)
6366
#define INTEL_ARCH_TOPDOWN_SLOTS RAW_EVENT(0xa4, 0x01)
67+
#define INTEL_ARCH_TOPDOWN_BE_BOUND RAW_EVENT(0xa4, 0x02)
68+
#define INTEL_ARCH_TOPDOWN_BAD_SPEC RAW_EVENT(0x73, 0x00)
69+
#define INTEL_ARCH_TOPDOWN_FE_BOUND RAW_EVENT(0x9c, 0x01)
70+
#define INTEL_ARCH_TOPDOWN_RETIRING RAW_EVENT(0xc2, 0x02)
71+
#define INTEL_ARCH_LBR_INSERTS RAW_EVENT(0xe4, 0x01)
6472

6573
#define AMD_ZEN_CORE_CYCLES RAW_EVENT(0x76, 0x00)
6674
#define AMD_ZEN_INSTRUCTIONS_RETIRED RAW_EVENT(0xc0, 0x00)
@@ -80,6 +88,11 @@ enum intel_pmu_architectural_events {
8088
INTEL_ARCH_BRANCHES_RETIRED_INDEX,
8189
INTEL_ARCH_BRANCHES_MISPREDICTED_INDEX,
8290
INTEL_ARCH_TOPDOWN_SLOTS_INDEX,
91+
INTEL_ARCH_TOPDOWN_BE_BOUND_INDEX,
92+
INTEL_ARCH_TOPDOWN_BAD_SPEC_INDEX,
93+
INTEL_ARCH_TOPDOWN_FE_BOUND_INDEX,
94+
INTEL_ARCH_TOPDOWN_RETIRING_INDEX,
95+
INTEL_ARCH_LBR_INSERTS_INDEX,
8396
NR_INTEL_ARCH_EVENTS,
8497
};
8598

@@ -94,4 +107,17 @@ enum amd_pmu_zen_events {
94107
extern const uint64_t intel_pmu_arch_events[];
95108
extern const uint64_t amd_pmu_zen_events[];
96109

110+
enum pmu_errata {
111+
INSTRUCTIONS_RETIRED_OVERCOUNT,
112+
BRANCHES_RETIRED_OVERCOUNT,
113+
};
114+
extern uint64_t pmu_errata_mask;
115+
116+
void kvm_init_pmu_errata(void);
117+
118+
static inline bool this_pmu_has_errata(enum pmu_errata errata)
119+
{
120+
return pmu_errata_mask & BIT_ULL(errata);
121+
}
122+
97123
#endif /* SELFTEST_KVM_PMU_H */

tools/testing/selftests/kvm/include/x86/processor.h

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ extern uint64_t guest_tsc_khz;
3434

3535
#define NMI_VECTOR 0x02
3636

37+
const char *ex_str(int vector);
38+
3739
#define X86_EFLAGS_FIXED (1u << 1)
3840

3941
#define X86_CR4_VME (1ul << 0)
@@ -265,7 +267,7 @@ struct kvm_x86_cpu_property {
265267
#define X86_PROPERTY_PMU_NR_GP_COUNTERS KVM_X86_CPU_PROPERTY(0xa, 0, EAX, 8, 15)
266268
#define X86_PROPERTY_PMU_GP_COUNTERS_BIT_WIDTH KVM_X86_CPU_PROPERTY(0xa, 0, EAX, 16, 23)
267269
#define X86_PROPERTY_PMU_EBX_BIT_VECTOR_LENGTH KVM_X86_CPU_PROPERTY(0xa, 0, EAX, 24, 31)
268-
#define X86_PROPERTY_PMU_EVENTS_MASK KVM_X86_CPU_PROPERTY(0xa, 0, EBX, 0, 7)
270+
#define X86_PROPERTY_PMU_EVENTS_MASK KVM_X86_CPU_PROPERTY(0xa, 0, EBX, 0, 12)
269271
#define X86_PROPERTY_PMU_FIXED_COUNTERS_BITMASK KVM_X86_CPU_PROPERTY(0xa, 0, ECX, 0, 31)
270272
#define X86_PROPERTY_PMU_NR_FIXED_COUNTERS KVM_X86_CPU_PROPERTY(0xa, 0, EDX, 0, 4)
271273
#define X86_PROPERTY_PMU_FIXED_COUNTERS_BIT_WIDTH KVM_X86_CPU_PROPERTY(0xa, 0, EDX, 5, 12)
@@ -332,6 +334,11 @@ struct kvm_x86_pmu_feature {
332334
#define X86_PMU_FEATURE_BRANCH_INSNS_RETIRED KVM_X86_PMU_FEATURE(EBX, 5)
333335
#define X86_PMU_FEATURE_BRANCHES_MISPREDICTED KVM_X86_PMU_FEATURE(EBX, 6)
334336
#define X86_PMU_FEATURE_TOPDOWN_SLOTS KVM_X86_PMU_FEATURE(EBX, 7)
337+
#define X86_PMU_FEATURE_TOPDOWN_BE_BOUND KVM_X86_PMU_FEATURE(EBX, 8)
338+
#define X86_PMU_FEATURE_TOPDOWN_BAD_SPEC KVM_X86_PMU_FEATURE(EBX, 9)
339+
#define X86_PMU_FEATURE_TOPDOWN_FE_BOUND KVM_X86_PMU_FEATURE(EBX, 10)
340+
#define X86_PMU_FEATURE_TOPDOWN_RETIRING KVM_X86_PMU_FEATURE(EBX, 11)
341+
#define X86_PMU_FEATURE_LBR_INSERTS KVM_X86_PMU_FEATURE(EBX, 12)
335342

336343
#define X86_PMU_FEATURE_INSNS_RETIRED_FIXED KVM_X86_PMU_FEATURE(ECX, 0)
337344
#define X86_PMU_FEATURE_CPU_CYCLES_FIXED KVM_X86_PMU_FEATURE(ECX, 1)
@@ -1179,6 +1186,12 @@ struct idt_entry {
11791186
void vm_install_exception_handler(struct kvm_vm *vm, int vector,
11801187
void (*handler)(struct ex_regs *));
11811188

1189+
/*
1190+
* Exception fixup morphs #DE to an arbitrary magic vector so that '0' can be
1191+
* used to signal "no expcetion".
1192+
*/
1193+
#define KVM_MAGIC_DE_VECTOR 0xff
1194+
11821195
/* If a toddler were to say "abracadabra". */
11831196
#define KVM_EXCEPTION_MAGIC 0xabacadabaULL
11841197

@@ -1314,6 +1327,26 @@ static inline uint8_t xsetbv_safe(uint32_t index, uint64_t value)
13141327

13151328
bool kvm_is_tdp_enabled(void);
13161329

1330+
static inline bool get_kvm_intel_param_bool(const char *param)
1331+
{
1332+
return kvm_get_module_param_bool("kvm_intel", param);
1333+
}
1334+
1335+
static inline bool get_kvm_amd_param_bool(const char *param)
1336+
{
1337+
return kvm_get_module_param_bool("kvm_amd", param);
1338+
}
1339+
1340+
static inline int get_kvm_intel_param_integer(const char *param)
1341+
{
1342+
return kvm_get_module_param_integer("kvm_intel", param);
1343+
}
1344+
1345+
static inline int get_kvm_amd_param_integer(const char *param)
1346+
{
1347+
return kvm_get_module_param_integer("kvm_amd", param);
1348+
}
1349+
13171350
static inline bool kvm_is_pmu_enabled(void)
13181351
{
13191352
return get_kvm_param_bool("enable_pmu");

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

Lines changed: 6 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ uint32_t guest_random_seed;
2424
struct guest_random_state guest_rng;
2525
static uint32_t last_guest_seed;
2626

27-
static int vcpu_mmap_sz(void);
27+
static size_t vcpu_mmap_sz(void);
2828

2929
int __open_path_or_exit(const char *path, int flags, const char *enoent_help)
3030
{
@@ -95,7 +95,7 @@ static ssize_t get_module_param(const char *module_name, const char *param,
9595
return bytes_read;
9696
}
9797

98-
static int get_module_param_integer(const char *module_name, const char *param)
98+
int kvm_get_module_param_integer(const char *module_name, const char *param)
9999
{
100100
/*
101101
* 16 bytes to hold a 64-bit value (1 byte per char), 1 byte for the
@@ -119,7 +119,7 @@ static int get_module_param_integer(const char *module_name, const char *param)
119119
return atoi_paranoid(value);
120120
}
121121

122-
static bool get_module_param_bool(const char *module_name, const char *param)
122+
bool kvm_get_module_param_bool(const char *module_name, const char *param)
123123
{
124124
char value;
125125
ssize_t r;
@@ -135,36 +135,6 @@ static bool get_module_param_bool(const char *module_name, const char *param)
135135
TEST_FAIL("Unrecognized value '%c' for boolean module param", value);
136136
}
137137

138-
bool get_kvm_param_bool(const char *param)
139-
{
140-
return get_module_param_bool("kvm", param);
141-
}
142-
143-
bool get_kvm_intel_param_bool(const char *param)
144-
{
145-
return get_module_param_bool("kvm_intel", param);
146-
}
147-
148-
bool get_kvm_amd_param_bool(const char *param)
149-
{
150-
return get_module_param_bool("kvm_amd", param);
151-
}
152-
153-
int get_kvm_param_integer(const char *param)
154-
{
155-
return get_module_param_integer("kvm", param);
156-
}
157-
158-
int get_kvm_intel_param_integer(const char *param)
159-
{
160-
return get_module_param_integer("kvm_intel", param);
161-
}
162-
163-
int get_kvm_amd_param_integer(const char *param)
164-
{
165-
return get_module_param_integer("kvm_amd", param);
166-
}
167-
168138
/*
169139
* Capability
170140
*
@@ -1324,14 +1294,14 @@ void vm_guest_mem_fallocate(struct kvm_vm *vm, uint64_t base, uint64_t size,
13241294
}
13251295

13261296
/* Returns the size of a vCPU's kvm_run structure. */
1327-
static int vcpu_mmap_sz(void)
1297+
static size_t vcpu_mmap_sz(void)
13281298
{
13291299
int dev_fd, ret;
13301300

13311301
dev_fd = open_kvm_dev_path_or_exit();
13321302

13331303
ret = ioctl(dev_fd, KVM_GET_VCPU_MMAP_SIZE, NULL);
1334-
TEST_ASSERT(ret >= sizeof(struct kvm_run),
1304+
TEST_ASSERT(ret >= 0 && ret >= sizeof(struct kvm_run),
13351305
KVM_IOCTL_ERROR(KVM_GET_VCPU_MMAP_SIZE, ret));
13361306

13371307
close(dev_fd);
@@ -1372,7 +1342,7 @@ struct kvm_vcpu *__vm_vcpu_add(struct kvm_vm *vm, uint32_t vcpu_id)
13721342
TEST_ASSERT_VM_VCPU_IOCTL(vcpu->fd >= 0, KVM_CREATE_VCPU, vcpu->fd, vm);
13731343

13741344
TEST_ASSERT(vcpu_mmap_sz() >= sizeof(*vcpu->run), "vcpu mmap size "
1375-
"smaller than expected, vcpu_mmap_sz: %i expected_min: %zi",
1345+
"smaller than expected, vcpu_mmap_sz: %zi expected_min: %zi",
13761346
vcpu_mmap_sz(), sizeof(*vcpu->run));
13771347
vcpu->run = (struct kvm_run *) mmap(NULL, vcpu_mmap_sz(),
13781348
PROT_READ | PROT_WRITE, MAP_SHARED, vcpu->fd, 0);

tools/testing/selftests/kvm/lib/x86/pmu.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <linux/kernel.h>
99

1010
#include "kvm_util.h"
11+
#include "processor.h"
1112
#include "pmu.h"
1213

1314
const uint64_t intel_pmu_arch_events[] = {
@@ -19,6 +20,11 @@ const uint64_t intel_pmu_arch_events[] = {
1920
INTEL_ARCH_BRANCHES_RETIRED,
2021
INTEL_ARCH_BRANCHES_MISPREDICTED,
2122
INTEL_ARCH_TOPDOWN_SLOTS,
23+
INTEL_ARCH_TOPDOWN_BE_BOUND,
24+
INTEL_ARCH_TOPDOWN_BAD_SPEC,
25+
INTEL_ARCH_TOPDOWN_FE_BOUND,
26+
INTEL_ARCH_TOPDOWN_RETIRING,
27+
INTEL_ARCH_LBR_INSERTS,
2228
};
2329
kvm_static_assert(ARRAY_SIZE(intel_pmu_arch_events) == NR_INTEL_ARCH_EVENTS);
2430

@@ -29,3 +35,46 @@ const uint64_t amd_pmu_zen_events[] = {
2935
AMD_ZEN_BRANCHES_MISPREDICTED,
3036
};
3137
kvm_static_assert(ARRAY_SIZE(amd_pmu_zen_events) == NR_AMD_ZEN_EVENTS);
38+
39+
/*
40+
* For Intel Atom CPUs, the PMU events "Instruction Retired" or
41+
* "Branch Instruction Retired" may be overcounted for some certain
42+
* instructions, like FAR CALL/JMP, RETF, IRET, VMENTRY/VMEXIT/VMPTRLD
43+
* and complex SGX/SMX/CSTATE instructions/flows.
44+
*
45+
* The detailed information can be found in the errata (section SRF7):
46+
* https://edc.intel.com/content/www/us/en/design/products-and-solutions/processors-and-chipsets/sierra-forest/xeon-6700-series-processor-with-e-cores-specification-update/errata-details/
47+
*
48+
* For the Atom platforms before Sierra Forest (including Sierra Forest),
49+
* Both 2 events "Instruction Retired" and "Branch Instruction Retired" would
50+
* be overcounted on these certain instructions, but for Clearwater Forest
51+
* only "Instruction Retired" event is overcounted on these instructions.
52+
*/
53+
static uint64_t get_pmu_errata(void)
54+
{
55+
if (!this_cpu_is_intel())
56+
return 0;
57+
58+
if (this_cpu_family() != 0x6)
59+
return 0;
60+
61+
switch (this_cpu_model()) {
62+
case 0xDD: /* Clearwater Forest */
63+
return BIT_ULL(INSTRUCTIONS_RETIRED_OVERCOUNT);
64+
case 0xAF: /* Sierra Forest */
65+
case 0x4D: /* Avaton, Rangely */
66+
case 0x5F: /* Denverton */
67+
case 0x86: /* Jacobsville */
68+
return BIT_ULL(INSTRUCTIONS_RETIRED_OVERCOUNT) |
69+
BIT_ULL(BRANCHES_RETIRED_OVERCOUNT);
70+
default:
71+
return 0;
72+
}
73+
}
74+
75+
uint64_t pmu_errata_mask;
76+
77+
void kvm_init_pmu_errata(void)
78+
{
79+
pmu_errata_mask = get_pmu_errata();
80+
}

tools/testing/selftests/kvm/lib/x86/processor.c

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "linux/bitmap.h"
77
#include "test_util.h"
88
#include "kvm_util.h"
9+
#include "pmu.h"
910
#include "processor.h"
1011
#include "sev.h"
1112

@@ -23,6 +24,39 @@ bool host_cpu_is_intel;
2324
bool is_forced_emulation_enabled;
2425
uint64_t guest_tsc_khz;
2526

27+
const char *ex_str(int vector)
28+
{
29+
switch (vector) {
30+
#define VEC_STR(v) case v##_VECTOR: return "#" #v
31+
case DE_VECTOR: return "no exception";
32+
case KVM_MAGIC_DE_VECTOR: return "#DE";
33+
VEC_STR(DB);
34+
VEC_STR(NMI);
35+
VEC_STR(BP);
36+
VEC_STR(OF);
37+
VEC_STR(BR);
38+
VEC_STR(UD);
39+
VEC_STR(NM);
40+
VEC_STR(DF);
41+
VEC_STR(TS);
42+
VEC_STR(NP);
43+
VEC_STR(SS);
44+
VEC_STR(GP);
45+
VEC_STR(PF);
46+
VEC_STR(MF);
47+
VEC_STR(AC);
48+
VEC_STR(MC);
49+
VEC_STR(XM);
50+
VEC_STR(VE);
51+
VEC_STR(CP);
52+
VEC_STR(HV);
53+
VEC_STR(VC);
54+
VEC_STR(SX);
55+
default: return "#??";
56+
#undef VEC_STR
57+
}
58+
}
59+
2660
static void regs_dump(FILE *stream, struct kvm_regs *regs, uint8_t indent)
2761
{
2862
fprintf(stream, "%*srax: 0x%.16llx rbx: 0x%.16llx "
@@ -557,7 +591,7 @@ static bool kvm_fixup_exception(struct ex_regs *regs)
557591
return false;
558592

559593
if (regs->vector == DE_VECTOR)
560-
return false;
594+
regs->vector = KVM_MAGIC_DE_VECTOR;
561595

562596
regs->rip = regs->r11;
563597
regs->r9 = regs->vector;
@@ -638,6 +672,7 @@ void kvm_arch_vm_post_create(struct kvm_vm *vm, unsigned int nr_vcpus)
638672
sync_global_to_guest(vm, host_cpu_is_intel);
639673
sync_global_to_guest(vm, host_cpu_is_amd);
640674
sync_global_to_guest(vm, is_forced_emulation_enabled);
675+
sync_global_to_guest(vm, pmu_errata_mask);
641676

642677
if (is_sev_vm(vm)) {
643678
struct kvm_sev_init init = { 0 };
@@ -1269,6 +1304,8 @@ void kvm_selftest_arch_init(void)
12691304
host_cpu_is_intel = this_cpu_is_intel();
12701305
host_cpu_is_amd = this_cpu_is_amd();
12711306
is_forced_emulation_enabled = kvm_is_forced_emulation_enabled();
1307+
1308+
kvm_init_pmu_errata();
12721309
}
12731310

12741311
bool sys_clocksource_is_based_on_tsc(void)

tools/testing/selftests/kvm/s390/cpumodel_subfuncs_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,7 @@ int main(int argc, char *argv[])
291291
ksft_test_result_pass("%s\n", testlist[idx].subfunc_name);
292292
free(array);
293293
} else {
294-
ksft_test_result_skip("%s feature is not avaialable\n",
294+
ksft_test_result_skip("%s feature is not available\n",
295295
testlist[idx].subfunc_name);
296296
}
297297
}

0 commit comments

Comments
 (0)