@@ -665,6 +665,9 @@ enum spectre_v2_mitigation_cmd {
665
665
SPECTRE_V2_CMD_RETPOLINE ,
666
666
SPECTRE_V2_CMD_RETPOLINE_GENERIC ,
667
667
SPECTRE_V2_CMD_RETPOLINE_LFENCE ,
668
+ SPECTRE_V2_CMD_EIBRS ,
669
+ SPECTRE_V2_CMD_EIBRS_RETPOLINE ,
670
+ SPECTRE_V2_CMD_EIBRS_LFENCE ,
668
671
};
669
672
670
673
enum spectre_v2_user_cmd {
@@ -737,6 +740,13 @@ spectre_v2_parse_user_cmdline(enum spectre_v2_mitigation_cmd v2_cmd)
737
740
return SPECTRE_V2_USER_CMD_AUTO ;
738
741
}
739
742
743
+ static inline bool spectre_v2_in_eibrs_mode (enum spectre_v2_mitigation mode )
744
+ {
745
+ return (mode == SPECTRE_V2_EIBRS ||
746
+ mode == SPECTRE_V2_EIBRS_RETPOLINE ||
747
+ mode == SPECTRE_V2_EIBRS_LFENCE );
748
+ }
749
+
740
750
static void __init
741
751
spectre_v2_user_select_mitigation (enum spectre_v2_mitigation_cmd v2_cmd )
742
752
{
@@ -804,7 +814,7 @@ spectre_v2_user_select_mitigation(enum spectre_v2_mitigation_cmd v2_cmd)
804
814
*/
805
815
if (!boot_cpu_has (X86_FEATURE_STIBP ) ||
806
816
!smt_possible ||
807
- spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED )
817
+ spectre_v2_in_eibrs_mode ( spectre_v2_enabled ) )
808
818
return ;
809
819
810
820
/*
@@ -826,7 +836,9 @@ static const char * const spectre_v2_strings[] = {
826
836
[SPECTRE_V2_NONE ] = "Vulnerable" ,
827
837
[SPECTRE_V2_RETPOLINE ] = "Mitigation: Retpolines" ,
828
838
[SPECTRE_V2_LFENCE ] = "Mitigation: LFENCE" ,
829
- [SPECTRE_V2_IBRS_ENHANCED ] = "Mitigation: Enhanced IBRS" ,
839
+ [SPECTRE_V2_EIBRS ] = "Mitigation: Enhanced IBRS" ,
840
+ [SPECTRE_V2_EIBRS_LFENCE ] = "Mitigation: Enhanced IBRS + LFENCE" ,
841
+ [SPECTRE_V2_EIBRS_RETPOLINE ] = "Mitigation: Enhanced IBRS + Retpolines" ,
830
842
};
831
843
832
844
static const struct {
@@ -840,6 +852,9 @@ static const struct {
840
852
{ "retpoline,amd" , SPECTRE_V2_CMD_RETPOLINE_LFENCE , false },
841
853
{ "retpoline,lfence" , SPECTRE_V2_CMD_RETPOLINE_LFENCE , false },
842
854
{ "retpoline,generic" , SPECTRE_V2_CMD_RETPOLINE_GENERIC , false },
855
+ { "eibrs" , SPECTRE_V2_CMD_EIBRS , false },
856
+ { "eibrs,lfence" , SPECTRE_V2_CMD_EIBRS_LFENCE , false },
857
+ { "eibrs,retpoline" , SPECTRE_V2_CMD_EIBRS_RETPOLINE , false },
843
858
{ "auto" , SPECTRE_V2_CMD_AUTO , false },
844
859
};
845
860
@@ -877,15 +892,29 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
877
892
878
893
if ((cmd == SPECTRE_V2_CMD_RETPOLINE ||
879
894
cmd == SPECTRE_V2_CMD_RETPOLINE_LFENCE ||
880
- cmd == SPECTRE_V2_CMD_RETPOLINE_GENERIC ) &&
895
+ cmd == SPECTRE_V2_CMD_RETPOLINE_GENERIC ||
896
+ cmd == SPECTRE_V2_CMD_EIBRS_LFENCE ||
897
+ cmd == SPECTRE_V2_CMD_EIBRS_RETPOLINE ) &&
881
898
!IS_ENABLED (CONFIG_RETPOLINE )) {
882
- pr_err ("%s selected but not compiled in. Switching to AUTO select\n" , mitigation_options [i ].option );
899
+ pr_err ("%s selected but not compiled in. Switching to AUTO select\n" ,
900
+ mitigation_options [i ].option );
901
+ return SPECTRE_V2_CMD_AUTO ;
902
+ }
903
+
904
+ if ((cmd == SPECTRE_V2_CMD_EIBRS ||
905
+ cmd == SPECTRE_V2_CMD_EIBRS_LFENCE ||
906
+ cmd == SPECTRE_V2_CMD_EIBRS_RETPOLINE ) &&
907
+ !boot_cpu_has (X86_FEATURE_IBRS_ENHANCED )) {
908
+ pr_err ("%s selected but CPU doesn't have eIBRS. Switching to AUTO select\n" ,
909
+ mitigation_options [i ].option );
883
910
return SPECTRE_V2_CMD_AUTO ;
884
911
}
885
912
886
- if ((cmd == SPECTRE_V2_CMD_RETPOLINE_LFENCE ) &&
913
+ if ((cmd == SPECTRE_V2_CMD_RETPOLINE_LFENCE ||
914
+ cmd == SPECTRE_V2_CMD_EIBRS_LFENCE ) &&
887
915
!boot_cpu_has (X86_FEATURE_LFENCE_RDTSC )) {
888
- pr_err ("%s selected, but CPU doesn't have a serializing LFENCE. Switching to AUTO select\n" , mitigation_options [i ].option );
916
+ pr_err ("%s selected, but CPU doesn't have a serializing LFENCE. Switching to AUTO select\n" ,
917
+ mitigation_options [i ].option );
889
918
return SPECTRE_V2_CMD_AUTO ;
890
919
}
891
920
@@ -894,6 +923,25 @@ static enum spectre_v2_mitigation_cmd __init spectre_v2_parse_cmdline(void)
894
923
return cmd ;
895
924
}
896
925
926
+ static enum spectre_v2_mitigation __init spectre_v2_select_retpoline (void )
927
+ {
928
+ if (!IS_ENABLED (CONFIG_RETPOLINE )) {
929
+ pr_err ("Kernel not compiled with retpoline; no mitigation available!" );
930
+ return SPECTRE_V2_NONE ;
931
+ }
932
+
933
+ if (boot_cpu_data .x86_vendor == X86_VENDOR_AMD ||
934
+ boot_cpu_data .x86_vendor == X86_VENDOR_HYGON ) {
935
+ if (!boot_cpu_has (X86_FEATURE_LFENCE_RDTSC )) {
936
+ pr_err ("LFENCE not serializing, switching to generic retpoline\n" );
937
+ return SPECTRE_V2_RETPOLINE ;
938
+ }
939
+ return SPECTRE_V2_LFENCE ;
940
+ }
941
+
942
+ return SPECTRE_V2_RETPOLINE ;
943
+ }
944
+
897
945
static void __init spectre_v2_select_mitigation (void )
898
946
{
899
947
enum spectre_v2_mitigation_cmd cmd = spectre_v2_parse_cmdline ();
@@ -914,49 +962,60 @@ static void __init spectre_v2_select_mitigation(void)
914
962
case SPECTRE_V2_CMD_FORCE :
915
963
case SPECTRE_V2_CMD_AUTO :
916
964
if (boot_cpu_has (X86_FEATURE_IBRS_ENHANCED )) {
917
- mode = SPECTRE_V2_IBRS_ENHANCED ;
918
- /* Force it so VMEXIT will restore correctly */
919
- x86_spec_ctrl_base |= SPEC_CTRL_IBRS ;
920
- wrmsrl (MSR_IA32_SPEC_CTRL , x86_spec_ctrl_base );
921
- goto specv2_set_mode ;
965
+ mode = SPECTRE_V2_EIBRS ;
966
+ break ;
922
967
}
923
- if ( IS_ENABLED ( CONFIG_RETPOLINE ))
924
- goto retpoline_auto ;
968
+
969
+ mode = spectre_v2_select_retpoline () ;
925
970
break ;
971
+
926
972
case SPECTRE_V2_CMD_RETPOLINE_LFENCE :
927
- if (IS_ENABLED (CONFIG_RETPOLINE ))
928
- goto retpoline_lfence ;
973
+ mode = SPECTRE_V2_LFENCE ;
929
974
break ;
975
+
930
976
case SPECTRE_V2_CMD_RETPOLINE_GENERIC :
931
- if (IS_ENABLED (CONFIG_RETPOLINE ))
932
- goto retpoline_generic ;
977
+ mode = SPECTRE_V2_RETPOLINE ;
933
978
break ;
979
+
934
980
case SPECTRE_V2_CMD_RETPOLINE :
935
- if (IS_ENABLED (CONFIG_RETPOLINE ))
936
- goto retpoline_auto ;
981
+ mode = spectre_v2_select_retpoline ();
982
+ break ;
983
+
984
+ case SPECTRE_V2_CMD_EIBRS :
985
+ mode = SPECTRE_V2_EIBRS ;
986
+ break ;
987
+
988
+ case SPECTRE_V2_CMD_EIBRS_LFENCE :
989
+ mode = SPECTRE_V2_EIBRS_LFENCE ;
990
+ break ;
991
+
992
+ case SPECTRE_V2_CMD_EIBRS_RETPOLINE :
993
+ mode = SPECTRE_V2_EIBRS_RETPOLINE ;
937
994
break ;
938
995
}
939
- pr_err ("Spectre mitigation: kernel not compiled with retpoline; no mitigation available!" );
940
- return ;
941
996
942
- retpoline_auto :
943
- if (boot_cpu_data .x86_vendor == X86_VENDOR_AMD ||
944
- boot_cpu_data .x86_vendor == X86_VENDOR_HYGON ) {
945
- retpoline_lfence :
946
- if (!boot_cpu_has (X86_FEATURE_LFENCE_RDTSC )) {
947
- pr_err ("Spectre mitigation: LFENCE not serializing, switching to generic retpoline\n" );
948
- goto retpoline_generic ;
949
- }
950
- mode = SPECTRE_V2_LFENCE ;
997
+ if (spectre_v2_in_eibrs_mode (mode )) {
998
+ /* Force it so VMEXIT will restore correctly */
999
+ x86_spec_ctrl_base |= SPEC_CTRL_IBRS ;
1000
+ wrmsrl (MSR_IA32_SPEC_CTRL , x86_spec_ctrl_base );
1001
+ }
1002
+
1003
+ switch (mode ) {
1004
+ case SPECTRE_V2_NONE :
1005
+ case SPECTRE_V2_EIBRS :
1006
+ break ;
1007
+
1008
+ case SPECTRE_V2_LFENCE :
1009
+ case SPECTRE_V2_EIBRS_LFENCE :
951
1010
setup_force_cpu_cap (X86_FEATURE_RETPOLINE_LFENCE );
1011
+ fallthrough ;
1012
+
1013
+ case SPECTRE_V2_RETPOLINE :
1014
+ case SPECTRE_V2_EIBRS_RETPOLINE :
952
1015
setup_force_cpu_cap (X86_FEATURE_RETPOLINE );
953
- } else {
954
- retpoline_generic :
955
- mode = SPECTRE_V2_RETPOLINE ;
956
- setup_force_cpu_cap (X86_FEATURE_RETPOLINE );
1016
+ break ;
957
1017
}
958
1018
959
- specv2_set_mode :
960
1019
spectre_v2_enabled = mode ;
961
1020
pr_info ("%s\n" , spectre_v2_strings [mode ]);
962
1021
@@ -982,7 +1041,7 @@ static void __init spectre_v2_select_mitigation(void)
982
1041
* the CPU supports Enhanced IBRS, kernel might un-intentionally not
983
1042
* enable IBRS around firmware calls.
984
1043
*/
985
- if (boot_cpu_has (X86_FEATURE_IBRS ) && mode != SPECTRE_V2_IBRS_ENHANCED ) {
1044
+ if (boot_cpu_has (X86_FEATURE_IBRS ) && ! spectre_v2_in_eibrs_mode ( mode ) ) {
986
1045
setup_force_cpu_cap (X86_FEATURE_USE_IBRS_FW );
987
1046
pr_info ("Enabling Restricted Speculation for firmware calls\n" );
988
1047
}
@@ -1691,7 +1750,7 @@ static ssize_t tsx_async_abort_show_state(char *buf)
1691
1750
1692
1751
static char * stibp_state (void )
1693
1752
{
1694
- if (spectre_v2_enabled == SPECTRE_V2_IBRS_ENHANCED )
1753
+ if (spectre_v2_in_eibrs_mode ( spectre_v2_enabled ) )
1695
1754
return "" ;
1696
1755
1697
1756
switch (spectre_v2_user_stibp ) {
0 commit comments