mirror of
https://github.com/torvalds/linux.git
synced 2024-11-22 04:38:03 +00:00
s390/nospec: Push down alternative handling
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>
This commit is contained in:
parent
7f9d85998f
commit
47837a5c74
@ -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
|
||||
@ -46,6 +47,10 @@
|
||||
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>
|
||||
|
@ -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);
|
||||
|
@ -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__ */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user