* [PATCH -v3 0/6] x86, MCE, AMD: Hardware MCE injection
@ 2011-05-09 18:35 Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 1/6] x86, MCE: Add a HW injection flag Borislav Petkov
` (5 more replies)
0 siblings, 6 replies; 9+ messages in thread
From: Borislav Petkov @ 2011-05-09 18:35 UTC (permalink / raw)
To: EDAC devel; +Cc: X86-ML, LKML, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
Hi,
this new set version moves the whole interface to debugfs since it
belongs there in the first place. Remaining functionality unchanged.
Changelog:
v2: only small changes from the last submission
(http://lkml.org/lkml/2011/4/15/171) so that we can have valid
MCG_STATUS values and don't choke on severity sanity checking.
v1: Initial submission.
Thanks.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH -v3 1/6] x86, MCE: Add a HW injection flag
2011-05-09 18:35 [PATCH -v3 0/6] x86, MCE, AMD: Hardware MCE injection Borislav Petkov
@ 2011-05-09 18:35 ` Borislav Petkov
2011-05-10 3:29 ` Hidetoshi Seto
2011-05-09 18:35 ` [PATCH -v3 2/6] x86, MCE: Export mce_get_debugfs_dir Borislav Petkov
` (4 subsequent siblings)
5 siblings, 1 reply; 9+ messages in thread
From: Borislav Petkov @ 2011-05-09 18:35 UTC (permalink / raw)
To: EDAC devel; +Cc: X86-ML, LKML, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
Add an mce->inject_flag to denote that we're doing HW injection.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Acked-by: Ingo Molnar <mingo@elte.hu>
---
arch/x86/include/asm/mce.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index eb16e94..a2e3dcf 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -49,6 +49,7 @@
#define MCJ_CTX_IRQ 2 /* inject context: IRQ */
#define MCJ_NMI_BROADCAST 4 /* do NMI broadcasting */
#define MCJ_EXCEPTION 8 /* raise as exception */
+#define MCJ_HW_INJECT 16 /* do a HW MCE inject, i.e. INT18 */
/* Fields are zero when not available */
struct mce {
--
1.7.4.rc2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH -v3 2/6] x86, MCE: Export mce_get_debugfs_dir
2011-05-09 18:35 [PATCH -v3 0/6] x86, MCE, AMD: Hardware MCE injection Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 1/6] x86, MCE: Add a HW injection flag Borislav Petkov
@ 2011-05-09 18:35 ` Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 3/6] EDAC, MCE, AMD: Add function to enable direct write to MCE MSRs Borislav Petkov
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2011-05-09 18:35 UTC (permalink / raw)
To: EDAC devel; +Cc: X86-ML, LKML, Borislav Petkov, Ingo Molnar
From: Borislav Petkov <borislav.petkov@amd.com>
This is needed for external users of the same debugfs toplevel dir.
Cc: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
arch/x86/include/asm/mce.h | 1 +
arch/x86/kernel/cpu/mcheck/mce-internal.h | 1 -
arch/x86/kernel/cpu/mcheck/mce.c | 1 +
3 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index a2e3dcf..1c9c7be 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -241,5 +241,6 @@ struct cper_sec_mem_err;
extern void apei_mce_report_mem_error(int corrected,
struct cper_sec_mem_err *mem_err);
+struct dentry *mce_get_debugfs_dir(void);
#endif /* __KERNEL__ */
#endif /* _ASM_X86_MCE_H */
diff --git a/arch/x86/kernel/cpu/mcheck/mce-internal.h b/arch/x86/kernel/cpu/mcheck/mce-internal.h
index fefcc69..660a9e1 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-internal.h
+++ b/arch/x86/kernel/cpu/mcheck/mce-internal.h
@@ -22,7 +22,6 @@ struct mce_bank {
};
int mce_severity(struct mce *a, int tolerant, char **msg);
-struct dentry *mce_get_debugfs_dir(void);
extern int mce_ser;
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 3385ea2..262f692 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -2170,6 +2170,7 @@ struct dentry *mce_get_debugfs_dir(void)
return dmce;
}
+EXPORT_SYMBOL_GPL(mce_get_debugfs_dir);
static void mce_reset(void)
{
--
1.7.4.rc2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH -v3 3/6] EDAC, MCE, AMD: Add function to enable direct write to MCE MSRs
2011-05-09 18:35 [PATCH -v3 0/6] x86, MCE, AMD: Hardware MCE injection Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 1/6] x86, MCE: Add a HW injection flag Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 2/6] x86, MCE: Export mce_get_debugfs_dir Borislav Petkov
@ 2011-05-09 18:35 ` Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 4/6] EDAC, MCE, AMD: Convert to debugfs Borislav Petkov
` (2 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2011-05-09 18:35 UTC (permalink / raw)
To: EDAC devel; +Cc: X86-ML, LKML, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
Normally, writing to MCE MSRs causes a #GP. Add a function to enable
direct access to those MSRs.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
drivers/edac/mce_amd_inj.c | 24 ++++++++++++++++++++++++
1 files changed, 24 insertions(+), 0 deletions(-)
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c
index a4987e0..eb36e15 100644
--- a/drivers/edac/mce_amd_inj.c
+++ b/drivers/edac/mce_amd_inj.c
@@ -30,6 +30,30 @@ static struct edac_mce_attr mce_attr_##_name = __ATTR(_name, _mode, _show, _stor
static struct kobject *mce_kobj;
/*
+ * Caller needs to be make sure this cpu doesn't disappear
+ * from under us, i.e.: get_cpu/put_cpu.
+ */
+static int toggle_hw_mce_inject(unsigned int cpu, bool enable)
+{
+ u32 l, h;
+ int err;
+
+ err = rdmsr_on_cpu(cpu, MSR_K7_HWCR, &l, &h);
+ if (err) {
+ printk(KERN_ERR "%s: error reading HWCR\n", __func__);
+ return err;
+ }
+
+ enable ? (l |= BIT(18)) : (l &= ~BIT(18));
+
+ err = wrmsr_on_cpu(cpu, MSR_K7_HWCR, l, h);
+ if (err)
+ printk(KERN_ERR "%s: error writing HWCR\n", __func__);
+
+ return err;
+}
+
+/*
* Collect all the MCi_XXX settings
*/
static struct mce i_mce;
--
1.7.4.rc2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH -v3 4/6] EDAC, MCE, AMD: Convert to debugfs
2011-05-09 18:35 [PATCH -v3 0/6] x86, MCE, AMD: Hardware MCE injection Borislav Petkov
` (2 preceding siblings ...)
2011-05-09 18:35 ` [PATCH -v3 3/6] EDAC, MCE, AMD: Add function to enable direct write to MCE MSRs Borislav Petkov
@ 2011-05-09 18:35 ` Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 5/6] EDAC, MCE, AMD: Add attributes needed for HW injection Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 6/6] EDAC, MCE, AMD: Add an injector function Borislav Petkov
5 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2011-05-09 18:35 UTC (permalink / raw)
To: EDAC devel; +Cc: X86-ML, LKML, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
This is a module which is used for debugging MCE decoding paths so its
userspace interface should go to debugfs, where it belongs conceptually.
While at it, add a warning to the Kconfig text that this interface is
unstable and no userspace scripts should rely all too much on it.
Make it so.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
drivers/edac/Kconfig | 8 +-
drivers/edac/mce_amd_inj.c | 191 ++++++++++++++++++++------------------------
2 files changed, 91 insertions(+), 108 deletions(-)
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig
index af1a17d..19f85da 100644
--- a/drivers/edac/Kconfig
+++ b/drivers/edac/Kconfig
@@ -52,15 +52,17 @@ config EDAC_DECODE_MCE
has been initialized.
config EDAC_MCE_INJ
- tristate "Simple MCE injection interface over /sysfs"
- depends on EDAC_DECODE_MCE
+ tristate "Simple debugfs MCE injection interface"
+ depends on EDAC_DECODE_MCE && DEBUG_FS
default n
help
- This is a simple interface to inject MCEs over /sysfs and test
+ This is a simple interface to inject MCEs over debugfs and test
the MCE decoding code in EDAC.
This is currently AMD-only.
+ WARNING: Do not even assume that this interface is staying stable!
+
config EDAC_MM_EDAC
tristate "Main Memory EDAC (Error Detection And Correction) reporting"
help
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c
index eb36e15..421c3b5 100644
--- a/drivers/edac/mce_amd_inj.c
+++ b/drivers/edac/mce_amd_inj.c
@@ -10,24 +10,47 @@
* Advanced Micro Devices Inc.
*/
-#include <linux/kobject.h>
-#include <linux/sysdev.h>
#include <linux/edac.h>
+#include <linux/debugfs.h>
#include <asm/mce.h>
#include "mce_amd.h"
-struct edac_mce_attr {
- struct attribute attr;
- ssize_t (*show) (struct kobject *kobj, struct edac_mce_attr *attr, char *buf);
- ssize_t (*store)(struct kobject *kobj, struct edac_mce_attr *attr,
- const char *buf, size_t count);
-};
+/*
+ * Collect all the MCi_XXX settings
+ */
+static struct mce i_mce;
+static struct dentry *dfs_inj;
+
+#define MCE_INJECT_SET(reg) \
+static int inj_##reg##_set(void *data, u64 val) \
+{ \
+ struct mce *m = (struct mce *)data; \
+ \
+ m->reg = val; \
+ return 0; \
+}
+
+MCE_INJECT_SET(status);
+MCE_INJECT_SET(misc);
+MCE_INJECT_SET(addr);
+
+#define MCE_INJECT_GET(reg) \
+static int inj_##reg##_get(void *data, u64 *val) \
+{ \
+ struct mce *m = (struct mce *)data; \
+ \
+ *val = m->reg; \
+ return 0; \
+}
-#define EDAC_MCE_ATTR(_name, _mode, _show, _store) \
-static struct edac_mce_attr mce_attr_##_name = __ATTR(_name, _mode, _show, _store)
+MCE_INJECT_GET(status);
+MCE_INJECT_GET(misc);
+MCE_INJECT_GET(addr);
-static struct kobject *mce_kobj;
+DEFINE_SIMPLE_ATTRIBUTE(status_fops, inj_status_get, inj_status_set, "%llx\n");
+DEFINE_SIMPLE_ATTRIBUTE(misc_fops, inj_misc_get, inj_misc_set, "%llx\n");
+DEFINE_SIMPLE_ATTRIBUTE(addr_fops, inj_addr_get, inj_addr_set, "%llx\n");
/*
* Caller needs to be make sure this cpu doesn't disappear
@@ -54,137 +77,95 @@ static int toggle_hw_mce_inject(unsigned int cpu, bool enable)
}
/*
- * Collect all the MCi_XXX settings
- */
-static struct mce i_mce;
-
-#define MCE_INJECT_STORE(reg) \
-static ssize_t edac_inject_##reg##_store(struct kobject *kobj, \
- struct edac_mce_attr *attr, \
- const char *data, size_t count)\
-{ \
- int ret = 0; \
- unsigned long value; \
- \
- ret = strict_strtoul(data, 16, &value); \
- if (ret < 0) \
- printk(KERN_ERR "Error writing MCE " #reg " field.\n"); \
- \
- i_mce.reg = value; \
- \
- return count; \
-}
-
-MCE_INJECT_STORE(status);
-MCE_INJECT_STORE(misc);
-MCE_INJECT_STORE(addr);
-
-#define MCE_INJECT_SHOW(reg) \
-static ssize_t edac_inject_##reg##_show(struct kobject *kobj, \
- struct edac_mce_attr *attr, \
- char *buf) \
-{ \
- return sprintf(buf, "0x%016llx\n", i_mce.reg); \
-}
-
-MCE_INJECT_SHOW(status);
-MCE_INJECT_SHOW(misc);
-MCE_INJECT_SHOW(addr);
-
-EDAC_MCE_ATTR(status, 0644, edac_inject_status_show, edac_inject_status_store);
-EDAC_MCE_ATTR(misc, 0644, edac_inject_misc_show, edac_inject_misc_store);
-EDAC_MCE_ATTR(addr, 0644, edac_inject_addr_show, edac_inject_addr_store);
-
-/*
* This denotes into which bank we're injecting and triggers
* the injection, at the same time.
*/
-static ssize_t edac_inject_bank_store(struct kobject *kobj,
- struct edac_mce_attr *attr,
- const char *data, size_t count)
+static int inj_bank_set(void *data, u64 val)
{
- int ret = 0;
- unsigned long value;
-
- ret = strict_strtoul(data, 10, &value);
- if (ret < 0) {
- printk(KERN_ERR "Invalid bank value!\n");
- return -EINVAL;
- }
+ struct mce *m = (struct mce *)data;
- if (value > 5)
- if (boot_cpu_data.x86 != 0x15 || value > 6) {
- printk(KERN_ERR "Non-existent MCE bank: %lu\n", value);
+ if (val > 5)
+ if (boot_cpu_data.x86 != 0x15 || val > 6) {
+ printk(KERN_ERR "Non-existent MCE bank: %llu\n", val);
return -EINVAL;
}
- i_mce.bank = value;
+ m->bank = val;
- amd_decode_mce(NULL, 0, &i_mce);
+ amd_decode_mce(NULL, 0, m);
- return count;
+ return 0;
}
-static ssize_t edac_inject_bank_show(struct kobject *kobj,
- struct edac_mce_attr *attr, char *buf)
+static int inj_bank_get(void *data, u64 *val)
{
- return sprintf(buf, "%d\n", i_mce.bank);
-}
+ struct mce *m = (struct mce *)data;
-EDAC_MCE_ATTR(bank, 0644, edac_inject_bank_show, edac_inject_bank_store);
+ *val = m->bank;
+ return 0;
+}
-static struct edac_mce_attr *sysfs_attrs[] = { &mce_attr_status, &mce_attr_misc,
- &mce_attr_addr, &mce_attr_bank
+DEFINE_SIMPLE_ATTRIBUTE(bank_fops, inj_bank_get, inj_bank_set, "%llu\n");
+
+struct dfs_node {
+ char *name;
+ struct dentry *d;
+ const struct file_operations *fops;
+} dfs_fls[] = {
+ { .name = "status", .fops = &status_fops },
+ { .name = "misc", .fops = &misc_fops },
+ { .name = "addr", .fops = &addr_fops },
+ { .name = "bank", .fops = &bank_fops },
};
static int __init edac_init_mce_inject(void)
{
- struct sysdev_class *edac_class = NULL;
- int i, err = 0;
+ struct dentry *dfs_mce_root;
+ int i;
- edac_class = edac_get_sysfs_class();
- if (!edac_class)
+ dfs_mce_root = mce_get_debugfs_dir();
+ if (!dfs_mce_root)
return -EINVAL;
- mce_kobj = kobject_create_and_add("mce", &edac_class->kset.kobj);
- if (!mce_kobj) {
- printk(KERN_ERR "Error creating a mce kset.\n");
- err = -ENOMEM;
- goto err_mce_kobj;
- }
+ dfs_inj = debugfs_create_dir("inject", dfs_mce_root);
+ if (!dfs_inj)
+ return -EINVAL;
+
+ for (i = 0; i < ARRAY_SIZE(dfs_fls); i++) {
+ dfs_fls[i].d = debugfs_create_file(dfs_fls[i].name,
+ S_IRUSR | S_IWUSR,
+ dfs_inj,
+ &i_mce,
+ dfs_fls[i].fops);
+
+ if (!dfs_fls[i].d)
+ goto err_dfs_add;
- for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++) {
- err = sysfs_create_file(mce_kobj, &sysfs_attrs[i]->attr);
- if (err) {
- printk(KERN_ERR "Error creating %s in sysfs.\n",
- sysfs_attrs[i]->attr.name);
- goto err_sysfs_create;
- }
}
+
return 0;
-err_sysfs_create:
+err_dfs_add:
while (--i >= 0)
- sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
+ debugfs_remove(dfs_fls[i].d);
- kobject_del(mce_kobj);
+ debugfs_remove(dfs_inj);
+ dfs_inj = NULL;
-err_mce_kobj:
- edac_put_sysfs_class();
-
- return err;
+ return -ENOMEM;
}
static void __exit edac_exit_mce_inject(void)
{
int i;
- for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++)
- sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr);
+ for (i = 0; i < ARRAY_SIZE(dfs_fls); i++)
+ debugfs_remove(dfs_fls[i].d);
- kobject_del(mce_kobj);
+ memset(&dfs_fls, 0, sizeof(dfs_fls));
- edac_put_sysfs_class();
+ debugfs_remove(dfs_inj);
+ dfs_inj = NULL;
}
module_init(edac_init_mce_inject);
--
1.7.4.rc2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH -v3 5/6] EDAC, MCE, AMD: Add attributes needed for HW injection
2011-05-09 18:35 [PATCH -v3 0/6] x86, MCE, AMD: Hardware MCE injection Borislav Petkov
` (3 preceding siblings ...)
2011-05-09 18:35 ` [PATCH -v3 4/6] EDAC, MCE, AMD: Convert to debugfs Borislav Petkov
@ 2011-05-09 18:35 ` Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 6/6] EDAC, MCE, AMD: Add an injector function Borislav Petkov
5 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2011-05-09 18:35 UTC (permalink / raw)
To: EDAC devel; +Cc: X86-ML, LKML, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
hw_inject denotes whether we want to do a hardware or a software
injection and, in the case of hardware injection, we want to do that on
a particular cpu, thus the second 'cpu' attribute.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
drivers/edac/mce_amd_inj.c | 57 ++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 57 insertions(+), 0 deletions(-)
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c
index 421c3b5..592871f 100644
--- a/drivers/edac/mce_amd_inj.c
+++ b/drivers/edac/mce_amd_inj.c
@@ -77,6 +77,61 @@ static int toggle_hw_mce_inject(unsigned int cpu, bool enable)
}
/*
+ * HW or SW injection
+ */
+static int hw_inj_get(void *data, u64 *val)
+{
+ struct mce *m = (struct mce *)data;
+
+ *val = !!(m->inject_flags & MCJ_HW_INJECT);
+
+ return 0;
+}
+
+static int hw_inj_set(void *data, u64 val)
+{
+ struct mce *m = (struct mce *)data;
+
+ switch (val) {
+ case 0:
+ m->inject_flags &= (u8)~MCJ_HW_INJECT;
+ break;
+
+ case 1:
+ m->inject_flags |= MCJ_HW_INJECT;
+ break;
+
+ default:
+ printk(KERN_ERR "%s: Only 0 or 1 allowed!\n", __func__);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(hw_inj_fops, hw_inj_get, hw_inj_set, "%llu\n");
+
+/*
+ * On which CPU to inject?
+ */
+
+MCE_INJECT_GET(extcpu);
+
+
+static int inj_extcpu_set(void *data, u64 val)
+{
+ struct mce *m = (struct mce *)data;
+
+ if (val >= num_online_cpus()) {
+ printk(KERN_ERR "%s: Non-existent CPU: %llu\n", __func__, val);
+ return -EINVAL;
+ }
+ m->extcpu = val;
+ return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(extcpu_fops, inj_extcpu_get, inj_extcpu_set, "%llu\n");
+
+/*
* This denotes into which bank we're injecting and triggers
* the injection, at the same time.
*/
@@ -116,6 +171,8 @@ struct dfs_node {
{ .name = "misc", .fops = &misc_fops },
{ .name = "addr", .fops = &addr_fops },
{ .name = "bank", .fops = &bank_fops },
+ { .name = "hw_inject", .fops = &hw_inj_fops },
+ { .name = "cpu", .fops = &extcpu_fops },
};
static int __init edac_init_mce_inject(void)
--
1.7.4.rc2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH -v3 6/6] EDAC, MCE, AMD: Add an injector function
2011-05-09 18:35 [PATCH -v3 0/6] x86, MCE, AMD: Hardware MCE injection Borislav Petkov
` (4 preceding siblings ...)
2011-05-09 18:35 ` [PATCH -v3 5/6] EDAC, MCE, AMD: Add attributes needed for HW injection Borislav Petkov
@ 2011-05-09 18:35 ` Borislav Petkov
5 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2011-05-09 18:35 UTC (permalink / raw)
To: EDAC devel; +Cc: X86-ML, LKML, Borislav Petkov
From: Borislav Petkov <borislav.petkov@amd.com>
Selectively inject either a real MCE or a sw-only version which
exercises the decoding code only. The hardware-injected MCE triggers a
machine check exception (#MC) so that the MCE handler can be bothered to
do something too.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
---
drivers/edac/mce_amd_inj.c | 50 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 48 insertions(+), 2 deletions(-)
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c
index 592871f..45e8122 100644
--- a/drivers/edac/mce_amd_inj.c
+++ b/drivers/edac/mce_amd_inj.c
@@ -131,6 +131,53 @@ static int inj_extcpu_set(void *data, u64 val)
DEFINE_SIMPLE_ATTRIBUTE(extcpu_fops, inj_extcpu_get, inj_extcpu_set, "%llu\n");
+static void trigger_mce(void *info)
+{
+ asm volatile("int $18");
+}
+
+static void do_inject(void)
+{
+ u64 mcg_status = 0;
+ unsigned int cpu = i_mce.extcpu;
+ int this_cpu;
+ u8 b = i_mce.bank;
+
+ if (!(i_mce.inject_flags & MCJ_HW_INJECT)) {
+ amd_decode_mce(NULL, 0, &i_mce);
+ return;
+ }
+
+ /* prep MCE global settings for the injection */
+ mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV;
+
+ if (!(i_mce.status & MCI_STATUS_PCC))
+ mcg_status |= MCG_STATUS_RIPV;
+
+ this_cpu = get_cpu();
+
+ toggle_hw_mce_inject(cpu, true);
+
+ wrmsr_on_cpu(cpu, MSR_IA32_MCG_STATUS,
+ (u32)mcg_status, (u32)(mcg_status >> 32));
+
+ wrmsr_on_cpu(cpu, MSR_IA32_MCx_STATUS(b),
+ (u32)i_mce.status, (u32)(i_mce.status >> 32));
+
+ wrmsr_on_cpu(cpu, MSR_IA32_MCx_ADDR(b),
+ (u32)i_mce.addr, (u32)(i_mce.addr >> 32));
+
+ wrmsr_on_cpu(cpu, MSR_IA32_MCx_MISC(b),
+ (u32)i_mce.misc, (u32)(i_mce.misc >> 32));
+
+ toggle_hw_mce_inject(cpu, false);
+
+ smp_call_function_single(cpu, trigger_mce, NULL, 0);
+
+ put_cpu();
+
+}
+
/*
* This denotes into which bank we're injecting and triggers
* the injection, at the same time.
@@ -146,8 +193,7 @@ static int inj_bank_set(void *data, u64 val)
}
m->bank = val;
-
- amd_decode_mce(NULL, 0, m);
+ do_inject();
return 0;
}
--
1.7.4.rc2
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH -v3 1/6] x86, MCE: Add a HW injection flag
2011-05-09 18:35 ` [PATCH -v3 1/6] x86, MCE: Add a HW injection flag Borislav Petkov
@ 2011-05-10 3:29 ` Hidetoshi Seto
2011-05-10 5:14 ` Borislav Petkov
0 siblings, 1 reply; 9+ messages in thread
From: Hidetoshi Seto @ 2011-05-10 3:29 UTC (permalink / raw)
To: Borislav Petkov; +Cc: EDAC devel, X86-ML, LKML, Borislav Petkov
(2011/05/10 3:35), Borislav Petkov wrote:
> From: Borislav Petkov <borislav.petkov@amd.com>
>
> Add an mce->inject_flag to denote that we're doing HW injection.
>
> Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
> Acked-by: Ingo Molnar <mingo@elte.hu>
> ---
> arch/x86/include/asm/mce.h | 1 +
> 1 files changed, 1 insertions(+), 0 deletions(-)
>
> diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
> index eb16e94..a2e3dcf 100644
> --- a/arch/x86/include/asm/mce.h
> +++ b/arch/x86/include/asm/mce.h
> @@ -49,6 +49,7 @@
> #define MCJ_CTX_IRQ 2 /* inject context: IRQ */
> #define MCJ_NMI_BROADCAST 4 /* do NMI broadcasting */
> #define MCJ_EXCEPTION 8 /* raise as exception */
> +#define MCJ_HW_INJECT 16 /* do a HW MCE inject, i.e. INT18 */
>
> /* Fields are zero when not available */
> struct mce {
IMHO, we should have better name for this feature; using wrmsr + int$18 is not
the only way to inject mce event to HW. I'd like to suggest MCJ_AMD_HW_INJECT,
MCJ_USE_WRMSR or so instead. Then we can have MCJ_USE_APEI_EINJ and so on, for
various way of MCE injection.
Thanks,
H.Seto
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH -v3 1/6] x86, MCE: Add a HW injection flag
2011-05-10 3:29 ` Hidetoshi Seto
@ 2011-05-10 5:14 ` Borislav Petkov
0 siblings, 0 replies; 9+ messages in thread
From: Borislav Petkov @ 2011-05-10 5:14 UTC (permalink / raw)
To: Hidetoshi Seto; +Cc: Borislav Petkov, EDAC devel, X86-ML, LKML
On Mon, May 09, 2011 at 11:29:27PM -0400, Hidetoshi Seto wrote:
> (2011/05/10 3:35), Borislav Petkov wrote:
> > From: Borislav Petkov <borislav.petkov@amd.com>
> >
> > Add an mce->inject_flag to denote that we're doing HW injection.
> >
> > Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
> > Acked-by: Ingo Molnar <mingo@elte.hu>
> > ---
> > arch/x86/include/asm/mce.h | 1 +
> > 1 files changed, 1 insertions(+), 0 deletions(-)
> >
> > diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
> > index eb16e94..a2e3dcf 100644
> > --- a/arch/x86/include/asm/mce.h
> > +++ b/arch/x86/include/asm/mce.h
> > @@ -49,6 +49,7 @@
> > #define MCJ_CTX_IRQ 2 /* inject context: IRQ */
> > #define MCJ_NMI_BROADCAST 4 /* do NMI broadcasting */
> > #define MCJ_EXCEPTION 8 /* raise as exception */
> > +#define MCJ_HW_INJECT 16 /* do a HW MCE inject, i.e. INT18 */
> >
> > /* Fields are zero when not available */
> > struct mce {
>
> IMHO, we should have better name for this feature; using wrmsr + int$18 is not
> the only way to inject mce event to HW. I'd like to suggest MCJ_AMD_HW_INJECT,
> MCJ_USE_WRMSR or so instead. Then we can have MCJ_USE_APEI_EINJ and so on, for
> various way of MCE injection.
Fair enough, the name might be too generic. Maybe I should change it to
MCJ_HW_MSR_INJECT to denote injecting of hw errors through the MCA MSRs.
--
Regards/Gruss,
Boris.
Advanced Micro Devices GmbH
Einsteinring 24, 85609 Dornach
General Managers: Alberto Bozzo, Andrew Bowd
Registration: Dornach, Gemeinde Aschheim, Landkreis Muenchen
Registergericht Muenchen, HRB Nr. 43632
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2011-05-10 5:14 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-09 18:35 [PATCH -v3 0/6] x86, MCE, AMD: Hardware MCE injection Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 1/6] x86, MCE: Add a HW injection flag Borislav Petkov
2011-05-10 3:29 ` Hidetoshi Seto
2011-05-10 5:14 ` Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 2/6] x86, MCE: Export mce_get_debugfs_dir Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 3/6] EDAC, MCE, AMD: Add function to enable direct write to MCE MSRs Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 4/6] EDAC, MCE, AMD: Convert to debugfs Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 5/6] EDAC, MCE, AMD: Add attributes needed for HW injection Borislav Petkov
2011-05-09 18:35 ` [PATCH -v3 6/6] EDAC, MCE, AMD: Add an injector function Borislav Petkov
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.