[PATCH 03/12] x86/mce/inject: Add notrigger entry to suppress MCE injection

From: isaku . yamahata
Date: Tue Oct 10 2023 - 04:35:47 EST


From: Isaku Yamahata <isaku.yamahata@xxxxxxxxx>

The current x86 MCE injection framework injects MCE when writing to
/sys/kernel/debug/mce-inject/bank. KVM wants to inject machine check on
behalf of vcpu context instead of the context of writing to the bank file.

Because ACPI APEI has a similar requirement and it adds
/sys/kernel/debug/apei/notrigger to suppress immediate injection.
By Following it, add /sys/kernel/debug/mce-inject/notrigger to suppress
MCE injection.

The alternative is add new value "notrigger" to
/sys/kernel/debug/mce-inject/flags in addition to "sw", "hw", "df", and
"th". Because it may break user space ABI, this option follow ACPI APEI
error injection.

Supposed usage flow:
$ echo 1 > notrigger
... setup MCE values
$ echo 0 > bank
The last step to setup mce value to inject with MC bank 0.
Originally this step injects mce. With noijnect=1, don't inject.

$ echo 1 > /sys/kernel/debug/kvm/<pid>-<fd>/vcpu<N>/mce-inject
tell KVM to inject MCE in the context of vcpu.

Signed-off-by: Isaku Yamahata <isaku.yamahata@xxxxxxxxx>
---
arch/x86/kernel/cpu/mce/inject.c | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)

diff --git a/arch/x86/kernel/cpu/mce/inject.c b/arch/x86/kernel/cpu/mce/inject.c
index 461858ae18f9..88603a6c0afe 100644
--- a/arch/x86/kernel/cpu/mce/inject.c
+++ b/arch/x86/kernel/cpu/mce/inject.c
@@ -34,6 +34,7 @@
#include "internal.h"

static bool hw_injection_possible;
+static u64 notrigger;

/*
* Collect all the MCi_XXX settings
@@ -598,6 +599,8 @@ static int inj_bank_set(void *data, u64 val)
}

m->bank = val;
+ if (notrigger)
+ return 0;

/*
* sw-only injection allows to write arbitrary values into the MCA
@@ -637,6 +640,21 @@ MCE_INJECT_GET(bank);

DEFINE_SIMPLE_ATTRIBUTE(bank_fops, inj_bank_get, inj_bank_set, "%llu\n");

+static int inj_notrigger_get(void *data, u64 *val)
+{
+ *val = notrigger;
+ return 0;
+}
+
+static int inj_notrigger_set(void *data, u64 val)
+{
+ notrigger = val;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(notrigger_fops, inj_notrigger_get, inj_notrigger_set,
+ "%llx\n");
+
static const char readme_msg[] =
"Description of the files and their usages:\n"
"\n"
@@ -685,6 +703,9 @@ static const char readme_msg[] =
"\n"
"mcgstatus:\t Set MCG_STATUS: the bits in that MSR describes the current state\n"
"\t of the processor after the MCE.\n"
+"\n"
+"notrigger:\t Suppress triggering the injection when set to non-zero\n"
+"\t The injection is triggered by other way.\n"
"\n";

static ssize_t
@@ -714,6 +735,8 @@ static struct dfs_node {
{ .name = "cpu", .fops = &extcpu_fops, .perm = S_IRUSR | S_IWUSR },
{ .name = "mcgstatus", .fops = &mcgstatus_fops,
.perm = S_IRUSR | S_IWUSR },
+ { .name = "notrigger", .fops = &notrigger_fops,
+ .perm = S_IRUSR | S_IWUSR },
{ .name = "README", .fops = &readme_fops, .perm = S_IRUSR | S_IRGRP | S_IROTH },
};

--
2.25.1