@@ -142,7 +142,8 @@ static unsigned int xfeature_get_offset(u64 xcomp_bv, int xfeature)
142
142
* Non-compacted format and legacy features use the cached fixed
143
143
* offsets.
144
144
*/
145
- if (!cpu_feature_enabled (X86_FEATURE_XSAVES ) || xfeature <= XFEATURE_SSE )
145
+ if (!cpu_feature_enabled (X86_FEATURE_XCOMPACTED ) ||
146
+ xfeature <= XFEATURE_SSE )
146
147
return xstate_offsets [xfeature ];
147
148
148
149
/*
@@ -369,12 +370,12 @@ static void __init setup_init_fpu_buf(void)
369
370
/*
370
371
* All components are now in init state. Read the state back so
371
372
* that init_fpstate contains all non-zero init state. This only
372
- * works with XSAVE, but not with XSAVEOPT and XSAVES because
373
+ * works with XSAVE, but not with XSAVEOPT and XSAVEC/S because
373
374
* those use the init optimization which skips writing data for
374
375
* components in init state.
375
376
*
376
377
* XSAVE could be used, but that would require to reshuffle the
377
- * data when XSAVES is available because XSAVES uses xstate
378
+ * data when XSAVEC/S is available because XSAVEC/S uses xstate
378
379
* compaction. But doing so is a pointless exercise because most
379
380
* components have an all zeros init state except for the legacy
380
381
* ones (FP and SSE). Those can be saved with FXSAVE into the
@@ -584,7 +585,8 @@ static unsigned int xstate_calculate_size(u64 xfeatures, bool compacted)
584
585
*/
585
586
static bool __init paranoid_xstate_size_valid (unsigned int kernel_size )
586
587
{
587
- bool compacted = cpu_feature_enabled (X86_FEATURE_XSAVES );
588
+ bool compacted = cpu_feature_enabled (X86_FEATURE_XCOMPACTED );
589
+ bool xsaves = cpu_feature_enabled (X86_FEATURE_XSAVES );
588
590
unsigned int size = FXSAVE_SIZE + XSAVE_HDR_SIZE ;
589
591
int i ;
590
592
@@ -595,7 +597,7 @@ static bool __init paranoid_xstate_size_valid(unsigned int kernel_size)
595
597
* Supervisor state components can be managed only by
596
598
* XSAVES.
597
599
*/
598
- if (!compacted && xfeature_is_supervisor (i )) {
600
+ if (!xsaves && xfeature_is_supervisor (i )) {
599
601
XSTATE_WARN_ON (1 );
600
602
return false;
601
603
}
@@ -612,8 +614,11 @@ static bool __init paranoid_xstate_size_valid(unsigned int kernel_size)
612
614
* the size of the *user* states. If we use it to size a buffer
613
615
* that we use 'XSAVES' on, we could potentially overflow the
614
616
* buffer because 'XSAVES' saves system states too.
617
+ *
618
+ * This also takes compaction into account. So this works for
619
+ * XSAVEC as well.
615
620
*/
616
- static unsigned int __init get_xsaves_size (void )
621
+ static unsigned int __init get_compacted_size (void )
617
622
{
618
623
unsigned int eax , ebx , ecx , edx ;
619
624
/*
@@ -623,6 +628,10 @@ static unsigned int __init get_xsaves_size(void)
623
628
* containing all the state components
624
629
* corresponding to bits currently set in
625
630
* XCR0 | IA32_XSS.
631
+ *
632
+ * When XSAVES is not available but XSAVEC is (virt), then there
633
+ * are no supervisor states, but XSAVEC still uses compacted
634
+ * format.
626
635
*/
627
636
cpuid_count (XSTATE_CPUID , 1 , & eax , & ebx , & ecx , & edx );
628
637
return ebx ;
@@ -632,13 +641,13 @@ static unsigned int __init get_xsaves_size(void)
632
641
* Get the total size of the enabled xstates without the independent supervisor
633
642
* features.
634
643
*/
635
- static unsigned int __init get_xsaves_size_no_independent (void )
644
+ static unsigned int __init get_xsave_compacted_size (void )
636
645
{
637
646
u64 mask = xfeatures_mask_independent ();
638
647
unsigned int size ;
639
648
640
649
if (!mask )
641
- return get_xsaves_size ();
650
+ return get_compacted_size ();
642
651
643
652
/* Disable independent features. */
644
653
wrmsrl (MSR_IA32_XSS , xfeatures_mask_supervisor ());
@@ -647,7 +656,7 @@ static unsigned int __init get_xsaves_size_no_independent(void)
647
656
* Ask the hardware what size is required of the buffer.
648
657
* This is the size required for the task->fpu buffer.
649
658
*/
650
- size = get_xsaves_size ();
659
+ size = get_compacted_size ();
651
660
652
661
/* Re-enable independent features so XSAVES will work on them again. */
653
662
wrmsrl (MSR_IA32_XSS , xfeatures_mask_supervisor () | mask );
@@ -687,20 +696,21 @@ static int __init init_xstate_size(void)
687
696
{
688
697
/* Recompute the context size for enabled features: */
689
698
unsigned int user_size , kernel_size , kernel_default_size ;
690
- bool compacted = cpu_feature_enabled (X86_FEATURE_XSAVES );
699
+ bool compacted = cpu_feature_enabled (X86_FEATURE_XCOMPACTED );
691
700
692
701
/* Uncompacted user space size */
693
702
user_size = get_xsave_size_user ();
694
703
695
704
/*
696
- * XSAVES kernel size includes supervisor states and
697
- * uses compacted format when available.
705
+ * XSAVES kernel size includes supervisor states and uses compacted
706
+ * format. XSAVEC uses compacted format, but does not save
707
+ * supervisor states.
698
708
*
699
- * XSAVE does not support supervisor states so
700
- * kernel and user size is identical.
709
+ * XSAVE[OPT] do not support supervisor states so kernel and user
710
+ * size is identical.
701
711
*/
702
712
if (compacted )
703
- kernel_size = get_xsaves_size_no_independent ();
713
+ kernel_size = get_xsave_compacted_size ();
704
714
else
705
715
kernel_size = user_size ;
706
716
@@ -813,8 +823,11 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
813
823
if (!cpu_feature_enabled (X86_FEATURE_XFD ))
814
824
fpu_kernel_cfg .max_features &= ~XFEATURE_MASK_USER_DYNAMIC ;
815
825
816
- fpu_kernel_cfg .max_features &= XFEATURE_MASK_USER_SUPPORTED |
817
- XFEATURE_MASK_SUPERVISOR_SUPPORTED ;
826
+ if (!cpu_feature_enabled (X86_FEATURE_XSAVES ))
827
+ fpu_kernel_cfg .max_features &= XFEATURE_MASK_USER_SUPPORTED ;
828
+ else
829
+ fpu_kernel_cfg .max_features &= XFEATURE_MASK_USER_SUPPORTED |
830
+ XFEATURE_MASK_SUPERVISOR_SUPPORTED ;
818
831
819
832
fpu_user_cfg .max_features = fpu_kernel_cfg .max_features ;
820
833
fpu_user_cfg .max_features &= XFEATURE_MASK_USER_SUPPORTED ;
@@ -837,6 +850,11 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
837
850
*/
838
851
init_fpstate .xfd = fpu_user_cfg .max_features & XFEATURE_MASK_USER_DYNAMIC ;
839
852
853
+ /* Set up compaction feature bit */
854
+ if (cpu_feature_enabled (X86_FEATURE_XSAVEC ) ||
855
+ cpu_feature_enabled (X86_FEATURE_XSAVES ))
856
+ setup_force_cpu_cap (X86_FEATURE_XCOMPACTED );
857
+
840
858
/* Enable xstate instructions to be able to continue with initialization: */
841
859
fpu__init_cpu_xstate ();
842
860
@@ -873,7 +891,7 @@ void __init fpu__init_system_xstate(unsigned int legacy_size)
873
891
pr_info ("x86/fpu: Enabled xstate features 0x%llx, context size is %d bytes, using '%s' format.\n" ,
874
892
fpu_kernel_cfg .max_features ,
875
893
fpu_kernel_cfg .max_size ,
876
- boot_cpu_has (X86_FEATURE_XSAVES ) ? "compacted" : "standard" );
894
+ boot_cpu_has (X86_FEATURE_XCOMPACTED ) ? "compacted" : "standard" );
877
895
return ;
878
896
879
897
out_disable :
@@ -917,7 +935,7 @@ static void *__raw_xsave_addr(struct xregs_state *xsave, int xfeature_nr)
917
935
if (WARN_ON_ONCE (!xfeature_enabled (xfeature_nr )))
918
936
return NULL ;
919
937
920
- if (cpu_feature_enabled (X86_FEATURE_XSAVES )) {
938
+ if (cpu_feature_enabled (X86_FEATURE_XCOMPACTED )) {
921
939
if (WARN_ON_ONCE (!(xcomp_bv & BIT_ULL (xfeature_nr ))))
922
940
return NULL ;
923
941
}
@@ -1215,7 +1233,7 @@ static int copy_uabi_to_xstate(struct fpstate *fpstate, const void *kbuf,
1215
1233
}
1216
1234
1217
1235
for (i = 0 ; i < XFEATURE_MAX ; i ++ ) {
1218
- u64 mask = (( u64 ) 1 << i );
1236
+ mask = BIT_ULL ( i );
1219
1237
1220
1238
if (hdr .xfeatures & mask ) {
1221
1239
void * dst = __raw_xsave_addr (xsave , i );
@@ -1525,7 +1543,7 @@ static int __xstate_request_perm(u64 permitted, u64 requested, bool guest)
1525
1543
* vendors into extending XFD for the pre AMX states, especially
1526
1544
* AVX512.
1527
1545
*/
1528
- bool compacted = cpu_feature_enabled (X86_FEATURE_XSAVES );
1546
+ bool compacted = cpu_feature_enabled (X86_FEATURE_XCOMPACTED );
1529
1547
struct fpu * fpu = & current -> group_leader -> thread .fpu ;
1530
1548
struct fpu_state_perm * perm ;
1531
1549
unsigned int ksize , usize ;
0 commit comments