xref: /kvm-unit-tests/lib/s390x/asm/facility.h (revision 1f08a91a41402b0e032ecce8ed1b5952cbfca0ea)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 /*
3  * Copyright (c) 2017 Red Hat Inc
4  *
5  * Authors:
6  *  David Hildenbrand <david@redhat.com>
7  */
8 #ifndef _ASMS390X_FACILITY_H_
9 #define _ASMS390X_FACILITY_H_
10 
11 #include <libcflat.h>
12 #include <asm/facility.h>
13 #include <asm/arch_def.h>
14 #include <bitops.h>
15 #include <sclp.h>
16 
17 #define NB_STFL_DOUBLEWORDS 32
18 extern uint64_t stfl_doublewords[];
19 
test_facility(int nr)20 static inline bool test_facility(int nr)
21 {
22 	return test_bit_inv(nr, stfl_doublewords);
23 }
24 
stfl(void)25 static inline void stfl(void)
26 {
27 	asm volatile("	stfl	0(0)\n" : : : "memory");
28 }
29 
stfle(uint64_t * fac,unsigned int nb_doublewords)30 static inline unsigned int stfle(uint64_t *fac, unsigned int nb_doublewords)
31 {
32 	register unsigned long r0 asm("0") = nb_doublewords - 1;
33 
34 	asm volatile("	.insn	s,0xb2b00000,0(%1)\n"
35 		     : "+d" (r0) : "a" (fac) : "memory", "cc");
36 	return r0 + 1;
37 }
38 
stfle_size(void)39 static inline unsigned long stfle_size(void)
40 {
41 	uint64_t dummy;
42 
43 	return stfle(&dummy, 1);
44 }
45 
setup_facilities(void)46 static inline void setup_facilities(void)
47 {
48 	stfl();
49 	memcpy(stfl_doublewords, &lowcore.stfl, sizeof(lowcore.stfl));
50 	if (test_facility(7))
51 		stfle(stfl_doublewords, NB_STFL_DOUBLEWORDS);
52 }
53 
54 enum supp_on_prot_facility {
55 	SOP_NONE,
56 	SOP_BASIC,
57 	SOP_ENHANCED_1,
58 	SOP_ENHANCED_2,
59 };
60 
get_supp_on_prot_facility(void)61 static inline enum supp_on_prot_facility get_supp_on_prot_facility(void)
62 {
63 	if (sclp_facilities.has_esop) {
64 		if (test_facility(131)) /* side-effect-access facility */
65 			return SOP_ENHANCED_2;
66 		else
67 			return SOP_ENHANCED_1;
68 	}
69 	if (sclp_facilities.has_sop)
70 		return SOP_BASIC;
71 	return SOP_NONE;
72 }
73 
74 #endif
75