1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright IBM Corp. 1999, 2009 4 * 5 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> 6 */ 7 8 #ifndef __ASM_FACILITY_H 9 #define __ASM_FACILITY_H 10 11 #include <asm/facility-defs.h> 12 13 #include <linux/minmax.h> 14 #include <linux/string.h> 15 #include <linux/types.h> 16 #include <linux/preempt.h> 17 18 #include <asm/lowcore.h> 19 20 #define MAX_FACILITY_BIT (sizeof(stfle_fac_list) * 8) 21 22 extern u64 stfle_fac_list[16]; 23 24 static inline void __set_facility(unsigned long nr, void *facilities) 25 { 26 unsigned char *ptr = (unsigned char *) facilities; 27 28 if (nr >= MAX_FACILITY_BIT) 29 return; 30 ptr[nr >> 3] |= 0x80 >> (nr & 7); 31 } 32 33 static inline void __clear_facility(unsigned long nr, void *facilities) 34 { 35 unsigned char *ptr = (unsigned char *) facilities; 36 37 if (nr >= MAX_FACILITY_BIT) 38 return; 39 ptr[nr >> 3] &= ~(0x80 >> (nr & 7)); 40 } 41 42 static inline int __test_facility(unsigned long nr, void *facilities) 43 { 44 unsigned char *ptr; 45 46 if (nr >= MAX_FACILITY_BIT) 47 return 0; 48 ptr = (unsigned char *) facilities + (nr >> 3); 49 return (*ptr & (0x80 >> (nr & 7))) != 0; 50 } 51 52 /* 53 * The test_facility function uses the bit ordering where the MSB is bit 0. 54 * That makes it easier to query facility bits with the bit number as 55 * documented in the Principles of Operation. 56 */ 57 static inline int test_facility(unsigned long nr) 58 { 59 unsigned long facilities_als[] = { FACILITIES_ALS }; 60 61 if (__builtin_constant_p(nr) && nr < sizeof(facilities_als) * 8) { 62 if (__test_facility(nr, &facilities_als)) { 63 if (!__is_defined(__DECOMPRESSOR)) 64 return 1; 65 } 66 } 67 return __test_facility(nr, &stfle_fac_list); 68 } 69 70 static inline unsigned long __stfle_asm(u64 *stfle_fac_list, int size) 71 { 72 unsigned long reg0 = size - 1; 73 74 asm volatile( 75 " lgr 0,%[reg0]\n" 76 " .insn s,0xb2b00000,%[list]\n" /* stfle */ 77 " lgr %[reg0],0\n" 78 : [reg0] "+&d" (reg0), [list] "+Q" (*stfle_fac_list) 79 : 80 : "memory", "cc", ""); 81 return reg0; 82 } 83 84 /** 85 * stfle - Store facility list extended 86 * @stfle_fac_list: array where facility list can be stored 87 * @size: size of passed in array in double words 88 */ 89 static inline void __stfle(u64 *stfle_fac_list, int size) 90 { 91 unsigned long nr; 92 u32 stfl_fac_list; 93 94 asm volatile( 95 " stfl 0(0)\n" 96 : "=m" (get_lowcore()->stfl_fac_list)); 97 stfl_fac_list = get_lowcore()->stfl_fac_list; 98 memcpy(stfle_fac_list, &stfl_fac_list, 4); 99 nr = 4; /* bytes stored by stfl */ 100 if (stfl_fac_list & 0x01000000) { 101 /* More facility bits available with stfle */ 102 nr = __stfle_asm(stfle_fac_list, size); 103 nr = min_t(unsigned long, (nr + 1) * 8, size * 8); 104 } 105 memset((char *) stfle_fac_list + nr, 0, size * 8 - nr); 106 } 107 108 static inline void stfle(u64 *stfle_fac_list, int size) 109 { 110 preempt_disable(); 111 __stfle(stfle_fac_list, size); 112 preempt_enable(); 113 } 114 115 /** 116 * stfle_size - Actual size of the facility list as specified by stfle 117 * (number of double words) 118 */ 119 unsigned int stfle_size(void); 120 121 #endif /* __ASM_FACILITY_H */ 122
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.