| .. | .. |
|---|
| 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, |
|---|