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