1 /* SPDX-License-Identifier: GPL-2.0 */
2 /*
3  * Copyright IBM Corp. 2024
4  */
5 
6 #ifndef __ASM_S390_MACHINE_H
7 #define __ASM_S390_MACHINE_H
8 
9 #include <linux/const.h>
10 
11 #define MFEATURE_LOWCORE	0
12 #define MFEATURE_PCI_MIO	1
13 #define MFEATURE_SCC		2
14 #define MFEATURE_TLB_GUEST	3
15 #define MFEATURE_TX		4
16 #define MFEATURE_ESOP		5
17 #define MFEATURE_DIAG9C		6
18 #define MFEATURE_VM		7
19 #define MFEATURE_KVM		8
20 #define MFEATURE_LPAR		9
21 
22 #ifndef __ASSEMBLY__
23 
24 #include <linux/bitops.h>
25 #include <asm/alternative.h>
26 
27 extern unsigned long machine_features[1];
28 
29 #define MAX_MFEATURE_BIT (sizeof(machine_features) * BITS_PER_BYTE)
30 
__set_machine_feature(unsigned int nr,unsigned long * mfeatures)31 static inline void __set_machine_feature(unsigned int nr, unsigned long *mfeatures)
32 {
33 	if (nr >= MAX_MFEATURE_BIT)
34 		return;
35 	__set_bit(nr, mfeatures);
36 }
37 
set_machine_feature(unsigned int nr)38 static inline void set_machine_feature(unsigned int nr)
39 {
40 	__set_machine_feature(nr, machine_features);
41 }
42 
__clear_machine_feature(unsigned int nr,unsigned long * mfeatures)43 static inline void __clear_machine_feature(unsigned int nr, unsigned long *mfeatures)
44 {
45 	if (nr >= MAX_MFEATURE_BIT)
46 		return;
47 	__clear_bit(nr, mfeatures);
48 }
49 
clear_machine_feature(unsigned int nr)50 static inline void clear_machine_feature(unsigned int nr)
51 {
52 	__clear_machine_feature(nr, machine_features);
53 }
54 
__test_machine_feature(unsigned int nr,unsigned long * mfeatures)55 static bool __test_machine_feature(unsigned int nr, unsigned long *mfeatures)
56 {
57 	if (nr >= MAX_MFEATURE_BIT)
58 		return false;
59 	return test_bit(nr, mfeatures);
60 }
61 
test_machine_feature(unsigned int nr)62 static bool test_machine_feature(unsigned int nr)
63 {
64 	return __test_machine_feature(nr, machine_features);
65 }
66 
__test_machine_feature_constant(unsigned int nr)67 static __always_inline bool __test_machine_feature_constant(unsigned int nr)
68 {
69 	asm goto(
70 		ALTERNATIVE("brcl 15,%l[l_no]", "brcl 0,0", ALT_FEATURE(%[nr]))
71 		:
72 		: [nr] "i" (nr)
73 		:
74 		: l_no);
75 	return true;
76 l_no:
77 	return false;
78 }
79 
80 #define DEFINE_MACHINE_HAS_FEATURE(name, feature)				\
81 static __always_inline bool machine_has_##name(void)				\
82 {										\
83 	if (!__is_defined(__DECOMPRESSOR) && __builtin_constant_p(feature))	\
84 		return __test_machine_feature_constant(feature);		\
85 	return test_machine_feature(feature);					\
86 }
87 
88 DEFINE_MACHINE_HAS_FEATURE(relocated_lowcore, MFEATURE_LOWCORE)
89 DEFINE_MACHINE_HAS_FEATURE(scc, MFEATURE_SCC)
90 DEFINE_MACHINE_HAS_FEATURE(tlb_guest, MFEATURE_TLB_GUEST)
91 DEFINE_MACHINE_HAS_FEATURE(tx, MFEATURE_TX)
92 DEFINE_MACHINE_HAS_FEATURE(esop, MFEATURE_ESOP)
93 DEFINE_MACHINE_HAS_FEATURE(diag9c, MFEATURE_DIAG9C)
94 DEFINE_MACHINE_HAS_FEATURE(vm, MFEATURE_VM)
95 DEFINE_MACHINE_HAS_FEATURE(kvm, MFEATURE_KVM)
96 DEFINE_MACHINE_HAS_FEATURE(lpar, MFEATURE_LPAR)
97 
98 #define machine_is_vm	machine_has_vm
99 #define machine_is_kvm	machine_has_kvm
100 #define machine_is_lpar	machine_has_lpar
101 
102 #endif /* __ASSEMBLY__ */
103 #endif /* __ASM_S390_MACHINE_H */
104