162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci#ifndef __ASM_ASM_EXTABLE_H 362306a36Sopenharmony_ci#define __ASM_ASM_EXTABLE_H 462306a36Sopenharmony_ci 562306a36Sopenharmony_ci#include <linux/bits.h> 662306a36Sopenharmony_ci#include <asm/gpr-num.h> 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#define EX_TYPE_NONE 0 962306a36Sopenharmony_ci#define EX_TYPE_BPF 1 1062306a36Sopenharmony_ci#define EX_TYPE_UACCESS_ERR_ZERO 2 1162306a36Sopenharmony_ci#define EX_TYPE_KACCESS_ERR_ZERO 3 1262306a36Sopenharmony_ci#define EX_TYPE_LOAD_UNALIGNED_ZEROPAD 4 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci/* Data fields for EX_TYPE_UACCESS_ERR_ZERO */ 1562306a36Sopenharmony_ci#define EX_DATA_REG_ERR_SHIFT 0 1662306a36Sopenharmony_ci#define EX_DATA_REG_ERR GENMASK(4, 0) 1762306a36Sopenharmony_ci#define EX_DATA_REG_ZERO_SHIFT 5 1862306a36Sopenharmony_ci#define EX_DATA_REG_ZERO GENMASK(9, 5) 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/* Data fields for EX_TYPE_LOAD_UNALIGNED_ZEROPAD */ 2162306a36Sopenharmony_ci#define EX_DATA_REG_DATA_SHIFT 0 2262306a36Sopenharmony_ci#define EX_DATA_REG_DATA GENMASK(4, 0) 2362306a36Sopenharmony_ci#define EX_DATA_REG_ADDR_SHIFT 5 2462306a36Sopenharmony_ci#define EX_DATA_REG_ADDR GENMASK(9, 5) 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#ifdef __ASSEMBLY__ 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \ 2962306a36Sopenharmony_ci .pushsection __ex_table, "a"; \ 3062306a36Sopenharmony_ci .align 2; \ 3162306a36Sopenharmony_ci .long ((insn) - .); \ 3262306a36Sopenharmony_ci .long ((fixup) - .); \ 3362306a36Sopenharmony_ci .short (type); \ 3462306a36Sopenharmony_ci .short (data); \ 3562306a36Sopenharmony_ci .popsection; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define EX_DATA_REG(reg, gpr) \ 3862306a36Sopenharmony_ci (.L__gpr_num_##gpr << EX_DATA_REG_##reg##_SHIFT) 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci#define _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, zero) \ 4162306a36Sopenharmony_ci __ASM_EXTABLE_RAW(insn, fixup, \ 4262306a36Sopenharmony_ci EX_TYPE_UACCESS_ERR_ZERO, \ 4362306a36Sopenharmony_ci ( \ 4462306a36Sopenharmony_ci EX_DATA_REG(ERR, err) | \ 4562306a36Sopenharmony_ci EX_DATA_REG(ZERO, zero) \ 4662306a36Sopenharmony_ci )) 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci#define _ASM_EXTABLE_UACCESS_ERR(insn, fixup, err) \ 4962306a36Sopenharmony_ci _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, wzr) 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#define _ASM_EXTABLE_UACCESS(insn, fixup) \ 5262306a36Sopenharmony_ci _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, wzr, wzr) 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci/* 5562306a36Sopenharmony_ci * Create an exception table entry for uaccess `insn`, which will branch to `fixup` 5662306a36Sopenharmony_ci * when an unhandled fault is taken. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ci .macro _asm_extable_uaccess, insn, fixup 5962306a36Sopenharmony_ci _ASM_EXTABLE_UACCESS(\insn, \fixup) 6062306a36Sopenharmony_ci .endm 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci/* 6362306a36Sopenharmony_ci * Create an exception table entry for `insn` if `fixup` is provided. Otherwise 6462306a36Sopenharmony_ci * do nothing. 6562306a36Sopenharmony_ci */ 6662306a36Sopenharmony_ci .macro _cond_uaccess_extable, insn, fixup 6762306a36Sopenharmony_ci .ifnc \fixup, 6862306a36Sopenharmony_ci _asm_extable_uaccess \insn, \fixup 6962306a36Sopenharmony_ci .endif 7062306a36Sopenharmony_ci .endm 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci#else /* __ASSEMBLY__ */ 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#include <linux/stringify.h> 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \ 7762306a36Sopenharmony_ci ".pushsection __ex_table, \"a\"\n" \ 7862306a36Sopenharmony_ci ".align 2\n" \ 7962306a36Sopenharmony_ci ".long ((" insn ") - .)\n" \ 8062306a36Sopenharmony_ci ".long ((" fixup ") - .)\n" \ 8162306a36Sopenharmony_ci ".short (" type ")\n" \ 8262306a36Sopenharmony_ci ".short (" data ")\n" \ 8362306a36Sopenharmony_ci ".popsection\n" 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define EX_DATA_REG(reg, gpr) \ 8662306a36Sopenharmony_ci "((.L__gpr_num_" #gpr ") << " __stringify(EX_DATA_REG_##reg##_SHIFT) ")" 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#define _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, zero) \ 8962306a36Sopenharmony_ci __DEFINE_ASM_GPR_NUMS \ 9062306a36Sopenharmony_ci __ASM_EXTABLE_RAW(#insn, #fixup, \ 9162306a36Sopenharmony_ci __stringify(EX_TYPE_UACCESS_ERR_ZERO), \ 9262306a36Sopenharmony_ci "(" \ 9362306a36Sopenharmony_ci EX_DATA_REG(ERR, err) " | " \ 9462306a36Sopenharmony_ci EX_DATA_REG(ZERO, zero) \ 9562306a36Sopenharmony_ci ")") 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define _ASM_EXTABLE_KACCESS_ERR_ZERO(insn, fixup, err, zero) \ 9862306a36Sopenharmony_ci __DEFINE_ASM_GPR_NUMS \ 9962306a36Sopenharmony_ci __ASM_EXTABLE_RAW(#insn, #fixup, \ 10062306a36Sopenharmony_ci __stringify(EX_TYPE_KACCESS_ERR_ZERO), \ 10162306a36Sopenharmony_ci "(" \ 10262306a36Sopenharmony_ci EX_DATA_REG(ERR, err) " | " \ 10362306a36Sopenharmony_ci EX_DATA_REG(ZERO, zero) \ 10462306a36Sopenharmony_ci ")") 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci#define _ASM_EXTABLE_UACCESS_ERR(insn, fixup, err) \ 10762306a36Sopenharmony_ci _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, wzr) 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ci#define _ASM_EXTABLE_UACCESS(insn, fixup) \ 11062306a36Sopenharmony_ci _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, wzr, wzr) 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci#define _ASM_EXTABLE_KACCESS_ERR(insn, fixup, err) \ 11362306a36Sopenharmony_ci _ASM_EXTABLE_KACCESS_ERR_ZERO(insn, fixup, err, wzr) 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci#define _ASM_EXTABLE_LOAD_UNALIGNED_ZEROPAD(insn, fixup, data, addr) \ 11662306a36Sopenharmony_ci __DEFINE_ASM_GPR_NUMS \ 11762306a36Sopenharmony_ci __ASM_EXTABLE_RAW(#insn, #fixup, \ 11862306a36Sopenharmony_ci __stringify(EX_TYPE_LOAD_UNALIGNED_ZEROPAD), \ 11962306a36Sopenharmony_ci "(" \ 12062306a36Sopenharmony_ci EX_DATA_REG(DATA, data) " | " \ 12162306a36Sopenharmony_ci EX_DATA_REG(ADDR, addr) \ 12262306a36Sopenharmony_ci ")") 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#endif /* __ASSEMBLY__ */ 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci#endif /* __ASM_ASM_EXTABLE_H */ 127