mirror of https://github.com/torvalds/linux.git
109 lines
3.0 KiB
C
109 lines
3.0 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 */
|