1
2
3
4
5
6#include <linux/compat.h>
7#include <linux/cpu.h>
8
9#include <asm/fpu/api.h>
10#include <asm/fpu/internal.h>
11#include <asm/fpu/signal.h>
12#include <asm/fpu/regset.h>
13
14#include <asm/tlbflush.h>
15
16static const char *xfeature_names[] =
17{
18 "x87 floating point registers" ,
19 "SSE registers" ,
20 "AVX registers" ,
21 "MPX bounds registers" ,
22 "MPX CSR" ,
23 "AVX-512 opmask" ,
24 "AVX-512 Hi256" ,
25 "AVX-512 ZMM_Hi256" ,
26 "unknown xstate feature" ,
27};
28
29
30
31
32u64 xfeatures_mask __read_mostly;
33
34static unsigned int xstate_offsets[XFEATURE_MAX] = { [ 0 ... XFEATURE_MAX - 1] = -1};
35static unsigned int xstate_sizes[XFEATURE_MAX] = { [ 0 ... XFEATURE_MAX - 1] = -1};
36static unsigned int xstate_comp_offsets[sizeof(xfeatures_mask)*8];
37
38
39
40
41
42void fpu__xstate_clear_all_cpu_caps(void)
43{
44 setup_clear_cpu_cap(X86_FEATURE_XSAVE);
45 setup_clear_cpu_cap(X86_FEATURE_XSAVEOPT);
46 setup_clear_cpu_cap(X86_FEATURE_XSAVEC);
47 setup_clear_cpu_cap(X86_FEATURE_XSAVES);
48 setup_clear_cpu_cap(X86_FEATURE_AVX);
49 setup_clear_cpu_cap(X86_FEATURE_AVX2);
50 setup_clear_cpu_cap(X86_FEATURE_AVX512F);
51 setup_clear_cpu_cap(X86_FEATURE_AVX512PF);
52 setup_clear_cpu_cap(X86_FEATURE_AVX512ER);
53 setup_clear_cpu_cap(X86_FEATURE_AVX512CD);
54 setup_clear_cpu_cap(X86_FEATURE_MPX);
55 setup_clear_cpu_cap(X86_FEATURE_XGETBV1);
56}
57
58
59
60
61
62
63int cpu_has_xfeatures(u64 xfeatures_needed, const char **feature_name)
64{
65 u64 xfeatures_missing = xfeatures_needed & ~xfeatures_mask;
66
67 if (unlikely(feature_name)) {
68 long xfeature_idx, max_idx;
69 u64 xfeatures_print;
70
71
72
73
74
75
76
77 if (xfeatures_missing)
78 xfeatures_print = xfeatures_missing;
79 else
80 xfeatures_print = xfeatures_needed;
81
82 xfeature_idx = fls64(xfeatures_print)-1;
83 max_idx = ARRAY_SIZE(xfeature_names)-1;
84 xfeature_idx = min(xfeature_idx, max_idx);
85
86 *feature_name = xfeature_names[xfeature_idx];
87 }
88
89 if (xfeatures_missing)
90 return 0;
91
92 return 1;
93}
94EXPORT_SYMBOL_GPL(cpu_has_xfeatures);
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111void fpstate_sanitize_xstate(struct fpu *fpu)
112{
113 struct fxregs_state *fx = &fpu->state.fxsave;
114 int feature_bit;
115 u64 xfeatures;
116
117 if (!use_xsaveopt())
118 return;
119
120 xfeatures = fpu->state.xsave.header.xfeatures;
121
122
123
124
125
126 if ((xfeatures & xfeatures_mask) == xfeatures_mask)
127 return;
128
129
130
131
132 if (!(xfeatures & XFEATURE_MASK_FP)) {
133 fx->cwd = 0x37f;
134 fx->swd = 0;
135 fx->twd = 0;
136 fx->fop = 0;
137 fx->rip = 0;
138 fx->rdp = 0;
139 memset(&fx->st_space[0], 0, 128);
140 }
141
142
143
144
145 if (!(xfeatures & XFEATURE_MASK_SSE))
146 memset(&fx->xmm_space[0], 0, 256);
147
148
149
150
151
152 feature_bit = 0x2;
153 xfeatures = (xfeatures_mask & ~xfeatures) >> 2;
154
155
156
157
158
159
160 while (xfeatures) {
161 if (xfeatures & 0x1) {
162 int offset = xstate_offsets[feature_bit];
163 int size = xstate_sizes[feature_bit];
164
165 memcpy((void *)fx + offset,
166 (void *)&init_fpstate.xsave + offset,
167 size);
168 }
169
170 xfeatures >>= 1;
171 feature_bit++;
172 }
173}
174
175
176
177
178
179void fpu__init_cpu_xstate(void)
180{
181 if (!cpu_has_xsave || !xfeatures_mask)
182 return;
183
184 cr4_set_bits(X86_CR4_OSXSAVE);
185 xsetbv(XCR_XFEATURE_ENABLED_MASK, xfeatures_mask);
186}
187
188
189
190
191
192
193static int xfeature_enabled(enum xfeature xfeature)
194{
195 return !!(xfeatures_mask & (1UL << xfeature));
196}
197
198
199
200
201
202static void __init setup_xstate_features(void)
203{
204 u32 eax, ebx, ecx, edx, i;
205
206 unsigned int last_good_offset = offsetof(struct xregs_state,
207 extended_state_area);
208
209 for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
210 if (!xfeature_enabled(i))
211 continue;
212
213 cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx);
214 xstate_offsets[i] = ebx;
215 xstate_sizes[i] = eax;
216
217
218
219
220
221 WARN_ONCE(last_good_offset > xstate_offsets[i],
222 "x86/fpu: misordered xstate at %d\n", last_good_offset);
223 last_good_offset = xstate_offsets[i];
224
225 printk(KERN_INFO "x86/fpu: xstate_offset[%d]: %4d, xstate_sizes[%d]: %4d\n", i, ebx, i, eax);
226 }
227}
228
229static void __init print_xstate_feature(u64 xstate_mask)
230{
231 const char *feature_name;
232
233 if (cpu_has_xfeatures(xstate_mask, &feature_name))
234 pr_info("x86/fpu: Supporting XSAVE feature 0x%02Lx: '%s'\n", xstate_mask, feature_name);
235}
236
237
238
239
240static void __init print_xstate_features(void)
241{
242 print_xstate_feature(XFEATURE_MASK_FP);
243 print_xstate_feature(XFEATURE_MASK_SSE);
244 print_xstate_feature(XFEATURE_MASK_YMM);
245 print_xstate_feature(XFEATURE_MASK_BNDREGS);
246 print_xstate_feature(XFEATURE_MASK_BNDCSR);
247 print_xstate_feature(XFEATURE_MASK_OPMASK);
248 print_xstate_feature(XFEATURE_MASK_ZMM_Hi256);
249 print_xstate_feature(XFEATURE_MASK_Hi16_ZMM);
250}
251
252
253
254
255
256
257static void __init setup_xstate_comp(void)
258{
259 unsigned int xstate_comp_sizes[sizeof(xfeatures_mask)*8];
260 int i;
261
262
263
264
265
266
267 xstate_comp_offsets[0] = 0;
268 xstate_comp_offsets[1] = offsetof(struct fxregs_state, xmm_space);
269
270 if (!cpu_has_xsaves) {
271 for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
272 if (xfeature_enabled(i)) {
273 xstate_comp_offsets[i] = xstate_offsets[i];
274 xstate_comp_sizes[i] = xstate_sizes[i];
275 }
276 }
277 return;
278 }
279
280 xstate_comp_offsets[FIRST_EXTENDED_XFEATURE] =
281 FXSAVE_SIZE + XSAVE_HDR_SIZE;
282
283 for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
284 if (xfeature_enabled(i))
285 xstate_comp_sizes[i] = xstate_sizes[i];
286 else
287 xstate_comp_sizes[i] = 0;
288
289 if (i > FIRST_EXTENDED_XFEATURE)
290 xstate_comp_offsets[i] = xstate_comp_offsets[i-1]
291 + xstate_comp_sizes[i-1];
292
293 }
294}
295
296
297
298
299static void __init setup_init_fpu_buf(void)
300{
301 static int on_boot_cpu __initdata = 1;
302
303 WARN_ON_FPU(!on_boot_cpu);
304 on_boot_cpu = 0;
305
306 if (!cpu_has_xsave)
307 return;
308
309 setup_xstate_features();
310 print_xstate_features();
311
312 if (cpu_has_xsaves) {
313 init_fpstate.xsave.header.xcomp_bv = (u64)1 << 63 | xfeatures_mask;
314 init_fpstate.xsave.header.xfeatures = xfeatures_mask;
315 }
316
317
318
319
320 copy_kernel_to_xregs_booting(&init_fpstate.xsave);
321
322
323
324
325
326 copy_xregs_to_kernel_booting(&init_fpstate.xsave);
327}
328
329static int xfeature_is_supervisor(int xfeature_nr)
330{
331
332
333
334
335
336
337
338
339
340
341
342 return 0;
343}
344
345
346
347
348
349
350
351
352
353
354
355#define CHECK_XFEATURE(nr) do { \
356 WARN_ON(nr < FIRST_EXTENDED_XFEATURE); \
357 WARN_ON(nr >= XFEATURE_MAX); \
358} while (0)
359
360
361
362
363
364static int xfeature_is_aligned(int xfeature_nr)
365{
366 u32 eax, ebx, ecx, edx;
367
368 CHECK_XFEATURE(xfeature_nr);
369 cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx);
370
371
372
373
374
375 return !!(ecx & 2);
376}
377
378static int xfeature_uncompacted_offset(int xfeature_nr)
379{
380 u32 eax, ebx, ecx, edx;
381
382 CHECK_XFEATURE(xfeature_nr);
383 cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx);
384 return ebx;
385}
386
387static int xfeature_size(int xfeature_nr)
388{
389 u32 eax, ebx, ecx, edx;
390
391 CHECK_XFEATURE(xfeature_nr);
392 cpuid_count(XSTATE_CPUID, xfeature_nr, &eax, &ebx, &ecx, &edx);
393 return eax;
394}
395
396
397
398
399
400
401
402
403
404
405static int using_compacted_format(void)
406{
407 return cpu_has_xsaves;
408}
409
410static void __xstate_dump_leaves(void)
411{
412 int i;
413 u32 eax, ebx, ecx, edx;
414 static int should_dump = 1;
415
416 if (!should_dump)
417 return;
418 should_dump = 0;
419
420
421
422
423 for (i = 0; i < XFEATURE_MAX + 10; i++) {
424 cpuid_count(XSTATE_CPUID, i, &eax, &ebx, &ecx, &edx);
425 pr_warn("CPUID[%02x, %02x]: eax=%08x ebx=%08x ecx=%08x edx=%08x\n",
426 XSTATE_CPUID, i, eax, ebx, ecx, edx);
427 }
428}
429
430#define XSTATE_WARN_ON(x) do { \
431 if (WARN_ONCE(x, "XSAVE consistency problem, dumping leaves")) { \
432 __xstate_dump_leaves(); \
433 } \
434} while (0)
435
436#define XCHECK_SZ(sz, nr, nr_macro, __struct) do { \
437 if ((nr == nr_macro) && \
438 WARN_ONCE(sz != sizeof(__struct), \
439 "%s: struct is %zu bytes, cpu state %d bytes\n", \
440 __stringify(nr_macro), sizeof(__struct), sz)) { \
441 __xstate_dump_leaves(); \
442 } \
443} while (0)
444
445
446
447
448
449
450static void check_xstate_against_struct(int nr)
451{
452
453
454
455 int sz = xfeature_size(nr);
456
457
458
459
460 XCHECK_SZ(sz, nr, XFEATURE_YMM, struct ymmh_struct);
461 XCHECK_SZ(sz, nr, XFEATURE_BNDREGS, struct mpx_bndreg_state);
462 XCHECK_SZ(sz, nr, XFEATURE_BNDCSR, struct mpx_bndcsr_state);
463 XCHECK_SZ(sz, nr, XFEATURE_OPMASK, struct avx_512_opmask_state);
464 XCHECK_SZ(sz, nr, XFEATURE_ZMM_Hi256, struct avx_512_zmm_uppers_state);
465 XCHECK_SZ(sz, nr, XFEATURE_Hi16_ZMM, struct avx_512_hi16_state);
466
467
468
469
470
471
472 if ((nr < XFEATURE_YMM) ||
473 (nr >= XFEATURE_MAX)) {
474 WARN_ONCE(1, "no structure for xstate: %d\n", nr);
475 XSTATE_WARN_ON(1);
476 }
477}
478
479
480
481
482
483
484static void do_extra_xstate_size_checks(void)
485{
486 int paranoid_xstate_size = FXSAVE_SIZE + XSAVE_HDR_SIZE;
487 int i;
488
489 for (i = FIRST_EXTENDED_XFEATURE; i < XFEATURE_MAX; i++) {
490 if (!xfeature_enabled(i))
491 continue;
492
493 check_xstate_against_struct(i);
494
495
496
497
498 if (!using_compacted_format())
499 XSTATE_WARN_ON(xfeature_is_supervisor(i));
500
501
502 if (xfeature_is_aligned(i))
503 paranoid_xstate_size = ALIGN(paranoid_xstate_size, 64);
504
505
506
507
508
509
510 if (!using_compacted_format())
511 paranoid_xstate_size = xfeature_uncompacted_offset(i);
512
513
514
515
516 paranoid_xstate_size += xfeature_size(i);
517 }
518 XSTATE_WARN_ON(paranoid_xstate_size != xstate_size);
519}
520
521
522
523
524
525
526
527
528
529
530
531
532static unsigned int __init calculate_xstate_size(void)
533{
534 unsigned int eax, ebx, ecx, edx;
535 unsigned int calculated_xstate_size;
536
537 if (!cpu_has_xsaves) {
538
539
540
541
542
543
544
545 cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
546 calculated_xstate_size = ebx;
547 } else {
548
549
550
551
552
553
554
555
556 cpuid_count(XSTATE_CPUID, 1, &eax, &ebx, &ecx, &edx);
557 calculated_xstate_size = ebx;
558 }
559 return calculated_xstate_size;
560}
561
562
563
564
565
566static bool is_supported_xstate_size(unsigned int test_xstate_size)
567{
568 if (test_xstate_size <= sizeof(union fpregs_state))
569 return true;
570
571 pr_warn("x86/fpu: xstate buffer too small (%zu < %d), disabling xsave\n",
572 sizeof(union fpregs_state), test_xstate_size);
573 return false;
574}
575
576static int init_xstate_size(void)
577{
578
579 unsigned int possible_xstate_size = calculate_xstate_size();
580
581
582 if (!is_supported_xstate_size(possible_xstate_size))
583 return -EINVAL;
584
585
586
587
588
589 xstate_size = possible_xstate_size;
590 do_extra_xstate_size_checks();
591 return 0;
592}
593
594
595
596
597
598static void fpu__init_disable_system_xstate(void)
599{
600 xfeatures_mask = 0;
601 cr4_clear_bits(X86_CR4_OSXSAVE);
602 fpu__xstate_clear_all_cpu_caps();
603}
604
605
606
607
608
609void __init fpu__init_system_xstate(void)
610{
611 unsigned int eax, ebx, ecx, edx;
612 static int on_boot_cpu __initdata = 1;
613 int err;
614
615 WARN_ON_FPU(!on_boot_cpu);
616 on_boot_cpu = 0;
617
618 if (!cpu_has_xsave) {
619 pr_info("x86/fpu: Legacy x87 FPU detected.\n");
620 return;
621 }
622
623 if (boot_cpu_data.cpuid_level < XSTATE_CPUID) {
624 WARN_ON_FPU(1);
625 return;
626 }
627
628 cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
629 xfeatures_mask = eax + ((u64)edx << 32);
630
631 if ((xfeatures_mask & XFEATURE_MASK_FPSSE) != XFEATURE_MASK_FPSSE) {
632 pr_err("x86/fpu: FP/SSE not present amongst the CPU's xstate features: 0x%llx.\n", xfeatures_mask);
633 BUG();
634 }
635
636 xfeatures_mask &= fpu__get_supported_xfeatures_mask();
637
638
639 fpu__init_cpu_xstate();
640 err = init_xstate_size();
641 if (err) {
642
643 fpu__init_disable_system_xstate();
644 return;
645 }
646
647 update_regset_xstate_info(xstate_size, xfeatures_mask);
648 fpu__init_prepare_fx_sw_frame();
649 setup_init_fpu_buf();
650 setup_xstate_comp();
651
652 pr_info("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n",
653 xfeatures_mask,
654 xstate_size,
655 cpu_has_xsaves ? "compacted" : "standard");
656}
657
658
659
660
661void fpu__resume_cpu(void)
662{
663
664
665
666 if (cpu_has_xsave)
667 xsetbv(XCR_XFEATURE_ENABLED_MASK, xfeatures_mask);
668}
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688void *get_xsave_addr(struct xregs_state *xsave, int xstate_feature)
689{
690 int feature_nr = fls64(xstate_feature) - 1;
691
692
693
694 if (!boot_cpu_has(X86_FEATURE_XSAVE))
695 return NULL;
696
697
698
699
700
701
702 WARN_ONCE(!(xfeatures_mask & xstate_feature),
703 "get of unsupported state");
704
705
706
707
708
709
710
711
712
713
714
715 if (!(xsave->header.xfeatures & xstate_feature))
716 return NULL;
717
718 return (void *)xsave + xstate_comp_offsets[feature_nr];
719}
720EXPORT_SYMBOL_GPL(get_xsave_addr);
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739const void *get_xsave_field_ptr(int xsave_state)
740{
741 struct fpu *fpu = ¤t->thread.fpu;
742
743 if (!fpu->fpstate_active)
744 return NULL;
745
746
747
748
749 fpu__save(fpu);
750
751 return get_xsave_addr(&fpu->state.xsave, xsave_state);
752}
753