]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/nospec: Push down alternative handling
authorHeiko Carstens <hca@linux.ibm.com>
Tue, 16 Jul 2024 11:50:55 +0000 (13:50 +0200)
committerVasily Gorbik <gor@linux.ibm.com>
Tue, 23 Jul 2024 14:02:31 +0000 (16:02 +0200)
The nospec implementation is deeply integrated into the alternatives
code: only for nospec an alternative facility list is implemented and
used by the alternative code, while it is modified by nospec specific
needs.

Push down the nospec alternative handling into the nospec by
introducing a new alternative type and a specific nospec callback to
decide if alternatives should be applied.

Also introduce a new global nobp variable which together with facility
82 can be used to decide if nobp is enabled or not.

Acked-by: Alexander Gordeev <agordeev@linux.ibm.com>
Tested-by: Sven Schnelle <svens@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/include/asm/alternative.h
arch/s390/include/asm/nospec-branch.h
arch/s390/include/asm/processor.h
arch/s390/kernel/alternative.c
arch/s390/kernel/early.c
arch/s390/kernel/entry.S
arch/s390/kernel/nospec-branch.c
arch/s390/kernel/nospec-sysfs.c

index 32c208332e579c25f03d3cd0e4a9ecbef365e8d0..5f56a2f3aba624832918b1bc033c46ae13d80243 100644 (file)
@@ -33,6 +33,7 @@
 
 #define ALT_TYPE_FACILITY_EARLY        0
 #define ALT_TYPE_FACILITY      1
+#define ALT_TYPE_SPEC          2
 
 #define ALT_DATA_SHIFT         0
 #define ALT_TYPE_SHIFT         20
                                         ALT_TYPE_FACILITY << ALT_TYPE_SHIFT    | \
                                         (facility) << ALT_DATA_SHIFT)
 
+#define ALT_SPEC(facility)             (ALT_CTX_LATE << ALT_CTX_SHIFT          | \
+                                        ALT_TYPE_SPEC << ALT_TYPE_SHIFT        | \
+                                        (facility) << ALT_DATA_SHIFT)
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
index b9c1f3cae84267d05c93f473414c31ce82157eb8..192835a3e24dcf195e31552e266d37791b537f52 100644 (file)
@@ -5,8 +5,17 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
+#include <asm/facility.h>
 
 extern int nospec_disable;
+extern int nobp;
+
+static inline bool nobp_enabled(void)
+{
+       if (__is_defined(__DECOMPRESSOR))
+               return false;
+       return nobp && test_facility(82);
+}
 
 void nospec_init_branches(void);
 void nospec_auto_detect(void);
index 8a52554f49f09732446f758e5f7d27bc992656b5..3063488014eb4e42687f9dba27e05e46e9bcee51 100644 (file)
@@ -419,7 +419,7 @@ static __always_inline bool regs_irqs_disabled(struct pt_regs *regs)
 
 static __always_inline void bpon(void)
 {
-       asm volatile(ALTERNATIVE("nop", ".insn  rrf,0xb2e80000,0,0,13,0", ALT_FACILITY(82)));
+       asm volatile(ALTERNATIVE("nop", ".insn  rrf,0xb2e80000,0,0,13,0", ALT_SPEC(82)));
 }
 
 #endif /* __ASSEMBLY__ */
index de89c9e8b1a3087e42f8c43603f4dbb058e6a54c..05545669552ffa8e37819f85f34fc73130218771 100644 (file)
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 
 #include <linux/uaccess.h>
+#include <asm/nospec-branch.h>
 #include <asm/alternative.h>
 #include <asm/facility.h>
 
@@ -26,6 +27,9 @@ void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsign
                        replace = __test_facility(a->data, alt_stfle_fac_list);
                        break;
 #endif
+               case ALT_TYPE_SPEC:
+                       replace = nobp_enabled();
+                       break;
                default:
                        replace = false;
                }
index 467ed4dba817b08b4d4e17d57165f886e40f6cda..d142598e05323034b0e9b9a82fcf19250fa89459 100644 (file)
@@ -193,8 +193,6 @@ static noinline __init void setup_lowcore_early(void)
 static noinline __init void setup_facility_list(void)
 {
        memcpy(alt_stfle_fac_list, stfle_fac_list, sizeof(alt_stfle_fac_list));
-       if (!IS_ENABLED(CONFIG_KERNEL_NOBP))
-               __clear_facility(82, alt_stfle_fac_list);
 }
 
 static __init void detect_diag9c(void)
index 90027a57a524900eb0a9f454016ee0a12206f9bb..8caf893d1b591e76a86d0cd098d0ed44310042ef 100644 (file)
@@ -100,22 +100,22 @@ _LPP_OFFSET       = __LC_LPP
        .endm
 
        .macro BPOFF
-       ALTERNATIVE "nop", ".insn rrf,0xb2e80000,0,0,12,0", ALT_FACILITY(82)
+       ALTERNATIVE "nop", ".insn rrf,0xb2e80000,0,0,12,0", ALT_SPEC(82)
        .endm
 
        .macro BPON
-       ALTERNATIVE "nop", ".insn rrf,0xb2e80000,0,0,13,0", ALT_FACILITY(82)
+       ALTERNATIVE "nop", ".insn rrf,0xb2e80000,0,0,13,0", ALT_SPEC(82)
        .endm
 
        .macro BPENTER tif_ptr,tif_mask
        ALTERNATIVE "TSTMSK \tif_ptr,\tif_mask; jz .+8; .insn rrf,0xb2e80000,0,0,13,0", \
-                   "j .+12; nop; nop", ALT_FACILITY(82)
+                   "j .+12; nop; nop", ALT_SPEC(82)
        .endm
 
        .macro BPEXIT tif_ptr,tif_mask
        TSTMSK  \tif_ptr,\tif_mask
        ALTERNATIVE "jz .+8;  .insn rrf,0xb2e80000,0,0,12,0", \
-                   "jnz .+8; .insn rrf,0xb2e80000,0,0,13,0", ALT_FACILITY(82)
+                   "jnz .+8; .insn rrf,0xb2e80000,0,0,13,0", ALT_SPEC(82)
        .endm
 
 #if IS_ENABLED(CONFIG_KVM)
index 9b8c24ebb00858561df634ac3a17124d53bc92e9..e11ec15960a18f77d208e3e50bcc31177b91a3af 100644 (file)
@@ -4,6 +4,8 @@
 #include <linux/cpu.h>
 #include <asm/nospec-branch.h>
 
+int nobp = IS_ENABLED(CONFIG_KERNEL_NOBP);
+
 static int __init nobp_setup_early(char *str)
 {
        bool enabled;
@@ -17,11 +19,11 @@ static int __init nobp_setup_early(char *str)
                 * The user explicitly requested nobp=1, enable it and
                 * disable the expoline support.
                 */
-               __set_facility(82, alt_stfle_fac_list);
+               nobp = 1;
                if (IS_ENABLED(CONFIG_EXPOLINE))
                        nospec_disable = 1;
        } else {
-               __clear_facility(82, alt_stfle_fac_list);
+               nobp = 0;
        }
        return 0;
 }
@@ -29,7 +31,7 @@ early_param("nobp", nobp_setup_early);
 
 static int __init nospec_setup_early(char *str)
 {
-       __clear_facility(82, alt_stfle_fac_list);
+       nobp = 0;
        return 0;
 }
 early_param("nospec", nospec_setup_early);
@@ -40,7 +42,7 @@ static int __init nospec_report(void)
                pr_info("Spectre V2 mitigation: etokens\n");
        if (nospec_uses_trampoline())
                pr_info("Spectre V2 mitigation: execute trampolines\n");
-       if (__test_facility(82, alt_stfle_fac_list))
+       if (nobp_enabled())
                pr_info("Spectre V2 mitigation: limited branch prediction\n");
        return 0;
 }
@@ -66,14 +68,14 @@ void __init nospec_auto_detect(void)
                 */
                if (__is_defined(CC_USING_EXPOLINE))
                        nospec_disable = 1;
-               __clear_facility(82, alt_stfle_fac_list);
+               nobp = 0;
        } else if (__is_defined(CC_USING_EXPOLINE)) {
                /*
                 * The kernel has been compiled with expolines.
                 * Keep expolines enabled and disable nobp.
                 */
                nospec_disable = 0;
-               __clear_facility(82, alt_stfle_fac_list);
+               nobp = 0;
        }
        /*
         * If the kernel has not been compiled with expolines the
@@ -86,7 +88,7 @@ static int __init spectre_v2_setup_early(char *str)
 {
        if (str && !strncmp(str, "on", 2)) {
                nospec_disable = 0;
-               __clear_facility(82, alt_stfle_fac_list);
+               nobp = 0;
        }
        if (str && !strncmp(str, "off", 3))
                nospec_disable = 1;
index 52d4353188ad8cb3328dabe3f437f2e57fa6baaa..a951888186370ddb7c72c8db34e91269997c9e45 100644 (file)
@@ -17,7 +17,7 @@ ssize_t cpu_show_spectre_v2(struct device *dev,
                return sprintf(buf, "Mitigation: etokens\n");
        if (nospec_uses_trampoline())
                return sprintf(buf, "Mitigation: execute trampolines\n");
-       if (__test_facility(82, alt_stfle_fac_list))
+       if (nobp_enabled())
                return sprintf(buf, "Mitigation: limited branch prediction\n");
        return sprintf(buf, "Vulnerable\n");
 }