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>
---
arch/x86/include/asm/nmi.h | 43 ++++++++++++++++++++++++++++++++-
arch/x86/include/asm/x86_init.h | 1 +
2 files changed, 43 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h
index f85aea7bf7f1..79d88d12c8fb 100644
--- a/arch/x86/include/asm/nmi.h
+++ b/arch/x86/include/asm/nmi.h
@@ -20,8 +20,20 @@ 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,
@@ -30,6 +42,7 @@ enum {
NMI_MAX
};
+/* NMI handler return values */
#define NMI_DONE 0
#define NMI_HANDLED 1
@@ -43,6 +56,25 @@ struct nmiaction {
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 = { \
@@ -56,7 +88,16 @@ struct nmiaction {
int __register_nmi_handler(unsigned int, struct nmiaction *);
-void unregister_nmi_handler(unsigned int, const char *);
+/**
+ * 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);
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 213cf5379a5a..36698cc9fb44 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -292,6 +292,7 @@ struct x86_hyper_runtime {
* @set_wallclock: set time back to HW clock
* @is_untracked_pat_range exclude from PAT logic
* @nmi_init enable NMI on cpus
+ * @get_nmi_reason get the reason an NMI was received
* @save_sched_clock_state: save state for sched_clock() on suspend
* @restore_sched_clock_state: restore state for sched_clock() on resume
* @apic_post_init: adjust apic if needed
--
2.43.0
* Sohil Mehta <sohil.mehta@intel.com> wrote:
> diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
> index 213cf5379a5a..36698cc9fb44 100644
> --- a/arch/x86/include/asm/x86_init.h
> +++ b/arch/x86/include/asm/x86_init.h
> @@ -292,6 +292,7 @@ struct x86_hyper_runtime {
> * @set_wallclock: set time back to HW clock
> * @is_untracked_pat_range exclude from PAT logic
> * @nmi_init enable NMI on cpus
> + * @get_nmi_reason get the reason an NMI was received
> * @save_sched_clock_state: save state for sched_clock() on suspend
> * @restore_sched_clock_state: restore state for sched_clock() on resume
> * @apic_post_init: adjust apic if needed
Note that I've split off this second half into a separate commit:
x86/nmi: Add missing description x86_hyper_runtime::get_nmi_reason to <asm/x86_init.h>
as it's basically an independent KernelDoc bugfix AFAICS.
Thanks,
Ingo
On 3/31/2025 3:47 AM, Ingo Molnar wrote:
>
> * Sohil Mehta <sohil.mehta@intel.com> wrote:
>
>> diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
>> index 213cf5379a5a..36698cc9fb44 100644
>> --- a/arch/x86/include/asm/x86_init.h
>> +++ b/arch/x86/include/asm/x86_init.h
>> @@ -292,6 +292,7 @@ struct x86_hyper_runtime {
>> * @set_wallclock: set time back to HW clock
>> * @is_untracked_pat_range exclude from PAT logic
>> * @nmi_init enable NMI on cpus
>> + * @get_nmi_reason get the reason an NMI was received
>> * @save_sched_clock_state: save state for sched_clock() on suspend
>> * @restore_sched_clock_state: restore state for sched_clock() on resume
>> * @apic_post_init: adjust apic if needed
>
> Note that I've split off this second half into a separate commit:
>
> x86/nmi: Add missing description x86_hyper_runtime::get_nmi_reason to <asm/x86_init.h>
>
> as it's basically an independent KernelDoc bugfix AFAICS.
>
That's fine with me. I did consider it for a moment but choose otherwise
to avoid micro-patches. Here is my sign-off if you need one.
Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
On 3/31/2025 9:04 AM, Sohil Mehta wrote:
> On 3/31/2025 3:47 AM, Ingo Molnar wrote:
>>
>> * Sohil Mehta <sohil.mehta@intel.com> wrote:
>>
>>> diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
>>> index 213cf5379a5a..36698cc9fb44 100644
>>> --- a/arch/x86/include/asm/x86_init.h
>>> +++ b/arch/x86/include/asm/x86_init.h
>>> @@ -292,6 +292,7 @@ struct x86_hyper_runtime {
>>> * @set_wallclock: set time back to HW clock
>>> * @is_untracked_pat_range exclude from PAT logic
>>> * @nmi_init enable NMI on cpus
>>> + * @get_nmi_reason get the reason an NMI was received
>>> * @save_sched_clock_state: save state for sched_clock() on suspend
>>> * @restore_sched_clock_state: restore state for sched_clock() on resume
>>> * @apic_post_init: adjust apic if needed
>>
>> Note that I've split off this second half into a separate commit:
>>
>> x86/nmi: Add missing description x86_hyper_runtime::get_nmi_reason to <asm/x86_init.h>
>>
Upon closer inspection, I realized that the commit title for the new
patch is incorrect.
s/x86_hyper_runtime/x86_platform_ops
The git diff context shown above is misleading. We are modifying the
struct x86_platform_ops documentation and not struct x86_hyper_runtime.
/**
* struct x86_platform_ops - platform specific runtime functions
* @calibrate_cpu: calibrate CPU
* @calibrate_tsc: calibrate TSC, if different from CPU
* @get_wallclock: get time from HW clock like RTC etc.
* @set_wallclock: set time back to HW clock
* @is_untracked_pat_range exclude from PAT logic
* @nmi_init enable NMI on cpus
* @get_nmi_reason get the reason an NMI was received
* @save_sched_clock_state: save state for sched_clock() on suspend
* @restore_sched_clock_state: restore state for sched_clock() on resu
>> as it's basically an independent KernelDoc bugfix AFAICS.
>>
>
> That's fine with me. I did consider it for a moment but choose otherwise
> to avoid micro-patches. Here is my sign-off if you need one.
>
> Signed-off-by: Sohil Mehta <sohil.mehta@intel.com>
Sohil
* Sohil Mehta <sohil.mehta@intel.com> wrote:
> On 3/31/2025 9:04 AM, Sohil Mehta wrote:
> > On 3/31/2025 3:47 AM, Ingo Molnar wrote:
> >>
> >> * Sohil Mehta <sohil.mehta@intel.com> wrote:
> >>
> >>> diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
> >>> index 213cf5379a5a..36698cc9fb44 100644
> >>> --- a/arch/x86/include/asm/x86_init.h
> >>> +++ b/arch/x86/include/asm/x86_init.h
> >>> @@ -292,6 +292,7 @@ struct x86_hyper_runtime {
> >>> * @set_wallclock: set time back to HW clock
> >>> * @is_untracked_pat_range exclude from PAT logic
> >>> * @nmi_init enable NMI on cpus
> >>> + * @get_nmi_reason get the reason an NMI was received
> >>> * @save_sched_clock_state: save state for sched_clock() on suspend
> >>> * @restore_sched_clock_state: restore state for sched_clock() on resume
> >>> * @apic_post_init: adjust apic if needed
> >>
> >> Note that I've split off this second half into a separate commit:
> >>
> >> x86/nmi: Add missing description x86_hyper_runtime::get_nmi_reason to <asm/x86_init.h>
> >>
>
> Upon closer inspection, I realized that the commit title for the new
> patch is incorrect.
> s/x86_hyper_runtime/x86_platform_ops
Yeah, the git patch context threw me off: I fixed the title, have
included the other review feedback, and added the Reviewed-by tags of
Kai Huang as well.
Thanks!
Ingo
On 4/1/2025 1:08 AM, Ingo Molnar wrote: >> Upon closer inspection, I realized that the commit title for the new >> patch is incorrect. >> s/x86_hyper_runtime/x86_platform_ops > > Yeah, the git patch context threw me off: I fixed the title, have > included the other review feedback, and added the Reviewed-by tags of > Kai Huang as well. > Great, that's awesome! We now have ACKs from PeterZ and Nikolay as well. Thank you for the reviews. I haven't seen the tip-bot emails yet. Just out of curiosity, when do the tip-bot emails get sent? Does it happen automatically when you push the patches to upstream tip:x86/nmi or do you trigger them manually at a later point? Thanks, Sohil
The following commit has been merged into the x86/nmi branch of tip:
Commit-ID: 7324d7de7740fdbb29c79f5e2a001524370fa732
Gitweb: https://git.kernel.org/tip/7324d7de7740fdbb29c79f5e2a001524370fa732
Author: Sohil Mehta <sohil.mehta@intel.com>
AuthorDate: Thu, 27 Mar 2025 23:46:27
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Tue, 01 Apr 2025 22:26:27 +02:00
x86/nmi: Add missing description x86_platform_ops::get_nmi_reason to <asm/x86_init.h>
[ mingo: Split off from another patch. ]
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
---
arch/x86/include/asm/x86_init.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 213cf53..36698cc 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -292,6 +292,7 @@ struct x86_hyper_runtime {
* @set_wallclock: set time back to HW clock
* @is_untracked_pat_range exclude from PAT logic
* @nmi_init enable NMI on cpus
+ * @get_nmi_reason get the reason an NMI was received
* @save_sched_clock_state: save state for sched_clock() on suspend
* @restore_sched_clock_state: restore state for sched_clock() on resume
* @apic_post_init: adjust apic if needed
The following commit has been merged into the x86/nmi branch of tip:
Commit-ID: 3b1292706305e5949d2aa739eb0ae009a9e6f824
Gitweb: https://git.kernel.org/tip/3b1292706305e5949d2aa739eb0ae009a9e6f824
Author: Sohil Mehta <sohil.mehta@intel.com>
AuthorDate: Thu, 27 Mar 2025 23:46:27
Committer: Ingo Molnar <mingo@kernel.org>
CommitterDate: Tue, 01 Apr 2025 22:26:21 +02:00
x86/nmi: Improve <asm/nmi.h> documentation
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
---
arch/x86/include/asm/nmi.h | 43 ++++++++++++++++++++++++++++++++++++-
1 file changed, 42 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/nmi.h b/arch/x86/include/asm/nmi.h
index f85aea7..79d88d1 100644
--- a/arch/x86/include/asm/nmi.h
+++ b/arch/x86/include/asm/nmi.h
@@ -20,8 +20,20 @@ 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,
@@ -30,6 +42,7 @@ enum {
NMI_MAX
};
+/* NMI handler return values */
#define NMI_DONE 0
#define NMI_HANDLED 1
@@ -43,6 +56,25 @@ struct nmiaction {
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 = { \
@@ -56,7 +88,16 @@ struct nmiaction {
int __register_nmi_handler(unsigned int, struct nmiaction *);
-void unregister_nmi_handler(unsigned int, const char *);
+/**
+ * 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);
© 2016 - 2025 Red Hat, Inc.