xref: /linux/arch/s390/include/asm/runtime-const.h (revision c532de5a67a70f8533d495f8f2aaa9a0491c3ad0)
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 */
47 static inline void __runtime_fixup_32(u32 *p, unsigned int val)
48 {
49 	s390_kernel_write(p, &val, sizeof(val));
50 }
51 
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 */
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 
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