/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_X86_CFI_H
#define _ASM_X86_CFI_H


#include <linux/bug.h>
#include <asm/ibt.h>


enum cfi_mode {
	CFI_AUTO,	
	CFI_OFF,	
	CFI_KCFI,	
	CFI_FINEIBT,	
};

extern enum cfi_mode cfi_mode;

#ifdef CONFIG_FINEIBT_BHI
extern bool cfi_bhi;
#else
#define cfi_bhi (0)
#endif

typedef u8 bhi_thunk[32];
extern bhi_thunk __bhi_args[];
extern bhi_thunk __bhi_args_end[];

struct pt_regs;

#ifdef CONFIG_CALL_PADDING
#define CFI_OFFSET (CONFIG_FUNCTION_PADDING_CFI+5)
#else
#define CFI_OFFSET 5
#endif

#ifdef CONFIG_CFI
enum bug_trap_type handle_cfi_failure(struct pt_regs *regs);
#define __bpfcall

static inline int cfi_get_offset(void)
{
	switch (cfi_mode) {
	case CFI_FINEIBT:
		return  16;
	case CFI_KCFI:
		return CFI_OFFSET;
	default:
		return 0;
	}
}
#define cfi_get_offset cfi_get_offset

extern u32 cfi_get_func_hash(void *func);
#define cfi_get_func_hash cfi_get_func_hash

extern int cfi_get_func_arity(void *func);

#ifdef CONFIG_FINEIBT
extern bool decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type);
#else
static inline bool
decode_fineibt_insn(struct pt_regs *regs, unsigned long *target, u32 *type)
{
	return false;
}

#endif

#else
static inline enum bug_trap_type handle_cfi_failure(struct pt_regs *regs)
{
	return BUG_TRAP_TYPE_NONE;
}
static inline int cfi_get_func_arity(void *func)
{
	return 0;
}
#endif 

#if HAS_KERNEL_IBT == 1
#define CFI_NOSEAL(x)	asm(IBT_NOSEAL(__stringify(x)))
#endif

#endif 
