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