1 /*
2  * include/asm-i386/xstate.h
3  *
4  * x86 extended state (xsave/xrstor) related definitions
5  *
6  */
7 
8 #ifndef __ASM_XSTATE_H
9 #define __ASM_XSTATE_H
10 
11 #include <xen/sched.h>
12 #include <asm/cpufeature.h>
13 #include <asm/x86-defns.h>
14 
15 #define FCW_DEFAULT               0x037f
16 #define FCW_RESET                 0x0040
17 #define MXCSR_DEFAULT             0x1f80
18 
19 extern uint32_t mxcsr_mask;
20 
21 #define XSTATE_CPUID              0x0000000d
22 
23 #define XCR_XFEATURE_ENABLED_MASK 0x00000000  /* index of XCR0 */
24 
25 #define XSAVE_HDR_SIZE            64
26 #define XSAVE_SSE_OFFSET          160
27 #define XSTATE_YMM_SIZE           256
28 #define FXSAVE_SIZE               512
29 #define XSAVE_HDR_OFFSET          FXSAVE_SIZE
30 #define XSTATE_AREA_MIN_SIZE      (FXSAVE_SIZE + XSAVE_HDR_SIZE)
31 
32 #define XSTATE_FP_SSE  (X86_XCR0_FP | X86_XCR0_SSE)
33 #define XCNTXT_MASK    (X86_XCR0_FP | X86_XCR0_SSE | X86_XCR0_YMM | \
34                         X86_XCR0_OPMASK | X86_XCR0_ZMM | X86_XCR0_HI_ZMM | \
35                         XSTATE_NONLAZY)
36 
37 #define XSTATE_ALL     (~(1ULL << 63))
38 #define XSTATE_NONLAZY (X86_XCR0_BNDREGS | X86_XCR0_BNDCSR | X86_XCR0_PKRU)
39 #define XSTATE_LAZY    (XSTATE_ALL & ~XSTATE_NONLAZY)
40 #define XSTATE_XSAVES_ONLY         0
41 #define XSTATE_COMPACTION_ENABLED  (1ULL << 63)
42 
43 #define XSTATE_ALIGN64 (1U << 1)
44 
45 extern u64 xfeature_mask;
46 extern u64 xstate_align;
47 extern unsigned int *xstate_offsets;
48 extern unsigned int *xstate_sizes;
49 
50 /* extended state save area */
51 struct __attribute__((aligned (64))) xsave_struct
52 {
53     union __attribute__((aligned(16))) {     /* FPU/MMX, SSE */
54         char x[512];
55         struct {
56             uint16_t fcw;
57             uint16_t fsw;
58             uint8_t ftw;
59             uint8_t rsvd1;
60             uint16_t fop;
61             union {
62                 uint64_t addr;
63                 struct {
64                     uint32_t offs;
65                     uint16_t sel;
66                     uint16_t rsvd;
67                 };
68             } fip, fdp;
69             uint32_t mxcsr;
70             uint32_t mxcsr_mask;
71             /* data registers follow here */
72         };
73     } fpu_sse;
74 
75     struct xsave_hdr {
76         u64 xstate_bv;
77         u64 xcomp_bv;
78         u64 reserved[6];
79     } xsave_hdr;                             /* The 64-byte header */
80 
81     char data[];                             /* Variable layout states */
82 };
83 
84 struct xstate_bndcsr {
85     uint64_t bndcfgu;
86     uint64_t bndstatus;
87 };
88 
89 /* extended state operations */
90 bool __must_check set_xcr0(u64 xfeatures);
91 uint64_t get_xcr0(void);
92 void set_msr_xss(u64 xss);
93 uint64_t get_msr_xss(void);
94 uint64_t read_bndcfgu(void);
95 void xsave(struct vcpu *v, uint64_t mask);
96 void xrstor(struct vcpu *v, uint64_t mask);
97 void xstate_set_init(uint64_t mask);
98 bool xsave_enabled(const struct vcpu *v);
99 int __must_check validate_xstate(const struct domain *d,
100                                  uint64_t xcr0, uint64_t xcr0_accum,
101                                  const struct xsave_hdr *hdr);
102 int __must_check handle_xsetbv(u32 index, u64 new_bv);
103 void expand_xsave_states(struct vcpu *v, void *dest, unsigned int size);
104 void compress_xsave_states(struct vcpu *v, const void *src, unsigned int size);
105 
106 /* extended state init and cleanup functions */
107 void xstate_free_save_area(struct vcpu *v);
108 int xstate_alloc_save_area(struct vcpu *v);
109 void xstate_init(struct cpuinfo_x86 *c);
110 unsigned int xstate_ctxt_size(u64 xcr0);
111 
xgetbv(unsigned int index)112 static inline uint64_t xgetbv(unsigned int index)
113 {
114     uint32_t lo, hi;
115 
116     ASSERT(index); /* get_xcr0() should be used instead. */
117     asm volatile ( ".byte 0x0f,0x01,0xd0" /* xgetbv */
118                    : "=a" (lo), "=d" (hi) : "c" (index) );
119 
120     return lo | ((uint64_t)hi << 32);
121 }
122 
xstate_all(const struct vcpu * v)123 static inline bool xstate_all(const struct vcpu *v)
124 {
125     /*
126      * XSTATE_FP_SSE may be excluded, because the offsets of XSTATE_FP_SSE
127      * (in the legacy region of xsave area) are fixed, so saving
128      * XSTATE_FP_SSE will not cause overwriting problem with XSAVES/XSAVEC.
129      */
130     return (v->arch.xsave_area->xsave_hdr.xcomp_bv &
131             XSTATE_COMPACTION_ENABLED) &&
132            (v->arch.xcr0_accum & XSTATE_LAZY & ~XSTATE_FP_SSE);
133 }
134 
135 static inline bool __nonnull(1)
xsave_area_compressed(const struct xsave_struct * xsave_area)136 xsave_area_compressed(const struct xsave_struct *xsave_area)
137 {
138     return xsave_area->xsave_hdr.xcomp_bv & XSTATE_COMPACTION_ENABLED;
139 }
140 
141 #endif /* __ASM_XSTATE_H */
142