mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

NMI handlers can be registered by various subsystems, including drivers. However, the interface for registering and unregistering such handlers is not clearly documented. In the future, the interface may need to be extended to identify the source of the NMI. Add documentation to make the current API more understandable and easier to use. Signed-off-by: Sohil Mehta <sohil.mehta@intel.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Nikolay Borisov <nik.borisov@suse.com> Link: https://lore.kernel.org/r/20250327234629.3953536-8-sohil.mehta@intel.com
108 lines
3 KiB
C
108 lines
3 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _ASM_X86_NMI_H
|
|
#define _ASM_X86_NMI_H
|
|
|
|
#include <linux/irq_work.h>
|
|
#include <linux/pm.h>
|
|
#include <asm/irq.h>
|
|
#include <asm/io.h>
|
|
|
|
#ifdef CONFIG_X86_LOCAL_APIC
|
|
|
|
extern int reserve_perfctr_nmi(unsigned int);
|
|
extern void release_perfctr_nmi(unsigned int);
|
|
extern int reserve_evntsel_nmi(unsigned int);
|
|
extern void release_evntsel_nmi(unsigned int);
|
|
|
|
#endif /* CONFIG_X86_LOCAL_APIC */
|
|
|
|
extern int unknown_nmi_panic;
|
|
extern int panic_on_unrecovered_nmi;
|
|
extern int panic_on_io_nmi;
|
|
|
|
/* NMI handler flags */
|
|
#define NMI_FLAG_FIRST 1
|
|
|
|
/**
|
|
* enum - NMI types.
|
|
* @NMI_LOCAL: Local NMI, CPU-specific NMI generated by the Local APIC.
|
|
* @NMI_UNKNOWN: Unknown NMI, the source of the NMI may not be identified.
|
|
* @NMI_SERR: System Error NMI, typically triggered by PCI errors.
|
|
* @NMI_IO_CHECK: I/O Check NMI, related to I/O errors.
|
|
* @NMI_MAX: Maximum value for NMI types.
|
|
*
|
|
* NMI types are used to categorize NMIs and to dispatch them to the
|
|
* appropriate handler.
|
|
*/
|
|
enum {
|
|
NMI_LOCAL=0,
|
|
NMI_UNKNOWN,
|
|
NMI_SERR,
|
|
NMI_IO_CHECK,
|
|
NMI_MAX
|
|
};
|
|
|
|
/* NMI handler return values */
|
|
#define NMI_DONE 0
|
|
#define NMI_HANDLED 1
|
|
|
|
typedef int (*nmi_handler_t)(unsigned int, struct pt_regs *);
|
|
|
|
struct nmiaction {
|
|
struct list_head list;
|
|
nmi_handler_t handler;
|
|
u64 max_duration;
|
|
unsigned long flags;
|
|
const char *name;
|
|
};
|
|
|
|
/**
|
|
* register_nmi_handler - Register a handler for a specific NMI type
|
|
* @t: NMI type (e.g. NMI_LOCAL)
|
|
* @fn: The NMI handler
|
|
* @fg: Flags associated with the NMI handler
|
|
* @n: Name of the NMI handler
|
|
* @init: Optional __init* attributes for struct nmiaction
|
|
*
|
|
* Adds the provided handler to the list of handlers for the specified
|
|
* NMI type. Handlers flagged with NMI_FLAG_FIRST would be executed first.
|
|
*
|
|
* Sometimes the source of an NMI can't be reliably determined which
|
|
* results in an NMI being tagged as "unknown". Register an additional
|
|
* handler using the NMI type - NMI_UNKNOWN to handle such cases. The
|
|
* caller would get one last chance to assume responsibility for the
|
|
* NMI.
|
|
*
|
|
* Return: 0 on success, or an error code on failure.
|
|
*/
|
|
#define register_nmi_handler(t, fn, fg, n, init...) \
|
|
({ \
|
|
static struct nmiaction init fn##_na = { \
|
|
.list = LIST_HEAD_INIT(fn##_na.list), \
|
|
.handler = (fn), \
|
|
.name = (n), \
|
|
.flags = (fg), \
|
|
}; \
|
|
__register_nmi_handler((t), &fn##_na); \
|
|
})
|
|
|
|
int __register_nmi_handler(unsigned int, struct nmiaction *);
|
|
|
|
/**
|
|
* unregister_nmi_handler - Unregister a handler for a specific NMI type
|
|
* @type: NMI type (e.g. NMI_LOCAL)
|
|
* @name: Name of the NMI handler used during registration
|
|
*
|
|
* Removes the handler associated with the specified NMI type from the
|
|
* NMI handler list. The "name" is used as a lookup key to identify the
|
|
* handler.
|
|
*/
|
|
void unregister_nmi_handler(unsigned int type, const char *name);
|
|
|
|
void set_emergency_nmi_handler(unsigned int type, nmi_handler_t handler);
|
|
|
|
void stop_nmi(void);
|
|
void restart_nmi(void);
|
|
void local_touch_nmi(void);
|
|
|
|
#endif /* _ASM_X86_NMI_H */
|