1  /* SPDX-License-Identifier: GPL-2.0 */
2  #ifndef _ASM_S390_RUNTIME_CONST_H
3  #define _ASM_S390_RUNTIME_CONST_H
4  
5  #include <linux/uaccess.h>
6  
7  #define runtime_const_ptr(sym)					\
8  ({								\
9  	typeof(sym) __ret;					\
10  								\
11  	asm_inline(						\
12  		"0:	iihf	%[__ret],%[c1]\n"		\
13  		"	iilf	%[__ret],%[c2]\n"		\
14  		".pushsection runtime_ptr_" #sym ",\"a\"\n"	\
15  		".long 0b - .\n"				\
16  		".popsection"					\
17  		: [__ret] "=d" (__ret)				\
18  		: [c1] "i" (0x01234567UL),			\
19  		  [c2] "i" (0x89abcdefUL));			\
20  	__ret;							\
21  })
22  
23  #define runtime_const_shift_right_32(val, sym)			\
24  ({								\
25  	unsigned int __ret = (val);				\
26  								\
27  	asm_inline(						\
28  		"0:	srl	%[__ret],12\n"			\
29  		".pushsection runtime_shift_" #sym ",\"a\"\n"	\
30  		".long 0b - .\n"				\
31  		".popsection"					\
32  		: [__ret] "+d" (__ret));			\
33  	__ret;							\
34  })
35  
36  #define runtime_const_init(type, sym) do {			\
37  	extern s32 __start_runtime_##type##_##sym[];		\
38  	extern s32 __stop_runtime_##type##_##sym[];		\
39  								\
40  	runtime_const_fixup(__runtime_fixup_##type,		\
41  			    (unsigned long)(sym),		\
42  			    __start_runtime_##type##_##sym,	\
43  			    __stop_runtime_##type##_##sym);	\
44  } while (0)
45  
46  /* 32-bit immediate for iihf and iilf in bits in I2 field */
__runtime_fixup_32(u32 * p,unsigned int val)47  static inline void __runtime_fixup_32(u32 *p, unsigned int val)
48  {
49  	s390_kernel_write(p, &val, sizeof(val));
50  }
51  
__runtime_fixup_ptr(void * where,unsigned long val)52  static inline void __runtime_fixup_ptr(void *where, unsigned long val)
53  {
54  	__runtime_fixup_32(where + 2, val >> 32);
55  	__runtime_fixup_32(where + 8, val);
56  }
57  
58  /* Immediate value is lower 12 bits of D2 field of srl */
__runtime_fixup_shift(void * where,unsigned long val)59  static inline void __runtime_fixup_shift(void *where, unsigned long val)
60  {
61  	u32 insn = *(u32 *)where;
62  
63  	insn &= 0xfffff000;
64  	insn |= (val & 63);
65  	s390_kernel_write(where, &insn, sizeof(insn));
66  }
67  
runtime_const_fixup(void (* fn)(void *,unsigned long),unsigned long val,s32 * start,s32 * end)68  static inline void runtime_const_fixup(void (*fn)(void *, unsigned long),
69  				       unsigned long val, s32 *start, s32 *end)
70  {
71  	while (start < end) {
72  		fn(*start + (void *)start, val);
73  		start++;
74  	}
75  }
76  
77  #endif /* _ASM_S390_RUNTIME_CONST_H */
78