mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-08 14:02:37 -04:00
s390: Static branches for machine features infrastructure
Provide infrastructure which allows to generate machine_has_<feature>() functions, which are replacing the existing MACHINE_HAS_<feature> macros. Such function usages generate a static branch depending on <feature>. The static branch is patched using an alternative. Each <feature> correlates with a bit set in the machine_features bit field. If the corresponding bit is set, the branch will be patched. In order to have any effect on branch patching feature bits must be set with set_machine_features() in the decompressor before alternatives patching of the kernel image. It is possible to use clear_machine_feature() and test_machine_feature() for machine features which cannot be completely detected within the decompressor, e.g. if common code command line parameters allow to enable or disable certain features. In such cases test_machine_feature() instead of machine_has_feature() must be used within the kernel. This results in a runtime check and not a static branch. Reviewed-by: Vasily Gorbik <gor@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:
committed by
Vasily Gorbik
parent
949b73c990
commit
b7e81efc24
@@ -32,8 +32,9 @@
|
||||
#define ALT_CTX_ALL (ALT_CTX_EARLY | ALT_CTX_LATE)
|
||||
|
||||
#define ALT_TYPE_FACILITY 0
|
||||
#define ALT_TYPE_SPEC 1
|
||||
#define ALT_TYPE_LOWCORE 2
|
||||
#define ALT_TYPE_FEATURE 1
|
||||
#define ALT_TYPE_SPEC 2
|
||||
#define ALT_TYPE_LOWCORE 3
|
||||
|
||||
#define ALT_DATA_SHIFT 0
|
||||
#define ALT_TYPE_SHIFT 20
|
||||
@@ -43,6 +44,10 @@
|
||||
ALT_TYPE_FACILITY << ALT_TYPE_SHIFT | \
|
||||
(facility) << ALT_DATA_SHIFT)
|
||||
|
||||
#define ALT_FEATURE(feature) (ALT_CTX_EARLY << ALT_CTX_SHIFT | \
|
||||
ALT_TYPE_FEATURE << ALT_TYPE_SHIFT | \
|
||||
(feature) << ALT_DATA_SHIFT)
|
||||
|
||||
#define ALT_SPEC(facility) (ALT_CTX_LATE << ALT_CTX_SHIFT | \
|
||||
ALT_TYPE_SPEC << ALT_TYPE_SHIFT | \
|
||||
(facility) << ALT_DATA_SHIFT)
|
||||
|
||||
76
arch/s390/include/asm/machine.h
Normal file
76
arch/s390/include/asm/machine.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright IBM Corp. 2024
|
||||
*/
|
||||
|
||||
#ifndef __ASM_S390_MACHINE_H
|
||||
#define __ASM_S390_MACHINE_H
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <asm/alternative.h>
|
||||
|
||||
extern unsigned long machine_features[1];
|
||||
|
||||
#define MAX_MFEATURE_BIT (sizeof(machine_features) * BITS_PER_BYTE)
|
||||
|
||||
static inline void __set_machine_feature(unsigned int nr, unsigned long *mfeatures)
|
||||
{
|
||||
if (nr >= MAX_MFEATURE_BIT)
|
||||
return;
|
||||
__set_bit(nr, mfeatures);
|
||||
}
|
||||
|
||||
static inline void set_machine_feature(unsigned int nr)
|
||||
{
|
||||
__set_machine_feature(nr, machine_features);
|
||||
}
|
||||
|
||||
static inline void __clear_machine_feature(unsigned int nr, unsigned long *mfeatures)
|
||||
{
|
||||
if (nr >= MAX_MFEATURE_BIT)
|
||||
return;
|
||||
__clear_bit(nr, mfeatures);
|
||||
}
|
||||
|
||||
static inline void clear_machine_feature(unsigned int nr)
|
||||
{
|
||||
__clear_machine_feature(nr, machine_features);
|
||||
}
|
||||
|
||||
static bool __test_machine_feature(unsigned int nr, unsigned long *mfeatures)
|
||||
{
|
||||
if (nr >= MAX_MFEATURE_BIT)
|
||||
return false;
|
||||
return test_bit(nr, mfeatures);
|
||||
}
|
||||
|
||||
static bool test_machine_feature(unsigned int nr)
|
||||
{
|
||||
return __test_machine_feature(nr, machine_features);
|
||||
}
|
||||
|
||||
static __always_inline bool __test_machine_feature_constant(unsigned int nr)
|
||||
{
|
||||
asm goto(
|
||||
ALTERNATIVE("brcl 15,%l[l_no]", "brcl 0,0", ALT_FEATURE(%[nr]))
|
||||
:
|
||||
: [nr] "i" (nr)
|
||||
:
|
||||
: l_no);
|
||||
return true;
|
||||
l_no:
|
||||
return false;
|
||||
}
|
||||
|
||||
#define DEFINE_MACHINE_HAS_FEATURE(name, feature) \
|
||||
static __always_inline bool machine_has_##name(void) \
|
||||
{ \
|
||||
if (!__is_defined(__DECOMPRESSOR) && __builtin_constant_p(feature)) \
|
||||
return __test_machine_feature_constant(feature); \
|
||||
return test_machine_feature(feature); \
|
||||
}
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ASM_S390_MACHINE_H */
|
||||
@@ -5,6 +5,10 @@
|
||||
#include <asm/abs_lowcore.h>
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/facility.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/machine.h>
|
||||
|
||||
unsigned long __bootdata_preserved(machine_features[1]);
|
||||
|
||||
void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsigned int ctx)
|
||||
{
|
||||
@@ -23,6 +27,9 @@ void __apply_alternatives(struct alt_instr *start, struct alt_instr *end, unsign
|
||||
case ALT_TYPE_FACILITY:
|
||||
replace = test_facility(a->data);
|
||||
break;
|
||||
case ALT_TYPE_FEATURE:
|
||||
replace = test_machine_feature(a->data);
|
||||
break;
|
||||
case ALT_TYPE_SPEC:
|
||||
replace = nobp_enabled();
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user