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