kernel_samsung_a53x/include/linux/samsung/jump_table_target.h
2024-06-15 16:02:09 -03:00

71 lines
1.6 KiB
C
Executable file

// SPDX-License-Identifier: GPL-2.0
/*
* COPYRIGHT(C) 2021 Samsung Electronics Co., Ltd. All Right Reserved.
*/
#ifndef __JUMP_TABLE_TARGET_H__
#define __JUMP_TABLE_TARGET_H__
#include <linux/uaccess.h>
/* FIXME: this implementaion should be placed on arch/arm64/include/asm. */
/* TODO: Performance degradation is suspected when this code is used. */
#if IS_ENABLED(CONFIG_ARM64)
static const __always_inline void *__arm64_jump_table_target(const void *va)
{
const uint32_t bti_c_code = 0xD503245F;
const uint32_t b_op_code = 0x5;
union b_instr {
struct {
uint32_t imm26:26;
uint32_t op:6;
};
struct {
uint32_t __imm26:25;
uint32_t __msb26:1;
uint32_t __op:6;
};
};
uint32_t bti_c_instr;
const void *b_instr_ptr;
union b_instr b_instr;
uintptr_t offset;
if (!IS_ENABLED(CONFIG_CFI_CLANG))
return va;
if (unlikely(get_kernel_nofault(bti_c_instr, va)))
return va;
if (unlikely(IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) &&
bti_c_instr != bti_c_code))
return va;
b_instr_ptr = va + (IS_ENABLED(CONFIG_ARM64_BTI_KERNEL) ? 0x4ULL : 0);
if (unlikely(get_kernel_nofault(b_instr, b_instr_ptr)))
return va;
if (unlikely(b_instr.op != b_op_code))
return va;
offset = (uintptr_t)b_instr.imm26;
if (b_instr.__msb26)
offset |= ~((1ULL << 26ULL) - 1ULL);
offset = offset << 2ULL;
return (void *)((uintptr_t)b_instr_ptr + offset);
}
#define __jump_table_target(__va) __arm64_jump_table_target(__va)
#endif
/* NOTE: architecture independent layer */
#ifdef __jump_table_target
#define jump_table_target(__va) __jump_table_target(__va)
#else
#define jump_table_target(__va) (__va)
#endif
#endif /* __JUMP_TABLE_TARGET_H__ */