mirror of
https://github.com/torvalds/linux.git
synced 2026-03-09 18:16:36 +01:00
Similar as commit 284922f4c5 ("x86: uaccess: don't use runtime-const
rewriting in modules") does, make arm64's runtime const not usable by
modules too, to "make sure this doesn't get forgotten the next time
somebody wants to do runtime constant optimizations". The reason is
well explained in the above commit: "The runtime-const infrastructure
was never designed to handle the modular case, because the constant
fixup is only done at boot time for core kernel code."
Signed-off-by: Jisheng Zhang <jszhang@kernel.org>
Signed-off-by: Will Deacon <will@kernel.org>
92 lines
2.4 KiB
C
92 lines
2.4 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _ASM_RUNTIME_CONST_H
|
|
#define _ASM_RUNTIME_CONST_H
|
|
|
|
#ifdef MODULE
|
|
#error "Cannot use runtime-const infrastructure from modules"
|
|
#endif
|
|
|
|
#include <asm/cacheflush.h>
|
|
|
|
/* Sigh. You can still run arm64 in BE mode */
|
|
#include <asm/byteorder.h>
|
|
|
|
#define runtime_const_ptr(sym) ({ \
|
|
typeof(sym) __ret; \
|
|
asm_inline("1:\t" \
|
|
"movz %0, #0xcdef\n\t" \
|
|
"movk %0, #0x89ab, lsl #16\n\t" \
|
|
"movk %0, #0x4567, lsl #32\n\t" \
|
|
"movk %0, #0x0123, lsl #48\n\t" \
|
|
".pushsection runtime_ptr_" #sym ",\"a\"\n\t" \
|
|
".long 1b - .\n\t" \
|
|
".popsection" \
|
|
:"=r" (__ret)); \
|
|
__ret; })
|
|
|
|
#define runtime_const_shift_right_32(val, sym) ({ \
|
|
unsigned long __ret; \
|
|
asm_inline("1:\t" \
|
|
"lsr %w0,%w1,#12\n\t" \
|
|
".pushsection runtime_shift_" #sym ",\"a\"\n\t" \
|
|
".long 1b - .\n\t" \
|
|
".popsection" \
|
|
:"=r" (__ret) \
|
|
:"r" (0u+(val))); \
|
|
__ret; })
|
|
|
|
#define runtime_const_init(type, sym) do { \
|
|
extern s32 __start_runtime_##type##_##sym[]; \
|
|
extern s32 __stop_runtime_##type##_##sym[]; \
|
|
runtime_const_fixup(__runtime_fixup_##type, \
|
|
(unsigned long)(sym), \
|
|
__start_runtime_##type##_##sym, \
|
|
__stop_runtime_##type##_##sym); \
|
|
} while (0)
|
|
|
|
/* 16-bit immediate for wide move (movz and movk) in bits 5..20 */
|
|
static inline void __runtime_fixup_16(__le32 *p, unsigned int val)
|
|
{
|
|
u32 insn = le32_to_cpu(*p);
|
|
insn &= 0xffe0001f;
|
|
insn |= (val & 0xffff) << 5;
|
|
*p = cpu_to_le32(insn);
|
|
}
|
|
|
|
static inline void __runtime_fixup_caches(void *where, unsigned int insns)
|
|
{
|
|
unsigned long va = (unsigned long)where;
|
|
caches_clean_inval_pou(va, va + 4*insns);
|
|
}
|
|
|
|
static inline void __runtime_fixup_ptr(void *where, unsigned long val)
|
|
{
|
|
__le32 *p = lm_alias(where);
|
|
__runtime_fixup_16(p, val);
|
|
__runtime_fixup_16(p+1, val >> 16);
|
|
__runtime_fixup_16(p+2, val >> 32);
|
|
__runtime_fixup_16(p+3, val >> 48);
|
|
__runtime_fixup_caches(where, 4);
|
|
}
|
|
|
|
/* Immediate value is 6 bits starting at bit #16 */
|
|
static inline void __runtime_fixup_shift(void *where, unsigned long val)
|
|
{
|
|
__le32 *p = lm_alias(where);
|
|
u32 insn = le32_to_cpu(*p);
|
|
insn &= 0xffc0ffff;
|
|
insn |= (val & 63) << 16;
|
|
*p = cpu_to_le32(insn);
|
|
__runtime_fixup_caches(where, 1);
|
|
}
|
|
|
|
static inline void runtime_const_fixup(void (*fn)(void *, unsigned long),
|
|
unsigned long val, s32 *start, s32 *end)
|
|
{
|
|
while (start < end) {
|
|
fn(*start + (void *)start, val);
|
|
start++;
|
|
}
|
|
}
|
|
|
|
#endif
|