Skip to contentSkip to conversation

AMD MCE injection improvs

PATCH In review Borislav Petkov 2 participants 11 messages Oct 8, 2012 – Oct 9, 2012

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover AMD MCE injection improvs

From: Borislav Petkov <[email protected]>

So this basically moves the mce-inject module to arch/x86/ras/ and adds a bunch of features to it.

More importantly, though, it creates all the glue to add the arch/x86/ras/ directory to Kconfig. The idea is to gradually collect RAS-related stuff there.

Tony, please take a look and let me know how do you find the general layout, etc.

Thanks.

Borislav Petkov (6):
x86, RAS: Add a barebones RAS subtree
x86, RAS: Move AMD MCE injection code into ras/ x86, RAS: Convert mce-inject module to debugfs x86, RAS: Add function enabling direct writes to MCE MSRs x86, RAS: Add attributes needed for HW injection x86, RAS: Add an injector function

 arch/x86/Kconfig              |  10 ++
 arch/x86/Makefile             |   3 +
 arch/x86/ras/Kconfig          |  14 +++
 arch/x86/ras/Makefile         |   2 +
 arch/x86/ras/amd/Makefile     |   3 +
 arch/x86/ras/amd/mce-inject.c | 274 ++++++++++++++++++++++++++++++++++++++++++
 drivers/edac/Kconfig          |  10 --
 drivers/edac/mce_amd_inj.c    | 173 --------------------------
 8 files changed, 306 insertions(+), 183 deletions(-)
 create mode 100644 arch/x86/ras/Kconfig
 create mode 100644 arch/x86/ras/Makefile
 create mode 100644 arch/x86/ras/amd/Makefile
 create mode 100644 arch/x86/ras/amd/mce-inject.c
 create mode 100644 arch/x86/ras/ras.c
 delete mode 100644 drivers/edac/mce_amd_inj.c
Signature · 1 line
1.8.0.rc0.18.gf84667d
#1 lore raw

PATCH 1/6 x86, RAS: Add a barebones RAS subtree

From: Borislav Petkov <[email protected]>

This should collect all x86 RAS-related stuff.

---
 arch/x86/Kconfig      | 8 ++++++++
 arch/x86/Makefile     | 3 +++
 arch/x86/ras/Makefile | 1 +
 3 files changed, 12 insertions(+)
 create mode 100644 arch/x86/ras/Makefile
 create mode 100644 arch/x86/ras/ras.c
arch/x86/Kconfig +8 -0
index e0323d67ee42..e5cae3de52ff 100644
@@ -687,6 +687,14 @@ config X86_CYCLONE_TIMER
 	def_bool y
 	depends on X86_SUMMIT
 
+config X86_RAS
+	def_bool y
+	prompt "X86 RAS features"
+	---help---
+	A collection of Reliability, Availability and Serviceability software
+	features which enable hardware error logging and reporting. Leave it
+	at 'y' unless you really know what you're doing.
+
 source "arch/x86/Kconfig.cpu"
 
 config HPET_TIMER
arch/x86/Makefile +3 -0
index 58790bd85c1d..2810e50b670d 100644
@@ -163,6 +163,9 @@ libs-y  += arch/x86/lib/
 # See arch/x86/Kbuild for content of core part of the kernel
 core-y += arch/x86/
 
+# RAS support
+core-$(CONFIG_X86_RAS)		+= arch/x86/ras/
+
 # drivers-y are linked after core-y
 drivers-$(CONFIG_MATH_EMULATION) += arch/x86/math-emu/
 drivers-$(CONFIG_PCI)            += arch/x86/pci/
arch/x86/ras/Makefile new file +1 -0
new file mode 100644
index 000000000000..7a70bb5cd057
@@ -0,0 +1 @@
+obj-y		:= ras.o
arch/x86/ras/ras.c new file +0 -0
new file mode 100644
index 000000000000..e69de29bb2d1
Signature · 1 line
1.8.0.rc0.18.gf84667d
maintainer
#2 lore raw

Re: [PATCH 1/6] x86, RAS: Add a barebones RAS subtree

arch/x86/Kconfig config X86_CYCLONE_TIMER · line 697

Quoted 8 lines · Borislav Petkov
arch/x86/Kconfig +8 -0
+config X86_RAS
+       def_bool y
+       prompt "X86 RAS features"
+       ---help---
+       A collection of Reliability, Availability and Serviceability software
+       features which enable hardware error logging and reporting. Leave it
+       at 'y' unless you really know what you're doing.
+

The intent of "X86_RAS" is just to show/hide all the menu options for the individual features - which will all use
depends on X86_RAS
right? Having this set to "y" doesn't actually enable any of the features - they all have their own CONFIG_* variables.

Perhaps we could make that clearer in the help text? And ditch the "Leave it at 'y' ... ", I don't think it helps anyone.

-Tony

#3 lore raw

Re: [PATCH 1/6] x86, RAS: Add a barebones RAS subtree

Quoted 16 lines · Tony Luck

Review

Quoted 8 lines · Borislav Petkov
(quoted diff) +8 -0
+config X86_RAS
+       def_bool y
+       prompt "X86 RAS features"
+       ---help---
+       A collection of Reliability, Availability and Serviceability software
+       features which enable hardware error logging and reporting. Leave it
+       at 'y' unless you really know what you're doing.
+

The intent of "X86_RAS" is just to show/hide all the menu options for the individual features - which will all use
depends on X86_RAS
right? Having this set to "y" doesn't actually enable any of the features - they all have their own CONFIG_* variables.

Quoted 2 lines

Perhaps we could make that clearer in the help text? And ditch the "Leave it at 'y' ... ", I don't think it helps anyone.

Good point. I've changed it to a simple bool which opens a submenu when enabled (diff ontop):

arch/x86/Kconfig +2 -4
index 85f666390b5e..d39c2fc20a81 100644
@@ -688,12 +688,10 @@ config X86_CYCLONE_TIMER
        depends on X86_SUMMIT
 
 config X86_RAS
-       def_bool y
-       prompt "X86 RAS features"
+       bool "X86 RAS features"
        ---help---
        A collection of Reliability, Availability and Serviceability software
-       features which enable hardware error logging and reporting. Leave it
-       at 'y' unless you really know what you're doing.
+       features which enable hardware error logging and reporting.
 

The def_bool y intent was from earlier but it materialized in a patch which I sent last week or so which makes CONFIG_X86_MCE enabled by default so no need to enable those additional RAS stuff by default.

Thanks.

Signature · 8 lines
Regards/Gruss,
Boris.

Advanced Micro Devices GmbH
Einsteinring 24, 85609 Dornach
GM: Alberto Bozzo
Reg: Dornach, Landkreis Muenchen
HRB Nr. 43632 WEEE Registernr: 129 19551
#4 lore raw

PATCH 2/6 x86, RAS: Move AMD MCE injection code into ras/

In reply to Borislav Petkov

From: Borislav Petkov <[email protected]>

This is the code collecting all AMD MCE injection methods.

No functionality change.

---
 arch/x86/Kconfig                                            |  2 ++
 arch/x86/ras/Kconfig                                        | 11 +++++++++++
 arch/x86/ras/Makefile                                       |  3 ++-
 arch/x86/ras/amd/Makefile                                   |  3 +++
 drivers/edac/mce_amd_inj.c => arch/x86/ras/amd/mce-inject.c |  2 +-
 drivers/edac/Kconfig                                        | 10 ----------
 6 files changed, 19 insertions(+), 12 deletions(-)
 create mode 100644 arch/x86/ras/Kconfig
 create mode 100644 arch/x86/ras/amd/Makefile
 rename drivers/edac/mce_amd_inj.c => arch/x86/ras/amd/mce-inject.c (99%)
arch/x86/Kconfig +2 -0
index e5cae3de52ff..85f666390b5e 100644
@@ -695,6 +695,8 @@ config X86_RAS
 	features which enable hardware error logging and reporting. Leave it
 	at 'y' unless you really know what you're doing.
 
+source "arch/x86/ras/Kconfig"
+
 source "arch/x86/Kconfig.cpu"
 
 config HPET_TIMER
arch/x86/ras/Kconfig new file +11 -0
new file mode 100644
index 000000000000..9362f54bfe0f
@@ -0,0 +1,11 @@
+menu "AMD RAS features"
+	depends on X86_RAS && CPU_SUP_AMD
+
+config X86_AMD_MCE_INJECT
+	tristate "Simple MCE injection interface over /sysfs"
+	default n
+	help
+	  This is a simple interface to inject MCEs over /sysfs and test
+	  the MCE decoding code.
+
+endmenu
arch/x86/ras/Makefile +2 -1
index 7a70bb5cd057..4d8d37a301c4 100644
@@ -1 +1,2 @@
-obj-y		:= ras.o
+obj-y				:= ras.o
+obj-$(CONFIG_X86_MCE)		+= amd/
arch/x86/ras/amd/Makefile new file +3 -0
new file mode 100644
index 000000000000..74f2a1e676b4
@@ -0,0 +1,3 @@
+amd_mce_inject-y				:= mce-inject.o
+obj-$(CONFIG_X86_AMD_MCE_INJECT)		+= amd_mce_inject.o
+
arch/x86/ras/amd/mce-inject.c renamed from drivers/edac/mce_amd_inj.c +1 -1
similarity index 99%
rename from drivers/edac/mce_amd_inj.c
rename to arch/x86/ras/amd/mce-inject.c
index 66b5151c1080..90aa317b09a6 100644
@@ -16,7 +16,7 @@
 #include <linux/module.h>
 #include <asm/mce.h>
 
-#include "mce_amd.h"
+#include "../../../drivers/edac/mce_amd.h"
 
 struct edac_mce_attr {
 	struct attribute attr;
drivers/edac/Kconfig +0 -10
index bb82d6be793c..0e6afbd7749c 100644
@@ -59,16 +59,6 @@ config EDAC_DECODE_MCE
 	  which occur really early upon boot, before the module infrastructure
 	  has been initialized.
 
-config EDAC_MCE_INJ
-	tristate "Simple MCE injection interface over /sysfs"
-	depends on EDAC_DECODE_MCE
-	default n
-	help
-	  This is a simple interface to inject MCEs over /sysfs and test
-	  the MCE decoding code in EDAC.
-
-	  This is currently AMD-only.
-
 config EDAC_MM_EDAC
 	tristate "Main Memory EDAC (Error Detection And Correction) reporting"
 	help
Signature · 1 line
1.8.0.rc0.18.gf84667d
#5 lore raw

PATCH 3/6 x86, RAS: Convert mce-inject module to debugfs

In reply to Borislav Petkov

From: Borislav Petkov <[email protected]>

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.

---
 arch/x86/ras/Kconfig          |  11 ++-
 arch/x86/ras/amd/mce-inject.c | 182 ++++++++++++++++++------------------------
 2 files changed, 86 insertions(+), 107 deletions(-)
arch/x86/ras/Kconfig +7 -4
index 9362f54bfe0f..4334ab92b3b0 100644
@@ -2,10 +2,13 @@ menu "AMD RAS features"
 	depends on X86_RAS && CPU_SUP_AMD
 
 config X86_AMD_MCE_INJECT
-	tristate "Simple MCE injection interface over /sysfs"
+	tristate "Inject MCEs"
+	depends on DEBUG_FS
 	default n
-	help
-	  This is a simple interface to inject MCEs over /sysfs and test
-	  the MCE decoding code.
+	---help---
+	  This is a simple debugfs interface to inject MCEs and test different
+	  aspects of the MCE handling code.
+
+	  WARNING: Do not even assume that this interface is staying stable!
 
 endmenu
arch/x86/ras/amd/mce-inject.c +79 -103

252 lines not on this page · raw message

Signature · 1 line
1.8.0.rc0.18.gf84667d
#6 lore raw

PATCH 4/6 x86, RAS: Add function enabling direct writes to MCE MSRs

In reply to Borislav Petkov

From: Borislav Petkov <[email protected]>

Normally, writing to MCE MSRs causes a #GP. Add a function to enable direct accesses to those MSRs.

---
 arch/x86/ras/amd/mce-inject.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)
arch/x86/ras/amd/mce-inject.c +24 -0
index 66969eab5591..c0c811579ce9 100644
@@ -55,6 +55,30 @@ 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
+ * 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) {
+		pr_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)
+		pr_err("%s: error writing HWCR\n", __func__);
+
+	return err;
+}
+
+/*
  * This denotes into which bank we're injecting and triggers
  * the injection, at the same time.
  */
Signature · 1 line
1.8.0.rc0.18.gf84667d
#7 lore raw

PATCH 5/6 x86, RAS: Add attributes needed for HW injection

In reply to Borislav Petkov

From: Borislav Petkov <[email protected]>

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 'cpu' attribute.

---
 arch/x86/ras/amd/mce-inject.c | 55 +++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)
arch/x86/ras/amd/mce-inject.c +55 -0
index c0c811579ce9..b55d69fbd6e3 100644
@@ -79,6 +79,59 @@ 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_EXCEPTION);
+
+	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_EXCEPTION;
+		break;
+
+	case 1:
+		m->inject_flags |= MCJ_EXCEPTION;
+		break;
+
+	default:
+		pr_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 >= nr_cpu_ids || !cpu_online(val)) {
+		pr_err("%s: Invalid 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.
  */
@@ -119,6 +172,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 init_mce_inject(void)
Signature · 1 line
1.8.0.rc0.18.gf84667d
#8 lore raw

PATCH 6/6 x86, RAS: Add an injector function

In reply to Borislav Petkov

From: Borislav Petkov <[email protected]>

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.

---
 arch/x86/ras/amd/mce-inject.c | 50 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 48 insertions(+), 2 deletions(-)
arch/x86/ras/amd/mce-inject.c +48 -2
index b55d69fbd6e3..24a1c870cd18 100644
@@ -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_EXCEPTION)) {
+		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.
@@ -147,8 +194,7 @@ static int inj_bank_set(void *data, u64 val)
 	}
 
 	m->bank = val;
-
-	amd_decode_mce(NULL, 0, m);
+	do_inject();
 
 	return 0;
 }
Signature · 1 line
1.8.0.rc0.18.gf84667d
maintainer
#9 lore raw
In reply to Borislav Petkov
Quoted 1 line · Borislav Petkov
 create mode 100644 arch/x86/ras/ras.c

Overall it looks good - but I'm a bit puzzled by this ras.c file that gets created as an empty file in part1, and is still empty at the end of the series.

What is going to go into it?

-Tony

#10 lore raw
Quoted 8 lines · Tony Luck
Quoted 1 line · Borislav Petkov
 create mode 100644 arch/x86/ras/ras.c

Overall it looks good - but I'm a bit puzzled by this ras.c file that gets created as an empty file in part1, and is still empty at the end of the series.

What is going to go into it?

Yeah, maybe it should be called core.c and all the shared functionality would go there. I put it there initially for the first patch but I realize now, we won't need it just yet - I'll drop it.

Thanks.

Signature · 8 lines
Regards/Gruss,
Boris.

Advanced Micro Devices GmbH
Einsteinring 24, 85609 Dornach
GM: Alberto Bozzo
Reg: Dornach, Landkreis Muenchen
HRB Nr. 43632 WEEE Registernr: 129 19551