]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: selftests: Add a fully functional "struct xstate" for x86
authorMingwei Zhang <mizhang@google.com>
Tue, 21 Feb 2023 16:36:44 +0000 (16:36 +0000)
committerSean Christopherson <seanjc@google.com>
Fri, 24 Mar 2023 21:21:36 +0000 (14:21 -0700)
Add a working xstate data structure for the usage of AMX and potential
future usage on other xstate components. AMX selftest requires checking
both the xstate_bv and xcomp_bv. Existing code relies on pointer
arithmetics to fetch xstate_bv and does not support xcomp_bv.

So, add a working xstate data structure into processor.h for x86.

Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Mingwei Zhang <mizhang@google.com>
Link: https://lore.kernel.org/r/20230221163655.920289-3-mizhang@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
tools/testing/selftests/kvm/include/x86_64/processor.h
tools/testing/selftests/kvm/x86_64/amx_test.c

index 90387ddcb2a9de8e63f0a1b853975895efe46bab..44b6c23d08f7e7e7c629c0f6c9a6691961f85602 100644 (file)
@@ -48,6 +48,18 @@ extern bool host_cpu_is_amd;
 #define X86_CR4_SMAP           (1ul << 21)
 #define X86_CR4_PKE            (1ul << 22)
 
+struct xstate_header {
+       u64                             xstate_bv;
+       u64                             xcomp_bv;
+       u64                             reserved[6];
+} __attribute__((packed));
+
+struct xstate {
+       u8                              i387[512];
+       struct xstate_header            header;
+       u8                              extended_state_area[0];
+} __attribute__ ((packed, aligned (64)));
+
 /* Note, these are ordered alphabetically to match kvm_cpuid_entry2.  Eww. */
 enum cpuid_output_regs {
        KVM_CPUID_EAX,
index b646cdb5055adb3ab9f3f03e68381d422ed5e27d..59e0a573652d9b504d2d253d262068f20223f708 100644 (file)
 
 #define XSAVE_HDR_OFFSET               512
 
-struct xsave_data {
-       u8 area[XSAVE_SIZE];
-} __aligned(64);
-
 struct tile_config {
        u8  palette_id;
        u8  start_row;
@@ -103,13 +99,13 @@ static inline void __tilerelease(void)
        asm volatile(".byte 0xc4, 0xe2, 0x78, 0x49, 0xc0" ::);
 }
 
-static inline void __xsavec(struct xsave_data *data, uint64_t rfbm)
+static inline void __xsavec(struct xstate *xstate, uint64_t rfbm)
 {
        uint32_t rfbm_lo = rfbm;
        uint32_t rfbm_hi = rfbm >> 32;
 
        asm volatile("xsavec (%%rdi)"
-                    : : "D" (data), "a" (rfbm_lo), "d" (rfbm_hi)
+                    : : "D" (xstate), "a" (rfbm_lo), "d" (rfbm_hi)
                     : "memory");
 }
 
@@ -158,16 +154,6 @@ static void set_tilecfg(struct tile_config *cfg)
        }
 }
 
-static void set_xstatebv(void *data, uint64_t bv)
-{
-       *(uint64_t *)(data + XSAVE_HDR_OFFSET) = bv;
-}
-
-static u64 get_xstatebv(void *data)
-{
-       return *(u64 *)(data + XSAVE_HDR_OFFSET);
-}
-
 static void init_regs(void)
 {
        uint64_t cr4, xcr0;
@@ -184,7 +170,7 @@ static void init_regs(void)
 
 static void __attribute__((__flatten__)) guest_code(struct tile_config *amx_cfg,
                                                    struct tile_data *tiledata,
-                                                   struct xsave_data *xsave_data)
+                                                   struct xstate *xstate)
 {
        init_regs();
        check_cpuid_xsave();
@@ -205,9 +191,9 @@ static void __attribute__((__flatten__)) guest_code(struct tile_config *amx_cfg,
        __tilerelease();
        GUEST_SYNC(5);
        /* bit 18 not in the XCOMP_BV after xsavec() */
-       set_xstatebv(xsave_data, XFEATURE_MASK_XTILEDATA);
-       __xsavec(xsave_data, XFEATURE_MASK_XTILEDATA);
-       GUEST_ASSERT((get_xstatebv(xsave_data) & XFEATURE_MASK_XTILEDATA) == 0);
+       xstate->header.xstate_bv = XFEATURE_MASK_XTILEDATA;
+       __xsavec(xstate, XFEATURE_MASK_XTILEDATA);
+       GUEST_ASSERT(!(xstate->header.xstate_bv & XFEATURE_MASK_XTILEDATA));
 
        /* xfd=0x40000, disable amx tiledata */
        wrmsr(MSR_IA32_XFD, XFEATURE_MASK_XTILEDATA);
@@ -243,7 +229,7 @@ int main(int argc, char *argv[])
        struct kvm_vm *vm;
        struct kvm_x86_state *state;
        int xsave_restore_size;
-       vm_vaddr_t amx_cfg, tiledata, xsavedata;
+       vm_vaddr_t amx_cfg, tiledata, xstate;
        struct ucall uc;
        u32 amx_offset;
        int stage, ret;
@@ -282,10 +268,10 @@ int main(int argc, char *argv[])
        tiledata = vm_vaddr_alloc_pages(vm, 2);
        memset(addr_gva2hva(vm, tiledata), rand() | 1, 2 * getpagesize());
 
-       /* xsave data for guest_code */
-       xsavedata = vm_vaddr_alloc_pages(vm, 3);
-       memset(addr_gva2hva(vm, xsavedata), 0, 3 * getpagesize());
-       vcpu_args_set(vcpu, 3, amx_cfg, tiledata, xsavedata);
+       /* XSAVE state for guest_code */
+       xstate = vm_vaddr_alloc_pages(vm, DIV_ROUND_UP(XSAVE_SIZE, PAGE_SIZE));
+       memset(addr_gva2hva(vm, xstate), 0, PAGE_SIZE * DIV_ROUND_UP(XSAVE_SIZE, PAGE_SIZE));
+       vcpu_args_set(vcpu, 3, amx_cfg, tiledata, xstate);
 
        for (stage = 1; ; stage++) {
                vcpu_run(vcpu);