summaryrefslogtreecommitdiffstats
path: root/arch/s390/include/asm/machine.h
blob: 54478caa52378b6a04c4baaed330330a37d03691 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Copyright IBM Corp. 2024
 */

#ifndef __ASM_S390_MACHINE_H
#define __ASM_S390_MACHINE_H

#include <linux/const.h>

#define MFEATURE_LOWCORE	0
#define MFEATURE_PCI_MIO	1
#define MFEATURE_SCC		2
#define MFEATURE_TLB_GUEST	3
#define MFEATURE_TX		4
#define MFEATURE_ESOP		5
#define MFEATURE_DIAG9C		6
#define MFEATURE_VM		7
#define MFEATURE_KVM		8
#define MFEATURE_LPAR		9

#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);					\
}

DEFINE_MACHINE_HAS_FEATURE(relocated_lowcore, MFEATURE_LOWCORE)
DEFINE_MACHINE_HAS_FEATURE(scc, MFEATURE_SCC)
DEFINE_MACHINE_HAS_FEATURE(tlb_guest, MFEATURE_TLB_GUEST)
DEFINE_MACHINE_HAS_FEATURE(tx, MFEATURE_TX)
DEFINE_MACHINE_HAS_FEATURE(esop, MFEATURE_ESOP)
DEFINE_MACHINE_HAS_FEATURE(diag9c, MFEATURE_DIAG9C)
DEFINE_MACHINE_HAS_FEATURE(vm, MFEATURE_VM)
DEFINE_MACHINE_HAS_FEATURE(kvm, MFEATURE_KVM)
DEFINE_MACHINE_HAS_FEATURE(lpar, MFEATURE_LPAR)

#define machine_is_vm	machine_has_vm
#define machine_is_kvm	machine_has_kvm
#define machine_is_lpar	machine_has_lpar

#endif /* __ASSEMBLY__ */
#endif /* __ASM_S390_MACHINE_H */