.. | .. |
---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0-only */ |
---|
1 | 2 | /* |
---|
2 | 3 | * Copyright (C) 2013 Huawei Ltd. |
---|
3 | 4 | * Author: Jiang Liu <liuj97@gmail.com> |
---|
4 | 5 | * |
---|
5 | 6 | * Copyright (C) 2014 Zi Shen Lim <zlim.lnx@gmail.com> |
---|
6 | | - * |
---|
7 | | - * This program is free software; you can redistribute it and/or modify |
---|
8 | | - * it under the terms of the GNU General Public License version 2 as |
---|
9 | | - * published by the Free Software Foundation. |
---|
10 | | - * |
---|
11 | | - * This program is distributed in the hope that it will be useful, |
---|
12 | | - * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
13 | | - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
14 | | - * GNU General Public License for more details. |
---|
15 | | - * |
---|
16 | | - * You should have received a copy of the GNU General Public License |
---|
17 | | - * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
18 | 7 | */ |
---|
19 | 8 | #ifndef __ASM_INSN_H |
---|
20 | 9 | #define __ASM_INSN_H |
---|
| 10 | +#include <linux/build_bug.h> |
---|
21 | 11 | #include <linux/types.h> |
---|
22 | 12 | |
---|
23 | | -/* A64 instructions are always 32 bits. */ |
---|
24 | | -#define AARCH64_INSN_SIZE 4 |
---|
| 13 | +#include <asm/alternative.h> |
---|
25 | 14 | |
---|
26 | 15 | #ifndef __ASSEMBLY__ |
---|
27 | 16 | /* |
---|
.. | .. |
---|
49 | 38 | * system instructions */ |
---|
50 | 39 | }; |
---|
51 | 40 | |
---|
52 | | -enum aarch64_insn_hint_op { |
---|
| 41 | +enum aarch64_insn_hint_cr_op { |
---|
53 | 42 | AARCH64_INSN_HINT_NOP = 0x0 << 5, |
---|
54 | 43 | AARCH64_INSN_HINT_YIELD = 0x1 << 5, |
---|
55 | 44 | AARCH64_INSN_HINT_WFE = 0x2 << 5, |
---|
56 | 45 | AARCH64_INSN_HINT_WFI = 0x3 << 5, |
---|
57 | 46 | AARCH64_INSN_HINT_SEV = 0x4 << 5, |
---|
58 | 47 | AARCH64_INSN_HINT_SEVL = 0x5 << 5, |
---|
| 48 | + |
---|
| 49 | + AARCH64_INSN_HINT_XPACLRI = 0x07 << 5, |
---|
| 50 | + AARCH64_INSN_HINT_PACIA_1716 = 0x08 << 5, |
---|
| 51 | + AARCH64_INSN_HINT_PACIB_1716 = 0x0A << 5, |
---|
| 52 | + AARCH64_INSN_HINT_AUTIA_1716 = 0x0C << 5, |
---|
| 53 | + AARCH64_INSN_HINT_AUTIB_1716 = 0x0E << 5, |
---|
| 54 | + AARCH64_INSN_HINT_PACIAZ = 0x18 << 5, |
---|
| 55 | + AARCH64_INSN_HINT_PACIASP = 0x19 << 5, |
---|
| 56 | + AARCH64_INSN_HINT_PACIBZ = 0x1A << 5, |
---|
| 57 | + AARCH64_INSN_HINT_PACIBSP = 0x1B << 5, |
---|
| 58 | + AARCH64_INSN_HINT_AUTIAZ = 0x1C << 5, |
---|
| 59 | + AARCH64_INSN_HINT_AUTIASP = 0x1D << 5, |
---|
| 60 | + AARCH64_INSN_HINT_AUTIBZ = 0x1E << 5, |
---|
| 61 | + AARCH64_INSN_HINT_AUTIBSP = 0x1F << 5, |
---|
| 62 | + |
---|
| 63 | + AARCH64_INSN_HINT_ESB = 0x10 << 5, |
---|
| 64 | + AARCH64_INSN_HINT_PSB = 0x11 << 5, |
---|
| 65 | + AARCH64_INSN_HINT_TSB = 0x12 << 5, |
---|
| 66 | + AARCH64_INSN_HINT_CSDB = 0x14 << 5, |
---|
| 67 | + AARCH64_INSN_HINT_CLEARBHB = 0x16 << 5, |
---|
| 68 | + |
---|
| 69 | + AARCH64_INSN_HINT_BTI = 0x20 << 5, |
---|
| 70 | + AARCH64_INSN_HINT_BTIC = 0x22 << 5, |
---|
| 71 | + AARCH64_INSN_HINT_BTIJ = 0x24 << 5, |
---|
| 72 | + AARCH64_INSN_HINT_BTIJC = 0x26 << 5, |
---|
59 | 73 | }; |
---|
60 | 74 | |
---|
61 | 75 | enum aarch64_insn_imm_type { |
---|
.. | .. |
---|
261 | 275 | AARCH64_INSN_PRFM_POLICY_STRM, |
---|
262 | 276 | }; |
---|
263 | 277 | |
---|
264 | | -#define __AARCH64_INSN_FUNCS(abbr, mask, val) \ |
---|
265 | | -static __always_inline bool aarch64_insn_is_##abbr(u32 code) \ |
---|
266 | | -{ return (code & (mask)) == (val); } \ |
---|
267 | | -static __always_inline u32 aarch64_insn_get_##abbr##_value(void) \ |
---|
268 | | -{ return (val); } |
---|
| 278 | +enum aarch64_insn_adr_type { |
---|
| 279 | + AARCH64_INSN_ADR_TYPE_ADRP, |
---|
| 280 | + AARCH64_INSN_ADR_TYPE_ADR, |
---|
| 281 | +}; |
---|
| 282 | + |
---|
| 283 | +#define __AARCH64_INSN_FUNCS(abbr, mask, val) \ |
---|
| 284 | +static __always_inline bool aarch64_insn_is_##abbr(u32 code) \ |
---|
| 285 | +{ \ |
---|
| 286 | + BUILD_BUG_ON(~(mask) & (val)); \ |
---|
| 287 | + return (code & (mask)) == (val); \ |
---|
| 288 | +} \ |
---|
| 289 | +static __always_inline u32 aarch64_insn_get_##abbr##_value(void) \ |
---|
| 290 | +{ \ |
---|
| 291 | + return (val); \ |
---|
| 292 | +} |
---|
269 | 293 | |
---|
270 | 294 | __AARCH64_INSN_FUNCS(adr, 0x9F000000, 0x10000000) |
---|
271 | 295 | __AARCH64_INSN_FUNCS(adrp, 0x9F000000, 0x90000000) |
---|
.. | .. |
---|
335 | 359 | __AARCH64_INSN_FUNCS(exception, 0xFF000000, 0xD4000000) |
---|
336 | 360 | __AARCH64_INSN_FUNCS(hint, 0xFFFFF01F, 0xD503201F) |
---|
337 | 361 | __AARCH64_INSN_FUNCS(br, 0xFFFFFC1F, 0xD61F0000) |
---|
| 362 | +__AARCH64_INSN_FUNCS(br_auth, 0xFEFFF800, 0xD61F0800) |
---|
338 | 363 | __AARCH64_INSN_FUNCS(blr, 0xFFFFFC1F, 0xD63F0000) |
---|
| 364 | +__AARCH64_INSN_FUNCS(blr_auth, 0xFEFFF800, 0xD63F0800) |
---|
339 | 365 | __AARCH64_INSN_FUNCS(ret, 0xFFFFFC1F, 0xD65F0000) |
---|
| 366 | +__AARCH64_INSN_FUNCS(ret_auth, 0xFFFFFBFF, 0xD65F0BFF) |
---|
340 | 367 | __AARCH64_INSN_FUNCS(eret, 0xFFFFFFFF, 0xD69F03E0) |
---|
| 368 | +__AARCH64_INSN_FUNCS(eret_auth, 0xFFFFFBFF, 0xD69F0BFF) |
---|
341 | 369 | __AARCH64_INSN_FUNCS(mrs, 0xFFF00000, 0xD5300000) |
---|
342 | 370 | __AARCH64_INSN_FUNCS(msr_imm, 0xFFF8F01F, 0xD500401F) |
---|
343 | 371 | __AARCH64_INSN_FUNCS(msr_reg, 0xFFF00000, 0xD5100000) |
---|
344 | 372 | |
---|
345 | 373 | #undef __AARCH64_INSN_FUNCS |
---|
346 | 374 | |
---|
347 | | -bool aarch64_insn_is_nop(u32 insn); |
---|
| 375 | +bool aarch64_insn_is_steppable_hint(u32 insn); |
---|
348 | 376 | bool aarch64_insn_is_branch_imm(u32 insn); |
---|
349 | 377 | |
---|
350 | 378 | static inline bool aarch64_insn_is_adr_adrp(u32 insn) |
---|
.. | .. |
---|
370 | 398 | enum aarch64_insn_branch_type type); |
---|
371 | 399 | u32 aarch64_insn_gen_cond_branch_imm(unsigned long pc, unsigned long addr, |
---|
372 | 400 | enum aarch64_insn_condition cond); |
---|
373 | | -u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_op op); |
---|
| 401 | +u32 aarch64_insn_gen_hint(enum aarch64_insn_hint_cr_op op); |
---|
374 | 402 | u32 aarch64_insn_gen_nop(void); |
---|
375 | 403 | u32 aarch64_insn_gen_branch_reg(enum aarch64_insn_register reg, |
---|
376 | 404 | enum aarch64_insn_branch_type type); |
---|
.. | .. |
---|
401 | 429 | enum aarch64_insn_register src, |
---|
402 | 430 | int imm, enum aarch64_insn_variant variant, |
---|
403 | 431 | enum aarch64_insn_adsb_type type); |
---|
| 432 | +u32 aarch64_insn_gen_adr(unsigned long pc, unsigned long addr, |
---|
| 433 | + enum aarch64_insn_register reg, |
---|
| 434 | + enum aarch64_insn_adr_type type); |
---|
404 | 435 | u32 aarch64_insn_gen_bitfield(enum aarch64_insn_register dst, |
---|
405 | 436 | enum aarch64_insn_register src, |
---|
406 | 437 | int immr, int imms, |
---|
.. | .. |
---|
437 | 468 | int shift, |
---|
438 | 469 | enum aarch64_insn_variant variant, |
---|
439 | 470 | enum aarch64_insn_logic_type type); |
---|
| 471 | +u32 aarch64_insn_gen_move_reg(enum aarch64_insn_register dst, |
---|
| 472 | + enum aarch64_insn_register src, |
---|
| 473 | + enum aarch64_insn_variant variant); |
---|
440 | 474 | u32 aarch64_insn_gen_logical_immediate(enum aarch64_insn_logic_type type, |
---|
441 | 475 | enum aarch64_insn_variant variant, |
---|
442 | 476 | enum aarch64_insn_register Rn, |
---|