Skip to content

Commit 60d351f

Browse files
sean-jcbonzini
authored andcommitted
KVM: selftests: Touch relevant XSAVE state in guest for state test
Modify support XSAVE state in the "state test's" guest code so that saving and loading state via KVM_{G,S}ET_XSAVE actually does something useful, i.e. so that xstate_bv in XSAVE state isn't empty. Punt on BNDCSR for now, it's easier to just stuff that xfeature from the host side. Signed-off-by: Sean Christopherson <[email protected]> Message-Id: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 8647c52 commit 60d351f

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ struct xstate {
6868
#define XFEATURE_MASK_OPMASK BIT_ULL(5)
6969
#define XFEATURE_MASK_ZMM_Hi256 BIT_ULL(6)
7070
#define XFEATURE_MASK_Hi16_ZMM BIT_ULL(7)
71+
#define XFEATURE_MASK_PT BIT_ULL(8)
72+
#define XFEATURE_MASK_PKRU BIT_ULL(9)
73+
#define XFEATURE_MASK_PASID BIT_ULL(10)
74+
#define XFEATURE_MASK_CET_USER BIT_ULL(11)
75+
#define XFEATURE_MASK_CET_KERNEL BIT_ULL(12)
76+
#define XFEATURE_MASK_LBR BIT_ULL(15)
7177
#define XFEATURE_MASK_XTILE_CFG BIT_ULL(17)
7278
#define XFEATURE_MASK_XTILE_DATA BIT_ULL(18)
7379

@@ -147,6 +153,7 @@ struct kvm_x86_cpu_feature {
147153
#define X86_FEATURE_CLWB KVM_X86_CPU_FEATURE(0x7, 0, EBX, 24)
148154
#define X86_FEATURE_UMIP KVM_X86_CPU_FEATURE(0x7, 0, ECX, 2)
149155
#define X86_FEATURE_PKU KVM_X86_CPU_FEATURE(0x7, 0, ECX, 3)
156+
#define X86_FEATURE_OSPKE KVM_X86_CPU_FEATURE(0x7, 0, ECX, 4)
150157
#define X86_FEATURE_LA57 KVM_X86_CPU_FEATURE(0x7, 0, ECX, 16)
151158
#define X86_FEATURE_RDPID KVM_X86_CPU_FEATURE(0x7, 0, ECX, 22)
152159
#define X86_FEATURE_SGX_LC KVM_X86_CPU_FEATURE(0x7, 0, ECX, 30)
@@ -553,6 +560,13 @@ static inline void xsetbv(u32 index, u64 value)
553560
__asm__ __volatile__("xsetbv" :: "a" (eax), "d" (edx), "c" (index));
554561
}
555562

563+
static inline void wrpkru(u32 pkru)
564+
{
565+
/* Note, ECX and EDX are architecturally required to be '0'. */
566+
asm volatile(".byte 0x0f,0x01,0xef\n\t"
567+
: : "a" (pkru), "c"(0), "d"(0));
568+
}
569+
556570
static inline struct desc_ptr get_gdt(void)
557571
{
558572
struct desc_ptr gdt;

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

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,83 @@ static void vmx_l1_guest_code(struct vmx_pages *vmx_pages)
139139
static void __attribute__((__flatten__)) guest_code(void *arg)
140140
{
141141
GUEST_SYNC(1);
142+
143+
if (this_cpu_has(X86_FEATURE_XSAVE)) {
144+
uint64_t supported_xcr0 = this_cpu_supported_xcr0();
145+
uint8_t buffer[4096];
146+
147+
memset(buffer, 0xcc, sizeof(buffer));
148+
149+
set_cr4(get_cr4() | X86_CR4_OSXSAVE);
150+
GUEST_ASSERT(this_cpu_has(X86_FEATURE_OSXSAVE));
151+
152+
xsetbv(0, xgetbv(0) | supported_xcr0);
153+
154+
/*
155+
* Modify state for all supported xfeatures to take them out of
156+
* their "init" state, i.e. to make them show up in XSTATE_BV.
157+
*
158+
* Note off-by-default features, e.g. AMX, are out of scope for
159+
* this particular testcase as they have a different ABI.
160+
*/
161+
GUEST_ASSERT(supported_xcr0 & XFEATURE_MASK_FP);
162+
asm volatile ("fincstp");
163+
164+
GUEST_ASSERT(supported_xcr0 & XFEATURE_MASK_SSE);
165+
asm volatile ("vmovdqu %0, %%xmm0" :: "m" (buffer));
166+
167+
if (supported_xcr0 & XFEATURE_MASK_YMM)
168+
asm volatile ("vmovdqu %0, %%ymm0" :: "m" (buffer));
169+
170+
if (supported_xcr0 & XFEATURE_MASK_AVX512) {
171+
asm volatile ("kmovq %0, %%k1" :: "r" (-1ull));
172+
asm volatile ("vmovupd %0, %%zmm0" :: "m" (buffer));
173+
asm volatile ("vmovupd %0, %%zmm16" :: "m" (buffer));
174+
}
175+
176+
if (this_cpu_has(X86_FEATURE_MPX)) {
177+
uint64_t bounds[2] = { 10, 0xffffffffull };
178+
uint64_t output[2] = { };
179+
180+
GUEST_ASSERT(supported_xcr0 & XFEATURE_MASK_BNDREGS);
181+
GUEST_ASSERT(supported_xcr0 & XFEATURE_MASK_BNDCSR);
182+
183+
/*
184+
* Don't bother trying to get BNDCSR into the INUSE
185+
* state. MSR_IA32_BNDCFGS doesn't count as it isn't
186+
* managed via XSAVE/XRSTOR, and BNDCFGU can only be
187+
* modified by XRSTOR. Stuffing XSTATE_BV in the host
188+
* is simpler than doing XRSTOR here in the guest.
189+
*
190+
* However, temporarily enable MPX in BNDCFGS so that
191+
* BNDMOV actually loads BND1. If MPX isn't *fully*
192+
* enabled, all MPX instructions are treated as NOPs.
193+
*
194+
* Hand encode "bndmov (%rax),%bnd1" as support for MPX
195+
* mnemonics/registers has been removed from gcc and
196+
* clang (and was never fully supported by clang).
197+
*/
198+
wrmsr(MSR_IA32_BNDCFGS, BIT_ULL(0));
199+
asm volatile (".byte 0x66,0x0f,0x1a,0x08" :: "a" (bounds));
200+
/*
201+
* Hand encode "bndmov %bnd1, (%rax)" to sanity check
202+
* that BND1 actually got loaded.
203+
*/
204+
asm volatile (".byte 0x66,0x0f,0x1b,0x08" :: "a" (output));
205+
wrmsr(MSR_IA32_BNDCFGS, 0);
206+
207+
GUEST_ASSERT_EQ(bounds[0], output[0]);
208+
GUEST_ASSERT_EQ(bounds[1], output[1]);
209+
}
210+
if (this_cpu_has(X86_FEATURE_PKU)) {
211+
GUEST_ASSERT(supported_xcr0 & XFEATURE_MASK_PKRU);
212+
set_cr4(get_cr4() | X86_CR4_PKE);
213+
GUEST_ASSERT(this_cpu_has(X86_FEATURE_OSPKE));
214+
215+
wrpkru(-1u);
216+
}
217+
}
218+
142219
GUEST_SYNC(2);
143220

144221
if (arg) {

0 commit comments

Comments
 (0)