.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-or-later */ |
---|
1 | 2 | #ifndef _ASM_POWERPC_CODE_PATCHING_H |
---|
2 | 3 | #define _ASM_POWERPC_CODE_PATCHING_H |
---|
3 | 4 | |
---|
4 | 5 | /* |
---|
5 | 6 | * Copyright 2008, Michael Ellerman, IBM Corporation. |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or |
---|
8 | | - * modify it under the terms of the GNU General Public License |
---|
9 | | - * as published by the Free Software Foundation; either version |
---|
10 | | - * 2 of the License, or (at your option) any later version. |
---|
11 | 7 | */ |
---|
12 | 8 | |
---|
13 | 9 | #include <asm/types.h> |
---|
.. | .. |
---|
15 | 11 | #include <linux/string.h> |
---|
16 | 12 | #include <linux/kallsyms.h> |
---|
17 | 13 | #include <asm/asm-compat.h> |
---|
| 14 | +#include <asm/inst.h> |
---|
18 | 15 | |
---|
19 | 16 | /* Flags for create_branch: |
---|
20 | 17 | * "b" == create_branch(addr, target, 0); |
---|
.. | .. |
---|
27 | 24 | |
---|
28 | 25 | bool is_offset_in_branch_range(long offset); |
---|
29 | 26 | bool is_offset_in_cond_branch_range(long offset); |
---|
30 | | -unsigned int create_branch(const unsigned int *addr, |
---|
31 | | - unsigned long target, int flags); |
---|
32 | | -unsigned int create_cond_branch(const unsigned int *addr, |
---|
33 | | - unsigned long target, int flags); |
---|
34 | | -int patch_branch(unsigned int *addr, unsigned long target, int flags); |
---|
35 | | -int patch_instruction(unsigned int *addr, unsigned int instr); |
---|
36 | | -int raw_patch_instruction(unsigned int *addr, unsigned int instr); |
---|
37 | | -int patch_instruction_site(s32 *addr, unsigned int instr); |
---|
38 | | -int patch_branch_site(s32 *site, unsigned long target, int flags); |
---|
| 27 | +int create_branch(struct ppc_inst *instr, const struct ppc_inst *addr, |
---|
| 28 | + unsigned long target, int flags); |
---|
| 29 | +int create_cond_branch(struct ppc_inst *instr, const struct ppc_inst *addr, |
---|
| 30 | + unsigned long target, int flags); |
---|
| 31 | +int patch_branch(struct ppc_inst *addr, unsigned long target, int flags); |
---|
| 32 | +int patch_instruction(struct ppc_inst *addr, struct ppc_inst instr); |
---|
| 33 | +int raw_patch_instruction(struct ppc_inst *addr, struct ppc_inst instr); |
---|
39 | 34 | |
---|
40 | | -int instr_is_relative_branch(unsigned int instr); |
---|
41 | | -int instr_is_relative_link_branch(unsigned int instr); |
---|
42 | | -int instr_is_branch_to_addr(const unsigned int *instr, unsigned long addr); |
---|
43 | | -unsigned long branch_target(const unsigned int *instr); |
---|
44 | | -unsigned int translate_branch(const unsigned int *dest, |
---|
45 | | - const unsigned int *src); |
---|
46 | | -extern bool is_conditional_branch(unsigned int instr); |
---|
| 35 | +static inline unsigned long patch_site_addr(s32 *site) |
---|
| 36 | +{ |
---|
| 37 | + return (unsigned long)site + *site; |
---|
| 38 | +} |
---|
| 39 | + |
---|
| 40 | +static inline int patch_instruction_site(s32 *site, struct ppc_inst instr) |
---|
| 41 | +{ |
---|
| 42 | + return patch_instruction((struct ppc_inst *)patch_site_addr(site), instr); |
---|
| 43 | +} |
---|
| 44 | + |
---|
| 45 | +static inline int patch_branch_site(s32 *site, unsigned long target, int flags) |
---|
| 46 | +{ |
---|
| 47 | + return patch_branch((struct ppc_inst *)patch_site_addr(site), target, flags); |
---|
| 48 | +} |
---|
| 49 | + |
---|
| 50 | +static inline int modify_instruction(unsigned int *addr, unsigned int clr, |
---|
| 51 | + unsigned int set) |
---|
| 52 | +{ |
---|
| 53 | + return patch_instruction((struct ppc_inst *)addr, ppc_inst((*addr & ~clr) | set)); |
---|
| 54 | +} |
---|
| 55 | + |
---|
| 56 | +static inline int modify_instruction_site(s32 *site, unsigned int clr, unsigned int set) |
---|
| 57 | +{ |
---|
| 58 | + return modify_instruction((unsigned int *)patch_site_addr(site), clr, set); |
---|
| 59 | +} |
---|
| 60 | + |
---|
| 61 | +int instr_is_relative_branch(struct ppc_inst instr); |
---|
| 62 | +int instr_is_relative_link_branch(struct ppc_inst instr); |
---|
| 63 | +int instr_is_branch_to_addr(const struct ppc_inst *instr, unsigned long addr); |
---|
| 64 | +unsigned long branch_target(const struct ppc_inst *instr); |
---|
| 65 | +int translate_branch(struct ppc_inst *instr, const struct ppc_inst *dest, |
---|
| 66 | + const struct ppc_inst *src); |
---|
| 67 | +extern bool is_conditional_branch(struct ppc_inst instr); |
---|
47 | 68 | #ifdef CONFIG_PPC_BOOK3E_64 |
---|
48 | 69 | void __patch_exception(int exc, unsigned long addr); |
---|
49 | 70 | #define patch_exception(exc, name) do { \ |
---|