In order to remove further .fixup usage, extend the extable infrastructure to take additional information from the extable entry sites. Specifically add _ASM_EXTABLE_TYPE_REG() and EX_TYPE_IMM_REG that extend the existing _ASM_EXTABLE_TYPE() by taking an additional register argument and encoding that and an s16 immediate into the existing s32 type field. This limits the actual types to the first byte, 255 seem plenty. Also add a few flags into the type word, specifically CLEAR_AX and CLEAR_DX which clear the return and extended return register. Notes: - due to the % in our register names it's hard to make it more generally usable as arm64 did. - the s16 is far larger than used in these patches, future extentions can easily shrink this to get more bits. - without the bitfield fix this will not compile, because: 0xFF > -1 and we can't even extract the TYPE field. [nathanchance: Build fix for clang-lto builds: https://lkml.kernel.org/r/20211210234953.3420108-1-nathan@kernel.org ] Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com> Reviewed-by: Nick Desaulniers <ndesaulniers@google.com> Tested-by: Nick Desaulniers <ndesaulniers@google.com> Link: https://lore.kernel.org/r/20211110101325.303890153@infradead.org
57 lines
1.8 KiB
C
57 lines
1.8 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _ASM_X86_EXTABLE_H
|
|
#define _ASM_X86_EXTABLE_H
|
|
|
|
#include <asm/extable_fixup_types.h>
|
|
|
|
/*
|
|
* The exception table consists of two addresses relative to the
|
|
* exception table entry itself and a type selector field.
|
|
*
|
|
* The first address is of an instruction that is allowed to fault, the
|
|
* second is the target at which the program should continue.
|
|
*
|
|
* The type entry is used by fixup_exception() to select the handler to
|
|
* deal with the fault caused by the instruction in the first field.
|
|
*
|
|
* All the routines below use bits of fixup code that are out of line
|
|
* with the main instruction path. This means when everything is well,
|
|
* we don't even have to jump over them. Further, they do not intrude
|
|
* on our cache or tlb entries.
|
|
*/
|
|
|
|
struct exception_table_entry {
|
|
int insn, fixup, data;
|
|
};
|
|
struct pt_regs;
|
|
|
|
#define ARCH_HAS_RELATIVE_EXTABLE
|
|
|
|
#define swap_ex_entry_fixup(a, b, tmp, delta) \
|
|
do { \
|
|
(a)->fixup = (b)->fixup + (delta); \
|
|
(b)->fixup = (tmp).fixup - (delta); \
|
|
(a)->data = (b)->data; \
|
|
(b)->data = (tmp).data; \
|
|
} while (0)
|
|
|
|
extern int fixup_exception(struct pt_regs *regs, int trapnr,
|
|
unsigned long error_code, unsigned long fault_addr);
|
|
extern int fixup_bug(struct pt_regs *regs, int trapnr);
|
|
extern int ex_get_fixup_type(unsigned long ip);
|
|
extern void early_fixup_exception(struct pt_regs *regs, int trapnr);
|
|
|
|
#ifdef CONFIG_X86_MCE
|
|
extern void ex_handler_msr_mce(struct pt_regs *regs, bool wrmsr);
|
|
#else
|
|
static inline void ex_handler_msr_mce(struct pt_regs *regs, bool wrmsr) { }
|
|
#endif
|
|
|
|
#if defined(CONFIG_BPF_JIT) && defined(CONFIG_X86_64)
|
|
bool ex_handler_bpf(const struct exception_table_entry *x, struct pt_regs *regs);
|
|
#else
|
|
static inline bool ex_handler_bpf(const struct exception_table_entry *x,
|
|
struct pt_regs *regs) { return false; }
|
|
#endif
|
|
|
|
#endif
|