xref: /linux/arch/s390/include/asm/runtime-const.h (revision dfa35434d7f20142fedd7120277b1044a0a2bb64)
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_mask_32(val, sym)				\
37 ({								\
38 	unsigned int __ret = (val);				\
39 								\
40 	asm_inline(						\
41 		"0:	nilf	%[__ret],12\n"			\
42 		".pushsection runtime_mask_" #sym ",\"a\"\n"	\
43 		".long 0b - .\n"				\
44 		".popsection"					\
45 		: [__ret] "+d" (__ret)				\
46 		: : "cc");					\
47 	__ret;							\
48 })
49 
50 #define runtime_const_init(type, sym) do {			\
51 	extern s32 __start_runtime_##type##_##sym[];		\
52 	extern s32 __stop_runtime_##type##_##sym[];		\
53 								\
54 	runtime_const_fixup(__runtime_fixup_##type,		\
55 			    (unsigned long)(sym),		\
56 			    __start_runtime_##type##_##sym,	\
57 			    __stop_runtime_##type##_##sym);	\
58 } while (0)
59 
60 static inline void __runtime_fixup_32(u32 *p, unsigned int val)
61 {
62 	s390_kernel_write(p, &val, sizeof(val));
63 }
64 
65 /* 32-bit immediate for iihf and iilf in bits in I2 field */
66 static inline void __runtime_fixup_ptr(void *where, unsigned long val)
67 {
68 	__runtime_fixup_32(where + 2, val >> 32);
69 	__runtime_fixup_32(where + 8, val);
70 }
71 
72 /* Immediate value is lower 12 bits of D2 field of srl */
73 static inline void __runtime_fixup_shift(void *where, unsigned long val)
74 {
75 	u32 insn = *(u32 *)where;
76 
77 	insn &= 0xfffff000;
78 	insn |= (val & 63);
79 	s390_kernel_write(where, &insn, sizeof(insn));
80 }
81 
82 /* 32-bit immediate for nilf in bits in I2 field */
83 static inline void __runtime_fixup_mask(void *where, unsigned long val)
84 {
85 	__runtime_fixup_32(where + 2, val);
86 }
87 
88 static inline void runtime_const_fixup(void (*fn)(void *, unsigned long),
89 				       unsigned long val, s32 *start, s32 *end)
90 {
91 	while (start < end) {
92 		fn(*start + (void *)start, val);
93 		start++;
94 	}
95 }
96 
97 #endif /* _ASM_S390_RUNTIME_CONST_H */
98