^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* SPDX-License-Identifier: GPL-2.0-or-later */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #ifndef _ASM_POWERPC_CODE_PATCHING_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #define _ASM_POWERPC_CODE_PATCHING_H
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright 2008, Michael Ellerman, IBM Corporation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <asm/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <asm/ppc-opcode.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/kallsyms.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <asm/asm-compat.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <asm/inst.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /* Flags for create_branch:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * "b" == create_branch(addr, target, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * "ba" == create_branch(addr, target, BRANCH_ABSOLUTE);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) * "bl" == create_branch(addr, target, BRANCH_SET_LINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) * "bla" == create_branch(addr, target, BRANCH_ABSOLUTE | BRANCH_SET_LINK);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define BRANCH_SET_LINK 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #define BRANCH_ABSOLUTE 0x2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) bool is_offset_in_branch_range(long offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) bool is_offset_in_cond_branch_range(long offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) int create_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) unsigned long target, int flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) unsigned long target, int flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) int patch_branch(struct ppc_inst *addr, unsigned long target, int flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) int raw_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) static inline unsigned long patch_site_addr(s32 *site)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return (unsigned long)site + *site;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) static inline int patch_instruction_site(s32 *site, struct ppc_inst instr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) return patch_instruction((struct ppc_inst *)patch_site_addr(site), instr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) static inline int patch_branch_site(s32 *site, unsigned long target, int flags)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) return patch_branch((struct ppc_inst *)patch_site_addr(site), target, flags);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) static inline int modify_instruction(unsigned int *addr, unsigned int clr,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) unsigned int set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return patch_instruction((struct ppc_inst *)addr, ppc_inst((*addr & ~clr) | set));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static inline int modify_instruction_site(s32 *site, unsigned int clr, unsigned int set)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) return modify_instruction((unsigned int *)patch_site_addr(site), clr, set);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) int instr_is_relative_branch(struct ppc_inst instr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int instr_is_relative_link_branch(struct ppc_inst instr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) int instr_is_branch_to_addr(const struct ppc_inst *instr, unsigned long addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) unsigned long branch_target(const struct ppc_inst *instr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) int translate_branch(struct ppc_inst *instr, const struct ppc_inst *dest,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) const struct ppc_inst *src);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) extern bool is_conditional_branch(struct ppc_inst instr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) #ifdef CONFIG_PPC_BOOK3E_64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) void __patch_exception(int exc, unsigned long addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) #define patch_exception(exc, name) do { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) extern unsigned int name; \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) __patch_exception((exc), (unsigned long)&name); \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) } while (0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) #define OP_RT_RA_MASK 0xffff0000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) #define LIS_R2 0x3c400000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) #define ADDIS_R2_R12 0x3c4c0000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) #define ADDI_R2_R2 0x38420000UL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) static inline unsigned long ppc_function_entry(void *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) #ifdef PPC64_ELF_ABI_v2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) u32 *insn = func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) * A PPC64 ABIv2 function may have a local and a global entry
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) * point. We need to use the local entry point when patching
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) * functions, so identify and step over the global entry point
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) * sequence.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) * The global entry point sequence is always of the form:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) * addis r2,r12,XXXX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) * addi r2,r2,XXXX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) * A linker optimisation may convert the addis to lis:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * lis r2,XXXX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * addi r2,r2,XXXX
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) if ((((*insn & OP_RT_RA_MASK) == ADDIS_R2_R12) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) ((*insn & OP_RT_RA_MASK) == LIS_R2)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) ((*(insn+1) & OP_RT_RA_MASK) == ADDI_R2_R2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return (unsigned long)(insn + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) return (unsigned long)func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) #elif defined(PPC64_ELF_ABI_v1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * On PPC64 ABIv1 the function pointer actually points to the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) * function's descriptor. The first entry in the descriptor is the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) * address of the function text.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return ((func_descr_t *)func)->entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) return (unsigned long)func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) static inline unsigned long ppc_global_function_entry(void *func)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) #ifdef PPC64_ELF_ABI_v2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* PPC64 ABIv2 the global entry point is at the address */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) return (unsigned long)func;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* All other cases there is no change vs ppc_function_entry() */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) return ppc_function_entry(func);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) * Wrapper around kallsyms_lookup() to return function entry address:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) * - For ABIv1, we lookup the dot variant.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) * - For ABIv2, we return the local entry point.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) static inline unsigned long ppc_kallsyms_lookup_name(const char *name)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) unsigned long addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) #ifdef PPC64_ELF_ABI_v1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /* check for dot variant */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) char dot_name[1 + KSYM_NAME_LEN];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) bool dot_appended = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) if (strnlen(name, KSYM_NAME_LEN) >= KSYM_NAME_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (name[0] != '.') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dot_name[0] = '.';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) dot_name[1] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) strlcat(dot_name, name, sizeof(dot_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) dot_appended = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) dot_name[0] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) strlcat(dot_name, name, sizeof(dot_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) addr = kallsyms_lookup_name(dot_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (!addr && dot_appended)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) /* Let's try the original non-dot symbol lookup */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) addr = kallsyms_lookup_name(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) #elif defined(PPC64_ELF_ABI_v2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) addr = kallsyms_lookup_name(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) if (addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) addr = ppc_function_entry((void *)addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) addr = kallsyms_lookup_name(name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) return addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) #ifdef CONFIG_PPC64
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) * Some instruction encodings commonly used in dynamic ftracing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * and function live patching.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) /* This must match the definition of STK_GOT in <asm/ppc_asm.h> */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) #ifdef PPC64_ELF_ABI_v2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) #define R2_STACK_OFFSET 24
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) #define R2_STACK_OFFSET 40
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #define PPC_INST_LD_TOC (PPC_INST_LD | ___PPC_RT(__REG_R2) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) ___PPC_RA(__REG_R1) | R2_STACK_OFFSET)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* usually preceded by a mflr r0 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) #define PPC_INST_STD_LR (PPC_INST_STD | ___PPC_RS(__REG_R0) | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ___PPC_RA(__REG_R1) | PPC_LR_STKOFF)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) #endif /* CONFIG_PPC64 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) #endif /* _ASM_POWERPC_CODE_PATCHING_H */