[PATCH] arm64: crypto: Add ARM64 CRC32 hw accelerated module

2014-11-19 Thread Yazen Ghannam
This module registers a crc32 algorithm and a crc32c algorithm
that use the optional CRC32 and CRC32C instructions in ARMv8.

Tested on AMD Seattle.

Improvement compared to crc32c-generic algorithm:
TCRYPT CRC32C speed test shows ~450% speedup.
Simple dd write tests to btrfs filesystem show ~30% speedup.

Signed-off-by: Yazen Ghannam yazen.ghan...@linaro.org
Acked-by: Steve Capper steve.cap...@linaro.org
Acked-by: Ard Biesheuvel ard.biesheu...@linaro.org
---
 arch/arm64/crypto/Kconfig   |   4 +
 arch/arm64/crypto/Makefile  |   4 +
 arch/arm64/crypto/crc32-arm64.c | 274 
 3 files changed, 282 insertions(+)
 create mode 100644 arch/arm64/crypto/crc32-arm64.c

diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig
index 5562652..c1a0468 100644
--- a/arch/arm64/crypto/Kconfig
+++ b/arch/arm64/crypto/Kconfig
@@ -50,4 +50,8 @@ config CRYPTO_AES_ARM64_NEON_BLK
select CRYPTO_AES
select CRYPTO_ABLK_HELPER
 
+config CRYPTO_CRC32_ARM64
+   tristate CRC32 and CRC32C using optional ARMv8 instructions
+   depends on ARM64
+   select CRYPTO_HASH
 endif
diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
index a3f935f..5720608 100644
--- a/arch/arm64/crypto/Makefile
+++ b/arch/arm64/crypto/Makefile
@@ -34,5 +34,9 @@ AFLAGS_aes-neon.o := -DINTERLEAVE=4
 
 CFLAGS_aes-glue-ce.o   := -DUSE_V8_CRYPTO_EXTENSIONS
 
+obj-$(CONFIG_CRYPTO_CRC32_ARM64) += crc32-arm64.o
+
+CFLAGS_crc32-arm64.o   := -mcpu=generic+crc
+
 $(obj)/aes-glue-%.o: $(src)/aes-glue.c FORCE
$(call if_changed_rule,cc_o_c)
diff --git a/arch/arm64/crypto/crc32-arm64.c b/arch/arm64/crypto/crc32-arm64.c
new file mode 100644
index 000..9499199
--- /dev/null
+++ b/arch/arm64/crypto/crc32-arm64.c
@@ -0,0 +1,274 @@
+/*
+ * crc32-arm64.c - CRC32 and CRC32C using optional ARMv8 instructions
+ *
+ * Module based on crypto/crc32c_generic.c
+ *
+ * CRC32 loop taken from Ed Nevill's Hadoop CRC patch
+ * 
http://mail-archives.apache.org/mod_mbox/hadoop-common-dev/201406.mbox/%3C1403687030.3355.19.camel%40localhost.localdomain%3E
+ *
+ * Using inline assembly instead of intrinsics in order to be backwards
+ * compatible with older compilers.
+ *
+ * Copyright (C) 2014 Linaro Ltd yazen.ghan...@linaro.org
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include linux/unaligned/access_ok.h
+#include linux/cpufeature.h
+#include linux/init.h
+#include linux/kernel.h
+#include linux/module.h
+#include linux/string.h
+
+#include crypto/internal/hash.h
+
+MODULE_AUTHOR(Yazen Ghannam yazen.ghan...@linaro.org);
+MODULE_DESCRIPTION(CRC32 and CRC32C using optional ARMv8 instructions);
+MODULE_LICENSE(GPL v2);
+
+#define CRC32X(crc, value) __asm__(crc32x %w[c], %w[c], 
%x[v]:[c]+r(crc):[v]r(value))
+#define CRC32W(crc, value) __asm__(crc32w %w[c], %w[c], 
%w[v]:[c]+r(crc):[v]r(value))
+#define CRC32H(crc, value) __asm__(crc32h %w[c], %w[c], 
%w[v]:[c]+r(crc):[v]r(value))
+#define CRC32B(crc, value) __asm__(crc32b %w[c], %w[c], 
%w[v]:[c]+r(crc):[v]r(value))
+#define CRC32CX(crc, value) __asm__(crc32cx %w[c], %w[c], 
%x[v]:[c]+r(crc):[v]r(value))
+#define CRC32CW(crc, value) __asm__(crc32cw %w[c], %w[c], 
%w[v]:[c]+r(crc):[v]r(value))
+#define CRC32CH(crc, value) __asm__(crc32ch %w[c], %w[c], 
%w[v]:[c]+r(crc):[v]r(value))
+#define CRC32CB(crc, value) __asm__(crc32cb %w[c], %w[c], 
%w[v]:[c]+r(crc):[v]r(value))
+
+static u32 crc32_arm64_le_hw(u32 crc, const u8 *p, unsigned int len)
+{
+   s64 length = len;
+
+   while ((length -= sizeof(u64)) = 0) {
+   CRC32X(crc, get_unaligned_le64(p));
+   p += sizeof(u64);
+   }
+
+   /* The following is more efficient than the straight loop */
+   if (length  sizeof(u32)) {
+   CRC32W(crc, get_unaligned_le32(p));
+   p += sizeof(u32);
+   }
+   if (length  sizeof(u16)) {
+   CRC32H(crc, get_unaligned_le16(p));
+   p += sizeof(u16);
+   }
+   if (length  sizeof(u8))
+   CRC32B(crc, *p);
+
+   return crc;
+}
+
+static u32 crc32c_arm64_le_hw(u32 crc, const u8 *p, unsigned int len)
+{
+   s64 length = len;
+
+   while ((length -= sizeof(u64)) = 0) {
+   CRC32CX(crc, get_unaligned_le64(p));
+   p += sizeof(u64);
+   }
+
+   /* The following is more efficient than the straight loop */
+   if (length  sizeof(u32)) {
+   CRC32CW(crc, get_unaligned_le32(p));
+   p += sizeof(u32);
+   }
+   if (length  sizeof(u16)) {
+   CRC32CH(crc, get_unaligned_le16(p));
+   p += sizeof(u16);
+   }
+   if (length  sizeof(u8))
+   CRC32CB(crc, *p);
+
+   return crc;
+}
+
+#define CHKSUM_BLOCK_SIZE  1
+#define CHKSUM_DIGEST_SIZE 4
+
+struct chksum_ctx

Re: [PATCH] arm64: crypto: Add ARM64 CRC32 hw accelerated module

2014-11-20 Thread Yazen Ghannam
+linux-arm-ker...@lists.infradead.org

On Wed, Nov 19, 2014 at 11:19 AM, Yazen Ghannam
yazen.ghan...@linaro.org wrote:
 This module registers a crc32 algorithm and a crc32c algorithm
 that use the optional CRC32 and CRC32C instructions in ARMv8.

 Tested on AMD Seattle.

 Improvement compared to crc32c-generic algorithm:
 TCRYPT CRC32C speed test shows ~450% speedup.
 Simple dd write tests to btrfs filesystem show ~30% speedup.

 Signed-off-by: Yazen Ghannam yazen.ghan...@linaro.org
 Acked-by: Steve Capper steve.cap...@linaro.org
 Acked-by: Ard Biesheuvel ard.biesheu...@linaro.org
 ---
  arch/arm64/crypto/Kconfig   |   4 +
  arch/arm64/crypto/Makefile  |   4 +
  arch/arm64/crypto/crc32-arm64.c | 274 
 
  3 files changed, 282 insertions(+)
  create mode 100644 arch/arm64/crypto/crc32-arm64.c

 diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig
 index 5562652..c1a0468 100644
 --- a/arch/arm64/crypto/Kconfig
 +++ b/arch/arm64/crypto/Kconfig
 @@ -50,4 +50,8 @@ config CRYPTO_AES_ARM64_NEON_BLK
 select CRYPTO_AES
 select CRYPTO_ABLK_HELPER

 +config CRYPTO_CRC32_ARM64
 +   tristate CRC32 and CRC32C using optional ARMv8 instructions
 +   depends on ARM64
 +   select CRYPTO_HASH
  endif
 diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
 index a3f935f..5720608 100644
 --- a/arch/arm64/crypto/Makefile
 +++ b/arch/arm64/crypto/Makefile
 @@ -34,5 +34,9 @@ AFLAGS_aes-neon.o := -DINTERLEAVE=4

  CFLAGS_aes-glue-ce.o   := -DUSE_V8_CRYPTO_EXTENSIONS

 +obj-$(CONFIG_CRYPTO_CRC32_ARM64) += crc32-arm64.o
 +
 +CFLAGS_crc32-arm64.o   := -mcpu=generic+crc
 +
  $(obj)/aes-glue-%.o: $(src)/aes-glue.c FORCE
 $(call if_changed_rule,cc_o_c)
 diff --git a/arch/arm64/crypto/crc32-arm64.c b/arch/arm64/crypto/crc32-arm64.c
 new file mode 100644
 index 000..9499199
 --- /dev/null
 +++ b/arch/arm64/crypto/crc32-arm64.c
 @@ -0,0 +1,274 @@
 +/*
 + * crc32-arm64.c - CRC32 and CRC32C using optional ARMv8 instructions
 + *
 + * Module based on crypto/crc32c_generic.c
 + *
 + * CRC32 loop taken from Ed Nevill's Hadoop CRC patch
 + * 
 http://mail-archives.apache.org/mod_mbox/hadoop-common-dev/201406.mbox/%3C1403687030.3355.19.camel%40localhost.localdomain%3E
 + *
 + * Using inline assembly instead of intrinsics in order to be backwards
 + * compatible with older compilers.
 + *
 + * Copyright (C) 2014 Linaro Ltd yazen.ghan...@linaro.org
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include linux/unaligned/access_ok.h
 +#include linux/cpufeature.h
 +#include linux/init.h
 +#include linux/kernel.h
 +#include linux/module.h
 +#include linux/string.h
 +
 +#include crypto/internal/hash.h
 +
 +MODULE_AUTHOR(Yazen Ghannam yazen.ghan...@linaro.org);
 +MODULE_DESCRIPTION(CRC32 and CRC32C using optional ARMv8 instructions);
 +MODULE_LICENSE(GPL v2);
 +
 +#define CRC32X(crc, value) __asm__(crc32x %w[c], %w[c], 
 %x[v]:[c]+r(crc):[v]r(value))
 +#define CRC32W(crc, value) __asm__(crc32w %w[c], %w[c], 
 %w[v]:[c]+r(crc):[v]r(value))
 +#define CRC32H(crc, value) __asm__(crc32h %w[c], %w[c], 
 %w[v]:[c]+r(crc):[v]r(value))
 +#define CRC32B(crc, value) __asm__(crc32b %w[c], %w[c], 
 %w[v]:[c]+r(crc):[v]r(value))
 +#define CRC32CX(crc, value) __asm__(crc32cx %w[c], %w[c], 
 %x[v]:[c]+r(crc):[v]r(value))
 +#define CRC32CW(crc, value) __asm__(crc32cw %w[c], %w[c], 
 %w[v]:[c]+r(crc):[v]r(value))
 +#define CRC32CH(crc, value) __asm__(crc32ch %w[c], %w[c], 
 %w[v]:[c]+r(crc):[v]r(value))
 +#define CRC32CB(crc, value) __asm__(crc32cb %w[c], %w[c], 
 %w[v]:[c]+r(crc):[v]r(value))
 +
 +static u32 crc32_arm64_le_hw(u32 crc, const u8 *p, unsigned int len)
 +{
 +   s64 length = len;
 +
 +   while ((length -= sizeof(u64)) = 0) {
 +   CRC32X(crc, get_unaligned_le64(p));
 +   p += sizeof(u64);
 +   }
 +
 +   /* The following is more efficient than the straight loop */
 +   if (length  sizeof(u32)) {
 +   CRC32W(crc, get_unaligned_le32(p));
 +   p += sizeof(u32);
 +   }
 +   if (length  sizeof(u16)) {
 +   CRC32H(crc, get_unaligned_le16(p));
 +   p += sizeof(u16);
 +   }
 +   if (length  sizeof(u8))
 +   CRC32B(crc, *p);
 +
 +   return crc;
 +}
 +
 +static u32 crc32c_arm64_le_hw(u32 crc, const u8 *p, unsigned int len)
 +{
 +   s64 length = len;
 +
 +   while ((length -= sizeof(u64)) = 0) {
 +   CRC32CX(crc, get_unaligned_le64(p));
 +   p += sizeof(u64);
 +   }
 +
 +   /* The following is more efficient than the straight loop */
 +   if (length  sizeof(u32)) {
 +   CRC32CW(crc, get_unaligned_le32(p));
 +   p += sizeof(u32);
 +   }
 +   if (length  sizeof(u16)) {
 +   CRC32CH(crc

Re: [PATCH] arm64: crypto: Add ARM64 CRC32 hw accelerated module

2014-11-25 Thread Yazen Ghannam
Herbert,

I have a couple of questions.

1) To which release has the patch been applied? We're just curious for
tracking purposes.

2) I'd like to apply Ard's suggestion. Do you prefer a second version
of this patch or a separate fixup patch?

Thanks,
Yazen

On Fri, Nov 21, 2014 at 3:39 PM, Ard Biesheuvel
ard.biesheu...@linaro.org wrote:
 On 20 November 2014 15:22, Yazen Ghannam yazen.ghan...@linaro.org wrote:
 +linux-arm-ker...@lists.infradead.org

 On Wed, Nov 19, 2014 at 11:19 AM, Yazen Ghannam
 yazen.ghan...@linaro.org wrote:
 This module registers a crc32 algorithm and a crc32c algorithm
 that use the optional CRC32 and CRC32C instructions in ARMv8.

 Tested on AMD Seattle.

 Improvement compared to crc32c-generic algorithm:
 TCRYPT CRC32C speed test shows ~450% speedup.
 Simple dd write tests to btrfs filesystem show ~30% speedup.

 Signed-off-by: Yazen Ghannam yazen.ghan...@linaro.org
 Acked-by: Steve Capper steve.cap...@linaro.org
 Acked-by: Ard Biesheuvel ard.biesheu...@linaro.org
 ---
  arch/arm64/crypto/Kconfig   |   4 +
  arch/arm64/crypto/Makefile  |   4 +
  arch/arm64/crypto/crc32-arm64.c | 274 
 
  3 files changed, 282 insertions(+)
  create mode 100644 arch/arm64/crypto/crc32-arm64.c

 diff --git a/arch/arm64/crypto/Kconfig b/arch/arm64/crypto/Kconfig
 index 5562652..c1a0468 100644
 --- a/arch/arm64/crypto/Kconfig
 +++ b/arch/arm64/crypto/Kconfig
 @@ -50,4 +50,8 @@ config CRYPTO_AES_ARM64_NEON_BLK
 select CRYPTO_AES
 select CRYPTO_ABLK_HELPER

 +config CRYPTO_CRC32_ARM64
 +   tristate CRC32 and CRC32C using optional ARMv8 instructions
 +   depends on ARM64
 +   select CRYPTO_HASH
  endif
 diff --git a/arch/arm64/crypto/Makefile b/arch/arm64/crypto/Makefile
 index a3f935f..5720608 100644
 --- a/arch/arm64/crypto/Makefile
 +++ b/arch/arm64/crypto/Makefile
 @@ -34,5 +34,9 @@ AFLAGS_aes-neon.o := -DINTERLEAVE=4

  CFLAGS_aes-glue-ce.o   := -DUSE_V8_CRYPTO_EXTENSIONS

 +obj-$(CONFIG_CRYPTO_CRC32_ARM64) += crc32-arm64.o
 +
 +CFLAGS_crc32-arm64.o   := -mcpu=generic+crc
 +
  $(obj)/aes-glue-%.o: $(src)/aes-glue.c FORCE
 $(call if_changed_rule,cc_o_c)
 diff --git a/arch/arm64/crypto/crc32-arm64.c 
 b/arch/arm64/crypto/crc32-arm64.c
 new file mode 100644
 index 000..9499199
 --- /dev/null
 +++ b/arch/arm64/crypto/crc32-arm64.c
 @@ -0,0 +1,274 @@
 +/*
 + * crc32-arm64.c - CRC32 and CRC32C using optional ARMv8 instructions
 + *
 + * Module based on crypto/crc32c_generic.c
 + *
 + * CRC32 loop taken from Ed Nevill's Hadoop CRC patch
 + * 
 http://mail-archives.apache.org/mod_mbox/hadoop-common-dev/201406.mbox/%3C1403687030.3355.19.camel%40localhost.localdomain%3E
 + *
 + * Using inline assembly instead of intrinsics in order to be backwards
 + * compatible with older compilers.
 + *
 + * Copyright (C) 2014 Linaro Ltd yazen.ghan...@linaro.org
 + *
 + * This program is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include linux/unaligned/access_ok.h

 One final nit: you should not be including this file directly.
 You should include asm/unaligned.h instead, and it is up to the
 architecture to include either access_ok.h or another implementation
 of get_unaligned_leXX

 Granted, the distinction is fairly artificial on arm64, but it does
 increase the portability of the code.

 --
 Ard.


 +#include linux/cpufeature.h
 +#include linux/init.h
 +#include linux/kernel.h
 +#include linux/module.h
 +#include linux/string.h
 +
 +#include crypto/internal/hash.h
 +
 +MODULE_AUTHOR(Yazen Ghannam yazen.ghan...@linaro.org);
 +MODULE_DESCRIPTION(CRC32 and CRC32C using optional ARMv8 instructions);
 +MODULE_LICENSE(GPL v2);
 +
 +#define CRC32X(crc, value) __asm__(crc32x %w[c], %w[c], 
 %x[v]:[c]+r(crc):[v]r(value))
 +#define CRC32W(crc, value) __asm__(crc32w %w[c], %w[c], 
 %w[v]:[c]+r(crc):[v]r(value))
 +#define CRC32H(crc, value) __asm__(crc32h %w[c], %w[c], 
 %w[v]:[c]+r(crc):[v]r(value))
 +#define CRC32B(crc, value) __asm__(crc32b %w[c], %w[c], 
 %w[v]:[c]+r(crc):[v]r(value))
 +#define CRC32CX(crc, value) __asm__(crc32cx %w[c], %w[c], 
 %x[v]:[c]+r(crc):[v]r(value))
 +#define CRC32CW(crc, value) __asm__(crc32cw %w[c], %w[c], 
 %w[v]:[c]+r(crc):[v]r(value))
 +#define CRC32CH(crc, value) __asm__(crc32ch %w[c], %w[c], 
 %w[v]:[c]+r(crc):[v]r(value))
 +#define CRC32CB(crc, value) __asm__(crc32cb %w[c], %w[c], 
 %w[v]:[c]+r(crc):[v]r(value))
 +
 +static u32 crc32_arm64_le_hw(u32 crc, const u8 *p, unsigned int len)
 +{
 +   s64 length = len;
 +
 +   while ((length -= sizeof(u64)) = 0) {
 +   CRC32X(crc, get_unaligned_le64(p));
 +   p += sizeof(u64);
 +   }
 +
 +   /* The following is more efficient than the straight loop */
 +   if (length  sizeof(u32)) {
 +   CRC32W(crc, get_unaligned_le32(p));
 +   p += sizeof(u32

[PATCH] x86/AMD: Fix Socket ID for LLC topology for AMD Fam17h systems

2016-08-31 Thread Yazen Ghannam
The Socket ID is ApicId[bits] on Fam17h systems.

Change substraction to logical AND when extracting socket_id
from c->apicid.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/amd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index f5c69d8..479555f 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -365,7 +365,7 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
 if (c->x86 != 0x17 || !cpuid_edx(0x8006))
return;
 
-   socket_id   = (c->apicid >> bits) - 1;
+   socket_id   = (c->apicid >> bits) & 1;
core_complex_id = (c->apicid & ((1 << bits) - 1)) >> 3;
 
per_cpu(cpu_llc_id, cpu) = (socket_id << 3) | core_complex_id;
-- 
1.9.1



[PATCH v2] x86/AMD: Fix Socket ID for LLC topology for AMD Fam17h systems

2016-09-02 Thread Yazen Ghannam
Socket ID is an unsigned value and starts at 0. Subtracting 1
from it is incorrect and the result will underflow if
socket_id=0.

Remove substraction when extracting socket_id from c->apicid.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
http://lkml.kernel.org/r/1472674900-60688-1-git-send-email-yazen.ghan...@amd.com

v1->v2:
* Don't do logical AND so as to not restrict # of sockets to 2.

 arch/x86/kernel/cpu/amd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index f3d8a92..793bc23 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -365,7 +365,7 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
 if (c->x86 != 0x17 || !cpuid_edx(0x8006))
return;
 
-   socket_id   = (c->apicid >> bits) - 1;
+   socket_id   = c->apicid >> bits;
core_complex_id = (c->apicid & ((1 << bits) - 1)) >> 3;
 
per_cpu(cpu_llc_id, cpu) = (socket_id << 3) | core_complex_id;
-- 
1.9.1



[PATCH] x86/AMD: Fix LLC ID for AMD Fam17h systems

2016-10-26 Thread Yazen Ghannam
Fix an underflow bug with the current Fam17h LLC ID derivation by
simplifying the derivation, and also move it into amd_get_topology().

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
Cc: sta...@vger.kernel.org # v4.6..
Fixes: 3849e91f571d ("x86/AMD: Fix last level cache topology for AMD Fam17h 
systems")
---
 arch/x86/kernel/cpu/amd.c | 35 +++
 1 file changed, 19 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index b81fe2d..babb93a 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -314,11 +314,30 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
smp_num_siblings = ((ebx >> 8) & 3) + 1;
c->x86_max_cores /= smp_num_siblings;
c->cpu_core_id = ebx & 0xff;
+
+   /*
+* We may have multiple LLCs if L3 Caches exist, so check if we
+* have an L3 cache by looking at the L3 cache cpuid leaf.
+*/
+   if (cpuid_edx(0x8006)) {
+   /* LLC is at the Node level. */
+   if (c->x86 == 0x15)
+   per_cpu(cpu_llc_id, cpu) = node_id;
+
+   /*
+* LLC is at the Core Complex level.
+* Core Complex Id is ApicId[3].
+*/
+   else if (c->x86 == 0x17)
+   per_cpu(cpu_llc_id, cpu) = c->initial_apicid >> 
3;
+   }
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
u64 value;
 
rdmsrl(MSR_FAM10H_NODE_ID, value);
node_id = value & 7;
+
+   per_cpu(cpu_llc_id, cpu) = node_id;
} else
return;
 
@@ -329,9 +348,6 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_AMD_DCM);
cus_per_node = c->x86_max_cores / nodes_per_socket;
 
-   /* store NodeID, use llc_shared_map to store sibling info */
-   per_cpu(cpu_llc_id, cpu) = node_id;
-
/* core id has to be in the [0 .. cores_per_node - 1] range */
c->cpu_core_id %= cus_per_node;
}
@@ -347,7 +363,6 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
 #ifdef CONFIG_SMP
unsigned bits;
int cpu = smp_processor_id();
-   unsigned int socket_id, core_complex_id;
 
bits = c->x86_coreid_bits;
/* Low order bits define the core id (index of core in socket) */
@@ -357,18 +372,6 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
/* use socket ID also for last level cache */
per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
amd_get_topology(c);
-
-   /*
-* Fix percpu cpu_llc_id here as LLC topology is different
-* for Fam17h systems.
-*/
-if (c->x86 != 0x17 || !cpuid_edx(0x8006))
-   return;
-
-   socket_id   = (c->apicid >> bits) - 1;
-   core_complex_id = (c->apicid & ((1 << bits) - 1)) >> 3;
-
-   per_cpu(cpu_llc_id, cpu) = (socket_id << 3) | core_complex_id;
 #endif
 }
 
-- 
1.9.1



[PATCH v2 2/2] x86/AMD: Group cpu_llc_id assignment by topology feature and family

2016-10-28 Thread Yazen Ghannam
Currently, we assume that a system has multiple last level caches only if
there are multiple nodes, and that the cpu_llc_id is equal to the node_id.
This no longer applies since Fam17h can have multiple last level caches
within a node.

So group the cpu_llc_id assignment by topology feature and family.

The NODEID_MSR feature only applies to Fam10h in which case the llc is at
the node level.

The TOPOEXT feature is used on families 15h, 16h and 17h. So far we only
see multiple last level caches if L3 caches are available. Otherwise, the
cpu_llc_id will default to be the phys_proc_id. We have L3 caches only on
families 15h and 17h. On Fam15h, the llc is at the node level. On Fam17h,
the llc is at the core complex level and can be found by right shifting the
apicid. Also, keep the family checks explicit so that new families will
fall back to the default.

Single node systems in families 10h and 15h will have a Node ID of 0 which
will be the same as the phys_proc_id, so we don't need to check for
multiple nodes before using the node_id.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/amd.c | 32 
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index c3fc337..be70345 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -314,11 +314,31 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
smp_num_siblings = ((ebx >> 8) & 3) + 1;
c->x86_max_cores /= smp_num_siblings;
c->cpu_core_id = ebx & 0xff;
+
+   /*
+* We may have multiple LLCs if L3 caches exist, so check if we
+* have an L3 cache by looking at the L3 cache cpuid leaf.
+*/
+   if (cpuid_edx(0x8006)) {
+   if (c->x86 == 0x15) {
+   /* LLC is at the node level. */
+   per_cpu(cpu_llc_id, cpu) = node_id;
+
+   } else if (c->x86 == 0x17) {
+   /*
+* LLC is at the core complex level.
+* Core complex id is ApicId[3].
+*/
+   per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
+   }
+   }
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
u64 value;
 
rdmsrl(MSR_FAM10H_NODE_ID, value);
node_id = value & 7;
+
+   per_cpu(cpu_llc_id, cpu) = node_id;
} else
return;
 
@@ -329,9 +349,6 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_AMD_DCM);
cus_per_node = c->x86_max_cores / nodes_per_socket;
 
-   /* store NodeID, use llc_shared_map to store sibling info */
-   per_cpu(cpu_llc_id, cpu) = node_id;
-
/* core id has to be in the [0 .. cores_per_node - 1] range */
c->cpu_core_id %= cus_per_node;
}
@@ -356,15 +373,6 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
/* use socket ID also for last level cache */
per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
amd_get_topology(c);
-
-   /*
-* Fix percpu cpu_llc_id here as LLC topology is different
-* for Fam17h systems.
-*/
-if (c->x86 != 0x17 || !cpuid_edx(0x8006))
-   return;
-
-   per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
 #endif
 }
 
-- 
1.9.1



[PATCH v2 1/2] x86/AMD: Fix cpu_llc_id for AMD Fam17h systems

2016-10-28 Thread Yazen Ghannam
The current Fam17h cpu_llc_id derivation has an underflow bug when
extracting the socket_id value. The socket_id value starts from 0, so
subtracting 1 will result in an underflow. This breaks scheduling topology
later on since the cpu_llc_id will be incorrect.

The apicid decoding is fixed for bits 3 and above, which give the core
complex, node and socket IDs. The LLC is at the core complex level so we
can find a unique cpu_llc_id by right shifting the apicid by 3.

We can fix the underflow bug and simplify the code by replacing the
current cpu_llc_id derivation with a right shift.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
Cc: <sta...@vger.kernel.org> # v4.4..
Fixes: 3849e91f571d ("x86/AMD: Fix last level cache topology for AMD Fam17h 
systems")
---
 arch/x86/kernel/cpu/amd.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 7b76eb6..c3fc337 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -347,7 +347,6 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
 #ifdef CONFIG_SMP
unsigned bits;
int cpu = smp_processor_id();
-   unsigned int socket_id, core_complex_id;
 
bits = c->x86_coreid_bits;
/* Low order bits define the core id (index of core in socket) */
@@ -365,10 +364,7 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
 if (c->x86 != 0x17 || !cpuid_edx(0x8006))
return;
 
-   socket_id   = (c->apicid >> bits) - 1;
-   core_complex_id = (c->apicid & ((1 << bits) - 1)) >> 3;
-
-   per_cpu(cpu_llc_id, cpu) = (socket_id << 3) | core_complex_id;
+   per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
 #endif
 }
 
-- 
1.9.1



Re: [tip:ras/core] x86/RAS: Simplify SMCA HWID descriptor struct

2016-11-10 Thread Yazen Ghannam
> > 
> > Argh, the macro should be adding the additional parentheses:
> > 
> > #define HWID_MCATYPE(hwid, mcatype) (((hwid) << 16) | (mcatype))
> > 
> > That should fix the issue too.
>

Yep, sure does.
 
> Patch please.

Will do.

Thanks,
Yazen


Re: [tip:ras/core] x86/RAS: Simplify SMCA HWID descriptor struct

2016-11-10 Thread Yazen Ghannam
>  static void get_smca_bank_info(unsigned int bank)
>  {
>   unsigned int i, hwid_mcatype, cpu = smp_processor_id();
> - struct smca_hwid_mcatype *type;
> + struct smca_hwid *s_hwid;
>   u32 high, instance_id;
> - u16 hwid, mcatype;
>  
>   /* Collect bank_info using CPU 0 for now. */
>   if (cpu)
> @@ -162,14 +157,13 @@ static void get_smca_bank_info(unsigned int bank)
>   return;
>   }
>  
> - hwid = high & MCI_IPID_HWID;
> - mcatype = (high & MCI_IPID_MCATYPE) >> 16;
> - hwid_mcatype = HWID_MCATYPE(hwid, mcatype);
> + hwid_mcatype = HWID_MCATYPE(high & MCI_IPID_HWID,
> + (high & MCI_IPID_MCATYPE) >> 16);
>

Sorry for catching this late, but it seems this change doesn't compile
correctly. This causes the value of hwid_mcatype to be incorrect, so we
will never match a bank to its type.

I see this with GCC 4.8.5 and 5.4.0. 

There are no warnings or issues when building or booting just
that the behavior is incorrect. 

Disassembly of above change:
  db:   8b 45 e0mov-0x20(%rbp),%eax
  de:   41 89 c4mov%eax,%r12d
  e1:   25 00 00 ff 0f  and$0xfff,%eax
  e6:   41 c1 ec 10 shr$0x10,%r12d
  ea:   41 09 c4or %eax,%r12d

Disassembly of original code:
 286:   8b 45 d0mov-0x30(%rbp),%eax
 289:   41 89 c5mov%eax,%r13d
 28c:   c1 e8 10shr$0x10,%eax
 28f:   41 81 e5 ff 0f 00 00and$0xfff,%r13d
 296:   41 c1 e5 10 shl$0x10,%r13d
 29a:   41 09 c5or %eax,%r13d

Adding extra parentheses in HWID_MCATYPE() gives the same assembly as the
original code and fixes the behavior.

> + hwid_mcatype = HWID_MCATYPE((high & MCI_IPID_HWID)),
> + ((high & MCI_IPID_MCATYPE) >> 16));

Thanks,
Yazen



Re: [PATCH -v1.1] x86/topology: Document cpu_llc_id

2016-11-17 Thread Yazen Ghannam
On Thu, Nov 17, 2016 at 10:45:57AM +0100, Borislav Petkov wrote:
> It means different things on Intel and AMD so write it down so that
> there's no confusion.
> 
> Signed-off-by: Borislav Petkov <b...@suse.de>
> Cc: Peter Zijlstra <pet...@infradead.org>
> Cc: Thomas Gleixner <t...@linutronix.de>
> Cc: Yazen Ghannam <yazen.ghan...@amd.com>
> ---
>  Documentation/x86/topology.txt | 9 +
>  1 file changed, 9 insertions(+)
> 
> diff --git a/Documentation/x86/topology.txt b/Documentation/x86/topology.txt
> index 06afac252f5b..f3e9d7e9ed6c 100644
> --- a/Documentation/x86/topology.txt
> +++ b/Documentation/x86/topology.txt
> @@ -63,6 +63,15 @@ The topology of a system is described in the units of:
>  The maximum possible number of packages in the system. Helpful for per
>  package facilities to preallocate per package information.
>  
> +  - cpu_llc_id:
> +
> +A per-CPU variable containing:
> +- On Intel, the first APIC ID of the list of CPUs sharing the Last Level
> +Cache
> +
> +- On AMD, the Node ID or Core Complex ID containing the Last Level
> +Cache. In general, it is a number identifying an LLC uniquely on the
> +system.
>  
>  * Cores:
> 

Look good to me.

Thanks,
Yazen 


[PATCH v3 2/2] x86/AMD: Group cpu_llc_id assignment by topology feature and family

2016-11-01 Thread Yazen Ghannam
Currently, we assume that a system has multiple last level caches only if
there are multiple nodes, and that the cpu_llc_id is equal to the node_id.
This no longer applies since Fam17h can have multiple last level caches
within a node.

So group the cpu_llc_id assignment by topology feature and family.

The NODEID_MSR feature only applies to Fam10h in which case the LLC (Last
Level Cache) is at the node level.

The TOPOEXT feature is used on families 15h, 16h and 17h. So far we only
see multiple last level caches if L3 caches are available. Otherwise, the
cpu_llc_id will default to be the phys_proc_id. We have L3 caches only on
families 15h and 17h. On Fam15h, the LLC is at the node level. On Fam17h,
the LLC is at the core complex level and can be found by right shifting the
apicid. Also, keep the family checks explicit so that new families will
fall back to the default, which will be node_id for TOPOEXT systems.

Single node systems in families 10h and 15h will have a Node ID of 0 which
will be the same as the phys_proc_id, so we don't need to check for
multiple nodes before using the node_id.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
http://lkml.kernel.org/r/1477669918-56261-2-git-send-email-yazen.ghan...@amd.com

v2->v3:
* Fixup commit message based on comments.
* Make node_id the default cpu_llc_id for TOPOEXT systems.

 arch/x86/kernel/cpu/amd.c | 31 +++
 1 file changed, 19 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 1e81a37..4daad1e 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -314,11 +314,30 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
smp_num_siblings = ((ebx >> 8) & 3) + 1;
c->x86_max_cores /= smp_num_siblings;
c->cpu_core_id = ebx & 0xff;
+
+   /*
+* We may have multiple LLCs if L3 caches exist, so check if we
+* have an L3 cache by looking at the L3 cache CPUID leaf.
+*/
+   if (cpuid_edx(0x8006)) {
+   if (c->x86 == 0x17) {
+   /*
+* LLC is at the core complex level.
+* Core complex id is ApicId[3].
+*/
+   per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
+   } else {
+   /* LLC is at the node level. */
+   per_cpu(cpu_llc_id, cpu) = node_id;
+   }
+   }
} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
u64 value;
 
rdmsrl(MSR_FAM10H_NODE_ID, value);
node_id = value & 7;
+
+   per_cpu(cpu_llc_id, cpu) = node_id;
} else
return;
 
@@ -329,9 +348,6 @@ static void amd_get_topology(struct cpuinfo_x86 *c)
set_cpu_cap(c, X86_FEATURE_AMD_DCM);
cus_per_node = c->x86_max_cores / nodes_per_socket;
 
-   /* store NodeID, use llc_shared_map to store sibling info */
-   per_cpu(cpu_llc_id, cpu) = node_id;
-
/* core id has to be in the [0 .. cores_per_node - 1] range */
c->cpu_core_id %= cus_per_node;
}
@@ -356,15 +372,6 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
/* use socket ID also for last level cache */
per_cpu(cpu_llc_id, cpu) = c->phys_proc_id;
amd_get_topology(c);
-
-   /*
-* Fix percpu cpu_llc_id here as LLC topology is different
-* for Fam17h systems.
-*/
-if (c->x86 != 0x17 || !cpuid_edx(0x8006))
-   return;
-
-   per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
 #endif
 }
 
-- 
1.9.1



[PATCH v3 1/2] x86/AMD: Fix cpu_llc_id for AMD Fam17h systems

2016-11-01 Thread Yazen Ghannam
The current Fam17h cpu_llc_id (Last Level Cache ID) derivation has an
underflow bug when extracting the socket_id value. The socket_id value
starts from 0, so subtracting 1 will result in an underflow. This breaks
scheduling topology later on since the cpu_llc_id will be incorrect.

The APICID decoding is fixed, in register, for bits 3 and above, which give
the core complex, node and socket IDs. The LLC is at the core complex level
so we can find a unique cpu_llc_id by right shifting the APICID by 3
because then the least significant bit will be the Core Complex ID.

We can fix the underflow bug and simplify the code by replacing the
current cpu_llc_id derivation with a right shift.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
Cc: <sta...@vger.kernel.org> # v4.4..
Fixes: 3849e91f571d ("x86/AMD: Fix last level cache topology for AMD Fam17h 
systems")
---
Link:
http://lkml.kernel.org/r/1477669918-56261-1-git-send-email-yazen.ghan...@amd.com

v2->v3:
* Fixup commit message based on comments.

 arch/x86/kernel/cpu/amd.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index b81fe2d..1e81a37 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -347,7 +347,6 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
 #ifdef CONFIG_SMP
unsigned bits;
int cpu = smp_processor_id();
-   unsigned int socket_id, core_complex_id;
 
bits = c->x86_coreid_bits;
/* Low order bits define the core id (index of core in socket) */
@@ -365,10 +364,7 @@ static void amd_detect_cmp(struct cpuinfo_x86 *c)
 if (c->x86 != 0x17 || !cpuid_edx(0x8006))
return;
 
-   socket_id   = (c->apicid >> bits) - 1;
-   core_complex_id = (c->apicid & ((1 << bits) - 1)) >> 3;
-
-   per_cpu(cpu_llc_id, cpu) = (socket_id << 3) | core_complex_id;
+   per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
 #endif
 }
 
-- 
1.9.1



Re: [PATCH] x86/AMD: Fix LLC ID for AMD Fam17h systems

2016-10-27 Thread Yazen Ghannam
>> +/*
>> + * LLC is at the Core Complex level.
>> + * Core Complex Id is ApicId[3].
>> + */
>> +else if (c->x86 == 0x17)
>> +per_cpu(cpu_llc_id, cpu) = c->initial_apicid >> 
>> 3;
> 
> This whole if/else block lacks curly braces. See:
> 
>   https://marc.info/?l=linux-kernel=147351236615103
> 

Okay, understood.

>> -/*
>> - * Fix percpu cpu_llc_id here as LLC topology is different
>> - * for Fam17h systems.
>> - */
>> - if (c->x86 != 0x17 || !cpuid_edx(0x8006))
>> -return;
>> -
>> -socket_id   = (c->apicid >> bits) - 1;
>> -core_complex_id = (c->apicid & ((1 << bits) - 1)) >> 3;
>> -
>> -per_cpu(cpu_llc_id, cpu) = (socket_id << 3) | core_complex_id;
> 
> So if I've read the patch correctly then the trivial fix for fam17h would
> have been:
> 
>> +per_cpu(cpu_llc_id, cpu) = c->initial_apicid >> 3;
> 
> Right?
> 

Right.

> And this one liner wants to be a seperate patch with a proper
> explanation. And that simple hunk can be tagged for stable.
> 

Okay, I'll make it a separate patch. It still wouldn't be a one-liner
because then socket_id and core_complex_id would be left unused and
should be removed.

> The rest of the patch is cleanup and improvement and want's to be seperated
> out and explained proper.
> 

Okay, will do.

Thanks,
Yazen


Re: [PATCH 1/3] x86/RAS: Simplify SMCA bank descriptor struct

2016-11-04 Thread Yazen Ghannam
> 
> Call the struct simply smca_bank, it's instance ID can be simply ->id.
> Makes the code much more readable.
> 
> Signed-off-by: Borislav Petkov <b...@suse.de>

Looks good to me.

Please add:
Tested-by: Yazen Ghannam <yazen.ghan...@amd.com>

Ditto for the others.

Thanks,
Yazen


Re: [PATCH v2 2/2] x86/AMD: Group cpu_llc_id assignment by topology feature and family

2016-10-31 Thread Yazen Ghannam
> 
> > The NODEID_MSR feature only applies to Fam10h in which case the llc is at
> 
> s/llc/LLC (Last Level Cache/
> 
> Let's try to have abbreviations written out in their first mention in the 
> text.
> 

Okay.

> > the node level.
> > 
> > The TOPOEXT feature is used on families 15h, 16h and 17h. So far we only
> > see multiple last level caches if L3 caches are available. Otherwise, the
> > cpu_llc_id will default to be the phys_proc_id. We have L3 caches only on
> > families 15h and 17h. On Fam15h, the llc is at the node level. On Fam17h,
> 
> s/llc/LLC/g
> 

Ack.

> > the llc is at the core complex level and can be found by right shifting the
>   ^^^
> 
> LLC
> 

Ack.

> > +
> > +   /*
> > +* We may have multiple LLCs if L3 caches exist, so check if we
> > +* have an L3 cache by looking at the L3 cache cpuid leaf.
> 
> x86 instructions in caps please: CPUID
>

Ack.
 
> > +*/
> > +   if (cpuid_edx(0x8006)) {
> > +   if (c->x86 == 0x15) {
> > +   /* LLC is at the node level. */
> > +   per_cpu(cpu_llc_id, cpu) = node_id;
> > +
> > +   } else if (c->x86 == 0x17) {
> 
>   How about >= ?
>

This APICID format is only valid for Fam17h. What I'm going for is that
we fall back to a sensible default if we don't have a better assignment
for a new family. At first I thought that phys_proc_id would be good but
now I think node_id is better as a sensible default. I'll make this change
in the V3 set.

> 
> Btw, please add for your next submission:
> 
> Tested-by: Borislav Petkov 
> 

For both patches?

Thanks,
Yazen


Re: [PATCH v2 1/2] x86/AMD: Fix cpu_llc_id for AMD Fam17h systems

2016-10-31 Thread Yazen Ghannam
> > The current Fam17h cpu_llc_id  derivation has an underflow bug when
>   ^
>   (Last Level Cache ID)
> 
> Let's write it out the first time.
> 

Ack.

> > 
> > The apicid decoding is fixed for bits 3 and above,
>   ^
> "is fixed ... in register... "
> 

Ack.

> > which give the core
> > complex, node and socket IDs. The LLC is at the core complex level so we
> > can find a unique cpu_llc_id by right shifting the apicid by 3.
> 
> "... because then the LSBit will be the Core Complex ID."
> 

Ack.

> > We can fix the underflow bug and simplify the code by replacing the
> > current cpu_llc_id derivation with a right shift.
> > 
> > Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
> > Cc: <sta...@vger.kernel.org> # v4.4..
> > Fixes: 3849e91f571d ("x86/AMD: Fix last level cache topology for AMD Fam17h 
> > systems")
> > ---
> 
> I'll run it soon.
>

Thanks,
Yazen 


Re: linux-next: manual merge of the edac-amd tree with the edac tree

2016-12-01 Thread Yazen Ghannam
On Thu, Dec 01, 2016 at 10:06:17AM -0200, Mauro Carvalho Chehab wrote:
> 
> However, rebasing over your tree showed a new documentation gap:
>   ./include/linux/edac.h:144: warning: Enum value 'HW_EVENT_ERR_DEFERRED' 
> not described in enum 'hw_event_mc_err_type'
> 
> With was introduced by this commit:
> 
>   commit d12a969ebbfcfc25853c4147d42b388f758e8784
>   Author: Yazen Ghannam <yazen.ghan...@amd.com>
>   Date:   Thu Nov 17 17:57:32 2016 -0500
> 
> EDAC, amd64: Add Deferred Error type
> 
> Currently, deferred errors are classified as correctable in EDAC. Add a
> new error type for deferred errors so that they are correctly reported
> to the user.
> 
> Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
> Cc: Aravind Gopalakrishnan <aravindksg.l...@gmail.com>
> Cc: linux-edac <linux-e...@vger.kernel.org>
> Link: 
> http://lkml.kernel.org/r/1479423463-8536-7-git-send-email-yazen.ghan...@amd.com
> Signed-off-by: Borislav Petkov <b...@suse.de>
> 
> 
> Yazen introduced a "deferred error" code (whatever it means), but didn't
> document what's that. Unfortunately, the patch description is also
> not clear enough about what a "deferred error" means or how userspace
> is supposed to handle it.
> 
> Yazen,
> 
> Could you please send us a patch adding a proper description for this
> new error code?
>

Hi Mauro,
A deferred error is an uncorrectable error whose handling can be
deferred, i.e. it's not urgent. This affects the system behavior, but
I'm now thinking that this shouldn't affect users' behavior. I think it
would be simpler to just classify deferred errors as uncorrectable
errors so that users treat them as such.

Boris,
Can we drop or revert commit d12a969ebbfc?

And can we apply a fixup like this to commit 713ad54675fd?

---
From: Yazen Ghannam <yazen.ghan...@amd.com>
Date: Thu, 1 Dec 2016 08:54:49 -0600
Subject: [PATCH] fixup! EDAC, amd64: Define and register UMC error decode
 function

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 drivers/edac/amd64_edac.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 991b36c..245b9a0 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -2480,8 +2480,9 @@ static void decode_umc_error(int node_id, struct mce *m)
 
memset(, 0, sizeof(err));
 
+   /* Log deferred errors as uncorrectable errors. */
if (m->status & MCI_STATUS_DEFERRED)
-   ecc_type = 3;
+   ecc_type = 1;
 
err.channel = find_umc_channel(pvt, m);
if (err.channel < 0) {
-- 
2.7.4

---

Thanks,
Yazen


Re: linux-next: manual merge of the edac-amd tree with the edac tree

2016-12-01 Thread Yazen Ghannam
On Thu, Dec 01, 2016 at 07:15:01PM +0100, Borislav Petkov wrote:
> On Thu, Dec 01, 2016 at 11:02:04AM -0500, Yazen Ghannam wrote:
> > A deferred error is an uncorrectable error whose handling can be
> > deferred, i.e. it's not urgent. This affects the system behavior, but
> > I'm now thinking that this shouldn't affect users' behavior. I think it
> > would be simpler to just classify deferred errors as uncorrectable
> > errors so that users treat them as such.
> 
> Why would we want to lie about deferred errors being uncorrectable?
>

They are uncorrectable errors that can be handled differently. If you
can't handle them then there's not much difference.
 
> And I believe deferred errors can be handled differently like freeze the
> process using the page instead of killing it. And so on...
> 

If deferred errors can be handled differently in userspace, then you're
right we should maintain the distinction. I was thinking we'd only
handle them in the kernel.

> Why aren't you simply adding the documentation about
> HW_EVENT_ERR_DEFERRED and be done with it? The downstream path like
> tracepoint and all can handle all that just fine.
> 

Okay, will do.

> > Boris,
> > Can we drop or revert commit d12a969ebbfc?
> 
> No can do. It is a public branch and there's no touching it.
> 

Okay, got it.

Thanks,
Yazen


[PATCH 1/2] x86/mce/AMD: Redo use of SMCA MCA_DE{STAT,ADDR} registers

2017-03-22 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

We have support for the new SMCA MCA_DE{STAT,ADDR} registers in Linux. So
we've used these registers in place of MCA_{STATUS,ADDR} on SMCA systems.
However, the guidance for current implementations of SMCA is to continue
using MCA_{STATUS,ADDR} and to use MCA_DE{STAT,ADDR} only if a Deferred
error was not found in the former registers. This also means we shouldn't
clear MCA_CONFIG[LogDeferredInMcaStat].

Redo the AMD Deferred error interrupt handler to follow the guidance for
current SMCA systems. Also, don't break after finding the first error.

Don't clear MCA_CONFIG[LogDeferredInMcaStat] during AMD mcheck init.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 47 
 1 file changed, 21 insertions(+), 26 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 524cc57..4e459e0 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -472,20 +472,6 @@ prepare_threshold_block(unsigned int bank, unsigned int 
block, u32 addr,
smca_high |= BIT(0);
 
/*
-* SMCA logs Deferred Error information in MCA_DE{STAT,ADDR}
-* registers with the option of additionally logging to
-* MCA_{STATUS,ADDR} if MCA_CONFIG[LogDeferredInMcaStat] is set.
-*
-* This bit is usually set by BIOS to retain the old behavior
-* for OSes that don't use the new registers. Linux supports the
-* new registers so let's disable that additional logging here.
-*
-* MCA_CONFIG[LogDeferredInMcaStat] is bit 34 (bit 2 in the high
-* portion of the MSR).
-*/
-   smca_high &= ~BIT(2);
-
-   /*
 * SMCA sets the Deferred Error Interrupt type per bank.
 *
 * MCA_CONFIG[DeferredIntTypeSupported] is bit 5, and tells us
@@ -756,7 +742,8 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, 
u64 *sys_addr)
 EXPORT_SYMBOL_GPL(umc_normaddr_to_sysaddr);
 
 static void
-__log_error(unsigned int bank, bool deferred_err, bool threshold_err, u64 misc)
+__log_error(unsigned int bank, bool deferred_err, bool use_smca_destat,
+  bool threshold_err, u64 misc)
 {
u32 msr_status = msr_ops.status(bank);
u32 msr_addr = msr_ops.addr(bank);
@@ -765,7 +752,7 @@ __log_error(unsigned int bank, bool deferred_err, bool 
threshold_err, u64 misc)
 
WARN_ON_ONCE(deferred_err && threshold_err);
 
-   if (deferred_err && mce_flags.smca) {
+   if (deferred_err && use_smca_destat) {
msr_status = MSR_AMD64_SMCA_MCx_DESTAT(bank);
msr_addr = MSR_AMD64_SMCA_MCx_DEADDR(bank);
}
@@ -807,6 +794,10 @@ __log_error(unsigned int bank, bool deferred_err, bool 
threshold_err, u64 misc)
 
mce_log();
 
+   /* We should still clear MCA_DESTAT even if we used MCA_STATUS. */
+   if (mce_flags.smca && !use_smca_destat)
+   wrmsrl(MSR_AMD64_SMCA_MCx_DESTAT(bank), 0);
+
wrmsrl(msr_status, 0);
 }
 
@@ -832,25 +823,29 @@ asmlinkage __visible void __irq_entry 
smp_trace_deferred_error_interrupt(void)
exiting_ack_irq();
 }
 
+static inline bool check_deferred_status(u64 status)
+{
+   return ((status & MCI_STATUS_VAL) && (status & MCI_STATUS_DEFERRED));
+}
+
 /* APIC interrupt handler for deferred errors */
 static void amd_deferred_error_interrupt(void)
 {
unsigned int bank;
-   u32 msr_status;
u64 status;
 
for (bank = 0; bank < mca_cfg.banks; ++bank) {
-   msr_status = (mce_flags.smca) ? MSR_AMD64_SMCA_MCx_DESTAT(bank)
- : msr_ops.status(bank);
+   rdmsrl(msr_ops.status(bank), status);
 
-   rdmsrl(msr_status, status);
+   if (check_deferred_status(status)) {
+   __log_error(bank, true, false, false, 0);
 
-   if (!(status & MCI_STATUS_VAL) ||
-   !(status & MCI_STATUS_DEFERRED))
-   continue;
+   } else if (mce_flags.smca) {
+   rdmsrl(MSR_AMD64_SMCA_MCx_DESTAT(bank), status);
 
-   __log_error(bank, true, false, 0);
-   break;
+   if (check_deferred_status(status))
+   __log_error(bank, true, true, false, 0);
+   }
}
 }
 
@@ -904,7 +899,7 @@ static void amd_threshold_interrupt(void)
return;
 
 log:
-   __log_error(bank, false, true, ((u64)high << 32) | low);
+   __log_error(bank, false, false, true, ((u64)high << 32) | low);
 
/* Reset threshold block after logging error. */
memset(, 0, sizeof(tr));
-- 
2.7.4



[PATCH 2/2] x86/mce/AMD: Carve out SMCA bank configuration

2017-03-22 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Scalable MCA systems have a new MCA_CONFIG register that we use to
configure each bank. We currently use this when we set up thresholding.
However, this is logically separate.

Move setup of MCA_CONFIG into a separate function.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 48 
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 4e459e0..95870b3 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -433,7 +433,7 @@ prepare_threshold_block(unsigned int bank, unsigned int 
block, u32 addr,
int offset, u32 misc_high)
 {
unsigned int cpu = smp_processor_id();
-   u32 smca_low, smca_high, smca_addr;
+   u32 smca_low, smca_high;
struct threshold_block b;
int new;
 
@@ -457,7 +457,29 @@ prepare_threshold_block(unsigned int bank, unsigned int 
block, u32 addr,
goto set_offset;
}
 
-   smca_addr = MSR_AMD64_SMCA_MCx_CONFIG(bank);
+   /* Gather LVT offset for thresholding: */
+   if (rdmsr_safe(MSR_CU_DEF_ERR, _low, _high))
+   goto out;
+
+   new = (smca_low & SMCA_THR_LVT_OFF) >> 12;
+
+set_offset:
+   offset = setup_APIC_mce_threshold(offset, new);
+
+   if ((offset == new) && (mce_threshold_vector != 
amd_threshold_interrupt))
+   mce_threshold_vector = amd_threshold_interrupt;
+
+done:
+   mce_threshold_block_init(, offset);
+
+out:
+   return offset;
+}
+
+static void set_smca_config(unsigned int bank)
+{
+   u32 smca_low, smca_high;
+   u32 smca_addr = MSR_AMD64_SMCA_MCx_CONFIG(bank);
 
if (!rdmsr_safe(smca_addr, _low, _high)) {
/*
@@ -487,24 +509,6 @@ prepare_threshold_block(unsigned int bank, unsigned int 
block, u32 addr,
 
wrmsr(smca_addr, smca_low, smca_high);
}
-
-   /* Gather LVT offset for thresholding: */
-   if (rdmsr_safe(MSR_CU_DEF_ERR, _low, _high))
-   goto out;
-
-   new = (smca_low & SMCA_THR_LVT_OFF) >> 12;
-
-set_offset:
-   offset = setup_APIC_mce_threshold(offset, new);
-
-   if ((offset == new) && (mce_threshold_vector != 
amd_threshold_interrupt))
-   mce_threshold_vector = amd_threshold_interrupt;
-
-done:
-   mce_threshold_block_init(, offset);
-
-out:
-   return offset;
 }
 
 /* cpu init entry point, called from mce.c with preempt off */
@@ -515,8 +519,10 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
int offset = -1;
 
for (bank = 0; bank < mca_cfg.banks; ++bank) {
-   if (mce_flags.smca)
+   if (mce_flags.smca) {
get_smca_bank_info(bank);
+   set_smca_config(bank);
+   }
 
for (block = 0; block < NR_BLOCKS; ++block) {
address = get_block_address(cpu, address, low, high, 
bank, block);
-- 
2.7.4



[PATCH v2 2/4] x86/mce/AMD; EDAC,amd64: Move find_umc_channel() to AMD mcheck

2017-03-20 Thread Yazen Ghannam
We need to find a UMC's channel number from mcheck code when translating
UMC normalized addresses to system physical addresses. So move the function
there from EDAC.

Also, drop the struct pvt from the function parameters since we don't use
it. And add a sanity check to make sure we're only looking at UMCs in case
the UMC instance IDs ever match up with other bank types.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link: 
http://lkml.kernel.org/r/1486760120-60944-2-git-send-email-yazen.ghan...@amd.com

v1->v2:
- Redo commit message based on comments.
- Add UMC bank type sanity check.

 arch/x86/include/asm/mce.h   |  2 ++
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 21 +
 drivers/edac/amd64_edac.c| 20 +---
 3 files changed, 24 insertions(+), 19 deletions(-)

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index e638736..1ac261c 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -258,9 +258,11 @@ static inline void cmci_recheck(void) {}
 #ifdef CONFIG_X86_MCE_AMD
 void mce_amd_feature_init(struct cpuinfo_x86 *c);
 int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 *sys_addr);
+int find_umc_channel(struct mce *m);
 #else
 static inline void mce_amd_feature_init(struct cpuinfo_x86 *c) { }
 static inline int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 umc, u64 
*sys_addr) { return -EINVAL; };
+static inline int find_umc_channel(struct mce *m) { return -EINVAL; };
 #endif
 
 int mce_available(struct cpuinfo_x86 *c);
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 524cc57..10fddcc 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -755,6 +755,27 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 
umc, u64 *sys_addr)
 }
 EXPORT_SYMBOL_GPL(umc_normaddr_to_sysaddr);
 
+/*
+ * To find the UMC channel represented by this bank we need to match on its
+ * instance_id. The instance_id of a bank is held in the lower 32 bits of its
+ * IPID.
+ */
+int find_umc_channel(struct mce *m)
+{
+   u32 umc_instance_id[] = {0x50f00, 0x150f00};
+   u32 instance_id = m->ipid & GENMASK(31, 0);
+   int i, channel = -EINVAL;
+
+   if (smca_banks[m->bank].hwid &&
+   smca_banks[m->bank].hwid->bank_type == SMCA_UMC)
+   for (i = 0; i < ARRAY_SIZE(umc_instance_id); i++)
+   if (umc_instance_id[i] == instance_id)
+   channel = i;
+
+   return channel;
+}
+EXPORT_SYMBOL_GPL(find_umc_channel);
+
 static void
 __log_error(unsigned int bank, bool deferred_err, bool threshold_err, u64 misc)
 {
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 82dab16..11f973d 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -2447,24 +2447,6 @@ static inline void decode_bus_error(int node_id, struct 
mce *m)
__log_ecc_error(mci, , ecc_type);
 }
 
-/*
- * To find the UMC channel represented by this bank we need to match on its
- * instance_id. The instance_id of a bank is held in the lower 32 bits of its
- * IPID.
- */
-static int find_umc_channel(struct amd64_pvt *pvt, struct mce *m)
-{
-   u32 umc_instance_id[] = {0x50f00, 0x150f00};
-   u32 instance_id = m->ipid & GENMASK(31, 0);
-   int i, channel = -1;
-
-   for (i = 0; i < ARRAY_SIZE(umc_instance_id); i++)
-   if (umc_instance_id[i] == instance_id)
-   channel = i;
-
-   return channel;
-}
-
 static void decode_umc_error(int node_id, struct mce *m)
 {
u8 ecc_type = (m->status >> 45) & 0x3;
@@ -2484,7 +2466,7 @@ static void decode_umc_error(int node_id, struct mce *m)
if (m->status & MCI_STATUS_DEFERRED)
ecc_type = 3;
 
-   err.channel = find_umc_channel(pvt, m);
+   err.channel = find_umc_channel(m);
if (err.channel < 0) {
err.err_code = ERR_CHANNEL;
goto log_error;
-- 
2.7.4



[PATCH v2 1/4] EDAC,mce_amd: Find node ID on SMCA systems using generic methods

2017-03-20 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

We should move away from using AMD-specific amd_get_nb_id() to find a node
ID and move toward using generic Linux methods. We can use cpu_to_node()
since NUMA should be working as expected on newly released Fam17h systems.

Replace call to amd_get_nb_id() and related shifting by a call to
cpu_to_node() which works as expected.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link: 
http://lkml.kernel.org/r/1486760120-60944-1-git-send-email-yazen.ghan...@amd.com

v1->v2:
- Just use cpu_to_node() instead of trying to make amd_get_nb_id() work.

 drivers/edac/mce_amd.c | 6 +-
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index ba35b7e..dbccf40 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -878,12 +878,8 @@ static void decode_smca_errors(struct mce *m)
pr_cont("%s.\n", smca_mce_descs[bank_type].descs[xec]);
}
 
-   /*
-* amd_get_nb_id() returns the last level cache id.
-* The last level cache on Fam17h is 1 level below the node.
-*/
if (bank_type == SMCA_UMC && xec == 0 && decode_dram_ecc)
-   decode_dram_ecc(amd_get_nb_id(m->extcpu) >> 1, m);
+   decode_dram_ecc(cpu_to_node(m->extcpu), m);
 }
 
 static inline void amd_decode_err_code(u16 ec)
-- 
2.7.4



[PATCH v2 3/4] x86/mce/AMD: Mark Deferred errors as Action Optional on SMCA systems

2017-03-20 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Give Deferred errors an Action Optional severity on SMCA systems so that
the SRAO notifier block can potentially handle them.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link: 
http://lkml.kernel.org/r/1486760120-60944-3-git-send-email-yazen.ghan...@amd.com

v1->v2:
- New in v2. Based on v1 patch 3.
- Use mce_severity() in AMD interrupt handlers.
- Set proper severity so we can use notifier chain instead of calling
memory_failure() directly.

 arch/x86/kernel/cpu/mcheck/mce-severity.c | 6 +-
 arch/x86/kernel/cpu/mcheck/mce_amd.c  | 4 
 2 files changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c 
b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 87cc9ab..2773c85 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -278,8 +278,12 @@ static int mce_severity_amd(struct mce *m, int tolerant, 
char **msg, bool is_exc
 * deferred error: poll handler catches these and adds to mce_ring so
 * memory-failure can take recovery actions.
 */
-   if (m->status & MCI_STATUS_DEFERRED)
+   if (m->status & MCI_STATUS_DEFERRED) {
+   if (mce_flags.smca)
+   return MCE_AO_SEVERITY;
+
return MCE_DEFERRED_SEVERITY;
+   }
 
/*
 * corrected error: poll handler catches these and passes responsibility
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 10fddcc..743ae31 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -28,6 +28,8 @@
 #include 
 #include 
 
+#include "mce-internal.h"
+
 #define NR_BLOCKS 5
 #define THRESHOLD_MAX 0xFFF
 #define INT_TYPE_APIC 0x0002
@@ -802,6 +804,8 @@ __log_error(unsigned int bank, bool deferred_err, bool 
threshold_err, u64 misc)
m.bank   = bank;
m.tsc= rdtsc();
 
+   m.severity = mce_severity(, mca_cfg.tolerant, NULL, false);
+
if (threshold_err)
m.misc = misc;
 
-- 
2.7.4



[PATCH v2 0/4] Call memory_failure() on Deferred errors

2017-03-20 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

This set is based on an earlier 3 patch set.

Patch 1:
- Address comments by using cpu_to_node() when finding a node ID rather
than amd_get_nb_id().
Link: 
http://lkml.kernel.org/r/1486760120-60944-1-git-send-email-yazen.ghan...@amd.com

Patch 2:
- Fix up commit message.
Link: 
http://lkml.kernel.org/r/1486760120-60944-2-git-send-email-yazen.ghan...@amd.com

Patches 3 and 4:
- Redo Patch 3 from old set.
- After looking at the CEC patch I got the idea to use the SRAO notifier
block instead of calling memory_failure() from the AMD Deferred error
interrupt handler.
Link: 
http://lkml.kernel.org/r/1486760120-60944-3-git-send-email-yazen.ghan...@amd.com

Yazen Ghannam (4):
  EDAC,mce_amd: Find node ID on SMCA systems using generic methods
  x86/mce/AMD; EDAC,amd64: Move find_umc_channel() to AMD mcheck
  x86/mce/AMD: Mark Deferred errors as Action Optional on SMCA systems
  x86/mce: Add AMD SMCA support to SRAO notifier

 arch/x86/include/asm/mce.h|  2 ++
 arch/x86/kernel/cpu/mcheck/mce-severity.c |  6 +++-
 arch/x86/kernel/cpu/mcheck/mce.c  | 52 ---
 arch/x86/kernel/cpu/mcheck/mce_amd.c  | 25 +++
 drivers/edac/amd64_edac.c | 20 +---
 drivers/edac/mce_amd.c|  2 +-
 6 files changed, 74 insertions(+), 33 deletions(-)

-- 
2.7.4



[PATCH v2 4/4] x86/mce: Add AMD SMCA support to SRAO notifier

2017-03-20 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Deferred errors on AMD systems may get an Action Optional severity with the
goal of being handled by the SRAO notifier block. However, the process of
determining if an address is usable is different between Intel and AMD. So
define vendor-specific functions for this.

Also, check for the AO severity before determining if an address is usable
to possibly save some cycles.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link: 
http://lkml.kernel.org/r/1486760120-60944-3-git-send-email-yazen.ghan...@amd.com

v1->v2:
- New in v2. Based on v1 patch 3.
- Update SRAO notifier block to handle errors from SMCA systems.

 arch/x86/kernel/cpu/mcheck/mce.c | 52 ++--
 1 file changed, 40 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 5e365a2..1a2669d 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -547,19 +547,49 @@ static void mce_report_event(struct pt_regs *regs)
  * be somewhat complicated (e.g. segment offset would require an instruction
  * parser). So only support physical addresses up to page granuality for now.
  */
-static int mce_usable_address(struct mce *m)
+static int mce_usable_address_intel(struct mce *m, unsigned long *pfn)
 {
-   if (!(m->status & MCI_STATUS_MISCV) || !(m->status & MCI_STATUS_ADDRV))
+   if (!(m->status & MCI_STATUS_MISCV))
return 0;
-
-   /* Checks after this one are Intel-specific: */
-   if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
-   return 1;
-
if (MCI_MISC_ADDR_LSB(m->misc) > PAGE_SHIFT)
return 0;
if (MCI_MISC_ADDR_MODE(m->misc) != MCI_MISC_ADDR_PHYS)
return 0;
+
+   *pfn = m->addr >> PAGE_SHIFT;
+   return 1;
+}
+
+/* Only support this on SMCA systems and errors logged from a UMC. */
+static int mce_usable_address_amd(struct mce *m, unsigned long *pfn)
+{
+   u8 umc;
+   u16 nid = cpu_to_node(m->extcpu);
+   u64 addr;
+
+   if (!mce_flags.smca)
+   return 0;
+
+   umc = find_umc_channel(m);
+
+   if (umc < 0 || umc_normaddr_to_sysaddr(m->addr, nid, umc, ))
+   return 0;
+
+   *pfn = addr >> PAGE_SHIFT;
+   return 1;
+}
+
+static int mce_usable_address(struct mce *m, unsigned long *pfn)
+{
+   if (!(m->status & MCI_STATUS_ADDRV))
+   return 0;
+
+   if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+   return mce_usable_address_intel(m, pfn);
+
+   if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
+   return mce_usable_address_amd(m, pfn);
+
return 1;
 }
 
@@ -567,15 +597,13 @@ static int srao_decode_notifier(struct notifier_block 
*nb, unsigned long val,
void *data)
 {
struct mce *mce = (struct mce *)data;
-   unsigned long pfn;
+   unsigned long pfn = 0;
 
if (!mce)
return NOTIFY_DONE;
 
-   if (mce_usable_address(mce) && (mce->severity == MCE_AO_SEVERITY)) {
-   pfn = mce->addr >> PAGE_SHIFT;
+   if ((mce->severity == MCE_AO_SEVERITY) && mce_usable_address(mce, ))
memory_failure(pfn, MCE_VECTOR, 0);
-   }
 
return NOTIFY_OK;
 }
@@ -750,7 +778,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t 
*b)
 */
if (!(flags & MCP_DONTLOG) && !mca_cfg.dont_log_ce)
mce_log();
-   else if (mce_usable_address()) {
+   else if (mce_usable_address(, NULL)) {
/*
 * Although we skipped logging this, we still want
 * to take action. Add to the pool so the registered
-- 
2.7.4



[PATCH] x86/mce/AMD: Give a name to MCA bank 3 to use with legacy MSRs

2017-03-21 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

MCA bank 3 is reserved on systems pre-Fam17h, so it didn't have a name.
However, MCA bank 3 is defined on Fam17h systems and can be accessed using
legacy MSRs. Without a name we get a stack trace on Fam17h systems when
trying to register sysfs files for bank 3 on kernels that don't recognize
Scalable MCA.

Call MCA bank 3 "decode_unit" since this is what it represents on Fam17h.
This will allow kernels without SMCA support to see this bank on Fam17h+
and prevent the stack trace. This will not affect older systems since this
bank is reserved on them, i.e. it'll be ignored.

Tested on AMD Fam15h and Fam17h systems.

 WARNING: CPU: 26 PID: 1 at lib/kobject.c:210 kobject_add_internal+0x23e/0x340()
 kobject: (88085bb256c0): attempted to be registered with empty name!
 ...
 Call Trace:
  [] dump_stack+0x63/0x90
  [] warn_slowpath_common+0x86/0xc0
  [] warn_slowpath_fmt+0x4c/0x50
  [] ? kobject_add_internal+0x18e/0x340
  [] ? kfree_const+0x22/0x30
  [] kobject_add_internal+0x23e/0x340
  [] ? kfree_const+0x22/0x30
  [] kobject_add+0x68/0xb0
  [] kobject_create_and_add+0x33/0x70
  [] threshold_create_device+0x107/0x350
  [] ? mcheck_vendor_init_severity+0x1a/0x1a
  [] threshold_init_device+0x35/0x4d
  [] do_one_initcall+0xb3/0x1d0
  [] kernel_init_freeable+0x163/0x1f0
  [] ? rest_init+0x80/0x80
  [] kernel_init+0xe/0xe0
  [] ret_from_fork+0x3f/0x70
  [] ? rest_init+0x80/0x80

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
Cc: <sta...@vger.kernel.org> # 3.10..
---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index d3e5be8..c82befc 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -62,7 +62,7 @@ static const char * const th_names[] = {
"load_store",
"insn_fetch",
"combined_unit",
-   "",
+   "decode_unit",
"northbridge",
"execution_unit",
 };
-- 
2.7.4



[PATCH] x86/mce: Do feature check earlier

2017-03-15 Thread Yazen Ghannam
We may miss some information when errors are logged during boot before the
feature flags are set. For example, on SMCA systems we will not log the
MCA_IPID and MCA_SYND registers and we won't mask MCA_ADDR appropriately.

Move the feature checks before generic init. The rest of the vendor feature
initialization will still happen after generic init.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce.c | 27 ---
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 177472a..d1f675b 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1702,14 +1702,9 @@ static int __mcheck_cpu_ancient_init(struct cpuinfo_x86 
*c)
return 0;
 }
 
-static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
+static void __mcheck_cpu_init_feature_early(struct cpuinfo_x86 *c)
 {
switch (c->x86_vendor) {
-   case X86_VENDOR_INTEL:
-   mce_intel_feature_init(c);
-   mce_adjust_timer = cmci_intel_adjust_timer;
-   break;
-
case X86_VENDOR_AMD: {
mce_flags.overflow_recov = !!cpu_has(c, 
X86_FEATURE_OVERFLOW_RECOV);
mce_flags.succor = !!cpu_has(c, X86_FEATURE_SUCCOR);
@@ -1724,7 +1719,6 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 
*c)
msr_ops.addr= smca_addr_reg;
msr_ops.misc= smca_misc_reg;
}
-   mce_amd_feature_init(c);
 
break;
}
@@ -1734,6 +1728,24 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 
*c)
}
 }
 
+static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
+{
+   switch (c->x86_vendor) {
+   case X86_VENDOR_INTEL:
+   mce_intel_feature_init(c);
+   mce_adjust_timer = cmci_intel_adjust_timer;
+   break;
+
+   case X86_VENDOR_AMD: {
+   mce_amd_feature_init(c);
+   break;
+   }
+
+   default:
+   break;
+   }
+}
+
 static void __mcheck_cpu_clear_vendor(struct cpuinfo_x86 *c)
 {
switch (c->x86_vendor) {
@@ -1812,6 +1824,7 @@ void mcheck_cpu_init(struct cpuinfo_x86 *c)
 
machine_check_vector = do_machine_check;
 
+   __mcheck_cpu_init_feature_early(c);
__mcheck_cpu_init_generic();
__mcheck_cpu_init_vendor(c);
__mcheck_cpu_init_clear_banks();
-- 
2.7.4



[PATCH v2 1/2] x86/mce/AMD: Redo use of SMCA MCA_DE{STAT,ADDR} registers

2017-04-04 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

We have support for the new SMCA MCA_DE{STAT,ADDR} registers in Linux. So
we've used these registers in place of MCA_{STATUS,ADDR} on SMCA systems.
However, the guidance for current implementations of SMCA is to continue
using MCA_{STATUS,ADDR} and to use MCA_DE{STAT,ADDR} only if a Deferred
error was not found in the former registers. This also means we shouldn't
clear MCA_CONFIG[LogDeferredInMcaStat].

Redo the AMD Deferred error interrupt handler to follow the guidance for
current SMCA systems. Also, don't break after finding the first error.

Rework __log_error() for clarity.

Don't clear MCA_CONFIG[LogDeferredInMcaStat] during AMD mcheck init.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/1490210971-62346-1-git-send-email-yazen.ghan...@amd.com

v1->v2:
- Change name of check_deferred_status() to is_deferred_error().
- Rework __log_error() to move out SMCA/Deferred error-specific code.

 arch/x86/kernel/cpu/mcheck/mce_amd.c | 67 
 1 file changed, 30 insertions(+), 37 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 6e4a047..2caa84c 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -472,20 +472,6 @@ prepare_threshold_block(unsigned int bank, unsigned int 
block, u32 addr,
smca_high |= BIT(0);
 
/*
-* SMCA logs Deferred Error information in MCA_DE{STAT,ADDR}
-* registers with the option of additionally logging to
-* MCA_{STATUS,ADDR} if MCA_CONFIG[LogDeferredInMcaStat] is set.
-*
-* This bit is usually set by BIOS to retain the old behavior
-* for OSes that don't use the new registers. Linux supports the
-* new registers so let's disable that additional logging here.
-*
-* MCA_CONFIG[LogDeferredInMcaStat] is bit 34 (bit 2 in the high
-* portion of the MSR).
-*/
-   smca_high &= ~BIT(2);
-
-   /*
 * SMCA sets the Deferred Error Interrupt type per bank.
 *
 * MCA_CONFIG[DeferredIntTypeSupported] is bit 5, and tells us
@@ -756,20 +742,11 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 
umc, u64 *sys_addr)
 EXPORT_SYMBOL_GPL(umc_normaddr_to_sysaddr);
 
 static void
-__log_error(unsigned int bank, bool deferred_err, bool threshold_err, u64 misc)
+__log_error(unsigned int bank, u32 msr_status, u32 msr_addr, u64 misc)
 {
-   u32 msr_status = msr_ops.status(bank);
-   u32 msr_addr = msr_ops.addr(bank);
struct mce m;
u64 status;
 
-   WARN_ON_ONCE(deferred_err && threshold_err);
-
-   if (deferred_err && mce_flags.smca) {
-   msr_status = MSR_AMD64_SMCA_MCx_DESTAT(bank);
-   msr_addr = MSR_AMD64_SMCA_MCx_DEADDR(bank);
-   }
-
rdmsrl(msr_status, status);
 
if (!(status & MCI_STATUS_VAL))
@@ -778,12 +755,10 @@ __log_error(unsigned int bank, bool deferred_err, bool 
threshold_err, u64 misc)
mce_setup();
 
m.status = status;
+   m.misc   = misc;
m.bank   = bank;
m.tsc= rdtsc();
 
-   if (threshold_err)
-   m.misc = misc;
-
if (m.status & MCI_STATUS_ADDRV) {
rdmsrl(msr_addr, m.addr);
 
@@ -810,6 +785,20 @@ __log_error(unsigned int bank, bool deferred_err, bool 
threshold_err, u64 misc)
wrmsrl(msr_status, 0);
 }
 
+static void __log_error_deferred(unsigned int bank, bool use_smca_destat)
+{
+   u32 msr_status  = use_smca_destat ? MSR_AMD64_SMCA_MCx_DESTAT(bank) :
+   msr_ops.status(bank);
+   u32 msr_addr= use_smca_destat ? MSR_AMD64_SMCA_MCx_DEADDR(bank) :
+   msr_ops.addr(bank);
+
+   __log_error(bank, msr_status, msr_addr, 0);
+
+   /* We should still clear MCA_DESTAT even if we used MCA_STATUS. */
+   if (mce_flags.smca && !use_smca_destat)
+   wrmsrl(MSR_AMD64_SMCA_MCx_DESTAT(bank), 0);
+}
+
 static inline void __smp_deferred_error_interrupt(void)
 {
inc_irq_stat(irq_deferred_error_count);
@@ -832,25 +821,29 @@ asmlinkage __visible void __irq_entry 
smp_trace_deferred_error_interrupt(void)
exiting_ack_irq();
 }
 
+static inline bool is_deferred_error(u64 status)
+{
+   return ((status & MCI_STATUS_VAL) && (status & MCI_STATUS_DEFERRED));
+}
+
 /* APIC interrupt handler for deferred errors */
 static void amd_deferred_error_interrupt(void)
 {
unsigned int bank;
-   u32 msr_status;
u64 status;
 
for (bank = 0; bank < mca_cfg.banks; ++bank) {
-   msr_status = (mce_flags.smca) ? MSR_AMD64_SMCA_MCx_DESTA

[PATCH v2 2/2] x86/mce/AMD: Carve out SMCA bank configuration

2017-04-04 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Scalable MCA systems have a new MCA_CONFIG register that we use to
configure each bank. We currently use this when we set up thresholding.
However, this is logically separate.

Group all SMCA-related initialization into a single, separate function.
This includes setting MCA_CONFIG and gathering SMCA bank info.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/1490210971-62346-2-git-send-email-yazen.ghan...@amd.com

v1->v2:
- Merge get_smca_bank_info() and set_smca_config() into smca_configure().

 arch/x86/kernel/cpu/mcheck/mce_amd.c | 74 ++--
 1 file changed, 37 insertions(+), 37 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 2caa84c..b51d4d7 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -164,17 +164,48 @@ static void default_deferred_error_interrupt(void)
 }
 void (*deferred_error_int_vector)(void) = default_deferred_error_interrupt;
 
-static void get_smca_bank_info(unsigned int bank)
+static void smca_configure(unsigned int bank)
 {
unsigned int i, hwid_mcatype, cpu = smp_processor_id();
struct smca_hwid *s_hwid;
-   u32 high, instance_id;
+   u32 high, low;
+   u32 smca_config = MSR_AMD64_SMCA_MCx_CONFIG(bank);
+
+   /* Set appropriate bits in MCA_CONFIG */
+   if (!rdmsr_safe(smca_config, , )) {
+   /*
+* OS is required to set the MCAX bit to acknowledge that it is
+* now using the new MSR ranges and new registers under each
+* bank. It also means that the OS will configure deferred
+* errors in the new MCx_CONFIG register. If the bit is not set,
+* uncorrectable errors will cause a system panic.
+*
+* MCA_CONFIG[MCAX] is bit 32 (0 in the high portion of the 
MSR.)
+*/
+   high |= BIT(0);
+
+   /*
+* SMCA sets the Deferred Error Interrupt type per bank.
+*
+* MCA_CONFIG[DeferredIntTypeSupported] is bit 5, and tells us
+* if the DeferredIntType bit field is available.
+*
+* MCA_CONFIG[DeferredIntType] is bits [38:37] ([6:5] in the
+* high portion of the MSR). OS should set this to 0x1 to enable
+* APIC based interrupt. First, check that no interrupt has been
+* set.
+*/
+   if ((low & BIT(5)) && !((high >> 5) & 0x3))
+   high |= BIT(5);
+
+   wrmsr(smca_config, low, high);
+   }
 
/* Collect bank_info using CPU 0 for now. */
if (cpu)
return;
 
-   if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), _id, 
)) {
+   if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), , )) 
{
pr_warn("Failed to read MCA_IPID for bank %d\n", bank);
return;
}
@@ -191,7 +222,7 @@ static void get_smca_bank_info(unsigned int bank)
 smca_get_name(s_hwid->bank_type));
 
smca_banks[bank].hwid = s_hwid;
-   smca_banks[bank].id = instance_id;
+   smca_banks[bank].id = low;
smca_banks[bank].sysfs_id = s_hwid->count++;
break;
}
@@ -433,7 +464,7 @@ prepare_threshold_block(unsigned int bank, unsigned int 
block, u32 addr,
int offset, u32 misc_high)
 {
unsigned int cpu = smp_processor_id();
-   u32 smca_low, smca_high, smca_addr;
+   u32 smca_low, smca_high;
struct threshold_block b;
int new;
 
@@ -457,37 +488,6 @@ prepare_threshold_block(unsigned int bank, unsigned int 
block, u32 addr,
goto set_offset;
}
 
-   smca_addr = MSR_AMD64_SMCA_MCx_CONFIG(bank);
-
-   if (!rdmsr_safe(smca_addr, _low, _high)) {
-   /*
-* OS is required to set the MCAX bit to acknowledge that it is
-* now using the new MSR ranges and new registers under each
-* bank. It also means that the OS will configure deferred
-* errors in the new MCx_CONFIG register. If the bit is not set,
-* uncorrectable errors will cause a system panic.
-*
-* MCA_CONFIG[MCAX] is bit 32 (0 in the high portion of the 
MSR.)
-*/
-   smca_high |= BIT(0);
-
-   /*
-* SMCA sets the Deferred Error Interrupt type per bank.
-*
-* MCA_CONFIG[DeferredIntTypeSupported] is bit 5, and tells us
-* if the DeferredIntType bit field is available.
-*
-

[PATCH] ACPI, APEI, EINJ: Subtract any matching Register Region from Trigger resources

2017-08-10 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

ACPI defines a number of instructions to use for triggering errors. However
we are currently removing the address resources from the trigger resources
for only the WRITE_REGISTER_VALUE instruction. This leads to a resource
conflict for any other valid instruction.

Remove the WRITE_REGISTER_VALUE instruction check to fix the resource
conflict with other instructions.

Fixes: b4e008dc53a3 ("ACPI, APEI, EINJ, Refine the fix of resource conflict")
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 drivers/acpi/apei/einj.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index ec50c32ea3da..e0f201ea161d 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -281,7 +281,6 @@ static struct acpi_generic_address 
*einj_get_trigger_parameter_region(
((char *)trigger_tab + sizeof(struct acpi_einj_trigger));
for (i = 0; i < trigger_tab->entry_count; i++) {
if (entry->action == ACPI_EINJ_TRIGGER_ERROR &&
-   entry->instruction == ACPI_EINJ_WRITE_REGISTER_VALUE &&
entry->register_region.space_id ==
ACPI_ADR_SPACE_SYSTEM_MEMORY &&
(entry->register_region.address & param2) == (param1 & param2))
-- 
2.7.4



[PATCH] x86/mce/AMD: Allow any CPU to initialize smca_banks array

2017-06-29 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Current SMCA implementations have the same banks on each CPU with the
non-core banks only visible to a "master thread" on each Die. Practically,
this means the smca_banks array, which describes the banks, only needs to
be populated once by a single master thread.

CPU0 seemed like a good candidate to do the populating. However, it's
possible that CPU0 is not enabled in which case the smca_banks array won't
be populated.

Rather than try to figure out another master thread to do the populating,
we should just allow any CPU to populate the array.

Drop the CPU0 check and return early if the bank was already initialized.
Also, drop the WARNing about an already initialized bank, since this will
be a common, expected occurrence.

The smca_banks array is only populated at boot time and CPUs are brought
online sequentially. So there's no need for locking around the array.

If the first CPU up is a master thread, then it will populate the array
with all banks, core and non-core. Every CPU afterwards will return early.

If the first CPU up is not a master thread, then it will populate the array
with all core banks. The first CPU afterwards that is a master thread will
skip populating the core banks and continue populating the non-core banks.
Every CPU afterwards will then return early.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 9 ++---
 1 file changed, 2 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index b41466723f71..37dc43f820b4 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -214,8 +214,8 @@ static void smca_configure(unsigned int bank, unsigned int 
cpu)
wrmsr(smca_config, low, high);
}
 
-   /* Collect bank_info using CPU 0 for now. */
-   if (cpu)
+   /* Return early if this bank was already initialized. */
+   if (smca_banks[bank].hwid)
return;
 
if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), , )) 
{
@@ -229,11 +229,6 @@ static void smca_configure(unsigned int bank, unsigned int 
cpu)
for (i = 0; i < ARRAY_SIZE(smca_hwid_mcatypes); i++) {
s_hwid = _hwid_mcatypes[i];
if (hwid_mcatype == s_hwid->hwid_mcatype) {
-
-   WARN(smca_banks[bank].hwid,
-"Bank %s already initialized!\n",
-smca_get_name(s_hwid->bank_type));
-
smca_banks[bank].hwid = s_hwid;
smca_banks[bank].id = low;
smca_banks[bank].sysfs_id = s_hwid->count++;
-- 
2.7.4



[PATCH] EDAC,amd64: Fix reporting of Chip Select sizes on Fam17h

2017-04-27 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The wrong value is being passed to our function to compute CS sizes which
results in the wrong size being computed.

Redo the printing function so that the correct values are computed and
printed.

Also, redo how we calculate the number of pages in a CS row.

Tested on AMD Fam15h and Fam17h systems.

Reported-by: Benjamin Bennett <benbenn...@gmail.com>
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
Cc: <sta...@vger.kernel.org> # 4.10.x
---
 drivers/edac/amd64_edac.c | 31 ++-
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 82dab16..e325a59b 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -782,24 +782,26 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, 
u32 dclr, int chan)
 
 static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl)
 {
-   u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
-   int dimm, size0, size1;
+   int dimm, size0, size1, cs0, cs1;
 
edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl);
 
for (dimm = 0; dimm < 4; dimm++) {
size0 = 0;
+   cs0 = dimm * 2;
 
-   if (dcsb[dimm*2] & DCSB_CS_ENABLE)
-   size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+   if (csrow_enabled(cs0, ctrl, pvt))
+   size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs0);
 
size1 = 0;
-   if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
-   size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, dimm);
+   cs1 = dimm * 2 + 1;
+
+   if (csrow_enabled(cs1, ctrl, pvt))
+   size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs1);
 
amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
-   dimm * 2, size0,
-   dimm * 2 + 1, size1);
+   cs0,size0,
+   cs1,size1);
}
 }
 
@@ -2756,11 +2758,11 @@ static void read_mc_regs(struct amd64_pvt *pvt)
  * encompasses
  *
  */
-static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
+static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr_orig)
 {
u32 cs_mode, nr_pages;
u32 dbam = dct ? pvt->dbam1 : pvt->dbam0;
-
+   int csrow_nr = csrow_nr_orig;
 
/*
 * The math on this doesn't look right on the surface because x/2*4 can
@@ -2769,13 +2771,16 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 
dct, int csrow_nr)
 * number of bits to shift the DBAM register to extract the proper CSROW
 * field.
 */
-   cs_mode = DBAM_DIMM(csrow_nr / 2, dbam);
+   if (!pvt->umc)
+   csrow_nr >>= 1;
+
+   cs_mode = DBAM_DIMM(csrow_nr, dbam);
 
-   nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, (csrow_nr / 2))
+   nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr)
   << (20 - PAGE_SHIFT);
 
edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n",
-   csrow_nr, dct,  cs_mode);
+   csrow_nr_orig, dct,  cs_mode);
edac_dbg(0, "nr_pages/channel: %u\n", nr_pages);
 
return nr_pages;
-- 
2.7.4



[PATCH v3 1/2] x86/mce/AMD: Redo logging of errors from APIC LVT interrupts

2017-04-25 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

We have support for the new SMCA MCA_DE{STAT,ADDR} registers in Linux. So
we've used these registers in place of MCA_{STATUS,ADDR} on SMCA systems.
However, the guidance for current implementations of SMCA is to continue
using MCA_{STATUS,ADDR} and to use MCA_DE{STAT,ADDR} only if a Deferred
error was not found in the former registers. If we logged a Deferred error
in MCA_STATUS then we should also clear MCA_DESTAT. This also means we
shouldn't clear MCA_CONFIG[LogDeferredInMcaStat].

Don't clear MCA_CONFIG[LogDeferredInMcaStat] during AMD mcheck init.

Don't break after finding the first error in either the Deferred or
Thresholding interrupt handlers.

Rework __log_error() to only log error. Most valid checks are moved into
__log_error_* helper functions.

Write the Deferred error __log_error_* helper function to follow the
guidance for current SMCA systems.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/1491326672-48298-1-git-send-email-yazen.ghan...@amd.com

v2->v3:
- Write __log_error_*() helper functions for Deferred and Thresholding errors.
- Redo __log_error() to only log the error and do valid checks in the helpers.
- Log every valid error in the DE handler rather than just Deferred errors.
- Don't break after the first error found in either interrupt handler.

v1->v2:
- Change name of check_deferred_status() to is_deferred_error().
- Rework __log_error() to move out SMCA/Deferred error-specific code.

 arch/x86/kernel/cpu/mcheck/mce_amd.c | 137 +++
 1 file changed, 75 insertions(+), 62 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 6e4a047..e6e507d 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -472,20 +472,6 @@ prepare_threshold_block(unsigned int bank, unsigned int 
block, u32 addr,
smca_high |= BIT(0);
 
/*
-* SMCA logs Deferred Error information in MCA_DE{STAT,ADDR}
-* registers with the option of additionally logging to
-* MCA_{STATUS,ADDR} if MCA_CONFIG[LogDeferredInMcaStat] is set.
-*
-* This bit is usually set by BIOS to retain the old behavior
-* for OSes that don't use the new registers. Linux supports the
-* new registers so let's disable that additional logging here.
-*
-* MCA_CONFIG[LogDeferredInMcaStat] is bit 34 (bit 2 in the high
-* portion of the MSR).
-*/
-   smca_high &= ~BIT(2);
-
-   /*
 * SMCA sets the Deferred Error Interrupt type per bank.
 *
 * MCA_CONFIG[DeferredIntTypeSupported] is bit 5, and tells us
@@ -756,36 +742,19 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 
umc, u64 *sys_addr)
 EXPORT_SYMBOL_GPL(umc_normaddr_to_sysaddr);
 
 static void
-__log_error(unsigned int bank, bool deferred_err, bool threshold_err, u64 misc)
+__log_error(unsigned int bank, u64 status, u64 addr, u64 misc)
 {
-   u32 msr_status = msr_ops.status(bank);
-   u32 msr_addr = msr_ops.addr(bank);
struct mce m;
-   u64 status;
-
-   WARN_ON_ONCE(deferred_err && threshold_err);
-
-   if (deferred_err && mce_flags.smca) {
-   msr_status = MSR_AMD64_SMCA_MCx_DESTAT(bank);
-   msr_addr = MSR_AMD64_SMCA_MCx_DEADDR(bank);
-   }
-
-   rdmsrl(msr_status, status);
-
-   if (!(status & MCI_STATUS_VAL))
-   return;
 
mce_setup();
 
m.status = status;
+   m.misc   = misc;
m.bank   = bank;
m.tsc= rdtsc();
 
-   if (threshold_err)
-   m.misc = misc;
-
if (m.status & MCI_STATUS_ADDRV) {
-   rdmsrl(msr_addr, m.addr);
+   m.addr = addr;
 
/*
 * Extract [55:] where lsb is the least significant
@@ -806,8 +775,6 @@ __log_error(unsigned int bank, bool deferred_err, bool 
threshold_err, u64 misc)
}
 
mce_log();
-
-   wrmsrl(msr_status, 0);
 }
 
 static inline void __smp_deferred_error_interrupt(void)
@@ -832,33 +799,83 @@ asmlinkage __visible void __irq_entry 
smp_trace_deferred_error_interrupt(void)
exiting_ack_irq();
 }
 
+/*
+ * We have three scenarios for checking for Deferred errors.
+ * 1) Non-SMCA systems check MCA_STATUS and log error if found.
+ * 2) SMCA systems check MCA_STATUS. If error is found then log it and also
+ *clear MCA_DESTAT.
+ * 3) SMCA systems check MCA_DESTAT, if error was not found in MCA_STATUS, and
+ *log it.
+ */
+static void
+__log_error_deferred(unsigned int bank)
+{
+   u64 status, addr;
+   bool logged_deferred = false;
+
+   rdmsrl(msr_ops.status(bank), status);
+
+   /* Log 

[PATCH v3 2/2] x86/mce/AMD: Carve out SMCA bank configuration

2017-04-25 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Scalable MCA systems have a new MCA_CONFIG register that we use to
configure each bank. We currently use this when we set up thresholding.
However, this is logically separate.

Group all SMCA-related initialization into a single, separate function.
This includes setting MCA_CONFIG and gathering SMCA bank info.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/1491326672-48298-2-git-send-email-yazen.ghan...@amd.com

v2->v3:
- Pass in CPU to smca_configure().

v1->v2:
- Merge get_smca_bank_info() and set_smca_config() into smca_configure().

 arch/x86/kernel/cpu/mcheck/mce_amd.c | 76 ++--
 1 file changed, 38 insertions(+), 38 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index e6e507d..f97bc60 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -164,17 +164,48 @@ static void default_deferred_error_interrupt(void)
 }
 void (*deferred_error_int_vector)(void) = default_deferred_error_interrupt;
 
-static void get_smca_bank_info(unsigned int bank)
+static void smca_configure(unsigned int bank, unsigned int cpu)
 {
-   unsigned int i, hwid_mcatype, cpu = smp_processor_id();
+   unsigned int i, hwid_mcatype;
struct smca_hwid *s_hwid;
-   u32 high, instance_id;
+   u32 high, low;
+   u32 smca_config = MSR_AMD64_SMCA_MCx_CONFIG(bank);
+
+   /* Set appropriate bits in MCA_CONFIG */
+   if (!rdmsr_safe(smca_config, , )) {
+   /*
+* OS is required to set the MCAX bit to acknowledge that it is
+* now using the new MSR ranges and new registers under each
+* bank. It also means that the OS will configure deferred
+* errors in the new MCx_CONFIG register. If the bit is not set,
+* uncorrectable errors will cause a system panic.
+*
+* MCA_CONFIG[MCAX] is bit 32 (0 in the high portion of the 
MSR.)
+*/
+   high |= BIT(0);
+
+   /*
+* SMCA sets the Deferred Error Interrupt type per bank.
+*
+* MCA_CONFIG[DeferredIntTypeSupported] is bit 5, and tells us
+* if the DeferredIntType bit field is available.
+*
+* MCA_CONFIG[DeferredIntType] is bits [38:37] ([6:5] in the
+* high portion of the MSR). OS should set this to 0x1 to enable
+* APIC based interrupt. First, check that no interrupt has been
+* set.
+*/
+   if ((low & BIT(5)) && !((high >> 5) & 0x3))
+   high |= BIT(5);
+
+   wrmsr(smca_config, low, high);
+   }
 
/* Collect bank_info using CPU 0 for now. */
if (cpu)
return;
 
-   if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), _id, 
)) {
+   if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_IPID(bank), , )) 
{
pr_warn("Failed to read MCA_IPID for bank %d\n", bank);
return;
}
@@ -191,7 +222,7 @@ static void get_smca_bank_info(unsigned int bank)
 smca_get_name(s_hwid->bank_type));
 
smca_banks[bank].hwid = s_hwid;
-   smca_banks[bank].id = instance_id;
+   smca_banks[bank].id = low;
smca_banks[bank].sysfs_id = s_hwid->count++;
break;
}
@@ -433,7 +464,7 @@ prepare_threshold_block(unsigned int bank, unsigned int 
block, u32 addr,
int offset, u32 misc_high)
 {
unsigned int cpu = smp_processor_id();
-   u32 smca_low, smca_high, smca_addr;
+   u32 smca_low, smca_high;
struct threshold_block b;
int new;
 
@@ -457,37 +488,6 @@ prepare_threshold_block(unsigned int bank, unsigned int 
block, u32 addr,
goto set_offset;
}
 
-   smca_addr = MSR_AMD64_SMCA_MCx_CONFIG(bank);
-
-   if (!rdmsr_safe(smca_addr, _low, _high)) {
-   /*
-* OS is required to set the MCAX bit to acknowledge that it is
-* now using the new MSR ranges and new registers under each
-* bank. It also means that the OS will configure deferred
-* errors in the new MCx_CONFIG register. If the bit is not set,
-* uncorrectable errors will cause a system panic.
-*
-* MCA_CONFIG[MCAX] is bit 32 (0 in the high portion of the 
MSR.)
-*/
-   smca_high |= BIT(0);
-
-   /*
-* SMCA sets the Deferred Error Interrupt type per bank.
-*
-* MCA_CONFIG[DeferredIntTypeSupported] is bit 5

[PATCH] x86/ACPI/cstate: Allow ACPI C1 FFH MWAIT use on AMD systems

2017-05-17 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

AMD systems support the Monitor/Mwait instructions and these can be used
for ACPI C1 in the same way as on Intel systems, with appropriate BIOS
support.

Allow ffh_cstate_init() to succeed on AMD systems and make the Cstate
description vendor-agnostic.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/acpi/cstate.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index 8a908ae..4c5dd5d 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -109,7 +109,7 @@ static long acpi_processor_ffh_cstate_probe_cpu(void *_cx)
cx->type);
}
snprintf(cx->desc,
-   ACPI_CX_DESC_LEN, "ACPI FFH INTEL MWAIT 0x%x",
+   ACPI_CX_DESC_LEN, "ACPI FFH X86 MWAIT 0x%x",
cx->address);
 out:
return retval;
@@ -169,7 +169,8 @@ static int __init ffh_cstate_init(void)
 {
struct cpuinfo_x86 *c = _cpu_data;
 
-   if (c->x86_vendor != X86_VENDOR_INTEL)
+   if (c->x86_vendor != X86_VENDOR_INTEL &&
+   c->x86_vendor != X86_VENDOR_AMD)
return -1;
 
cpu_cstate_entry = alloc_percpu(struct cstate_entry);
-- 
2.7.4



[PATCH] x86/mce: Always save severity in machine_check_poll

2017-06-12 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Remove code that was used to decide whether to schedule work. The decision
to schedule work is made later, so this code is now only deciding if we
should save the error severity.

Save the severity since we have it, and let the notifier blocks decide if
they want to do anything.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index b58b778..6dde049 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -673,7 +673,6 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t 
*b)
 {
bool error_seen = false;
struct mce m;
-   int severity;
int i;
 
this_cpu_inc(mce_poll_count);
@@ -710,11 +709,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t 
*b)
 
mce_read_aux(, i);
 
-   severity = mce_severity(, mca_cfg.tolerant, NULL, false);
-
-   if (severity == MCE_DEFERRED_SEVERITY && 
mce_is_memory_error())
-   if (m.status & MCI_STATUS_ADDRV)
-   m.severity = severity;
+   m.severity = mce_severity(, mca_cfg.tolerant, NULL, false);
 
/*
 * Don't get the IP here because it's unlikely to
-- 
2.7.4



[PATCH] EDAC, mce_amd: Fix typo in SMCA error description

2017-06-12 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Fix typo in "poison consumption" error description.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 drivers/edac/mce_amd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index ba35b7e..9a2658a 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -161,7 +161,7 @@ static const char * const smca_ls_mce_desc[] = {
"Sys Read data error thread 0",
"Sys read data error thread 1",
"DC tag error type 2",
-   "DC data error type 1 (poison comsumption)",
+   "DC data error type 1 (poison consumption)",
"DC data error type 2",
"DC data error type 3",
"DC tag error type 4",
-- 
2.7.4




[PATCH v2] x86/mce: Always save severity in machine_check_poll

2017-06-21 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The severity gives a hint as to how to handle the error. The notifier
blocks can then use the severity to decide on an action. It's not necessary
for machine_check_poll() to filter errors for the notifier chain, since
each block will check its own set of conditions before handling an error.
Also, there isn't any urgency for machine_check_poll() to make decisions
based on severity like in do_machine_check().

If we can assume that a severity is set then we can use them in more
notifier blocks. For example, the CEC block can check for a "KEEP" severity
rather than checking bits in the status. This isn't possible now since the
severity is not set except for "DEFFRRED/UCNA" errors with a valid address.

Save the severity since we have it, and let the notifier blocks decide if
they want to do anything.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/1497286446-59533-1-git-send-email-yazen.ghan...@amd.com

v1->v2:
* Expand commit message.

 arch/x86/kernel/cpu/mcheck/mce.c | 7 +--
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index b58b77808ce4..6dde0497efc7 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -673,7 +673,6 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t 
*b)
 {
bool error_seen = false;
struct mce m;
-   int severity;
int i;
 
this_cpu_inc(mce_poll_count);
@@ -710,11 +709,7 @@ bool machine_check_poll(enum mcp_flags flags, mce_banks_t 
*b)
 
mce_read_aux(, i);
 
-   severity = mce_severity(, mca_cfg.tolerant, NULL, false);
-
-   if (severity == MCE_DEFERRED_SEVERITY && 
mce_is_memory_error())
-   if (m.status & MCI_STATUS_ADDRV)
-   m.severity = severity;
+   m.severity = mce_severity(, mca_cfg.tolerant, NULL, false);
 
/*
 * Don't get the IP here because it's unlikely to
-- 
2.7.4



[PATCH v2] x86/ACPI/cstate: Allow ACPI C1 FFH MWAIT use on AMD systems

2017-06-07 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

AMD systems support the Monitor/Mwait instructions and these can be used
for ACPI C1 in the same way as on Intel systems.

Three things are needed:
1) This patch.
2) BIOS that declares a C1 state in _CST to use FFH, with correct values.
3) CPUID_Fn0005_EDX is non-zero on the system.

The BIOS on AMD systems have historically not defined a C1 state in _CST,
so the acpi_idle driver uses HALT for ACPI C1.

Currently released systems have CPUID_Fn0005_EDX as reserved/RAZ. If a
BIOS is released for these systems that requests a C1 state with FFH, the
FFH implementation in Linux will fail since CPUID_Fn0005_EDX is 0. The
acpi_idle driver will then fallback to using HALT for ACPI C1.

Future systems are expected to have non-zero CPUID_Fn0005_EDX and BIOS
support for using FFH for ACPI C1.

Allow ffh_cstate_init() to succeed on AMD systems.

Tested on Fam15h and Fam17h systems.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/1495030819-4347-1-git-send-email-yazen.ghan...@amd.com

v1->v2:
* Expand commit message.
* Drop change to description string.

 arch/x86/kernel/acpi/cstate.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index 8233a63..dde437f 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -167,7 +167,8 @@ static int __init ffh_cstate_init(void)
 {
struct cpuinfo_x86 *c = _cpu_data;
 
-   if (c->x86_vendor != X86_VENDOR_INTEL)
+   if (c->x86_vendor != X86_VENDOR_INTEL &&
+   c->x86_vendor != X86_VENDOR_AMD)
return -1;
 
cpu_cstate_entry = alloc_percpu(struct cstate_entry);
-- 
2.7.4



[PATCH] x86/mce: Update bootlog description to reflect behavior on AMD

2017-06-09 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The bootlog option is only disabled by default on AMD Fam10h and older
systems.

Update bootlog description to say this.

Change the family value to hex to avoid confusion.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 Documentation/x86/x86_64/boot-options.txt | 3 ++-
 arch/x86/kernel/cpu/mcheck/mce.c  | 5 +++--
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/Documentation/x86/x86_64/boot-options.txt 
b/Documentation/x86/x86_64/boot-options.txt
index 61b611e..b297c48 100644
--- a/Documentation/x86/x86_64/boot-options.txt
+++ b/Documentation/x86/x86_64/boot-options.txt
@@ -36,7 +36,8 @@ Machine check
to broadcast MCEs.
mce=bootlog
Enable logging of machine checks left over from booting.
-   Disabled by default on AMD because some BIOS leave bogus ones.
+   Disabled by default on AMD Fam10h and older because some BIOS
+   leave bogus ones.
If your BIOS doesn't do that it's a good idea to enable though
to make sure you log even machine check events that result
in a reboot. On Intel systems it is enabled by default.
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index e317a95..fa09d41 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1550,7 +1550,7 @@ static int __mcheck_cpu_apply_quirks(struct cpuinfo_x86 
*c)
 */
clear_bit(10, (unsigned long *)_banks[4].ctl);
}
-   if (c->x86 < 17 && cfg->bootlog < 0) {
+   if (c->x86 < 0x11 && cfg->bootlog < 0) {
/*
 * Lots of broken BIOS around that don't clear them
 * by default and leave crap in there. Don't log:
@@ -1832,7 +1832,8 @@ void mce_disable_bank(int bank)
  * mce=TOLERANCELEVEL[,monarchtimeout] (number, see above)
  * monarchtimeout is how long to wait for other CPUs on machine
  * check, or 0 to not wait
- * mce=bootlog Log MCEs from before booting. Disabled by default on AMD.
+ * mce=bootlog Log MCEs from before booting. Disabled by default on AMD Fam10h
+   and older.
  * mce=nobootlog Don't log MCEs from before booting.
  * mce=bios_cmci_threshold Don't program the CMCI threshold
  * mce=recovery force enable memcpy_mcsafe()
-- 
2.7.4



[PATCH 1/3] x86/mce/AMD: Use msr_stat when clearing MCA_STATUS

2017-05-24 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The value of MCA_STATUS is used as the MSR when clearing MCA_STATUS.

This may cause the following warning:
 unchecked MSR access error: WRMSR to 0x11b (tried to write 0x)
 Call Trace:
  
  ? amd_threshold_interrupt+0x209/0x220
  smp_threshold_interrupt+0x1b/0x40
  threshold_interrupt+0x89/0x90

Use msr_stat instead which has the MSR address.

Fixes: 37d43acfd79f ("x86/mce/AMD: Redo error logging from APIC LVT interrupt 
handlers")
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index d00f299..d11f94e 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -815,7 +815,7 @@ _log_error_bank(unsigned int bank, u32 msr_stat, u32 
msr_addr, u64 misc)
 
__log_error(bank, status, addr, misc);
 
-   wrmsrl(status, 0);
+   wrmsrl(msr_stat, 0);
 
return status & MCI_STATUS_DEFERRED;
 }
-- 
2.7.4



[PATCH 3/3] x86/mce/AMD: Use saved threshold block info in interrupt handler

2017-05-24 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

In the amd_threshold_interrupt() handler, we loop through every possible
block in each bank and rediscover the block's address and if it's valid,
e.g. valid, counter present and not locked. However, we already have the
address saved in the threshold blocks list for each CPU and bank. The list
only contains blocks that have passed all the valid checks.

Besides the redundancy, there's also an smp_call_function* in
get_block_address() and this causes a warning when servicing the interrupt.

 WARNING: CPU: 0 PID: 0 at kernel/smp.c:281 smp_call_function_single+0xdd/0xf0
 ...
 Call Trace:
  
  rdmsr_safe_on_cpu+0x5d/0x90
  get_block_address.isra.2+0x97/0x100
  amd_threshold_interrupt+0xae/0x220
  smp_threshold_interrupt+0x1b/0x40
  threshold_interrupt+0x89/0x90

Iterate over the threshold blocks list and use the saved address. Also,
drop the redundant valid checks.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 27 ++-
 1 file changed, 10 insertions(+), 17 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 2074b870..14e4dab 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -873,30 +873,23 @@ static void log_error_thresholding(unsigned int bank, u64 
misc)
  */
 static void amd_threshold_interrupt(void)
 {
-   u32 low = 0, high = 0, address = 0;
-   unsigned int bank, block, cpu = smp_processor_id();
+   u32 low = 0, high = 0;
+   unsigned int bank, cpu = smp_processor_id();
struct thresh_restart tr;
+   struct threshold_block *block = NULL, *tmp = NULL;
+   struct list_head *head = NULL;
 
for (bank = 0; bank < mca_cfg.banks; ++bank) {
if (!(per_cpu(bank_map, cpu) & (1 << bank)))
continue;
-   for (block = 0; block < NR_BLOCKS; ++block) {
-   address = get_block_address(cpu, address, low, high, 
bank, block);
-   if (!address)
-   break;
 
-   if (rdmsr_safe(address, , ))
-   break;
+   if (!per_cpu(threshold_banks, cpu)[bank]->blocks)
+   continue;
 
-   if (!(high & MASK_VALID_HI)) {
-   if (block)
-   continue;
-   else
-   break;
-   }
+   head = _cpu(threshold_banks, cpu)[bank]->blocks_head;
 
-   if (!(high & MASK_CNTP_HI)  ||
-(high & MASK_LOCKED_HI))
+   list_for_each_entry_safe(block, tmp, head, miscj) {
+   if (rdmsr_safe(block->address, , ))
continue;
 
if (!(high & MASK_OVERFLOW_HI))
@@ -907,7 +900,7 @@ static void amd_threshold_interrupt(void)
 
/* Reset threshold block after logging error. */
memset(, 0, sizeof(tr));
-   tr.b = _cpu(threshold_banks, 
cpu)[bank]->blocks[block];
+   tr.b = block;
threshold_restart_bank();
}
}
-- 
2.7.4



[PATCH 2/3] x86/mce/AMD: Define a list_head for threshold blocks outside the list

2017-05-24 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

There needs to be a list_head outside of a linked list in order to iterate
over it and have access to all its elements. This is because the
list_for_each* macros iterate starting from head->next rather than head.

Define a list_head for the threshold blocks list in struct threshold_bank
since this is the container of the list. Use this list_head as the head
instead of the first element in the blocks list.

This is needed in a future patch where we read the blocks list in the
threshold interrupt handler. Currently, we'll always skip block 0 since it
is the head of the list.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/include/asm/amd_nb.h|  2 ++
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 19 ++-
 2 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/arch/x86/include/asm/amd_nb.h b/arch/x86/include/asm/amd_nb.h
index da181ad..81334b4 100644
--- a/arch/x86/include/asm/amd_nb.h
+++ b/arch/x86/include/asm/amd_nb.h
@@ -55,6 +55,8 @@ struct threshold_bank {
struct kobject  *kobj;
struct threshold_block  *blocks;
 
+   struct list_headblocks_head;
+
/* initialized to the number of CPUs on the node sharing this bank */
refcount_t  cpus;
 };
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index d11f94e..2074b870 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -1119,15 +1119,15 @@ static int allocate_threshold_blocks(unsigned int cpu, 
unsigned int bank,
threshold_ktype.default_attrs[2] = NULL;
}
 
-   INIT_LIST_HEAD(>miscj);
-
-   if (per_cpu(threshold_banks, cpu)[bank]->blocks) {
-   list_add(>miscj,
-_cpu(threshold_banks, cpu)[bank]->blocks->miscj);
-   } else {
+   if (!per_cpu(threshold_banks, cpu)[bank]->blocks) {
+   INIT_LIST_HEAD(_cpu(threshold_banks, 
cpu)[bank]->blocks_head);
per_cpu(threshold_banks, cpu)[bank]->blocks = b;
}
 
+   INIT_LIST_HEAD(>miscj);
+
+   list_add(>miscj, _cpu(threshold_banks, cpu)[bank]->blocks_head);
+
err = kobject_init_and_add(>kobj, _ktype,
   per_cpu(threshold_banks, cpu)[bank]->kobj,
   get_name(bank, b));
@@ -1158,7 +1158,7 @@ static int allocate_threshold_blocks(unsigned int cpu, 
unsigned int bank,
 
 static int __threshold_add_blocks(struct threshold_bank *b)
 {
-   struct list_head *head = >blocks->miscj;
+   struct list_head *head = >blocks_head;
struct threshold_block *pos = NULL;
struct threshold_block *tmp = NULL;
int err = 0;
@@ -1256,7 +1256,7 @@ static void deallocate_threshold_block(unsigned int cpu,
if (!head)
return;
 
-   list_for_each_entry_safe(pos, tmp, >blocks->miscj, miscj) {
+   list_for_each_entry_safe(pos, tmp, >blocks_head, miscj) {
kobject_put(>kobj);
list_del(>miscj);
kfree(pos);
@@ -1273,7 +1273,7 @@ static void __threshold_remove_blocks(struct 
threshold_bank *b)
 
kobject_del(b->kobj);
 
-   list_for_each_entry_safe(pos, tmp, >blocks->miscj, miscj)
+   list_for_each_entry_safe(pos, tmp, >blocks_head, miscj)
kobject_del(>kobj);
 }
 
@@ -1307,6 +1307,7 @@ static void threshold_remove_bank(unsigned int cpu, int 
bank)
deallocate_threshold_block(cpu, bank);
 
 free_out:
+   list_del(>blocks_head);
kobject_del(b->kobj);
kobject_put(b->kobj);
kfree(b);
-- 
2.7.4



[PATCH v2] x86/mce/AMD: Use saved threshold block info in interrupt handler

2017-05-31 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

In the amd_threshold_interrupt() handler, we loop through every possible
block in each bank and rediscover the block's address and if it's valid,
e.g. valid, counter present and not locked. However, we already have the
address saved in the threshold blocks list for each CPU and bank. The list
only contains blocks that have passed all the valid checks.

Besides the redundancy, there's also a smp_call_function* in
get_block_address() and this causes a warning when servicing the interrupt.

 WARNING: CPU: 0 PID: 0 at kernel/smp.c:281 smp_call_function_single+0xdd/0xf0
 ...
 Call Trace:
  
  rdmsr_safe_on_cpu+0x5d/0x90
  get_block_address.isra.2+0x97/0x100
  amd_threshold_interrupt+0xae/0x220
  smp_threshold_interrupt+0x1b/0x40
  threshold_interrupt+0x89/0x90

Drop the redundant valid checks and move the overflow check, logging and
block reset into a separate function.

Check the first block then iterate over the rest. This procedure is needed
since the first block is used as the head of the list.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/1495658507-7413-3-git-send-email-yazen.ghan...@amd.com

Link for patch 2:
https://lkml.kernel.org/r/1495658507-7413-2-git-send-email-yazen.ghan...@amd.com

v1->v2:
* Drop patch 2 from the first set.
* Rather than iterating through all blocks in the list, check the first
  and iterate over the rest. This way we don't need to have an external
  list_head.
 
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 64 
 1 file changed, 35 insertions(+), 29 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index d11f94e..5cbb6ee 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -867,49 +867,55 @@ static void log_error_thresholding(unsigned int bank, u64 
misc)
_log_error_bank(bank, msr_ops.status(bank), msr_ops.addr(bank), misc);
 }
 
+static void log_and_reset_block(struct threshold_block *block)
+{
+   u32 low = 0, high = 0;
+   struct thresh_restart tr;
+
+   if (!block)
+   return;
+
+   if (rdmsr_safe(block->address, , ))
+   return;
+
+   if (!(high & MASK_OVERFLOW_HI))
+   return;
+
+   /* Log the MCE which caused the threshold event. */
+   log_error_thresholding(block->bank, ((u64)high << 32) | low);
+
+   /* Reset threshold block after logging error. */
+   memset(, 0, sizeof(tr));
+   tr.b = block;
+   threshold_restart_bank();
+}
+
 /*
  * Threshold interrupt handler will service THRESHOLD_APIC_VECTOR. The 
interrupt
  * goes off when error_count reaches threshold_limit.
  */
 static void amd_threshold_interrupt(void)
 {
-   u32 low = 0, high = 0, address = 0;
-   unsigned int bank, block, cpu = smp_processor_id();
-   struct thresh_restart tr;
+   unsigned int bank, cpu = smp_processor_id();
+   struct threshold_block *first_block = NULL, *block = NULL, *tmp = NULL;
 
for (bank = 0; bank < mca_cfg.banks; ++bank) {
if (!(per_cpu(bank_map, cpu) & (1 << bank)))
continue;
-   for (block = 0; block < NR_BLOCKS; ++block) {
-   address = get_block_address(cpu, address, low, high, 
bank, block);
-   if (!address)
-   break;
 
-   if (rdmsr_safe(address, , ))
-   break;
+   first_block = per_cpu(threshold_banks, cpu)[bank]->blocks;
 
-   if (!(high & MASK_VALID_HI)) {
-   if (block)
-   continue;
-   else
-   break;
-   }
-
-   if (!(high & MASK_CNTP_HI)  ||
-(high & MASK_LOCKED_HI))
-   continue;
-
-   if (!(high & MASK_OVERFLOW_HI))
-   continue;
+   if (!first_block)
+   continue;
 
-   /* Log the MCE which caused the threshold event. */
-   log_error_thresholding(bank, ((u64)high << 32) | low);
+   /*
+* The first block is also the head of the list.
+* Check it first before iterating over the rest.
+*/
+   log_and_reset_block(first_block);
 
-   /* Reset threshold block after logging error. */
-   memset(, 0, sizeof(tr));
-   tr.b = _cpu(threshold_banks, 
cpu)[bank]->blocks[block];
-   threshold_restart_bank();
-   }
+   list_for_each_entry_safe(block, t

[PATCH] x86/mce: Don't disable MCA banks when offlining a CPU on AMD systems

2017-06-05 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

AMD systems have non-core, shared MCA banks within a Die. These banks are
controlled by a master CPU per Die. If this CPU is offlined then all the
shared banks are disabled in addition to the CPU's core banks.

Also, Fam17h systems may have SMT enabled. The MCA_CTL register is shared
between SMT thread siblings. If a CPU is offlined then all its sibling's
MCA banks are also disabled.

Do a vendor check for AMD and return early when offling a CPU.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 5cfbaeb..e317a95 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1917,7 +1917,8 @@ static void vendor_disable_error_reporting(void)
 * inhibit reporting for all shared resources on the socket like the
 * last level cache (LLC), the integrated memory controller (iMC), etc.
 */
-   if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)
+   if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL ||
+   boot_cpu_data.x86_vendor == X86_VENDOR_AMD)
return;
 
mce_disable_error_reporting();
-- 
2.7.4



[PATCH] x86/MCE/AMD: Always give PANIC severity for UC errors in kernel context

2017-09-19 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Our current AMD severity logic can possibly give MCE_AR_SEVERITY for
uncorrectable errors in kernel context. The current #MC handler only calls
memory_failure() on errors in user context, but older versions will call
memory_failure() unconditionally. In older versions, the system can get
stuck in a loop as memory_failure() will try to handle the bad kernel
memory and find it busy.

Return MCE_PANIC_SEVERITY for all UC errors IN_KERNEL context. Newer
kernel versions have IN_KERNEL_RECOV context for recoverable kernel errors.
All others kernel uncorrectable errors can be considered unrecoverable.

Fixes: bf80bbd7dcf5 (x86/mce: Add an AMD severities-grading function)

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
Cc: <sta...@vger.kernel.org> # v4.9..
---
 arch/x86/kernel/cpu/mcheck/mce-severity.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c 
b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 2773c8547f69..f5518706baa6 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -245,6 +245,9 @@ static int mce_severity_amd(struct mce *m, int tolerant, 
char **msg, bool is_exc
 
if (m->status & MCI_STATUS_UC) {
 
+   if (ctx == IN_KERNEL)
+   return MCE_PANIC_SEVERITY;
+
/*
 * On older systems where overflow_recov flag is not present, we
 * should simply panic if an error overflow occurs. If
@@ -255,10 +258,6 @@ static int mce_severity_amd(struct mce *m, int tolerant, 
char **msg, bool is_exc
if (mce_flags.smca)
return mce_severity_amd_smca(m, ctx);
 
-   /* software can try to contain */
-   if (!(m->mcgstatus & MCG_STATUS_RIPV) && (ctx == 
IN_KERNEL))
-   return MCE_PANIC_SEVERITY;
-
/* kill current process */
return MCE_AR_SEVERITY;
} else {
-- 
2.7.4



[PATCH v2] ACPI, APEI, EINJ: Subtract any matching Register Region from Trigger resources

2017-08-28 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

ACPI defines a number of instructions to use for triggering errors. However
we are currently removing the address resources from the trigger resources
for only the WRITE_REGISTER_VALUE instruction. This leads to a resource
conflict for any other valid instruction.

Check that the instruction is less than or equal to the
WRITE_REGISTER_VALUE instruction. This allows all valid memory access
instructions and protects against invalid instructions.

Fixes: b4e008dc53a3 ("ACPI, APEI, EINJ, Refine the fix of resource conflict")
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
Acked-by: Tony Luck <tony.l...@intel.com>
---
Link:
https://lkml.kernel.org/r/1502387883-16667-1-git-send-email-yazen.ghan...@amd.com

v1->v2:
* Apply Tony's comment to restrict behavior to valid memory instructions.

 drivers/acpi/apei/einj.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/acpi/apei/einj.c b/drivers/acpi/apei/einj.c
index ec50c32ea3da..b38737c83a24 100644
--- a/drivers/acpi/apei/einj.c
+++ b/drivers/acpi/apei/einj.c
@@ -281,7 +281,7 @@ static struct acpi_generic_address 
*einj_get_trigger_parameter_region(
((char *)trigger_tab + sizeof(struct acpi_einj_trigger));
for (i = 0; i < trigger_tab->entry_count; i++) {
if (entry->action == ACPI_EINJ_TRIGGER_ERROR &&
-   entry->instruction == ACPI_EINJ_WRITE_REGISTER_VALUE &&
+   entry->instruction <= ACPI_EINJ_WRITE_REGISTER_VALUE &&
entry->register_region.space_id ==
ACPI_ADR_SPACE_SYSTEM_MEMORY &&
(entry->register_region.address & param2) == (param1 & param2))
-- 
2.7.4



[PATCH] x86/mce: Do Deferred error check for CEC

2017-12-12 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

AMD systems may log Deferred errors. These are errors that are uncorrected
but which do not need immediate action. The MCA_STATUS[UC] bit may not be
set for Deferred errors.

Flag the error as not correctable when MCA_STATUS[Deferred] is set.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
Cc: sta...@vger.kernel.org # 4.13.x
---
 arch/x86/kernel/cpu/mcheck/mce.c | 13 -
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 321c7a80be66..1b2c11473376 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -528,6 +528,17 @@ bool mce_is_memory_error(struct mce *m)
 }
 EXPORT_SYMBOL_GPL(mce_is_memory_error);
 
+static bool mce_is_correctable(struct mce *m)
+{
+   if (m->cpuvendor == X86_VENDOR_AMD && m->status & MCI_STATUS_DEFERRED)
+   return false;
+
+   if (m->status & MCI_STATUS_UC)
+   return false;
+
+   return true;
+}
+
 static bool cec_add_mce(struct mce *m)
 {
if (!m)
@@ -535,7 +546,7 @@ static bool cec_add_mce(struct mce *m)
 
/* We eat only correctable DRAM errors with usable addresses. */
if (mce_is_memory_error(m) &&
-   !(m->status & MCI_STATUS_UC) &&
+   mce_is_correctable(m)  &&
mce_usable_address(m))
if (!cec_add_elem(m->addr >> PAGE_SHIFT))
return true;
-- 
2.14.1



[PATCH] x86/mce/AMD: Don't set DEF_INT_TYPE in MSR_CU_DEF_ERR on SMCA systems

2017-11-20 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The McaIntrCfg register at MSRC000_0410, previously known as CU_DEFER_ERR,
is used on SMCA systems to set the LVT offset for the Threshold and
Deferred error interrupts.

This register was used on non-SMCA systems to also set the Deferred
interrupt type in bits 2:1. However, these bits are reserved on SMCA
systems.

Only set MSRC000_0410[2:1] on non-SMCA systems.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index e4e27adedc81..32008a8d293f 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -418,7 +418,9 @@ static void deferred_error_interrupt_enable(struct 
cpuinfo_x86 *c)
(deferred_error_int_vector != amd_deferred_error_interrupt))
deferred_error_int_vector = amd_deferred_error_interrupt;
 
-   low = (low & ~MASK_DEF_INT_TYPE) | DEF_INT_TYPE_APIC;
+   if (!mce_flags.smca)
+   low = (low & ~MASK_DEF_INT_TYPE) | DEF_INT_TYPE_APIC;
+
wrmsr(MSR_CU_DEF_ERR, low, high);
 }
 
-- 
2.14.1



[PATCH] x86/MCE/AMD: Always give panic severity for UC errors in kernel context

2017-11-21 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

[Upstream commit d65dfc81bb3894fdb68cbc74bbf5fb48d2354071]

The AMD severity grading function was introduced in kernel 4.1. The
current logic can possibly give MCE_AR_SEVERITY for uncorrectable
errors in kernel context. The system may then get stuck in a loop as
memory_failure() will try to handle the bad kernel memory and find it
busy.

Return MCE_PANIC_SEVERITY for all UC errors IN_KERNEL context on AMD
systems.

After:

  b2f9d678e28c ("x86/mce: Check for faults tagged in EXTABLE_CLASS_FAULT 
exception table entries")

was accepted in v4.6, this issue was masked because of the tail-end attempt
at kernel mode recovery in the #MC handler.

However, uncorrectable errors IN_KERNEL context should always be considered
unrecoverable and cause a panic.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
Cc: <sta...@vger.kernel.org> # 4.1.x, 4.4.x
Fixes: bf80bbd7dcf5 (x86/mce: Add an AMD severities-grading function)
---
Same as
  d65dfc81bb38 ("x86/MCE/AMD: Always give panic severity for UC errors in 
kernel context")
but fixed up to apply to v4.1 and v4.4 stable branches.

 arch/x86/kernel/cpu/mcheck/mce-severity.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c 
b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 9c682c222071..a9287f0f06f2 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -200,6 +200,9 @@ static int mce_severity_amd(struct mce *m, int tolerant, 
char **msg, bool is_exc
 
if (m->status & MCI_STATUS_UC) {
 
+   if (ctx == IN_KERNEL)
+   return MCE_PANIC_SEVERITY;
+
/*
 * On older systems where overflow_recov flag is not present, we
 * should simply panic if an error overflow occurs. If
@@ -207,10 +210,6 @@ static int mce_severity_amd(struct mce *m, int tolerant, 
char **msg, bool is_exc
 * to at least kill process to prolong system operation.
 */
if (mce_flags.overflow_recov) {
-   /* software can try to contain */
-   if (!(m->mcgstatus & MCG_STATUS_RIPV) && (ctx == 
IN_KERNEL))
-   return MCE_PANIC_SEVERITY;
-
/* kill current process */
return MCE_AR_SEVERITY;
} else {
-- 
2.14.1



[PATCH v2] x86/MCE/AMD: Always give PANIC severity for UC errors IN_KERNEL context

2017-11-01 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The AMD severity grading function was introduced in v4.1 and has remained
logically unchanged with the exception of a separate SMCA severity grading
function for SMCA systems. The current logic can possibly give
MCE_AR_SEVERITY for uncorrectable errors in kernel context. The system may
then get stuck in a loop as memory_failure() will try to handle the bad
kernel memory and find it busy.

Return MCE_PANIC_SEVERITY for all UC errors IN_KERNEL context on AMD
systems.

After:

  b2f9d678e28c ("x86/mce: Check for faults tagged in EXTABLE_CLASS_FAULT 
exception table entries")

was accepted in v4.6, this issue was masked because of the tail-end attempt
at kernel mode recovery in the #MC handler.

However, uncorrectable errors IN_KERNEL context should always be considered
unrecoverable and cause a panic.

Fixes: bf80bbd7dcf5 (x86/mce: Add an AMD severities-grading function)

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
[ This needs to be reworked to apply to v4.1 and v4.4 stable branches.]
Cc: <sta...@vger.kernel.org> # 4.9.x
---
Link:
https://lkml.kernel.org/r/1505830031-9630-1-git-send-email-yazen.ghan...@amd.com

v1->v2:
* Update commit message.

 arch/x86/kernel/cpu/mcheck/mce-severity.c | 7 +++
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c 
b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index 2773c8547f69..f5518706baa6 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -245,6 +245,9 @@ static int mce_severity_amd(struct mce *m, int tolerant, 
char **msg, bool is_exc
 
if (m->status & MCI_STATUS_UC) {
 
+   if (ctx == IN_KERNEL)
+   return MCE_PANIC_SEVERITY;
+
/*
 * On older systems where overflow_recov flag is not present, we
 * should simply panic if an error overflow occurs. If
@@ -255,10 +258,6 @@ static int mce_severity_amd(struct mce *m, int tolerant, 
char **msg, bool is_exc
if (mce_flags.smca)
return mce_severity_amd_smca(m, ctx);
 
-   /* software can try to contain */
-   if (!(m->mcgstatus & MCG_STATUS_RIPV) && (ctx == 
IN_KERNEL))
-   return MCE_PANIC_SEVERITY;
-
/* kill current process */
return MCE_AR_SEVERITY;
} else {
-- 
2.7.4



[PATCH] x86/mce/AMD: Fix mce_severity_amd_smca() signature

2017-11-01 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Change the err_ctx type to "enum context" to match the type passed in.

Suggested-by: Borislav Petkov <b...@suse.de>
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce-severity.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce-severity.c 
b/arch/x86/kernel/cpu/mcheck/mce-severity.c
index f5518706baa6..267311a7fc60 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-severity.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-severity.c
@@ -204,7 +204,7 @@ static int error_context(struct mce *m)
return IN_KERNEL;
 }
 
-static int mce_severity_amd_smca(struct mce *m, int err_ctx)
+static int mce_severity_amd_smca(struct mce *m, enum context err_ctx)
 {
u32 addr = MSR_AMD64_SMCA_MCx_CONFIG(m->bank);
u32 low, high;
-- 
2.7.4



[PATCH 1/2] x86/mce/AMD: Define function to get SMCA bank type

2017-12-01 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Scalable MCA systems have various types of banks. The bank's type can
determine how we handle errors from it. For example, if a bank represents
a UMC then we will need to convert its address from a normalized address
to a system physical address before handling the error.

Define an exported function to return a bank's SMCA type.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/include/asm/mce.h   |  1 +
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 11 +++
 2 files changed, 12 insertions(+)

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index b1e8d8db921f..9ab8bf32e61c 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -376,6 +376,7 @@ struct smca_bank {
 extern struct smca_bank smca_banks[MAX_NR_BANKS];
 
 extern const char *smca_get_long_name(enum smca_bank_types t);
+extern unsigned int smca_get_bank_type(struct mce *m);
 
 extern int mce_threshold_create_device(unsigned int cpu);
 extern int mce_threshold_remove_device(unsigned int cpu);
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index a38ab1fa53a2..bc0510a4f6c0 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -110,6 +110,17 @@ const char *smca_get_long_name(enum smca_bank_types t)
 }
 EXPORT_SYMBOL_GPL(smca_get_long_name);
 
+unsigned int smca_get_bank_type(struct mce *m)
+{
+   struct smca_bank bank = smca_banks[m->bank];
+
+   if (!bank.hwid)
+   return N_SMCA_BANK_TYPES;
+
+   return bank.hwid->bank_type;
+}
+EXPORT_SYMBOL_GPL(smca_get_bank_type);
+
 static struct smca_hwid smca_hwid_mcatypes[] = {
/* { bank_type, hwid_mcatype, xec_bitmap } */
 
-- 
2.14.1



[PATCH 2/2] x86/mce: Report only DRAM ECC as memory errors on AMD systems

2017-12-01 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The MCA_STATUS[ErrorCodeExt] field is very bank type specific. We currently
check if the ErrorCodeExt value is 0x0 or 0x8 in mce_is_memory_error(), but
we don't check the bank. This means that we could flag non-memory errors as
memory errors.

We know that we want to flag DRAM ECC errors as memory errors, so let's do
those cases first. We can add more cases later when needed.

Check that bank type is UMC and xec is 0 on SMCA systems.

Check that bank is 4 (Northbridge) and xec is 8 on legacy systems.

Define a wrapper function in mce_amd.c so we can use SMCA enums.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/include/asm/mce.h   |  2 ++
 arch/x86/kernel/cpu/mcheck/mce.c |  4 +---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 11 +++
 3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 9ab8bf32e61c..7b1cc4d1710c 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -377,6 +377,7 @@ extern struct smca_bank smca_banks[MAX_NR_BANKS];
 
 extern const char *smca_get_long_name(enum smca_bank_types t);
 extern unsigned int smca_get_bank_type(struct mce *m);
+extern bool amd_mce_is_memory_error(struct mce *m);
 
 extern int mce_threshold_create_device(unsigned int cpu);
 extern int mce_threshold_remove_device(unsigned int cpu);
@@ -385,6 +386,7 @@ extern int mce_threshold_remove_device(unsigned int cpu);
 
 static inline int mce_threshold_create_device(unsigned int cpu) { return 0; };
 static inline int mce_threshold_remove_device(unsigned int cpu) { return 0; };
+static inline bool amd_mce_is_memory_error(struct mce *m) { return false; };
 
 #endif
 
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index b1d616d08eee..321c7a80be66 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -503,10 +503,8 @@ static int mce_usable_address(struct mce *m)
 bool mce_is_memory_error(struct mce *m)
 {
if (m->cpuvendor == X86_VENDOR_AMD) {
-   /* ErrCodeExt[20:16] */
-   u8 xec = (m->status >> 16) & 0x1f;
+   return amd_mce_is_memory_error(m);
 
-   return (xec == 0x0 || xec == 0x8);
} else if (m->cpuvendor == X86_VENDOR_INTEL) {
/*
 * Intel SDM Volume 3B - 15.9.2 Compound Error Codes
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index bc0510a4f6c0..b2f016bd1de5 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -751,6 +751,17 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 
umc, u64 *sys_addr)
 }
 EXPORT_SYMBOL_GPL(umc_normaddr_to_sysaddr);
 
+bool amd_mce_is_memory_error(struct mce *m)
+{
+   /* ErrCodeExt[20:16] */
+   u8 xec = (m->status >> 16) & 0x1f;
+
+   if (mce_flags.smca)
+   return (smca_get_bank_type(m) == SMCA_UMC && xec == 0x0);
+
+   return (m->bank == 4 && xec == 0x8);
+}
+
 static void __log_error(unsigned int bank, u64 status, u64 addr, u64 misc)
 {
struct mce m;
-- 
2.14.1



[PATCH v2 2/2] x86/mce: Report only DRAM ECC as memory errors on AMD systems

2017-12-07 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The MCA_STATUS[ErrorCodeExt] field is very bank type specific. We currently
check if the ErrorCodeExt value is 0x0 or 0x8 in mce_is_memory_error(), but
we don't check the bank. This means that we could flag non-memory errors as
memory errors.

We know that we want to flag DRAM ECC errors as memory errors, so let's do
those cases first. We can add more cases later when needed.

Check that bank type is UMC and xec is 0 on SMCA systems.

Check that bank is 4 (Northbridge) and xec is 8 on legacy systems.

Define a wrapper function in mce_amd.c so we can use SMCA enums.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20171201155034.39206-2-yazen.ghan...@amd.com

v1->v2:
* No changes.

 arch/x86/include/asm/mce.h   |  2 ++
 arch/x86/kernel/cpu/mcheck/mce.c |  4 +---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 11 +++
 3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index b1e8d8db921f..96ea4b5ba658 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -376,6 +376,7 @@ struct smca_bank {
 extern struct smca_bank smca_banks[MAX_NR_BANKS];
 
 extern const char *smca_get_long_name(enum smca_bank_types t);
+extern bool amd_mce_is_memory_error(struct mce *m);
 
 extern int mce_threshold_create_device(unsigned int cpu);
 extern int mce_threshold_remove_device(unsigned int cpu);
@@ -384,6 +385,7 @@ extern int mce_threshold_remove_device(unsigned int cpu);
 
 static inline int mce_threshold_create_device(unsigned int cpu) { return 0; };
 static inline int mce_threshold_remove_device(unsigned int cpu) { return 0; };
+static inline bool amd_mce_is_memory_error(struct mce *m) { return false; };
 
 #endif
 
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index b1d616d08eee..321c7a80be66 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -503,10 +503,8 @@ static int mce_usable_address(struct mce *m)
 bool mce_is_memory_error(struct mce *m)
 {
if (m->cpuvendor == X86_VENDOR_AMD) {
-   /* ErrCodeExt[20:16] */
-   u8 xec = (m->status >> 16) & 0x1f;
+   return amd_mce_is_memory_error(m);
 
-   return (xec == 0x0 || xec == 0x8);
} else if (m->cpuvendor == X86_VENDOR_INTEL) {
/*
 * Intel SDM Volume 3B - 15.9.2 Compound Error Codes
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 219d5115f4d4..2b7f7ce4bedf 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -750,6 +750,17 @@ int umc_normaddr_to_sysaddr(u64 norm_addr, u16 nid, u8 
umc, u64 *sys_addr)
 }
 EXPORT_SYMBOL_GPL(umc_normaddr_to_sysaddr);
 
+bool amd_mce_is_memory_error(struct mce *m)
+{
+   /* ErrCodeExt[20:16] */
+   u8 xec = (m->status >> 16) & 0x1f;
+
+   if (mce_flags.smca)
+   return (smca_get_bank_type(m) == SMCA_UMC && xec == 0x0);
+
+   return (m->bank == 4 && xec == 0x8);
+}
+
 static void __log_error(unsigned int bank, u64 status, u64 addr, u64 misc)
 {
struct mce m;
-- 
2.14.1



[PATCH v2 1/2] x86/mce/AMD: Define function to get SMCA bank type

2017-12-07 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Scalable MCA systems have various types of banks. The bank's type can
determine how we handle errors from it. For example, if a bank represents
a UMC then we will need to convert its address from a normalized address
to a system physical address before handling the error.

Define a static function to return a bank's SMCA type.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20171201155034.39206-1-yazen.ghan...@amd.com

v1->v2:
* Make function static to mcheck/mce_amd.c.

 arch/x86/kernel/cpu/mcheck/mce_amd.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index a38ab1fa53a2..219d5115f4d4 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -110,6 +110,16 @@ const char *smca_get_long_name(enum smca_bank_types t)
 }
 EXPORT_SYMBOL_GPL(smca_get_long_name);
 
+static enum smca_bank_types smca_get_bank_type(struct mce *m)
+{
+   struct smca_bank bank = smca_banks[m->bank];
+
+   if (!bank.hwid)
+   return N_SMCA_BANK_TYPES;
+
+   return bank.hwid->bank_type;
+}
+
 static struct smca_hwid smca_hwid_mcatypes[] = {
/* { bank_type, hwid_mcatype, xec_bitmap } */
 
-- 
2.14.1



[PATCH] PCI/ACPI: Disable AER when _OSC control bit is clear.

2018-01-11 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Currently, aer_service_init() checks if AER is available and that
Firmware First handling is not enabled. The _OSC request for AER is
not taken into account when deciding to enable AER in Linux.

We should check that the _OSC control for AER is set. If it's not
then AER should be disabled.

The _OSC control for AER is not requested when APEI Firmware First is
used, so the same condition applies.

Mark AER as disabled if the _OSC request was not made or accepted.

Remove redunant check for aer_acpi_firmware_first() when calling
aer_service_init(), since this is check is already included when
checking the _OSC control.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 drivers/acpi/pci_root.c   | 3 +++
 drivers/pci/pcie/aer/aerdrv.c | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 6fc204a52493..19a625ed8de9 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -512,6 +512,9 @@ static void negotiate_os_control(struct acpi_pci_root 
*root, int *no_aspm)
 */
*no_aspm = 1;
}
+
+   if (!(requested & control & OSC_PCI_EXPRESS_AER_CONTROL))
+   pci_no_aer();
 }
 
 static int acpi_pci_root_add(struct acpi_device *device,
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 6ff5f5b4f5e6..39bb059777d0 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -374,7 +374,7 @@ static void aer_error_resume(struct pci_dev *dev)
  */
 static int __init aer_service_init(void)
 {
-   if (!pci_aer_available() || aer_acpi_firmware_first())
+   if (!pci_aer_available())
return -ENXIO;
return pcie_port_service_register();
 }
-- 
2.14.1



[PATCH v2] PCI/ACPI: Disable AER when _OSC control bit is clear.

2018-01-15 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Currently, aer_service_init() checks if AER is available and that
Firmware First handling is not enabled. The _OSC request for AER is not
taken into account when deciding to enable AER in Linux.

>From ACPI 6.2 Section 6.2.11.3, "If any bits in the Control Field are
returned cleared (masked to zero) by the _OSC control method, the
respective feature is designated unsupported by the platform and must
not be enabled by the OS."

The OS and the Platform should agree that the OS can have control of AER
otherwise we should disable AER in the OS.

Mark AER as disabled if the _OSC request was not made or accepted.

This covers two cases where the OS and Platform disagree:
1) The OS requests AER control and Platform denies the request.
2) The OS does not request AER control but the Platform returns the AER
   control bit set, possibly due to a Firmware bug.

The _OSC control for AER is not requested when APEI Firmware First is
used, so the same condition applies from case 2 above.

Remove redundant check for aer_acpi_firmware_first() when calling
aer_service_init(), since this check is already included when checking
the _OSC control.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/2018050316.19951-1-yazen.ghan...@amd.com

v1->v2:
* Expand commit message.
* Add Spec reference to commit message.
* Fix spelling error in commit message.
* Add comment for 3-way bitwise AND.

 drivers/acpi/pci_root.c   | 7 +++
 drivers/pci/pcie/aer/aerdrv.c | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c
index 6fc204a52493..ab0192fd24c7 100644
--- a/drivers/acpi/pci_root.c
+++ b/drivers/acpi/pci_root.c
@@ -512,6 +512,13 @@ static void negotiate_os_control(struct acpi_pci_root 
*root, int *no_aspm)
 */
*no_aspm = 1;
}
+
+   /*
+* We can use a 3-way bitwise AND to check that the AER control bit is
+* both requested by the OS and granted by the Platform.
+*/
+   if (!(requested & control & OSC_PCI_EXPRESS_AER_CONTROL))
+   pci_no_aer();
 }
 
 static int acpi_pci_root_add(struct acpi_device *device,
diff --git a/drivers/pci/pcie/aer/aerdrv.c b/drivers/pci/pcie/aer/aerdrv.c
index 6ff5f5b4f5e6..39bb059777d0 100644
--- a/drivers/pci/pcie/aer/aerdrv.c
+++ b/drivers/pci/pcie/aer/aerdrv.c
@@ -374,7 +374,7 @@ static void aer_error_resume(struct pci_dev *dev)
  */
 static int __init aer_service_init(void)
 {
-   if (!pci_aer_available() || aer_acpi_firmware_first())
+   if (!pci_aer_available())
return -ENXIO;
return pcie_port_service_register();
 }
-- 
2.14.1



[PATCH] ACPI / processor_idle: Set default C1 state description

2018-01-29 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The acpi_idle driver will default to ACPI_CSTATE_HALT for C1 if a _CST
object for C1 is not defined. However, the description will not be set,
so users will see "" when reading the description from sysfs.

Set the C1 state description when defaulting to ACPI_CSTATE_HALT.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
Cc: sta...@vger.kernel.org
---
 drivers/acpi/processor_idle.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index 5f0071c7e2e1..abb559cd28d7 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -292,6 +292,9 @@ static int acpi_processor_get_power_info_default(struct 
acpi_processor *pr)
pr->power.states[ACPI_STATE_C1].type = ACPI_STATE_C1;
pr->power.states[ACPI_STATE_C1].valid = 1;
pr->power.states[ACPI_STATE_C1].entry_method = ACPI_CSTATE_HALT;
+
+   snprintf(pr->power.states[ACPI_STATE_C1].desc,
+ACPI_CX_DESC_LEN, "ACPI HLT");
}
/* the C0 state only exists as a filler in our array */
pr->power.states[ACPI_STATE_C0].valid = 1;
-- 
2.14.1



[PATCH 2/3] x86/MCE/AMD, EDAC/mce_amd: Enumerate Reserved SMCA bank type

2018-02-01 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Currently, bank 4 is reserved on Fam17h, so we chose not to initialize
bank 4 in the smca_banks array. This means that when we check if a bank
is initialized, like during boot or resume, we will see that bank 4 is
not initialized and try to initialize it. This may cause a call trace,
when resuming from suspend, due to *on_cpu() calls in the init path.

Reserved banks will be read-as-zero, so their MCA_IPID register will be
zero. So, like the smca_banks array, the threshold_banks array will not
have an entry for a reserved bank since all its MCA_MISC* registers will
be zero.

Enumerate a "Reserved" bank type that matches on a HWID_MCATYPE of 0,0.

Use the "Reserved" type when checking if a bank is reserved. It's
possible that other bank numbers may be reserved on future systems.

Don't try to find the block address on reserved banks.

Cc: <sta...@vger.kernel.org> # 4.14.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/include/asm/mce.h   |  1 +
 arch/x86/kernel/cpu/mcheck/mce_amd.c |  7 +++
 drivers/edac/mce_amd.c   | 11 +++
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 96ea4b5ba658..340070415c2c 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -346,6 +346,7 @@ enum smca_bank_types {
SMCA_IF,/* Instruction Fetch */
SMCA_L2_CACHE,  /* L2 Cache */
SMCA_DE,/* Decoder Unit */
+   SMCA_RESERVED,  /* Reserved */
SMCA_EX,/* Execution Unit */
SMCA_FP,/* Floating Point */
SMCA_L3_CACHE,  /* L3 Cache */
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 4e16afc0794d..bf53b4549a17 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -82,6 +82,7 @@ static struct smca_bank_name smca_names[] = {
[SMCA_IF]   = { "insn_fetch",   "Instruction Fetch Unit" },
[SMCA_L2_CACHE] = { "l2_cache", "L2 Cache" },
[SMCA_DE]   = { "decode_unit",  "Decode Unit" },
+   [SMCA_RESERVED] = { "reserved", "Reserved" },
[SMCA_EX]   = { "execution_unit",   "Execution Unit" },
[SMCA_FP]   = { "floating_point",   "Floating Point Unit" },
[SMCA_L3_CACHE] = { "l3_cache", "L3 Cache" },
@@ -127,6 +128,9 @@ static enum smca_bank_types smca_get_bank_type(unsigned int 
bank)
 static struct smca_hwid smca_hwid_mcatypes[] = {
/* { bank_type, hwid_mcatype, xec_bitmap } */
 
+   /* Reserved type */
+   { SMCA_RESERVED, HWID_MCATYPE(0x00, 0x0), 0x0 },
+
/* ZN Core (HWID=0xB0) MCA types */
{ SMCA_LS,   HWID_MCATYPE(0xB0, 0x0), 0x1FFFEF },
{ SMCA_IF,   HWID_MCATYPE(0xB0, 0x1), 0x3FFF },
@@ -433,6 +437,9 @@ static u32 get_block_address(unsigned int cpu, u32 
current_addr, u32 low, u32 hi
u32 addr = 0, offset = 0;
 
if (mce_flags.smca) {
+   if (smca_get_bank_type(bank) == SMCA_RESERVED)
+   return addr;
+
if (!block) {
addr = MSR_AMD64_SMCA_MCx_MISC(bank);
} else {
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index a11a671c7a38..2ab4d61ee47e 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -854,21 +854,24 @@ static void decode_mc6_mce(struct mce *m)
 static void decode_smca_error(struct mce *m)
 {
struct smca_hwid *hwid;
-   unsigned int bank_type;
+   enum smca_bank_types bank_type;
const char *ip_name;
u8 xec = XEC(m->status, xec_mask);
 
if (m->bank >= ARRAY_SIZE(smca_banks))
return;
 
-   if (x86_family(m->cpuid) >= 0x17 && m->bank == 4)
-   pr_emerg(HW_ERR "Bank 4 is reserved on Fam17h.\n");
-
hwid = smca_banks[m->bank].hwid;
if (!hwid)
return;
 
bank_type = hwid->bank_type;
+
+   if (bank_type == SMCA_RESERVED) {
+   pr_emerg(HW_ERR "Bank %d is reserved.\n", m->bank);
+   return;
+   }
+
ip_name = smca_get_long_name(bank_type);
 
pr_emerg(HW_ERR "%s Extended Error Code: %d\n", ip_name, xec);
-- 
2.14.1



[PATCH 3/3] x86/MCE/AMD: Get address from already initialized block

2018-02-01 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The block address is saved after the block is initialized when
threshold_init_device() is called.

Use the saved block address, if available, rather than trying to
rediscover it.

We can avoid some *on_cpu() calls in the init path that will cause a
call trace when resuming from suspend.

Cc: <sta...@vger.kernel.org> # 4.14.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index bf53b4549a17..8c4f8f30c779 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -436,6 +436,21 @@ static u32 get_block_address(unsigned int cpu, u32 
current_addr, u32 low, u32 hi
 {
u32 addr = 0, offset = 0;
 
+   if ((bank >= mca_cfg.banks) || (block >= NR_BLOCKS))
+   return addr;
+
+   /* Get address from already initialized block. */
+   if (per_cpu(threshold_banks, cpu)) {
+   struct threshold_bank *bankp = per_cpu(threshold_banks, 
cpu)[bank];
+
+   if (bankp && bankp->blocks) {
+   struct threshold_block *blockp = >blocks[block];
+
+   if (blockp)
+   return blockp->address;
+   }
+   }
+
if (mce_flags.smca) {
if (smca_get_bank_type(bank) == SMCA_RESERVED)
return addr;
-- 
2.14.1



[PATCH 1/3] x86/MCE/AMD: Redo function to get SMCA bank type

2018-02-01 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Pass the bank number to smca_get_bank_type() since that's all we need.

Also, we should compare the bank number to the size of the smca_banks
array not the number of bank types. Bank types are reused for multiple
banks, so the number of types can be different from the number of banks
in a system. We could return an invalid bank type.

Use smca_get_bank_type() in get_name(), and change type of bank_type
variable to match return type of smca_get_bank_type().

Cc: <sta...@vger.kernel.org> # 4.14.x: 11cf887728a3 x86/MCE/AMD: Define a 
function to get SMCA bank type
Cc: <sta...@vger.kernel.org> # 4.14.x: c6708d50f166 x86/MCE: Report only DRAM 
ECC as memory errors on AMD systems
Cc: <sta...@vger.kernel.org> # 4.14.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 0f32ad242324..4e16afc0794d 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -110,14 +110,14 @@ const char *smca_get_long_name(enum smca_bank_types t)
 }
 EXPORT_SYMBOL_GPL(smca_get_long_name);
 
-static enum smca_bank_types smca_get_bank_type(struct mce *m)
+static enum smca_bank_types smca_get_bank_type(unsigned int bank)
 {
struct smca_bank *b;
 
-   if (m->bank >= N_SMCA_BANK_TYPES)
+   if (bank >= ARRAY_SIZE(smca_banks))
return N_SMCA_BANK_TYPES;
 
-   b = _banks[m->bank];
+   b = _banks[bank];
if (!b->hwid)
return N_SMCA_BANK_TYPES;
 
@@ -760,7 +760,7 @@ bool amd_mce_is_memory_error(struct mce *m)
u8 xec = (m->status >> 16) & 0x1f;
 
if (mce_flags.smca)
-   return smca_get_bank_type(m) == SMCA_UMC && xec == 0x0;
+   return smca_get_bank_type(m->bank) == SMCA_UMC && xec == 0x0;
 
return m->bank == 4 && xec == 0x8;
 }
@@ -1063,7 +1063,7 @@ static struct kobj_type threshold_ktype = {
 
 static const char *get_name(unsigned int bank, struct threshold_block *b)
 {
-   unsigned int bank_type;
+   enum smca_bank_types bank_type;
 
if (!mce_flags.smca) {
if (b && bank == 4)
@@ -1072,11 +1072,10 @@ static const char *get_name(unsigned int bank, struct 
threshold_block *b)
return th_names[bank];
}
 
-   if (!smca_banks[bank].hwid)
+   bank_type = smca_get_bank_type(bank);
+   if (bank_type >= N_SMCA_BANK_TYPES)
return NULL;
 
-   bank_type = smca_banks[bank].hwid->bank_type;
-
if (b && bank_type == SMCA_UMC) {
if (b->block < ARRAY_SIZE(smca_umc_block_names))
return smca_umc_block_names[b->block];
-- 
2.14.1



[PATCH v2 1/4] x86/MCE/AMD: Redo function to get SMCA bank type

2018-02-15 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Pass the bank number to smca_get_bank_type() since that's all we need.

Also, we should compare the bank number to the size of the smca_banks
array not the number of bank types. Bank types are reused for multiple
banks, so the number of types can be different from the number of banks
in a system. We could return an invalid bank type.

Use smca_get_bank_type() in get_name(), and change type of bank_type
variable to match return type of smca_get_bank_type().

Cc: <sta...@vger.kernel.org> # 4.14.x: 11cf887728a3 x86/MCE/AMD: Define a 
function to get SMCA bank type
Cc: <sta...@vger.kernel.org> # 4.14.x: c6708d50f166 x86/MCE: Report only DRAM 
ECC as memory errors on AMD systems
Cc: <sta...@vger.kernel.org> # 4.14.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180201184813.82253-1-yazen.ghan...@amd.com

v1->v2:
* Check bank number against MAX_NR_BANKS

 arch/x86/kernel/cpu/mcheck/mce_amd.c | 15 +++
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 0f32ad242324..7fbb19cb1859 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -110,14 +110,14 @@ const char *smca_get_long_name(enum smca_bank_types t)
 }
 EXPORT_SYMBOL_GPL(smca_get_long_name);
 
-static enum smca_bank_types smca_get_bank_type(struct mce *m)
+static enum smca_bank_types smca_get_bank_type(unsigned int bank)
 {
struct smca_bank *b;
 
-   if (m->bank >= N_SMCA_BANK_TYPES)
+   if (bank >= MAX_NR_BANKS)
return N_SMCA_BANK_TYPES;
 
-   b = _banks[m->bank];
+   b = _banks[bank];
if (!b->hwid)
return N_SMCA_BANK_TYPES;
 
@@ -760,7 +760,7 @@ bool amd_mce_is_memory_error(struct mce *m)
u8 xec = (m->status >> 16) & 0x1f;
 
if (mce_flags.smca)
-   return smca_get_bank_type(m) == SMCA_UMC && xec == 0x0;
+   return smca_get_bank_type(m->bank) == SMCA_UMC && xec == 0x0;
 
return m->bank == 4 && xec == 0x8;
 }
@@ -1063,7 +1063,7 @@ static struct kobj_type threshold_ktype = {
 
 static const char *get_name(unsigned int bank, struct threshold_block *b)
 {
-   unsigned int bank_type;
+   enum smca_bank_types bank_type;
 
if (!mce_flags.smca) {
if (b && bank == 4)
@@ -1072,11 +1072,10 @@ static const char *get_name(unsigned int bank, struct 
threshold_block *b)
return th_names[bank];
}
 
-   if (!smca_banks[bank].hwid)
+   bank_type = smca_get_bank_type(bank);
+   if (bank_type >= N_SMCA_BANK_TYPES)
return NULL;
 
-   bank_type = smca_banks[bank].hwid->bank_type;
-
if (b && bank_type == SMCA_UMC) {
if (b->block < ARRAY_SIZE(smca_umc_block_names))
return smca_umc_block_names[b->block];
-- 
2.14.1



[PATCH v2 3/4] x86/MCE/AMD: Get address from already initialized block

2018-02-15 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The block address is saved after the block is initialized when
threshold_init_device() is called.

Use the saved block address, if available, rather than trying to
rediscover it.

This will avoid a call trace, when resuming from suspend, due to the
rdmsr_safe_on_cpu() call in get_block_address(). The rdmsr_safe_on_cpu()
call issues an IPI but we're running with interrupts disabled.
This triggers:

WARNING: CPU: 0 PID: 11523 at kernel/smp.c:291
smp_call_function_single+0xdc/0xe0

Cc: <sta...@vger.kernel.org> # 4.14.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180201184813.82253-3-yazen.ghan...@amd.com

v1->v2:
* Give more detail on call trace issue.

 arch/x86/kernel/cpu/mcheck/mce_amd.c | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index d8ba9d0c3f01..12bc2863a4d6 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -436,6 +436,21 @@ static u32 get_block_address(unsigned int cpu, u32 
current_addr, u32 low, u32 hi
 {
u32 addr = 0, offset = 0;
 
+   if ((bank >= mca_cfg.banks) || (block >= NR_BLOCKS))
+   return addr;
+
+   /* Get address from already initialized block. */
+   if (per_cpu(threshold_banks, cpu)) {
+   struct threshold_bank *bankp = per_cpu(threshold_banks, 
cpu)[bank];
+
+   if (bankp && bankp->blocks) {
+   struct threshold_block *blockp = >blocks[block];
+
+   if (blockp)
+   return blockp->address;
+   }
+   }
+
if (mce_flags.smca) {
if (smca_get_bank_type(bank) == SMCA_RESERVED)
return addr;
-- 
2.14.1



[PATCH v2 2/4] x86/MCE/AMD, EDAC/mce_amd: Enumerate Reserved SMCA bank type

2018-02-15 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Currently, bank 4 is reserved on Fam17h, so we chose not to initialize
bank 4 in the smca_banks array. This means that when we check if a bank
is initialized, like during boot or resume, we will see that bank 4 is
not initialized and try to initialize it.

This will cause a call trace, when resuming from suspend, due to
rdmsr_*on_cpu() calls in the init path. The rdmsr_*on_cpu() calls issue
an IPI but we're running with interrupts disabled. This triggers:

WARNING: CPU: 0 PID: 11523 at kernel/smp.c:291
smp_call_function_single+0xdc/0xe0

Reserved banks will be read-as-zero, so their MCA_IPID register will be
zero. So, like the smca_banks array, the threshold_banks array will not
have an entry for a reserved bank since all its MCA_MISC* registers will
be zero.

Enumerate a "Reserved" bank type that matches on a HWID_MCATYPE of 0,0.

Use the "Reserved" type when checking if a bank is reserved. It's
possible that other bank numbers may be reserved on future systems.

Don't try to find the block address on reserved banks.

Cc: <sta...@vger.kernel.org> # 4.14.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180201184813.82253-2-yazen.ghan...@amd.com

v1->v2:
* Give more detail on call trace issue.

 arch/x86/include/asm/mce.h   |  1 +
 arch/x86/kernel/cpu/mcheck/mce_amd.c |  7 +++
 drivers/edac/mce_amd.c   | 11 +++
 3 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index 96ea4b5ba658..340070415c2c 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -346,6 +346,7 @@ enum smca_bank_types {
SMCA_IF,/* Instruction Fetch */
SMCA_L2_CACHE,  /* L2 Cache */
SMCA_DE,/* Decoder Unit */
+   SMCA_RESERVED,  /* Reserved */
SMCA_EX,/* Execution Unit */
SMCA_FP,/* Floating Point */
SMCA_L3_CACHE,  /* L3 Cache */
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 7fbb19cb1859..d8ba9d0c3f01 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -82,6 +82,7 @@ static struct smca_bank_name smca_names[] = {
[SMCA_IF]   = { "insn_fetch",   "Instruction Fetch Unit" },
[SMCA_L2_CACHE] = { "l2_cache", "L2 Cache" },
[SMCA_DE]   = { "decode_unit",  "Decode Unit" },
+   [SMCA_RESERVED] = { "reserved", "Reserved" },
[SMCA_EX]   = { "execution_unit",   "Execution Unit" },
[SMCA_FP]   = { "floating_point",   "Floating Point Unit" },
[SMCA_L3_CACHE] = { "l3_cache", "L3 Cache" },
@@ -127,6 +128,9 @@ static enum smca_bank_types smca_get_bank_type(unsigned int 
bank)
 static struct smca_hwid smca_hwid_mcatypes[] = {
/* { bank_type, hwid_mcatype, xec_bitmap } */
 
+   /* Reserved type */
+   { SMCA_RESERVED, HWID_MCATYPE(0x00, 0x0), 0x0 },
+
/* ZN Core (HWID=0xB0) MCA types */
{ SMCA_LS,   HWID_MCATYPE(0xB0, 0x0), 0x1FFFEF },
{ SMCA_IF,   HWID_MCATYPE(0xB0, 0x1), 0x3FFF },
@@ -433,6 +437,9 @@ static u32 get_block_address(unsigned int cpu, u32 
current_addr, u32 low, u32 hi
u32 addr = 0, offset = 0;
 
if (mce_flags.smca) {
+   if (smca_get_bank_type(bank) == SMCA_RESERVED)
+   return addr;
+
if (!block) {
addr = MSR_AMD64_SMCA_MCx_MISC(bank);
} else {
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index a11a671c7a38..2ab4d61ee47e 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce_amd.c
@@ -854,21 +854,24 @@ static void decode_mc6_mce(struct mce *m)
 static void decode_smca_error(struct mce *m)
 {
struct smca_hwid *hwid;
-   unsigned int bank_type;
+   enum smca_bank_types bank_type;
const char *ip_name;
u8 xec = XEC(m->status, xec_mask);
 
if (m->bank >= ARRAY_SIZE(smca_banks))
return;
 
-   if (x86_family(m->cpuid) >= 0x17 && m->bank == 4)
-   pr_emerg(HW_ERR "Bank 4 is reserved on Fam17h.\n");
-
hwid = smca_banks[m->bank].hwid;
if (!hwid)
return;
 
bank_type = hwid->bank_type;
+
+   if (bank_type == SMCA_RESERVED) {
+   pr_emerg(HW_ERR "Bank %d is reserved.\n", m->bank);
+   return;
+   }
+
ip_name = smca_get_long_name(bank_type);
 
pr_emerg(HW_ERR "%s Extended Error Code: %d\n", ip_name, xec);
-- 
2.14.1



[PATCH v2 4/4] x86/MCE/AMD: Carve out SMCA get_block_address() code

2018-02-15 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Carve out the SMCA code in get_block_address() into a separate helper
function.

No functional change.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
v1->v2:
* New in this series.

 arch/x86/kernel/cpu/mcheck/mce_amd.c | 59 
 1 file changed, 33 insertions(+), 26 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 12bc2863a4d6..7c451850d8aa 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -431,6 +431,37 @@ static void deferred_error_interrupt_enable(struct 
cpuinfo_x86 *c)
wrmsr(MSR_CU_DEF_ERR, low, high);
 }
 
+static u32 smca_get_block_address(unsigned int cpu, unsigned int bank,
+ unsigned int block)
+{
+   u32 addr = 0;
+
+   if (smca_get_bank_type(bank) == SMCA_RESERVED)
+   return addr;
+
+   if (!block) {
+   addr = MSR_AMD64_SMCA_MCx_MISC(bank);
+   } else {
+   /*
+* For SMCA enabled processors, BLKPTR field of the
+* first MISC register (MCx_MISC0) indicates presence of
+* additional MISC register set (MISC1-4).
+*/
+   u32 low, high;
+
+   if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_CONFIG(bank), 
, ))
+   return addr;
+
+   if (!(low & MCI_CONFIG_MCAX))
+   return addr;
+
+   if (!rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_MISC(bank), 
, ) &&
+   (low & MASK_BLKPTR_LO))
+   addr = MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1);
+   }
+   return addr;
+}
+
 static u32 get_block_address(unsigned int cpu, u32 current_addr, u32 low, u32 
high,
 unsigned int bank, unsigned int block)
 {
@@ -451,32 +482,8 @@ static u32 get_block_address(unsigned int cpu, u32 
current_addr, u32 low, u32 hi
}
}
 
-   if (mce_flags.smca) {
-   if (smca_get_bank_type(bank) == SMCA_RESERVED)
-   return addr;
-
-   if (!block) {
-   addr = MSR_AMD64_SMCA_MCx_MISC(bank);
-   } else {
-   /*
-* For SMCA enabled processors, BLKPTR field of the
-* first MISC register (MCx_MISC0) indicates presence of
-* additional MISC register set (MISC1-4).
-*/
-   u32 low, high;
-
-   if (rdmsr_safe_on_cpu(cpu, 
MSR_AMD64_SMCA_MCx_CONFIG(bank), , ))
-   return addr;
-
-   if (!(low & MCI_CONFIG_MCAX))
-   return addr;
-
-   if (!rdmsr_safe_on_cpu(cpu, 
MSR_AMD64_SMCA_MCx_MISC(bank), , ) &&
-   (low & MASK_BLKPTR_LO))
-   addr = MSR_AMD64_SMCA_MCx_MISCy(bank, block - 
1);
-   }
-   return addr;
-   }
+   if (mce_flags.smca)
+   return smca_get_block_address(cpu, bank, block);
 
/* Fall back to method we used for older processors: */
switch (block) {
-- 
2.14.1



[PATCH 4/8] efi: Decode UEFI-defined IA32/X64 Error Structure GUIDs

2018-02-23 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

For easier handling, match the known IA32/X64 error structure GUIDs to
enums.

Also, print out the name of the matching Error Structure Type.

GUIDs taken from UEFI 2.7 section N.2.4.2.1 IA32/X64 Processor Error
Information Structure.

Cc: <sta...@vger.kernel.org> # 4.16.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 drivers/firmware/efi/cper-x86.c | 41 +
 1 file changed, 41 insertions(+)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 9d608f742c98..3b86223bdb67 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -14,17 +14,53 @@
 #define VALID_CPUID_INFO   BIT_ULL(1)
 #define VALID_PROC_ERR_INFO_NUM(bits)  ((bits & GENMASK_ULL(7, 2)) >> 2)
 
+#define INFO_ERR_STRUCT_TYPE_CACHE \
+   GUID_INIT(0xA55701F5, 0xE3EF, 0x43DE, 0xAC, 0x72, 0x24, 0x9B,   \
+ 0x57, 0x3F, 0xAD, 0x2C)
+#define INFO_ERR_STRUCT_TYPE_TLB   \
+   GUID_INIT(0xFC06B535, 0x5E1F, 0x4562, 0x9F, 0x25, 0x0A, 0x3B,   \
+ 0x9A, 0xDB, 0x63, 0xC3)
+#define INFO_ERR_STRUCT_TYPE_BUS   \
+   GUID_INIT(0x1CF3F8B3, 0xC5B1, 0x49a2, 0xAA, 0x59, 0x5E, 0xEF,   \
+ 0x92, 0xFF, 0xA6, 0x3C)
+#define INFO_ERR_STRUCT_TYPE_MS
\
+   GUID_INIT(0x48AB7F57, 0xDC34, 0x4f6c, 0xA7, 0xD3, 0xB0, 0xB5,   \
+ 0xB0, 0xA7, 0x43, 0x14)
+
 #define INFO_VALID_CHECK_INFO  BIT_ULL(0)
 #define INFO_VALID_TARGET_ID   BIT_ULL(1)
 #define INFO_VALID_REQUESTOR_IDBIT_ULL(2)
 #define INFO_VALID_RESPONDER_IDBIT_ULL(3)
 #define INFO_VALID_IP  BIT_ULL(4)
 
+enum err_types {
+   ERR_TYPE_CACHE = 0,
+   ERR_TYPE_TLB,
+   ERR_TYPE_BUS,
+   ERR_TYPE_MS,
+   N_ERR_TYPES
+};
+
+static enum err_types cper_get_err_type(const guid_t *err_type)
+{
+   if (guid_equal(err_type, _ERR_STRUCT_TYPE_CACHE))
+   return ERR_TYPE_CACHE;
+   else if (guid_equal(err_type, _ERR_STRUCT_TYPE_TLB))
+   return ERR_TYPE_TLB;
+   else if (guid_equal(err_type, _ERR_STRUCT_TYPE_BUS))
+   return ERR_TYPE_BUS;
+   else if (guid_equal(err_type, _ERR_STRUCT_TYPE_MS))
+   return ERR_TYPE_MS;
+   else
+   return N_ERR_TYPES;
+}
+
 void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
 {
int i;
struct cper_ia_err_info *err_info;
char newpfx[64];
+   enum err_types err_type;
 
printk("%sValidation Bits: 0x%016llx\n", pfx, proc->validation_bits);
 
@@ -46,6 +82,11 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
printk("%sError Structure Type: %pUl\n", newpfx,
 _info->err_type);
 
+   err_type = cper_get_err_type(_info->err_type);
+   printk("%sError Structure Type: %s\n", newpfx,
+err_type < ARRAY_SIZE(cper_proc_error_type_strs) ?
+cper_proc_error_type_strs[err_type] : "unknown");
+
printk("%sValidation Bits: 0x%016llx\n",
 newpfx, err_info->validation_bits);
 
-- 
2.14.1



[PATCH 1/8] efi: Fix IA32/X64 Processor Error Record definition

2018-02-23 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Based on UEFI 2.7 Table 255. Processor Error Record, the "Local APIC_ID"
field is 8 bytes but Linux defines this field as 1 byte.

Fix this in the struct cper_sec_proc_ia definition.

Cc: <sta...@vger.kernel.org> # 4.16.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 include/linux/cper.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/cper.h b/include/linux/cper.h
index d14ef4e77c8a..4b5f8459b403 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -381,7 +381,7 @@ struct cper_sec_proc_generic {
 /* IA32/X64 Processor Error Section */
 struct cper_sec_proc_ia {
__u64   validation_bits;
-   __u8lapic_id;
+   __u64   lapic_id;
__u8cpuid[48];
 };
 
-- 
2.14.1



[PATCH 8/8] efi: Decode IA32/X64 Context Info structure

2018-02-23 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Print the fields of the IA32/X64 Context Information structure.

Print the "Register Array" as raw values. Some context types are defined
in the UEFI spec, so more detailed decoded may be added in the future.

Based on UEFI 2.7 section N.2.4.2.2 IA32/X64 Processor Context
Information Structure.

Cc: <sta...@vger.kernel.org> # 4.16.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 drivers/firmware/efi/cper-x86.c | 55 +
 1 file changed, 55 insertions(+)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 02b1b424f537..bb6cef0b5e53 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -13,6 +13,7 @@
 #define VALID_LAPIC_ID BIT_ULL(0)
 #define VALID_CPUID_INFO   BIT_ULL(1)
 #define VALID_PROC_ERR_INFO_NUM(bits)  ((bits & GENMASK_ULL(7, 2)) >> 2)
+#define VALID_PROC_CNXT_INFO_NUM(bits) ((bits & GENMASK_ULL(13, 8)) >> 8)
 
 #define INFO_ERR_STRUCT_TYPE_CACHE \
GUID_INIT(0xA55701F5, 0xE3EF, 0x43DE, 0xAC, 0x72, 0x24, 0x9B,   \
@@ -74,6 +75,9 @@
 #define CHECK_MS_RESTARTABLE_IPBIT_ULL(22)
 #define CHECK_MS_OVERFLOW  BIT_ULL(23)
 
+#define CTX_TYPE_MSR   1
+#define CTX_TYPE_MMREG 7
+
 enum err_types {
ERR_TYPE_CACHE = 0,
ERR_TYPE_TLB,
@@ -137,6 +141,17 @@ static const char * const ia_check_ms_error_type_strs[] = {
"Internal Unclassified",
 };
 
+static const char * const ia_reg_ctx_strs[] = {
+   "Unclassified Data",
+   "MSR Registers (Machine Check and other MSRs)",
+   "32-bit Mode Execution Context",
+   "64-bit Mode Execution Context",
+   "FXSAVE Context",
+   "32-bit Mode Debug Registers (DR0-DR7)",
+   "64-bit Mode Debug Registers (DR0-DR7)",
+   "Memory Mapped Registers",
+};
+
 static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
 {
printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
@@ -247,8 +262,10 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
 {
int i;
struct cper_ia_err_info *err_info;
+   struct cper_ia_proc_ctx *ctx_info;
char newpfx[64], infopfx[64];
enum err_types err_type;
+   unsigned int max_ctx_type = ARRAY_SIZE(ia_reg_ctx_strs) - 1;
 
printk("%sValidation Bits: 0x%016llx\n", pfx, proc->validation_bits);
 
@@ -313,4 +330,42 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
 
err_info++;
}
+
+   ctx_info = (struct cper_ia_proc_ctx *)err_info;
+   for (i = 0; i < VALID_PROC_CNXT_INFO_NUM(proc->validation_bits); i++) {
+   int size = sizeof(*ctx_info) + ctx_info->reg_arr_size;
+   int groupsize = 4;
+
+   printk("%sContext Information Structure %d:\n", pfx, i);
+
+   if (ctx_info->reg_ctx_type > max_ctx_type) {
+   printk("%sInvalid Register Context Type: %d (max: 
%d)\n",
+newpfx, ctx_info->reg_ctx_type, max_ctx_type);
+   goto next_ctx;
+   }
+
+   printk("%sRegister Context Type: %s\n", newpfx,
+ia_reg_ctx_strs[ctx_info->reg_ctx_type]);
+
+   printk("%sRegister Array Size: 0x%04x\n", newpfx,
+ctx_info->reg_arr_size);
+
+   if (ctx_info->reg_ctx_type == CTX_TYPE_MSR) {
+   groupsize = 8; /* MSRs are 8 bytes wide. */
+   printk("%sMSR Address: 0x%08x\n", newpfx,
+ctx_info->msr_addr);
+   }
+
+   if (ctx_info->reg_ctx_type == CTX_TYPE_MMREG) {
+   printk("%sMM Register Address: 0x%016llx\n", newpfx,
+ctx_info->mm_reg_addr);
+   }
+
+   printk("%sRegister Array:\n", newpfx);
+   print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, groupsize,
+  (ctx_info + 1), ctx_info->reg_arr_size, 0);
+
+next_ctx:
+   ctx_info = (struct cper_ia_proc_ctx *)((long)ctx_info + size);
+   }
 }
-- 
2.14.1



[PATCH 5/8] efi: Decode IA32/X64 Cache, TLB, and Bus Check structures

2018-02-23 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Print the common fields of the Cache, TLB, and Bus check structures.The
fields of these three check types are the same except for a few more
fields in the Bus check structure. The remaining Bus check structure
fields will be decoded in a following patch.

Based on UEFI 2.7,
Table 257. IA32/X64 Cache Check Structure
Table 258. IA32/X64 TLB Check Structure
Table 259. IA32/X64 Bus Check Structure

Cc: <sta...@vger.kernel.org> # 4.16.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 drivers/firmware/efi/cper-x86.c | 101 +++-
 1 file changed, 100 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 3b86223bdb67..75f664043076 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -33,6 +33,25 @@
 #define INFO_VALID_RESPONDER_IDBIT_ULL(3)
 #define INFO_VALID_IP  BIT_ULL(4)
 
+#define CHECK_VALID_TRANS_TYPE BIT_ULL(0)
+#define CHECK_VALID_OPERATION  BIT_ULL(1)
+#define CHECK_VALID_LEVEL  BIT_ULL(2)
+#define CHECK_VALID_PCCBIT_ULL(3)
+#define CHECK_VALID_UNCORRECTEDBIT_ULL(4)
+#define CHECK_VALID_PRECISE_IP BIT_ULL(5)
+#define CHECK_VALID_RESTARTABLE_IP BIT_ULL(6)
+#define CHECK_VALID_OVERFLOW   BIT_ULL(7)
+
+#define CHECK_VALID_BITS(check)((check & GENMASK_ULL(15, 0)))
+#define CHECK_TRANS_TYPE(check)((check & GENMASK_ULL(17, 16)) 
>> 16)
+#define CHECK_OPERATION(check) ((check & GENMASK_ULL(21, 18)) >> 18)
+#define CHECK_LEVEL(check) ((check & GENMASK_ULL(24, 22)) >> 22)
+#define CHECK_PCC  BIT_ULL(25)
+#define CHECK_UNCORRECTED  BIT_ULL(26)
+#define CHECK_PRECISE_IP   BIT_ULL(27)
+#define CHECK_RESTARTABLE_IP   BIT_ULL(28)
+#define CHECK_OVERFLOW BIT_ULL(29)
+
 enum err_types {
ERR_TYPE_CACHE = 0,
ERR_TYPE_TLB,
@@ -55,11 +74,83 @@ static enum err_types cper_get_err_type(const guid_t 
*err_type)
return N_ERR_TYPES;
 }
 
+static const char * const ia_check_trans_type_strs[] = {
+   "Instruction",
+   "Data Access",
+   "Generic",
+};
+
+static const char * const ia_check_op_strs[] = {
+   "generic error",
+   "generic read",
+   "generic write",
+   "data read",
+   "data write",
+   "instruction fetch",
+   "prefetch",
+   "eviction",
+   "snoop",
+};
+
+static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
+{
+   printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
+}
+
+static void print_err_info(const char *pfx, enum err_types err_type, u64 check)
+{
+   u16 validation_bits = CHECK_VALID_BITS(check);
+
+   printk("%sValidation Bits: 0x%04x\n", pfx, validation_bits);
+
+   if (err_type == ERR_TYPE_MS)
+   return;
+
+   if (validation_bits & CHECK_VALID_TRANS_TYPE) {
+   u8 trans_type = CHECK_TRANS_TYPE(check);
+
+   printk("%sTransaction Type: %u, %s\n", pfx, trans_type,
+trans_type < ARRAY_SIZE(ia_check_trans_type_strs) ?
+ia_check_trans_type_strs[trans_type] : "unknown");
+   }
+
+   if (validation_bits & CHECK_VALID_OPERATION) {
+   u8 op = CHECK_OPERATION(check);
+
+   /*
+* CACHE has more operation types than TLB or BUS, though the
+* name and the order are the same.
+*/
+   u8 max_ops = (err_type == ERR_TYPE_CACHE) ? 9 : 7;
+
+   printk("%sOperation: %u, %s\n", pfx, op,
+op < max_ops ? ia_check_op_strs[op] : "unknown");
+   }
+
+   if (validation_bits & CHECK_VALID_LEVEL)
+   printk("%sLevel: %llu\n", pfx, CHECK_LEVEL(check));
+
+   if (validation_bits & CHECK_VALID_PCC)
+   print_bool("Processor Context Corrupt", pfx, check, CHECK_PCC);
+
+   if (validation_bits & CHECK_VALID_UNCORRECTED)
+   print_bool("Uncorrected", pfx, check, CHECK_UNCORRECTED);
+
+   if (validation_bits & CHECK_VALID_PRECISE_IP)
+   print_bool("Precise IP", pfx, check, CHECK_PRECISE_IP);
+
+   if (validation_bits & CHECK_VALID_RESTARTABLE_IP)
+   print_bool("Restartable IP", pfx, check, CHECK_RESTARTABLE_IP);
+
+   if (validation_bits & CHECK_VALID_OVERFLOW)
+   print_bool("Overflow", pfx, check, CHECK_OVERFLOW);
+}
+
 void

[PATCH 0/8] Decode IA32/X64 CPER

2018-02-23 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

This series adds decoding for the IA32/X64 Common Platform Error Record.

Patch 1 fixes the IA32/X64 Processor Error Section definition to match
the UEFI spec.

Patches 2-8 add the new decoding. The patches incrementally add the
decoding starting from the top-level "Error Section". Hopefully, this
will make reviewing a bit easier compared to one large patch.

The formatting of the field names and options is taken from the UEFI
spec. I tried to keep everything the same to make searching easier.

The patches were written to the UEFI 2.7 spec though the definition of
the IA32/X64 CPER seems to be the same as when it was introduced in
the UEFI 2.1 spec.

Without basic decoding, users will be confused about what these
"Hardware Errors" mean. So I'm requesting this set to be applied to the
stable branches. This set applies to the v4.16. However, patch 2 will
have a conflict on older branches, so I'll send this set again with the
conflict fixed.

Thanks,
Yazen

Yazen Ghannam (8):
  efi: Fix IA32/X64 Processor Error Record definition
  efi: Decode IA32/X64 Processor Error Section
  efi: Decode IA32/X64 Processor Error Info Structure
  efi: Decode UEFI-defined IA32/X64 Error Structure GUIDs
  efi: Decode IA32/X64 Cache, TLB, and Bus Check structures
  efi: Decode additional IA32/X64 Bus Check fields
  efi: Decode IA32/X64 MS Check structure
  efi: Decode IA32/X64 Context Info structure

 drivers/firmware/efi/Kconfig|   5 +
 drivers/firmware/efi/Makefile   |   2 +
 drivers/firmware/efi/cper-x86.c | 371 
 drivers/firmware/efi/cper.c |  10 ++
 include/linux/cper.h|   4 +-
 5 files changed, 391 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/efi/cper-x86.c

-- 
2.14.1



[PATCH 3/8] efi: Decode IA32/X64 Processor Error Info Structure

2018-02-23 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Print the fields in the IA32/X64 Processor Error Info Structure.

Based on UEFI 2.7 Table 256. IA32/X64 Processor Error Information
Structure.

Cc: <sta...@vger.kernel.org> # 4.16.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 drivers/firmware/efi/cper-x86.c | 53 +
 1 file changed, 53 insertions(+)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index b50ee3cdf637..9d608f742c98 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -4,15 +4,28 @@
 
 #include 
 
+#define INDENT_SP  " "
+
 /*
  * We don't need a "CPER_IA" prefix since these are all locally defined.
  * This will save us a lot of line space.
  */
 #define VALID_LAPIC_ID BIT_ULL(0)
 #define VALID_CPUID_INFO   BIT_ULL(1)
+#define VALID_PROC_ERR_INFO_NUM(bits)  ((bits & GENMASK_ULL(7, 2)) >> 2)
+
+#define INFO_VALID_CHECK_INFO  BIT_ULL(0)
+#define INFO_VALID_TARGET_ID   BIT_ULL(1)
+#define INFO_VALID_REQUESTOR_IDBIT_ULL(2)
+#define INFO_VALID_RESPONDER_IDBIT_ULL(3)
+#define INFO_VALID_IP  BIT_ULL(4)
 
 void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
 {
+   int i;
+   struct cper_ia_err_info *err_info;
+   char newpfx[64];
+
printk("%sValidation Bits: 0x%016llx\n", pfx, proc->validation_bits);
 
if (proc->validation_bits & VALID_LAPIC_ID)
@@ -23,4 +36,44 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, proc->cpuid,
   sizeof(proc->cpuid), 0);
}
+
+   snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
+
+   err_info = (struct cper_ia_err_info *)(proc + 1);
+   for (i = 0; i < VALID_PROC_ERR_INFO_NUM(proc->validation_bits); i++) {
+   printk("%sError Information Structure %d:\n", pfx, i);
+
+   printk("%sError Structure Type: %pUl\n", newpfx,
+_info->err_type);
+
+   printk("%sValidation Bits: 0x%016llx\n",
+newpfx, err_info->validation_bits);
+
+   if (err_info->validation_bits & INFO_VALID_CHECK_INFO) {
+   printk("%sCheck Information: 0x%016llx\n", newpfx,
+err_info->check_info);
+   }
+
+   if (err_info->validation_bits & INFO_VALID_TARGET_ID) {
+   printk("%sTarget Identifier: 0x%016llx\n",
+newpfx, err_info->target_id);
+   }
+
+   if (err_info->validation_bits & INFO_VALID_REQUESTOR_ID) {
+   printk("%sRequestor Identifier: 0x%016llx\n",
+newpfx, err_info->requestor_id);
+   }
+
+   if (err_info->validation_bits & INFO_VALID_RESPONDER_ID) {
+   printk("%sResponder Identifier: 0x%016llx\n",
+newpfx, err_info->responder_id);
+   }
+
+   if (err_info->validation_bits & INFO_VALID_IP) {
+   printk("%sInstruction Pointer: 0x%016llx\n",
+newpfx, err_info->ip);
+   }
+
+   err_info++;
+   }
 }
-- 
2.14.1



[PATCH 6/8] efi: Decode additional IA32/X64 Bus Check fields

2018-02-23 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The "Participation Type", "Time Out", and "Address Space" fields are
unique to the IA32/X64 Bus Check structure. Print these fields.

Based on UEFI 2.7 Table 259. IA32/X64 Bus Check Structure

Cc: <sta...@vger.kernel.org> # 4.16.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 drivers/firmware/efi/cper-x86.c | 44 +
 1 file changed, 44 insertions(+)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 75f664043076..df4cf6221d8e 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -42,6 +42,10 @@
 #define CHECK_VALID_RESTARTABLE_IP BIT_ULL(6)
 #define CHECK_VALID_OVERFLOW   BIT_ULL(7)
 
+#define CHECK_VALID_BUS_PART_TYPE  BIT_ULL(8)
+#define CHECK_VALID_BUS_TIME_OUT   BIT_ULL(9)
+#define CHECK_VALID_BUS_ADDR_SPACE BIT_ULL(10)
+
 #define CHECK_VALID_BITS(check)((check & GENMASK_ULL(15, 0)))
 #define CHECK_TRANS_TYPE(check)((check & GENMASK_ULL(17, 16)) 
>> 16)
 #define CHECK_OPERATION(check) ((check & GENMASK_ULL(21, 18)) >> 18)
@@ -52,6 +56,10 @@
 #define CHECK_RESTARTABLE_IP   BIT_ULL(28)
 #define CHECK_OVERFLOW BIT_ULL(29)
 
+#define CHECK_BUS_PART_TYPE(check) ((check & GENMASK_ULL(31, 30)) >> 30)
+#define CHECK_BUS_TIME_OUT BIT_ULL(32)
+#define CHECK_BUS_ADDR_SPACE(check)((check & GENMASK_ULL(34, 33)) >> 33)
+
 enum err_types {
ERR_TYPE_CACHE = 0,
ERR_TYPE_TLB,
@@ -92,6 +100,20 @@ static const char * const ia_check_op_strs[] = {
"snoop",
 };
 
+static const char * const ia_check_bus_part_type_strs[] = {
+   "Local Processor originated request",
+   "Local Processor responded to request",
+   "Local Processor observed",
+   "Generic",
+};
+
+static const char * const ia_check_bus_addr_space_strs[] = {
+   "Memory Access",
+   "Reserved",
+   "I/O",
+   "Other Transaction",
+};
+
 static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
 {
printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
@@ -144,6 +166,28 @@ static void print_err_info(const char *pfx, enum err_types 
err_type, u64 check)
 
if (validation_bits & CHECK_VALID_OVERFLOW)
print_bool("Overflow", pfx, check, CHECK_OVERFLOW);
+
+   if (err_type != ERR_TYPE_BUS)
+   return;
+
+   if (validation_bits & CHECK_VALID_BUS_PART_TYPE) {
+   u8 part_type = CHECK_BUS_PART_TYPE(check);
+
+   printk("%sParticipation Type: %u, %s\n", pfx, part_type,
+part_type < ARRAY_SIZE(ia_check_bus_part_type_strs) ?
+ia_check_bus_part_type_strs[part_type] : "unknown");
+   }
+
+   if (validation_bits & CHECK_VALID_BUS_TIME_OUT)
+   print_bool("Time Out", pfx, check, CHECK_BUS_TIME_OUT);
+
+   if (validation_bits & CHECK_VALID_BUS_ADDR_SPACE) {
+   u8 addr_space = CHECK_BUS_ADDR_SPACE(check);
+
+   printk("%sAddress Space: %u, %s\n", pfx, addr_space,
+addr_space < ARRAY_SIZE(ia_check_bus_addr_space_strs) ?
+ia_check_bus_addr_space_strs[addr_space] : "unknown");
+   }
 }
 
 void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
-- 
2.14.1



[PATCH 7/8] efi: Decode IA32/X64 MS Check structure

2018-02-23 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The IA32/X64 MS Check structure varies from the other Check structures
in the the bit positions of its fields, and it includes an additional
"Error Type" field.

Decode the MS Check structure in a separate function.

Based on UEFI 2.7 Table 260. IA32/X64 MS Check Field Description.

Cc: <sta...@vger.kernel.org> # 4.16.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 drivers/firmware/efi/cper-x86.c | 55 -
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index df4cf6221d8e..02b1b424f537 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -60,6 +60,20 @@
 #define CHECK_BUS_TIME_OUT BIT_ULL(32)
 #define CHECK_BUS_ADDR_SPACE(check)((check & GENMASK_ULL(34, 33)) >> 33)
 
+#define CHECK_VALID_MS_ERR_TYPEBIT_ULL(0)
+#define CHECK_VALID_MS_PCC BIT_ULL(1)
+#define CHECK_VALID_MS_UNCORRECTED BIT_ULL(2)
+#define CHECK_VALID_MS_PRECISE_IP  BIT_ULL(3)
+#define CHECK_VALID_MS_RESTARTABLE_IP  BIT_ULL(4)
+#define CHECK_VALID_MS_OVERFLOWBIT_ULL(5)
+
+#define CHECK_MS_ERR_TYPE(check)   ((check & GENMASK_ULL(18, 16)) >> 16)
+#define CHECK_MS_PCC   BIT_ULL(19)
+#define CHECK_MS_UNCORRECTED   BIT_ULL(20)
+#define CHECK_MS_PRECISE_IPBIT_ULL(21)
+#define CHECK_MS_RESTARTABLE_IPBIT_ULL(22)
+#define CHECK_MS_OVERFLOW  BIT_ULL(23)
+
 enum err_types {
ERR_TYPE_CACHE = 0,
ERR_TYPE_TLB,
@@ -114,19 +128,58 @@ static const char * const ia_check_bus_addr_space_strs[] 
= {
"Other Transaction",
 };
 
+static const char * const ia_check_ms_error_type_strs[] = {
+   "No Error",
+   "Unclassified",
+   "Microcode ROM Parity Error",
+   "External Error",
+   "FRC Error",
+   "Internal Unclassified",
+};
+
 static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
 {
printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
 }
 
+static void print_err_info_ms(const char *pfx, u16 validation_bits, u64 check)
+{
+   if (validation_bits & CHECK_VALID_MS_ERR_TYPE) {
+   u8 err_type = CHECK_MS_ERR_TYPE(check);
+
+   printk("%sError Type: %u, %s\n", pfx, err_type,
+err_type < ARRAY_SIZE(ia_check_ms_error_type_strs) ?
+ia_check_ms_error_type_strs[err_type] : "unknown");
+   }
+
+   if (validation_bits & CHECK_VALID_MS_PCC)
+   print_bool("Processor Context Corrupt", pfx, check, 
CHECK_MS_PCC);
+
+   if (validation_bits & CHECK_VALID_MS_UNCORRECTED)
+   print_bool("Uncorrected", pfx, check, CHECK_MS_UNCORRECTED);
+
+   if (validation_bits & CHECK_VALID_MS_PRECISE_IP)
+   print_bool("Precise IP", pfx, check, CHECK_MS_PRECISE_IP);
+
+   if (validation_bits & CHECK_VALID_MS_RESTARTABLE_IP)
+   print_bool("Restartable IP", pfx, check, 
CHECK_MS_RESTARTABLE_IP);
+
+   if (validation_bits & CHECK_VALID_MS_OVERFLOW)
+   print_bool("Overflow", pfx, check, CHECK_MS_OVERFLOW);
+}
+
 static void print_err_info(const char *pfx, enum err_types err_type, u64 check)
 {
u16 validation_bits = CHECK_VALID_BITS(check);
 
printk("%sValidation Bits: 0x%04x\n", pfx, validation_bits);
 
+   /*
+* The MS Check structure varies a lot from the others, so use a
+* separate function for decoding.
+*/
if (err_type == ERR_TYPE_MS)
-   return;
+   return print_err_info_ms(pfx, validation_bits, check);
 
if (validation_bits & CHECK_VALID_TRANS_TYPE) {
u8 trans_type = CHECK_TRANS_TYPE(check);
-- 
2.14.1



[PATCH 2/8] efi: Decode IA32/X64 Processor Error Section

2018-02-23 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Recognize the IA32/X64 Processor Error Section.

Do the section decoding in a new "cper-x86.c" file and add this to the
Makefile depending on a new "UEFI_CPER_X86" config option.

Print the Local APIC ID and CPUID info from the Processor Error Record.

The "Processor Error Info" and "Processor Context" fields will be
decoded in following patches.

Based on UEFI 2.7 Table 255. Processor Error Record.

Cc: <sta...@vger.kernel.org> # 4.16.x
Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 drivers/firmware/efi/Kconfig|  5 +
 drivers/firmware/efi/Makefile   |  2 ++
 drivers/firmware/efi/cper-x86.c | 26 ++
 drivers/firmware/efi/cper.c | 10 ++
 include/linux/cper.h|  2 ++
 5 files changed, 45 insertions(+)
 create mode 100644 drivers/firmware/efi/cper-x86.c

diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 3098410abad8..8b684147835d 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -174,6 +174,11 @@ config UEFI_CPER_ARM
depends on UEFI_CPER && ( ARM || ARM64 )
default y
 
+config UEFI_CPER_X86
+   bool
+   depends on UEFI_CPER && ( X86_32 || X86_64 )
+   default y
+
 config EFI_DEV_PATH_PARSER
bool
depends on ACPI
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index cb805374f4bc..7cf8d75ebe51 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -31,3 +31,5 @@ obj-$(CONFIG_ARM) += $(arm-obj-y)
 obj-$(CONFIG_ARM64)+= $(arm-obj-y)
 obj-$(CONFIG_EFI_CAPSULE_LOADER)   += capsule-loader.o
 obj-$(CONFIG_UEFI_CPER_ARM)+= cper-arm.o
+
+obj-$(CONFIG_UEFI_CPER_X86)+= cper-x86.o
diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
new file mode 100644
index ..b50ee3cdf637
--- /dev/null
+++ b/drivers/firmware/efi/cper-x86.c
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018, Advanced Micro Devices, Inc.
+// Copyright (C) 2018, Yazen Ghannam <yazen.ghan...@amd.com>
+
+#include 
+
+/*
+ * We don't need a "CPER_IA" prefix since these are all locally defined.
+ * This will save us a lot of line space.
+ */
+#define VALID_LAPIC_ID BIT_ULL(0)
+#define VALID_CPUID_INFO   BIT_ULL(1)
+
+void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
+{
+   printk("%sValidation Bits: 0x%016llx\n", pfx, proc->validation_bits);
+
+   if (proc->validation_bits & VALID_LAPIC_ID)
+   printk("%sLocal APIC_ID: 0x%llx\n", pfx, proc->lapic_id);
+
+   if (proc->validation_bits & VALID_CPUID_INFO) {
+   printk("%sCPUID Info:\n", pfx);
+   print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, proc->cpuid,
+  sizeof(proc->cpuid), 0);
+   }
+}
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index c165933ebf38..5a59b582c9aa 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -469,6 +469,16 @@ cper_estatus_print_section(const char *pfx, struct 
acpi_hest_generic_data *gdata
cper_print_proc_arm(newpfx, arm_err);
else
goto err_section_too_small;
+#endif
+#if defined(CONFIG_UEFI_CPER_X86)
+   } else if (guid_equal(sec_type, _SEC_PROC_IA)) {
+   struct cper_sec_proc_ia *ia_err = acpi_hest_get_payload(gdata);
+
+   printk("%ssection_type: IA32/X64 processor error\n", newpfx);
+   if (gdata->error_data_length >= sizeof(*ia_err))
+   cper_print_proc_ia(newpfx, ia_err);
+   else
+   goto err_section_too_small;
 #endif
} else {
const void *err = acpi_hest_get_payload(gdata);
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 4b5f8459b403..9c703a0abe6e 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -551,5 +551,7 @@ const char *cper_mem_err_unpack(struct trace_seq *,
struct cper_mem_err_compact *);
 void cper_print_proc_arm(const char *pfx,
 const struct cper_sec_proc_arm *proc);
+void cper_print_proc_ia(const char *pfx,
+   const struct cper_sec_proc_ia *proc);
 
 #endif
-- 
2.14.1



[PATCH v2 8/8] efi: Decode IA32/X64 Context Info structure

2018-02-26 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Print the fields of the IA32/X64 Context Information structure.

Print the "Register Array" as raw values. Some context types are defined
in the UEFI spec, so more detailed decoded may be added in the future.

Based on UEFI 2.7 section N.2.4.2.2 IA32/X64 Processor Context
Information Structure.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180223200333.6410-9-yazen.ghan...@amd.com

v1->v2:
* Add parantheses around "bits" expression in macro.
* Change VALID_PROC_CNTXT_INFO_NUM to VALID_PROC_CTX_INFO_NUM.
* Fix indentation on multi-line statements.
* Remove conditional to skip unknown context types. The context info
  should be printed even if the type is unkown. This is just like what
  we do for the error information. 

 drivers/firmware/efi/cper-x86.c | 48 +
 1 file changed, 48 insertions(+)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 4c79401aace0..0407671ad7e6 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -12,6 +12,7 @@
 #define VALID_LAPIC_ID BIT_ULL(0)
 #define VALID_CPUID_INFO   BIT_ULL(1)
 #define VALID_PROC_ERR_INFO_NUM(bits)  (((bits) & GENMASK_ULL(7, 2)) >> 2)
+#define VALID_PROC_CXT_INFO_NUM(bits)  (((bits) & GENMASK_ULL(13, 8)) >> 8)
 
 #define INFO_ERR_STRUCT_TYPE_CACHE \
GUID_INIT(0xA55701F5, 0xE3EF, 0x43DE, 0xAC, 0x72, 0x24, 0x9B,   \
@@ -73,6 +74,9 @@
 #define CHECK_MS_RESTARTABLE_IPBIT_ULL(22)
 #define CHECK_MS_OVERFLOW  BIT_ULL(23)
 
+#define CTX_TYPE_MSR   1
+#define CTX_TYPE_MMREG 7
+
 enum err_types {
ERR_TYPE_CACHE = 0,
ERR_TYPE_TLB,
@@ -136,6 +140,17 @@ static const char * const ia_check_ms_error_type_strs[] = {
"Internal Unclassified",
 };
 
+static const char * const ia_reg_ctx_strs[] = {
+   "Unclassified Data",
+   "MSR Registers (Machine Check and other MSRs)",
+   "32-bit Mode Execution Context",
+   "64-bit Mode Execution Context",
+   "FXSAVE Context",
+   "32-bit Mode Debug Registers (DR0-DR7)",
+   "64-bit Mode Debug Registers (DR0-DR7)",
+   "Memory Mapped Registers",
+};
+
 static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
 {
printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
@@ -246,6 +261,7 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
 {
int i;
struct cper_ia_err_info *err_info;
+   struct cper_ia_proc_ctx *ctx_info;
char newpfx[64], infopfx[64];
u8 err_type;
 
@@ -312,4 +328,36 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
 
err_info++;
}
+
+   ctx_info = (struct cper_ia_proc_ctx *)err_info;
+   for (i = 0; i < VALID_PROC_CXT_INFO_NUM(proc->validation_bits); i++) {
+   int size = sizeof(*ctx_info) + ctx_info->reg_arr_size;
+   int groupsize = 4;
+
+   printk("%sContext Information Structure %d:\n", pfx, i);
+
+   printk("%sRegister Context Type: %s\n", newpfx,
+  ctx_info->reg_ctx_type < ARRAY_SIZE(ia_reg_ctx_strs) ?
+  ia_reg_ctx_strs[ctx_info->reg_ctx_type] : "unknown");
+
+   printk("%sRegister Array Size: 0x%04x\n", newpfx,
+  ctx_info->reg_arr_size);
+
+   if (ctx_info->reg_ctx_type == CTX_TYPE_MSR) {
+   groupsize = 8; /* MSRs are 8 bytes wide. */
+   printk("%sMSR Address: 0x%08x\n", newpfx,
+  ctx_info->msr_addr);
+   }
+
+   if (ctx_info->reg_ctx_type == CTX_TYPE_MMREG) {
+   printk("%sMM Register Address: 0x%016llx\n", newpfx,
+  ctx_info->mm_reg_addr);
+   }
+
+   printk("%sRegister Array:\n", newpfx);
+   print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, groupsize,
+  (ctx_info + 1), ctx_info->reg_arr_size, 0);
+
+   ctx_info = (struct cper_ia_proc_ctx *)((long)ctx_info + size);
+   }
 }
-- 
2.14.1



[PATCH v2 5/8] efi: Decode IA32/X64 Cache, TLB, and Bus Check structures

2018-02-26 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Print the common fields of the Cache, TLB, and Bus check structures.The
fields of these three check types are the same except for a few more
fields in the Bus check structure. The remaining Bus check structure
fields will be decoded in a following patch.

Based on UEFI 2.7,
Table 257. IA32/X64 Cache Check Structure
Table 258. IA32/X64 TLB Check Structure
Table 259. IA32/X64 Bus Check Structure

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180223200333.6410-6-yazen.ghan...@amd.com

v1->v2:
* Add parantheses around "check" expression in macro.
* Change use of enum type to u8.
* Fix indentation on multi-line statements.

 drivers/firmware/efi/cper-x86.c | 101 +++-
 1 file changed, 100 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 037986ca82dd..24f62e78b6c7 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -32,6 +32,25 @@
 #define INFO_VALID_RESPONDER_IDBIT_ULL(3)
 #define INFO_VALID_IP  BIT_ULL(4)
 
+#define CHECK_VALID_TRANS_TYPE BIT_ULL(0)
+#define CHECK_VALID_OPERATION  BIT_ULL(1)
+#define CHECK_VALID_LEVEL  BIT_ULL(2)
+#define CHECK_VALID_PCCBIT_ULL(3)
+#define CHECK_VALID_UNCORRECTEDBIT_ULL(4)
+#define CHECK_VALID_PRECISE_IP BIT_ULL(5)
+#define CHECK_VALID_RESTARTABLE_IP BIT_ULL(6)
+#define CHECK_VALID_OVERFLOW   BIT_ULL(7)
+
+#define CHECK_VALID_BITS(check)(((check) & GENMASK_ULL(15, 0)))
+#define CHECK_TRANS_TYPE(check)(((check) & GENMASK_ULL(17, 
16)) >> 16)
+#define CHECK_OPERATION(check) (((check) & GENMASK_ULL(21, 18)) >> 18)
+#define CHECK_LEVEL(check) (((check) & GENMASK_ULL(24, 22)) >> 22)
+#define CHECK_PCC  BIT_ULL(25)
+#define CHECK_UNCORRECTED  BIT_ULL(26)
+#define CHECK_PRECISE_IP   BIT_ULL(27)
+#define CHECK_RESTARTABLE_IP   BIT_ULL(28)
+#define CHECK_OVERFLOW BIT_ULL(29)
+
 enum err_types {
ERR_TYPE_CACHE = 0,
ERR_TYPE_TLB,
@@ -54,11 +73,83 @@ static enum err_types cper_get_err_type(const guid_t 
*err_type)
return N_ERR_TYPES;
 }
 
+static const char * const ia_check_trans_type_strs[] = {
+   "Instruction",
+   "Data Access",
+   "Generic",
+};
+
+static const char * const ia_check_op_strs[] = {
+   "generic error",
+   "generic read",
+   "generic write",
+   "data read",
+   "data write",
+   "instruction fetch",
+   "prefetch",
+   "eviction",
+   "snoop",
+};
+
+static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
+{
+   printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
+}
+
+static void print_err_info(const char *pfx, u8 err_type, u64 check)
+{
+   u16 validation_bits = CHECK_VALID_BITS(check);
+
+   printk("%sValidation Bits: 0x%04x\n", pfx, validation_bits);
+
+   if (err_type == ERR_TYPE_MS)
+   return;
+
+   if (validation_bits & CHECK_VALID_TRANS_TYPE) {
+   u8 trans_type = CHECK_TRANS_TYPE(check);
+
+   printk("%sTransaction Type: %u, %s\n", pfx, trans_type,
+  trans_type < ARRAY_SIZE(ia_check_trans_type_strs) ?
+  ia_check_trans_type_strs[trans_type] : "unknown");
+   }
+
+   if (validation_bits & CHECK_VALID_OPERATION) {
+   u8 op = CHECK_OPERATION(check);
+
+   /*
+* CACHE has more operation types than TLB or BUS, though the
+* name and the order are the same.
+*/
+   u8 max_ops = (err_type == ERR_TYPE_CACHE) ? 9 : 7;
+
+   printk("%sOperation: %u, %s\n", pfx, op,
+  op < max_ops ? ia_check_op_strs[op] : "unknown");
+   }
+
+   if (validation_bits & CHECK_VALID_LEVEL)
+   printk("%sLevel: %llu\n", pfx, CHECK_LEVEL(check));
+
+   if (validation_bits & CHECK_VALID_PCC)
+   print_bool("Processor Context Corrupt", pfx, check, CHECK_PCC);
+
+   if (validation_bits & CHECK_VALID_UNCORRECTED)
+   print_bool("Uncorrected", pfx, check, CHECK_UNCORRECTED);
+
+   if (validation_bits & CHECK_VALID_PRECISE_IP)
+   print_bool("Precise IP", pfx, check, CHECK_PRECISE_IP);
+
+   if (validation_bits & CHECK_VALID_RESTARTABLE_IP)
+   print_bool("Restartable IP", pf

[PATCH v2 3/8] efi: Decode IA32/X64 Processor Error Info Structure

2018-02-26 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Print the fields in the IA32/X64 Processor Error Info Structure.

Based on UEFI 2.7 Table 256. IA32/X64 Processor Error Information
Structure.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180223200333.6410-4-yazen.ghan...@amd.com

v1->v2:
* Add parantheses around "bits" expression in macro.
* Fix indentation on multi-line statements.

 drivers/firmware/efi/cper-x86.c | 53 +
 1 file changed, 53 insertions(+)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 9da0d981178f..417bd4e500a7 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -3,15 +3,28 @@
 
 #include 
 
+#define INDENT_SP  " "
+
 /*
  * We don't need a "CPER_IA" prefix since these are all locally defined.
  * This will save us a lot of line space.
  */
 #define VALID_LAPIC_ID BIT_ULL(0)
 #define VALID_CPUID_INFO   BIT_ULL(1)
+#define VALID_PROC_ERR_INFO_NUM(bits)  (((bits) & GENMASK_ULL(7, 2)) >> 2)
+
+#define INFO_VALID_CHECK_INFO  BIT_ULL(0)
+#define INFO_VALID_TARGET_ID   BIT_ULL(1)
+#define INFO_VALID_REQUESTOR_IDBIT_ULL(2)
+#define INFO_VALID_RESPONDER_IDBIT_ULL(3)
+#define INFO_VALID_IP  BIT_ULL(4)
 
 void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
 {
+   int i;
+   struct cper_ia_err_info *err_info;
+   char newpfx[64];
+
printk("%sValidation Bits: 0x%016llx\n", pfx, proc->validation_bits);
 
if (proc->validation_bits & VALID_LAPIC_ID)
@@ -22,4 +35,44 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, proc->cpuid,
   sizeof(proc->cpuid), 0);
}
+
+   snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
+
+   err_info = (struct cper_ia_err_info *)(proc + 1);
+   for (i = 0; i < VALID_PROC_ERR_INFO_NUM(proc->validation_bits); i++) {
+   printk("%sError Information Structure %d:\n", pfx, i);
+
+   printk("%sError Structure Type: %pUl\n", newpfx,
+  _info->err_type);
+
+   printk("%sValidation Bits: 0x%016llx\n",
+  newpfx, err_info->validation_bits);
+
+   if (err_info->validation_bits & INFO_VALID_CHECK_INFO) {
+   printk("%sCheck Information: 0x%016llx\n", newpfx,
+  err_info->check_info);
+   }
+
+   if (err_info->validation_bits & INFO_VALID_TARGET_ID) {
+   printk("%sTarget Identifier: 0x%016llx\n",
+  newpfx, err_info->target_id);
+   }
+
+   if (err_info->validation_bits & INFO_VALID_REQUESTOR_ID) {
+   printk("%sRequestor Identifier: 0x%016llx\n",
+  newpfx, err_info->requestor_id);
+   }
+
+   if (err_info->validation_bits & INFO_VALID_RESPONDER_ID) {
+   printk("%sResponder Identifier: 0x%016llx\n",
+  newpfx, err_info->responder_id);
+   }
+
+   if (err_info->validation_bits & INFO_VALID_IP) {
+   printk("%sInstruction Pointer: 0x%016llx\n",
+  newpfx, err_info->ip);
+   }
+
+   err_info++;
+   }
 }
-- 
2.14.1



[PATCH v2 1/8] efi: Fix IA32/X64 Processor Error Record definition

2018-02-26 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Based on UEFI 2.7 Table 255. Processor Error Record, the "Local APIC_ID"
field is 8 bytes but Linux defines this field as 1 byte.

Fix this in the struct cper_sec_proc_ia definition.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180223200333.6410-2-yazen.ghan...@amd.com

v1->v2:
* No changes.

 include/linux/cper.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/cper.h b/include/linux/cper.h
index d14ef4e77c8a..4b5f8459b403 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -381,7 +381,7 @@ struct cper_sec_proc_generic {
 /* IA32/X64 Processor Error Section */
 struct cper_sec_proc_ia {
__u64   validation_bits;
-   __u8lapic_id;
+   __u64   lapic_id;
__u8cpuid[48];
 };
 
-- 
2.14.1



[PATCH v2 2/8] efi: Decode IA32/X64 Processor Error Section

2018-02-26 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Recognize the IA32/X64 Processor Error Section.

Do the section decoding in a new "cper-x86.c" file and add this to the
Makefile depending on a new "UEFI_CPER_X86" config option.

Print the Local APIC ID and CPUID info from the Processor Error Record.

The "Processor Error Info" and "Processor Context" fields will be
decoded in following patches.

Based on UEFI 2.7 Table 255. Processor Error Record.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180223200333.6410-3-yazen.ghan...@amd.com

v1->v2:
* Change config option depends to "X86" instead of "X86_32 || X64_64".
* Remove extra newline in Makefile changes.
* Drop author copyright line.

 drivers/firmware/efi/Kconfig|  5 +
 drivers/firmware/efi/Makefile   |  1 +
 drivers/firmware/efi/cper-x86.c | 25 +
 drivers/firmware/efi/cper.c | 10 ++
 include/linux/cper.h|  2 ++
 5 files changed, 43 insertions(+)
 create mode 100644 drivers/firmware/efi/cper-x86.c

diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 3098410abad8..781a4a337557 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -174,6 +174,11 @@ config UEFI_CPER_ARM
depends on UEFI_CPER && ( ARM || ARM64 )
default y
 
+config UEFI_CPER_X86
+   bool
+   depends on UEFI_CPER && X86
+   default y
+
 config EFI_DEV_PATH_PARSER
bool
depends on ACPI
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index cb805374f4bc..5f9f5039de50 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -31,3 +31,4 @@ obj-$(CONFIG_ARM) += $(arm-obj-y)
 obj-$(CONFIG_ARM64)+= $(arm-obj-y)
 obj-$(CONFIG_EFI_CAPSULE_LOADER)   += capsule-loader.o
 obj-$(CONFIG_UEFI_CPER_ARM)+= cper-arm.o
+obj-$(CONFIG_UEFI_CPER_X86)+= cper-x86.o
diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
new file mode 100644
index ..9da0d981178f
--- /dev/null
+++ b/drivers/firmware/efi/cper-x86.c
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018, Advanced Micro Devices, Inc.
+
+#include 
+
+/*
+ * We don't need a "CPER_IA" prefix since these are all locally defined.
+ * This will save us a lot of line space.
+ */
+#define VALID_LAPIC_ID BIT_ULL(0)
+#define VALID_CPUID_INFO   BIT_ULL(1)
+
+void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
+{
+   printk("%sValidation Bits: 0x%016llx\n", pfx, proc->validation_bits);
+
+   if (proc->validation_bits & VALID_LAPIC_ID)
+   printk("%sLocal APIC_ID: 0x%llx\n", pfx, proc->lapic_id);
+
+   if (proc->validation_bits & VALID_CPUID_INFO) {
+   printk("%sCPUID Info:\n", pfx);
+   print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, proc->cpuid,
+  sizeof(proc->cpuid), 0);
+   }
+}
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index c165933ebf38..5a59b582c9aa 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -469,6 +469,16 @@ cper_estatus_print_section(const char *pfx, struct 
acpi_hest_generic_data *gdata
cper_print_proc_arm(newpfx, arm_err);
else
goto err_section_too_small;
+#endif
+#if defined(CONFIG_UEFI_CPER_X86)
+   } else if (guid_equal(sec_type, _SEC_PROC_IA)) {
+   struct cper_sec_proc_ia *ia_err = acpi_hest_get_payload(gdata);
+
+   printk("%ssection_type: IA32/X64 processor error\n", newpfx);
+   if (gdata->error_data_length >= sizeof(*ia_err))
+   cper_print_proc_ia(newpfx, ia_err);
+   else
+   goto err_section_too_small;
 #endif
} else {
const void *err = acpi_hest_get_payload(gdata);
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 4b5f8459b403..9c703a0abe6e 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -551,5 +551,7 @@ const char *cper_mem_err_unpack(struct trace_seq *,
struct cper_mem_err_compact *);
 void cper_print_proc_arm(const char *pfx,
 const struct cper_sec_proc_arm *proc);
+void cper_print_proc_ia(const char *pfx,
+   const struct cper_sec_proc_ia *proc);
 
 #endif
-- 
2.14.1



[PATCH v2 4/8] efi: Decode UEFI-defined IA32/X64 Error Structure GUIDs

2018-02-26 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

For easier handling, match the known IA32/X64 error structure GUIDs to
enums.

Also, print out the name of the matching Error Structure Type.

GUIDs taken from UEFI 2.7 section N.2.4.2.1 IA32/X64 Processor Error
Information Structure.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180223200333.6410-5-yazen.ghan...@amd.com

v1->v2:
* Change use of enum type to u8.
* Fix indentation on multi-line statements.

 drivers/firmware/efi/cper-x86.c | 41 +
 1 file changed, 41 insertions(+)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 417bd4e500a7..037986ca82dd 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -13,17 +13,53 @@
 #define VALID_CPUID_INFO   BIT_ULL(1)
 #define VALID_PROC_ERR_INFO_NUM(bits)  (((bits) & GENMASK_ULL(7, 2)) >> 2)
 
+#define INFO_ERR_STRUCT_TYPE_CACHE \
+   GUID_INIT(0xA55701F5, 0xE3EF, 0x43DE, 0xAC, 0x72, 0x24, 0x9B,   \
+ 0x57, 0x3F, 0xAD, 0x2C)
+#define INFO_ERR_STRUCT_TYPE_TLB   \
+   GUID_INIT(0xFC06B535, 0x5E1F, 0x4562, 0x9F, 0x25, 0x0A, 0x3B,   \
+ 0x9A, 0xDB, 0x63, 0xC3)
+#define INFO_ERR_STRUCT_TYPE_BUS   \
+   GUID_INIT(0x1CF3F8B3, 0xC5B1, 0x49a2, 0xAA, 0x59, 0x5E, 0xEF,   \
+ 0x92, 0xFF, 0xA6, 0x3C)
+#define INFO_ERR_STRUCT_TYPE_MS
\
+   GUID_INIT(0x48AB7F57, 0xDC34, 0x4f6c, 0xA7, 0xD3, 0xB0, 0xB5,   \
+ 0xB0, 0xA7, 0x43, 0x14)
+
 #define INFO_VALID_CHECK_INFO  BIT_ULL(0)
 #define INFO_VALID_TARGET_ID   BIT_ULL(1)
 #define INFO_VALID_REQUESTOR_IDBIT_ULL(2)
 #define INFO_VALID_RESPONDER_IDBIT_ULL(3)
 #define INFO_VALID_IP  BIT_ULL(4)
 
+enum err_types {
+   ERR_TYPE_CACHE = 0,
+   ERR_TYPE_TLB,
+   ERR_TYPE_BUS,
+   ERR_TYPE_MS,
+   N_ERR_TYPES
+};
+
+static enum err_types cper_get_err_type(const guid_t *err_type)
+{
+   if (guid_equal(err_type, _ERR_STRUCT_TYPE_CACHE))
+   return ERR_TYPE_CACHE;
+   else if (guid_equal(err_type, _ERR_STRUCT_TYPE_TLB))
+   return ERR_TYPE_TLB;
+   else if (guid_equal(err_type, _ERR_STRUCT_TYPE_BUS))
+   return ERR_TYPE_BUS;
+   else if (guid_equal(err_type, _ERR_STRUCT_TYPE_MS))
+   return ERR_TYPE_MS;
+   else
+   return N_ERR_TYPES;
+}
+
 void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
 {
int i;
struct cper_ia_err_info *err_info;
char newpfx[64];
+   u8 err_type;
 
printk("%sValidation Bits: 0x%016llx\n", pfx, proc->validation_bits);
 
@@ -45,6 +81,11 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
printk("%sError Structure Type: %pUl\n", newpfx,
   _info->err_type);
 
+   err_type = cper_get_err_type(_info->err_type);
+   printk("%sError Structure Type: %s\n", newpfx,
+  err_type < ARRAY_SIZE(cper_proc_error_type_strs) ?
+  cper_proc_error_type_strs[err_type] : "unknown");
+
printk("%sValidation Bits: 0x%016llx\n",
   newpfx, err_info->validation_bits);
 
-- 
2.14.1



[PATCH v2 6/8] efi: Decode additional IA32/X64 Bus Check fields

2018-02-26 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The "Participation Type", "Time Out", and "Address Space" fields are
unique to the IA32/X64 Bus Check structure. Print these fields.

Based on UEFI 2.7 Table 259. IA32/X64 Bus Check Structure

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180223200333.6410-7-yazen.ghan...@amd.com

v1->v2:
* Add parantheses around "check" expression in macro.
* Fix indentation on multi-line statements.

 drivers/firmware/efi/cper-x86.c | 44 +
 1 file changed, 44 insertions(+)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 24f62e78b6c7..c5209af3514b 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -41,6 +41,10 @@
 #define CHECK_VALID_RESTARTABLE_IP BIT_ULL(6)
 #define CHECK_VALID_OVERFLOW   BIT_ULL(7)
 
+#define CHECK_VALID_BUS_PART_TYPE  BIT_ULL(8)
+#define CHECK_VALID_BUS_TIME_OUT   BIT_ULL(9)
+#define CHECK_VALID_BUS_ADDR_SPACE BIT_ULL(10)
+
 #define CHECK_VALID_BITS(check)(((check) & GENMASK_ULL(15, 0)))
 #define CHECK_TRANS_TYPE(check)(((check) & GENMASK_ULL(17, 
16)) >> 16)
 #define CHECK_OPERATION(check) (((check) & GENMASK_ULL(21, 18)) >> 18)
@@ -51,6 +55,10 @@
 #define CHECK_RESTARTABLE_IP   BIT_ULL(28)
 #define CHECK_OVERFLOW BIT_ULL(29)
 
+#define CHECK_BUS_PART_TYPE(check) (((check) & GENMASK_ULL(31, 30)) >> 30)
+#define CHECK_BUS_TIME_OUT BIT_ULL(32)
+#define CHECK_BUS_ADDR_SPACE(check)(((check) & GENMASK_ULL(34, 33)) >> 33)
+
 enum err_types {
ERR_TYPE_CACHE = 0,
ERR_TYPE_TLB,
@@ -91,6 +99,20 @@ static const char * const ia_check_op_strs[] = {
"snoop",
 };
 
+static const char * const ia_check_bus_part_type_strs[] = {
+   "Local Processor originated request",
+   "Local Processor responded to request",
+   "Local Processor observed",
+   "Generic",
+};
+
+static const char * const ia_check_bus_addr_space_strs[] = {
+   "Memory Access",
+   "Reserved",
+   "I/O",
+   "Other Transaction",
+};
+
 static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
 {
printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
@@ -143,6 +165,28 @@ static void print_err_info(const char *pfx, u8 err_type, 
u64 check)
 
if (validation_bits & CHECK_VALID_OVERFLOW)
print_bool("Overflow", pfx, check, CHECK_OVERFLOW);
+
+   if (err_type != ERR_TYPE_BUS)
+   return;
+
+   if (validation_bits & CHECK_VALID_BUS_PART_TYPE) {
+   u8 part_type = CHECK_BUS_PART_TYPE(check);
+
+   printk("%sParticipation Type: %u, %s\n", pfx, part_type,
+  part_type < ARRAY_SIZE(ia_check_bus_part_type_strs) ?
+  ia_check_bus_part_type_strs[part_type] : "unknown");
+   }
+
+   if (validation_bits & CHECK_VALID_BUS_TIME_OUT)
+   print_bool("Time Out", pfx, check, CHECK_BUS_TIME_OUT);
+
+   if (validation_bits & CHECK_VALID_BUS_ADDR_SPACE) {
+   u8 addr_space = CHECK_BUS_ADDR_SPACE(check);
+
+   printk("%sAddress Space: %u, %s\n", pfx, addr_space,
+  addr_space < ARRAY_SIZE(ia_check_bus_addr_space_strs) ?
+  ia_check_bus_addr_space_strs[addr_space] : "unknown");
+   }
 }
 
 void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
-- 
2.14.1



[PATCH v2 7/8] efi: Decode IA32/X64 MS Check structure

2018-02-26 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The IA32/X64 MS Check structure varies from the other Check structures
in the the bit positions of its fields, and it includes an additional
"Error Type" field.

Decode the MS Check structure in a separate function.

Based on UEFI 2.7 Table 260. IA32/X64 MS Check Field Description.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180223200333.6410-8-yazen.ghan...@amd.com

v1->v2:
* Add parantheses around "check" expression in macro.
* Fix indentation on multi-line statements.

 drivers/firmware/efi/cper-x86.c | 55 -
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index c5209af3514b..4c79401aace0 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -59,6 +59,20 @@
 #define CHECK_BUS_TIME_OUT BIT_ULL(32)
 #define CHECK_BUS_ADDR_SPACE(check)(((check) & GENMASK_ULL(34, 33)) >> 33)
 
+#define CHECK_VALID_MS_ERR_TYPEBIT_ULL(0)
+#define CHECK_VALID_MS_PCC BIT_ULL(1)
+#define CHECK_VALID_MS_UNCORRECTED BIT_ULL(2)
+#define CHECK_VALID_MS_PRECISE_IP  BIT_ULL(3)
+#define CHECK_VALID_MS_RESTARTABLE_IP  BIT_ULL(4)
+#define CHECK_VALID_MS_OVERFLOWBIT_ULL(5)
+
+#define CHECK_MS_ERR_TYPE(check)   (((check) & GENMASK_ULL(18, 16)) >> 16)
+#define CHECK_MS_PCC   BIT_ULL(19)
+#define CHECK_MS_UNCORRECTED   BIT_ULL(20)
+#define CHECK_MS_PRECISE_IPBIT_ULL(21)
+#define CHECK_MS_RESTARTABLE_IPBIT_ULL(22)
+#define CHECK_MS_OVERFLOW  BIT_ULL(23)
+
 enum err_types {
ERR_TYPE_CACHE = 0,
ERR_TYPE_TLB,
@@ -113,19 +127,58 @@ static const char * const ia_check_bus_addr_space_strs[] 
= {
"Other Transaction",
 };
 
+static const char * const ia_check_ms_error_type_strs[] = {
+   "No Error",
+   "Unclassified",
+   "Microcode ROM Parity Error",
+   "External Error",
+   "FRC Error",
+   "Internal Unclassified",
+};
+
 static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
 {
printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
 }
 
+static void print_err_info_ms(const char *pfx, u16 validation_bits, u64 check)
+{
+   if (validation_bits & CHECK_VALID_MS_ERR_TYPE) {
+   u8 err_type = CHECK_MS_ERR_TYPE(check);
+
+   printk("%sError Type: %u, %s\n", pfx, err_type,
+  err_type < ARRAY_SIZE(ia_check_ms_error_type_strs) ?
+  ia_check_ms_error_type_strs[err_type] : "unknown");
+   }
+
+   if (validation_bits & CHECK_VALID_MS_PCC)
+   print_bool("Processor Context Corrupt", pfx, check, 
CHECK_MS_PCC);
+
+   if (validation_bits & CHECK_VALID_MS_UNCORRECTED)
+   print_bool("Uncorrected", pfx, check, CHECK_MS_UNCORRECTED);
+
+   if (validation_bits & CHECK_VALID_MS_PRECISE_IP)
+   print_bool("Precise IP", pfx, check, CHECK_MS_PRECISE_IP);
+
+   if (validation_bits & CHECK_VALID_MS_RESTARTABLE_IP)
+   print_bool("Restartable IP", pfx, check, 
CHECK_MS_RESTARTABLE_IP);
+
+   if (validation_bits & CHECK_VALID_MS_OVERFLOW)
+   print_bool("Overflow", pfx, check, CHECK_MS_OVERFLOW);
+}
+
 static void print_err_info(const char *pfx, u8 err_type, u64 check)
 {
u16 validation_bits = CHECK_VALID_BITS(check);
 
printk("%sValidation Bits: 0x%04x\n", pfx, validation_bits);
 
+   /*
+* The MS Check structure varies a lot from the others, so use a
+* separate function for decoding.
+*/
if (err_type == ERR_TYPE_MS)
-   return;
+   return print_err_info_ms(pfx, validation_bits, check);
 
if (validation_bits & CHECK_VALID_TRANS_TYPE) {
u8 trans_type = CHECK_TRANS_TYPE(check);
-- 
2.14.1



[PATCH v2 0/8] Decode IA32/X64 CPER

2018-02-26 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

This series adds decoding for the IA32/X64 Common Platform Error Record.

Patch 1 fixes the IA32/X64 Processor Error Section definition to match
the UEFI spec.

Patches 2-8 add the new decoding. The patches incrementally add the
decoding starting from the top-level "Error Section". Hopefully, this
will make reviewing a bit easier compared to one large patch.

The formatting of the field names and options is taken from the UEFI
spec. I tried to keep everything the same to make searching easier.

The patches were written to the UEFI 2.7 spec though the definition of
the IA32/X64 CPER seems to be the same as when it was introduced in
the UEFI 2.1 spec.

Link:
https://lkml.kernel.org/r/20180223200333.6410-1-yazen.ghan...@amd.com

Changes V1 to V2:
* Remove stable request for all patches.
* Address Ard's comments on formatting and other issues.
* In Patch 8, always print context info even if the type is not
  recognized.

Yazen Ghannam (8):
  efi: Fix IA32/X64 Processor Error Record definition
  efi: Decode IA32/X64 Processor Error Section
  efi: Decode IA32/X64 Processor Error Info Structure
  efi: Decode UEFI-defined IA32/X64 Error Structure GUIDs
  efi: Decode IA32/X64 Cache, TLB, and Bus Check structures
  efi: Decode additional IA32/X64 Bus Check fields
  efi: Decode IA32/X64 MS Check structure
  efi: Decode IA32/X64 Context Info structure

 drivers/firmware/efi/Kconfig|   5 +
 drivers/firmware/efi/Makefile   |   1 +
 drivers/firmware/efi/cper-x86.c | 363 
 drivers/firmware/efi/cper.c |  10 ++
 include/linux/cper.h|   4 +-
 5 files changed, 382 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/efi/cper-x86.c

-- 
2.14.1



[PATCH] x86/mce: Handle varying MCA bank counts

2018-07-27 Thread Yazen Ghannam
From: Yazen Ghannam 

Linux reads MCG_CAP[Count] to find the number of MCA banks visible to a
CPU. Currently, this is assumed to be the same for all CPUs and a
warning is shown if there is a difference. The number of banks is
overwritten with the MCG_CAP[Count] value of each following CPU that
boots.

According to the Intel SDM and AMD APM, the MCG_CAP[Count] value gives
the number of banks that are available to a "processor implementation".
The AMD BKDGs/PPRs further clarify that this value is per core. This
value has historically been the same for every core in the system, but
that is not an architectural requirement.

Future AMD systems may have different MCG_CAP[Count] values per core,
so the assumption that all CPUs will have the same MCG_CAP[Count] value
will no longer be valid.

Also, the first CPU to boot will allocate the struct mce_banks[] array
using the number of banks based on its MCG_CAP[Count] value. The machine
check handler and other functions use the global number of banks to
iterate and index into the mce_banks[] array. So it's possible to use an
out-of-bounds index on an asymmetric system where a following CPU sees a
MCG_CAP[Count] value greater than its predecessors.

For example, CPU0 sees MCG_CAP[Count]=2. It sets mca_cfg.banks=2 and
allocates mce_banks[] with 2 elements. CPU1 sees MCG_CAP[Count]=3 and
sets mca_cfg.banks=3, but mce_banks[] is already allocated and remains
having 2 elements.

Allocate the mce_banks[] array to the maximum number of banks. This will
avoid the potential out-of-bounds index since we cap the value of
mca_cfg.banks to MAX_NR_BANKS.

Set the value of mca_cfg.banks equal to the max of the previous value
and the value for the current CPU. This way mca_cfg.banks will always
represent the max number of banks detected on any CPU in the system.
This will ensure that all CPUs will access all the banks that are
visible to them. A CPU that can access fewer than the max number of
banks will find the registers of the extra banks to be read-as-zero.

Print the number of MCA banks that we're using. Do this in
mcheck_late_init() so that we print the final value after all CPUs have
been initialized.

Get bank count from target CPU when doing injection with mce-inject
module.

Signed-off-by: Yazen Ghannam 
---
 arch/x86/kernel/cpu/mcheck/mce-inject.c | 14 +++---
 arch/x86/kernel/cpu/mcheck/mce.c| 21 +++--
 2 files changed, 14 insertions(+), 21 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c 
b/arch/x86/kernel/cpu/mcheck/mce-inject.c
index c805a06e14c3..5dda56d56dd3 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-inject.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c
@@ -46,8 +46,6 @@
 static struct mce i_mce;
 static struct dentry *dfs_inj;
 
-static u8 n_banks;
-
 #define MAX_FLAG_OPT_SIZE  4
 #define NBCFG  0x44
 
@@ -567,9 +565,15 @@ static void do_inject(void)
 static int inj_bank_set(void *data, u64 val)
 {
struct mce *m = (struct mce *)data;
+   u64 cap;
+   u8 n_banks;
+
+   /* Get bank count on target CPU so we can handle non-uniform values. */
+   rdmsrl_on_cpu(m->extcpu, MSR_IA32_MCG_CAP, );
+   n_banks = cap & MCG_BANKCNT_MASK;
 
if (val >= n_banks) {
-   pr_err("Non-existent MCE bank: %llu\n", val);
+   pr_err("MCA bank %llu non-existent on CPU%d\n", val, m->extcpu);
return -EINVAL;
}
 
@@ -659,10 +663,6 @@ static struct dfs_node {
 static int __init debugfs_init(void)
 {
unsigned int i;
-   u64 cap;
-
-   rdmsrl(MSR_IA32_MCG_CAP, cap);
-   n_banks = cap & MCG_BANKCNT_MASK;
 
dfs_inj = debugfs_create_dir("mce-inject", NULL);
if (!dfs_inj)
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 4b767284b7f5..4238c65a0cce 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1479,13 +1479,12 @@ EXPORT_SYMBOL_GPL(mce_notify_irq);
 static int __mcheck_cpu_mce_banks_init(void)
 {
int i;
-   u8 num_banks = mca_cfg.banks;
 
-   mce_banks = kcalloc(num_banks, sizeof(struct mce_bank), GFP_KERNEL);
+   mce_banks = kcalloc(MAX_NR_BANKS, sizeof(struct mce_bank), GFP_KERNEL);
if (!mce_banks)
return -ENOMEM;
 
-   for (i = 0; i < num_banks; i++) {
+   for (i = 0; i < MAX_NR_BANKS; i++) {
struct mce_bank *b = _banks[i];
 
b->ctl = -1ULL;
@@ -1499,24 +1498,16 @@ static int __mcheck_cpu_mce_banks_init(void)
  */
 static int __mcheck_cpu_cap_init(void)
 {
-   unsigned b;
+   u8 b;
u64 cap;
 
rdmsrl(MSR_IA32_MCG_CAP, cap);
 
b = cap & MCG_BANKCNT_MASK;
-   if (!mca_cfg.banks)
-   pr_info("CPU supports %d MCE banks\n", b);
-
-   if (b > MAX_NR_BANKS) {
-   pr_warn("Using only %u machine check 

[PATCH 2/2] x86/MCE/AMD: Skip creating kobjects with NULL names

2018-08-09 Thread Yazen Ghannam
From: Yazen Ghannam 

During mce_threshold_create_device() data structures are allocated for
each CPUs MCA banks and thresholding blocks. These data structures are
used to save information related to AMD's MCA Error Thresholding
feature. The structures are used in the thresholding interrupt handler,
and they are exposed to the user through sysfs. The sysfs interface has
user-friendly names for each bank.

However, errors in mce_threshold_create_device() will cause all the data
structures to be deallocated. This will break the thresholding interrupt
handler since it depends on these structures.

One possible error is creating a kobject with a NULL name. This will
happen if a bank exists on a system that doesn't have a name, e.g. new
bank types on future systems.

Skip creating kobjects for banks without a name. This means that the
sysfs interface for this bank will not exist. But this will keep all the
data structures allocated, so the thresholding interrupt handler will
work, even for the unnamed bank. Also, the sysfs interface will still be
populated for all existing, known bank types.

Cc:  # 4.13.x
Signed-off-by: Yazen Ghannam 
---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 11 ++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index 2dbf34250bbf..521fd8f406df 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -1130,6 +1130,7 @@ static int allocate_threshold_blocks(unsigned int cpu, 
unsigned int bank,
struct threshold_block *b = NULL;
u32 low, high;
int err;
+   const char *name = NULL;
 
if ((bank >= mca_cfg.banks) || (block >= NR_BLOCKS))
return 0;
@@ -1176,9 +1177,13 @@ static int allocate_threshold_blocks(unsigned int cpu, 
unsigned int bank,
per_cpu(threshold_banks, cpu)[bank]->blocks = b;
}
 
+   name = get_name(bank, b);
+   if (!name)
+   goto recurse;
+
err = kobject_init_and_add(>kobj, _ktype,
   per_cpu(threshold_banks, cpu)[bank]->kobj,
-  get_name(bank, b));
+  name);
if (err)
goto out_free;
 recurse:
@@ -1265,12 +1270,16 @@ static int threshold_create_bank(unsigned int cpu, 
unsigned int bank)
goto out;
}
 
+   if (!name)
+   goto allocate;
+
b->kobj = kobject_create_and_add(name, >kobj);
if (!b->kobj) {
err = -EINVAL;
goto out_free;
}
 
+allocate:
per_cpu(threshold_banks, cpu)[bank] = b;
 
if (is_shared_bank(bank)) {
-- 
2.17.1



[PATCH 1/2] x86/MCE/AMD: Check for NULL banks in THR interrupt handler

2018-08-09 Thread Yazen Ghannam
From: Yazen Ghannam 

If threshold_init_device() fails then per_cpu(threshold_banks) will be
deallocated. The thresholding interrupt handler will still be active, so
it's possible to get a NULL pointer dereference if a THR interrupt
happens and any of the structures are NULL.

Exit the handler if per_cpu(threshold_banks) is NULL and skip NULL
banks. MCA error information will still be in the registers. The
information will be logged during polling or in another MCA exception or
interrupt handler.

Fixes: 17ef4af0ec0f ("x86/mce/AMD: Use saved threshold block info in interrupt 
handler")
Cc:  # 4.13.x
Signed-off-by: Yazen Ghannam 
---
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 10 +-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index dd33c357548f..2dbf34250bbf 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -934,13 +934,21 @@ static void log_and_reset_block(struct threshold_block 
*block)
 static void amd_threshold_interrupt(void)
 {
struct threshold_block *first_block = NULL, *block = NULL, *tmp = NULL;
+   struct threshold_bank *th_bank = NULL;
unsigned int bank, cpu = smp_processor_id();
 
+   if (!per_cpu(threshold_banks, cpu))
+   return;
+
for (bank = 0; bank < mca_cfg.banks; ++bank) {
if (!(per_cpu(bank_map, cpu) & (1 << bank)))
continue;
 
-   first_block = per_cpu(threshold_banks, cpu)[bank]->blocks;
+   th_bank = per_cpu(threshold_banks, cpu)[bank];
+   if (!th_bank)
+   continue;
+
+   first_block = th_bank->blocks;
if (!first_block)
continue;
 
-- 
2.17.1



[PATCH v3 1/8] efi: Fix IA32/X64 Processor Error Record definition

2018-03-24 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Based on UEFI 2.7 Table 252. Processor Error Record, the "Local APIC_ID"
field is 8 bytes but Linux defines this field as 1 byte.

Fix this in the struct cper_sec_proc_ia definition.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180226193904.20532-2-yazen.ghan...@amd.com

v2->v3:
* Fix table number in commit message.

v1->v2:
* No changes.

 include/linux/cper.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/include/linux/cper.h b/include/linux/cper.h
index d14ef4e77c8a..4b5f8459b403 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -381,7 +381,7 @@ struct cper_sec_proc_generic {
 /* IA32/X64 Processor Error Section */
 struct cper_sec_proc_ia {
__u64   validation_bits;
-   __u8lapic_id;
+   __u64   lapic_id;
__u8cpuid[48];
 };
 
-- 
2.14.1



[PATCH v3 8/8] efi: Decode IA32/X64 Context Info structure

2018-03-24 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Print the fields of the IA32/X64 Context Information structure.

Print the "Register Array" as raw values. Some context types are defined
in the UEFI spec, so more detailed decoded may be added in the future.

Based on UEFI 2.7 section N.2.4.2.2 IA32/X64 Processor Context
Information Structure.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180226193904.20532-9-yazen.ghan...@amd.com

v2->v3:
* No change.

v1->v2:
* Add parantheses around "bits" expression in macro.
* Change VALID_PROC_CNTXT_INFO_NUM to VALID_PROC_CTX_INFO_NUM.
* Fix indentation on multi-line statements.
* Remove conditional to skip unknown context types. The context info
  should be printed even if the type is unknown. This is just like what
  we do for the error information. 

 drivers/firmware/efi/cper-x86.c | 48 +
 1 file changed, 48 insertions(+)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index ffc01483cac2..fe479cc5a358 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -12,6 +12,7 @@
 #define VALID_LAPIC_ID BIT_ULL(0)
 #define VALID_CPUID_INFO   BIT_ULL(1)
 #define VALID_PROC_ERR_INFO_NUM(bits)  (((bits) & GENMASK_ULL(7, 2)) >> 2)
+#define VALID_PROC_CXT_INFO_NUM(bits)  (((bits) & GENMASK_ULL(13, 8)) >> 8)
 
 #define INFO_ERR_STRUCT_TYPE_CACHE \
GUID_INIT(0xA55701F5, 0xE3EF, 0x43DE, 0xAC, 0x72, 0x24, 0x9B,   \
@@ -73,6 +74,9 @@
 #define CHECK_MS_RESTARTABLE_IPBIT_ULL(22)
 #define CHECK_MS_OVERFLOW  BIT_ULL(23)
 
+#define CTX_TYPE_MSR   1
+#define CTX_TYPE_MMREG 7
+
 enum err_types {
ERR_TYPE_CACHE = 0,
ERR_TYPE_TLB,
@@ -136,6 +140,17 @@ static const char * const ia_check_ms_error_type_strs[] = {
"Internal Unclassified",
 };
 
+static const char * const ia_reg_ctx_strs[] = {
+   "Unclassified Data",
+   "MSR Registers (Machine Check and other MSRs)",
+   "32-bit Mode Execution Context",
+   "64-bit Mode Execution Context",
+   "FXSAVE Context",
+   "32-bit Mode Debug Registers (DR0-DR7)",
+   "64-bit Mode Debug Registers (DR0-DR7)",
+   "Memory Mapped Registers",
+};
+
 static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
 {
printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
@@ -244,6 +259,7 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
 {
int i;
struct cper_ia_err_info *err_info;
+   struct cper_ia_proc_ctx *ctx_info;
char newpfx[64], infopfx[64];
u8 err_type;
 
@@ -307,4 +323,36 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
 
err_info++;
}
+
+   ctx_info = (struct cper_ia_proc_ctx *)err_info;
+   for (i = 0; i < VALID_PROC_CXT_INFO_NUM(proc->validation_bits); i++) {
+   int size = sizeof(*ctx_info) + ctx_info->reg_arr_size;
+   int groupsize = 4;
+
+   printk("%sContext Information Structure %d:\n", pfx, i);
+
+   printk("%sRegister Context Type: %s\n", newpfx,
+  ctx_info->reg_ctx_type < ARRAY_SIZE(ia_reg_ctx_strs) ?
+  ia_reg_ctx_strs[ctx_info->reg_ctx_type] : "unknown");
+
+   printk("%sRegister Array Size: 0x%04x\n", newpfx,
+  ctx_info->reg_arr_size);
+
+   if (ctx_info->reg_ctx_type == CTX_TYPE_MSR) {
+   groupsize = 8; /* MSRs are 8 bytes wide. */
+   printk("%sMSR Address: 0x%08x\n", newpfx,
+  ctx_info->msr_addr);
+   }
+
+   if (ctx_info->reg_ctx_type == CTX_TYPE_MMREG) {
+   printk("%sMM Register Address: 0x%016llx\n", newpfx,
+  ctx_info->mm_reg_addr);
+   }
+
+   printk("%sRegister Array:\n", newpfx);
+   print_hex_dump(newpfx, "", DUMP_PREFIX_OFFSET, 16, groupsize,
+  (ctx_info + 1), ctx_info->reg_arr_size, 0);
+
+   ctx_info = (struct cper_ia_proc_ctx *)((long)ctx_info + size);
+   }
 }
-- 
2.14.1



[PATCH v3 6/8] efi: Decode additional IA32/X64 Bus Check fields

2018-03-24 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The "Participation Type", "Time Out", and "Address Space" fields are
unique to the IA32/X64 Bus Check structure. Print these fields.

Based on UEFI 2.7 Table 256. IA32/X64 Bus Check Structure

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180226193904.20532-7-yazen.ghan...@amd.com

v2->v3:
* Fix table number in commit message.

v1->v2:
* Add parantheses around "check" expression in macro.
* Fix indentation on multi-line statements.

 drivers/firmware/efi/cper-x86.c | 44 +
 1 file changed, 44 insertions(+)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 260e4bf7773c..54bd32d241b7 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -41,6 +41,10 @@
 #define CHECK_VALID_RESTARTABLE_IP BIT_ULL(6)
 #define CHECK_VALID_OVERFLOW   BIT_ULL(7)
 
+#define CHECK_VALID_BUS_PART_TYPE  BIT_ULL(8)
+#define CHECK_VALID_BUS_TIME_OUT   BIT_ULL(9)
+#define CHECK_VALID_BUS_ADDR_SPACE BIT_ULL(10)
+
 #define CHECK_VALID_BITS(check)(((check) & GENMASK_ULL(15, 0)))
 #define CHECK_TRANS_TYPE(check)(((check) & GENMASK_ULL(17, 
16)) >> 16)
 #define CHECK_OPERATION(check) (((check) & GENMASK_ULL(21, 18)) >> 18)
@@ -51,6 +55,10 @@
 #define CHECK_RESTARTABLE_IP   BIT_ULL(28)
 #define CHECK_OVERFLOW BIT_ULL(29)
 
+#define CHECK_BUS_PART_TYPE(check) (((check) & GENMASK_ULL(31, 30)) >> 30)
+#define CHECK_BUS_TIME_OUT BIT_ULL(32)
+#define CHECK_BUS_ADDR_SPACE(check)(((check) & GENMASK_ULL(34, 33)) >> 33)
+
 enum err_types {
ERR_TYPE_CACHE = 0,
ERR_TYPE_TLB,
@@ -91,6 +99,20 @@ static const char * const ia_check_op_strs[] = {
"snoop",
 };
 
+static const char * const ia_check_bus_part_type_strs[] = {
+   "Local Processor originated request",
+   "Local Processor responded to request",
+   "Local Processor observed",
+   "Generic",
+};
+
+static const char * const ia_check_bus_addr_space_strs[] = {
+   "Memory Access",
+   "Reserved",
+   "I/O",
+   "Other Transaction",
+};
+
 static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
 {
printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
@@ -141,6 +163,28 @@ static void print_err_info(const char *pfx, u8 err_type, 
u64 check)
 
if (validation_bits & CHECK_VALID_OVERFLOW)
print_bool("Overflow", pfx, check, CHECK_OVERFLOW);
+
+   if (err_type != ERR_TYPE_BUS)
+   return;
+
+   if (validation_bits & CHECK_VALID_BUS_PART_TYPE) {
+   u8 part_type = CHECK_BUS_PART_TYPE(check);
+
+   printk("%sParticipation Type: %u, %s\n", pfx, part_type,
+  part_type < ARRAY_SIZE(ia_check_bus_part_type_strs) ?
+  ia_check_bus_part_type_strs[part_type] : "unknown");
+   }
+
+   if (validation_bits & CHECK_VALID_BUS_TIME_OUT)
+   print_bool("Time Out", pfx, check, CHECK_BUS_TIME_OUT);
+
+   if (validation_bits & CHECK_VALID_BUS_ADDR_SPACE) {
+   u8 addr_space = CHECK_BUS_ADDR_SPACE(check);
+
+   printk("%sAddress Space: %u, %s\n", pfx, addr_space,
+  addr_space < ARRAY_SIZE(ia_check_bus_addr_space_strs) ?
+  ia_check_bus_addr_space_strs[addr_space] : "unknown");
+   }
 }
 
 void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
-- 
2.14.1



[PATCH v3 7/8] efi: Decode IA32/X64 MS Check structure

2018-03-24 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The IA32/X64 MS Check structure varies from the other Check structures
in the the bit positions of its fields, and it includes an additional
"Error Type" field.

Decode the MS Check structure in a separate function.

Based on UEFI 2.7 Table 257. IA32/X64 MS Check Field Description.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180226193904.20532-8-yazen.ghan...@amd.com

v2->v3:
* Fix table number in commit message.

v1->v2:
* Add parantheses around "check" expression in macro.
* Fix indentation on multi-line statements.

 drivers/firmware/efi/cper-x86.c | 55 -
 1 file changed, 54 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 54bd32d241b7..ffc01483cac2 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -59,6 +59,20 @@
 #define CHECK_BUS_TIME_OUT BIT_ULL(32)
 #define CHECK_BUS_ADDR_SPACE(check)(((check) & GENMASK_ULL(34, 33)) >> 33)
 
+#define CHECK_VALID_MS_ERR_TYPEBIT_ULL(0)
+#define CHECK_VALID_MS_PCC BIT_ULL(1)
+#define CHECK_VALID_MS_UNCORRECTED BIT_ULL(2)
+#define CHECK_VALID_MS_PRECISE_IP  BIT_ULL(3)
+#define CHECK_VALID_MS_RESTARTABLE_IP  BIT_ULL(4)
+#define CHECK_VALID_MS_OVERFLOWBIT_ULL(5)
+
+#define CHECK_MS_ERR_TYPE(check)   (((check) & GENMASK_ULL(18, 16)) >> 16)
+#define CHECK_MS_PCC   BIT_ULL(19)
+#define CHECK_MS_UNCORRECTED   BIT_ULL(20)
+#define CHECK_MS_PRECISE_IPBIT_ULL(21)
+#define CHECK_MS_RESTARTABLE_IPBIT_ULL(22)
+#define CHECK_MS_OVERFLOW  BIT_ULL(23)
+
 enum err_types {
ERR_TYPE_CACHE = 0,
ERR_TYPE_TLB,
@@ -113,17 +127,56 @@ static const char * const ia_check_bus_addr_space_strs[] 
= {
"Other Transaction",
 };
 
+static const char * const ia_check_ms_error_type_strs[] = {
+   "No Error",
+   "Unclassified",
+   "Microcode ROM Parity Error",
+   "External Error",
+   "FRC Error",
+   "Internal Unclassified",
+};
+
 static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
 {
printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
 }
 
+static void print_err_info_ms(const char *pfx, u16 validation_bits, u64 check)
+{
+   if (validation_bits & CHECK_VALID_MS_ERR_TYPE) {
+   u8 err_type = CHECK_MS_ERR_TYPE(check);
+
+   printk("%sError Type: %u, %s\n", pfx, err_type,
+  err_type < ARRAY_SIZE(ia_check_ms_error_type_strs) ?
+  ia_check_ms_error_type_strs[err_type] : "unknown");
+   }
+
+   if (validation_bits & CHECK_VALID_MS_PCC)
+   print_bool("Processor Context Corrupt", pfx, check, 
CHECK_MS_PCC);
+
+   if (validation_bits & CHECK_VALID_MS_UNCORRECTED)
+   print_bool("Uncorrected", pfx, check, CHECK_MS_UNCORRECTED);
+
+   if (validation_bits & CHECK_VALID_MS_PRECISE_IP)
+   print_bool("Precise IP", pfx, check, CHECK_MS_PRECISE_IP);
+
+   if (validation_bits & CHECK_VALID_MS_RESTARTABLE_IP)
+   print_bool("Restartable IP", pfx, check, 
CHECK_MS_RESTARTABLE_IP);
+
+   if (validation_bits & CHECK_VALID_MS_OVERFLOW)
+   print_bool("Overflow", pfx, check, CHECK_MS_OVERFLOW);
+}
+
 static void print_err_info(const char *pfx, u8 err_type, u64 check)
 {
u16 validation_bits = CHECK_VALID_BITS(check);
 
+   /*
+* The MS Check structure varies a lot from the others, so use a
+* separate function for decoding.
+*/
if (err_type == ERR_TYPE_MS)
-   return;
+   return print_err_info_ms(pfx, validation_bits, check);
 
if (validation_bits & CHECK_VALID_TRANS_TYPE) {
u8 trans_type = CHECK_TRANS_TYPE(check);
-- 
2.14.1



[PATCH v3 4/8] efi: Decode UEFI-defined IA32/X64 Error Structure GUIDs

2018-03-24 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

For easier handling, match the known IA32/X64 error structure GUIDs to
enums.

Also, print out the name of the matching Error Structure Type.

Only print the GUID for unknown types.

GUIDs taken from UEFI 2.7 section N.2.4.2.1 IA32/X64 Processor Error
Information Structure.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180226193904.20532-5-yazen.ghan...@amd.com

v2->v3:
* Only print raw GUID for unknown error types.

v1->v2:
* Change use of enum type to u8.
* Fix indentation on multi-line statements.

 drivers/firmware/efi/cper-x86.c | 47 +++--
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index a9ab3bbf7986..57fbea5b3a8c 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -13,17 +13,53 @@
 #define VALID_CPUID_INFO   BIT_ULL(1)
 #define VALID_PROC_ERR_INFO_NUM(bits)  (((bits) & GENMASK_ULL(7, 2)) >> 2)
 
+#define INFO_ERR_STRUCT_TYPE_CACHE \
+   GUID_INIT(0xA55701F5, 0xE3EF, 0x43DE, 0xAC, 0x72, 0x24, 0x9B,   \
+ 0x57, 0x3F, 0xAD, 0x2C)
+#define INFO_ERR_STRUCT_TYPE_TLB   \
+   GUID_INIT(0xFC06B535, 0x5E1F, 0x4562, 0x9F, 0x25, 0x0A, 0x3B,   \
+ 0x9A, 0xDB, 0x63, 0xC3)
+#define INFO_ERR_STRUCT_TYPE_BUS   \
+   GUID_INIT(0x1CF3F8B3, 0xC5B1, 0x49a2, 0xAA, 0x59, 0x5E, 0xEF,   \
+ 0x92, 0xFF, 0xA6, 0x3C)
+#define INFO_ERR_STRUCT_TYPE_MS
\
+   GUID_INIT(0x48AB7F57, 0xDC34, 0x4f6c, 0xA7, 0xD3, 0xB0, 0xB5,   \
+ 0xB0, 0xA7, 0x43, 0x14)
+
 #define INFO_VALID_CHECK_INFO  BIT_ULL(0)
 #define INFO_VALID_TARGET_ID   BIT_ULL(1)
 #define INFO_VALID_REQUESTOR_IDBIT_ULL(2)
 #define INFO_VALID_RESPONDER_IDBIT_ULL(3)
 #define INFO_VALID_IP  BIT_ULL(4)
 
+enum err_types {
+   ERR_TYPE_CACHE = 0,
+   ERR_TYPE_TLB,
+   ERR_TYPE_BUS,
+   ERR_TYPE_MS,
+   N_ERR_TYPES
+};
+
+static enum err_types cper_get_err_type(const guid_t *err_type)
+{
+   if (guid_equal(err_type, _ERR_STRUCT_TYPE_CACHE))
+   return ERR_TYPE_CACHE;
+   else if (guid_equal(err_type, _ERR_STRUCT_TYPE_TLB))
+   return ERR_TYPE_TLB;
+   else if (guid_equal(err_type, _ERR_STRUCT_TYPE_BUS))
+   return ERR_TYPE_BUS;
+   else if (guid_equal(err_type, _ERR_STRUCT_TYPE_MS))
+   return ERR_TYPE_MS;
+   else
+   return N_ERR_TYPES;
+}
+
 void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
 {
int i;
struct cper_ia_err_info *err_info;
char newpfx[64];
+   u8 err_type;
 
if (proc->validation_bits & VALID_LAPIC_ID)
printk("%sLocal APIC_ID: 0x%llx\n", pfx, proc->lapic_id);
@@ -40,8 +76,15 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
for (i = 0; i < VALID_PROC_ERR_INFO_NUM(proc->validation_bits); i++) {
printk("%sError Information Structure %d:\n", pfx, i);
 
-   printk("%sError Structure Type: %pUl\n", newpfx,
-  _info->err_type);
+   err_type = cper_get_err_type(_info->err_type);
+   printk("%sError Structure Type: %s\n", newpfx,
+  err_type < ARRAY_SIZE(cper_proc_error_type_strs) ?
+  cper_proc_error_type_strs[err_type] : "unknown");
+
+   if (err_type >= N_ERR_TYPES) {
+   printk("%sError Structure Type: %pUl\n", newpfx,
+  _info->err_type);
+   }
 
if (err_info->validation_bits & INFO_VALID_CHECK_INFO) {
printk("%sCheck Information: 0x%016llx\n", newpfx,
-- 
2.14.1



[PATCH v3 2/8] efi: Decode IA32/X64 Processor Error Section

2018-03-24 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Recognize the IA32/X64 Processor Error Section.

Do the section decoding in a new "cper-x86.c" file and add this to the
Makefile depending on a new "UEFI_CPER_X86" config option.

Print the Local APIC ID and CPUID info from the Processor Error Record.

The "Processor Error Info" and "Processor Context" fields will be
decoded in following patches.

Based on UEFI 2.7 Table 252. Processor Error Record.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180226193904.20532-3-yazen.ghan...@amd.com

v2->v3:
* Fix table number in commit message.
* Don't print raw validation bits.

v1->v2:
* Change config option depends to "X86" instead of "X86_32 || X64_64".
* Remove extra newline in Makefile changes.
* Drop author copyright line.

 drivers/firmware/efi/Kconfig|  5 +
 drivers/firmware/efi/Makefile   |  1 +
 drivers/firmware/efi/cper-x86.c | 23 +++
 drivers/firmware/efi/cper.c | 10 ++
 include/linux/cper.h|  2 ++
 5 files changed, 41 insertions(+)
 create mode 100644 drivers/firmware/efi/cper-x86.c

diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 3098410abad8..781a4a337557 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -174,6 +174,11 @@ config UEFI_CPER_ARM
depends on UEFI_CPER && ( ARM || ARM64 )
default y
 
+config UEFI_CPER_X86
+   bool
+   depends on UEFI_CPER && X86
+   default y
+
 config EFI_DEV_PATH_PARSER
bool
depends on ACPI
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile
index cb805374f4bc..5f9f5039de50 100644
--- a/drivers/firmware/efi/Makefile
+++ b/drivers/firmware/efi/Makefile
@@ -31,3 +31,4 @@ obj-$(CONFIG_ARM) += $(arm-obj-y)
 obj-$(CONFIG_ARM64)+= $(arm-obj-y)
 obj-$(CONFIG_EFI_CAPSULE_LOADER)   += capsule-loader.o
 obj-$(CONFIG_UEFI_CPER_ARM)+= cper-arm.o
+obj-$(CONFIG_UEFI_CPER_X86)+= cper-x86.o
diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
new file mode 100644
index ..863f0cd2a0ff
--- /dev/null
+++ b/drivers/firmware/efi/cper-x86.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2018, Advanced Micro Devices, Inc.
+
+#include 
+
+/*
+ * We don't need a "CPER_IA" prefix since these are all locally defined.
+ * This will save us a lot of line space.
+ */
+#define VALID_LAPIC_ID BIT_ULL(0)
+#define VALID_CPUID_INFO   BIT_ULL(1)
+
+void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
+{
+   if (proc->validation_bits & VALID_LAPIC_ID)
+   printk("%sLocal APIC_ID: 0x%llx\n", pfx, proc->lapic_id);
+
+   if (proc->validation_bits & VALID_CPUID_INFO) {
+   printk("%sCPUID Info:\n", pfx);
+   print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, proc->cpuid,
+  sizeof(proc->cpuid), 0);
+   }
+}
diff --git a/drivers/firmware/efi/cper.c b/drivers/firmware/efi/cper.c
index c165933ebf38..5a59b582c9aa 100644
--- a/drivers/firmware/efi/cper.c
+++ b/drivers/firmware/efi/cper.c
@@ -469,6 +469,16 @@ cper_estatus_print_section(const char *pfx, struct 
acpi_hest_generic_data *gdata
cper_print_proc_arm(newpfx, arm_err);
else
goto err_section_too_small;
+#endif
+#if defined(CONFIG_UEFI_CPER_X86)
+   } else if (guid_equal(sec_type, _SEC_PROC_IA)) {
+   struct cper_sec_proc_ia *ia_err = acpi_hest_get_payload(gdata);
+
+   printk("%ssection_type: IA32/X64 processor error\n", newpfx);
+   if (gdata->error_data_length >= sizeof(*ia_err))
+   cper_print_proc_ia(newpfx, ia_err);
+   else
+   goto err_section_too_small;
 #endif
} else {
const void *err = acpi_hest_get_payload(gdata);
diff --git a/include/linux/cper.h b/include/linux/cper.h
index 4b5f8459b403..9c703a0abe6e 100644
--- a/include/linux/cper.h
+++ b/include/linux/cper.h
@@ -551,5 +551,7 @@ const char *cper_mem_err_unpack(struct trace_seq *,
struct cper_mem_err_compact *);
 void cper_print_proc_arm(const char *pfx,
 const struct cper_sec_proc_arm *proc);
+void cper_print_proc_ia(const char *pfx,
+   const struct cper_sec_proc_ia *proc);
 
 #endif
-- 
2.14.1



[PATCH v3 0/8] Decode IA32/X64 CPER

2018-03-24 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

This series adds decoding for the IA32/X64 Common Platform Error Record.

Patch 1 fixes the IA32/X64 Processor Error Section definition to match
the UEFI spec.

Patches 2-8 add the new decoding. The patches incrementally add the
decoding starting from the top-level "Error Section". Hopefully, this
will make reviewing a bit easier compared to one large patch.

The formatting of the field names and options is taken from the UEFI
spec. I tried to keep everything the same to make searching easier.

The patches were written to the UEFI 2.7 spec though the definition of
the IA32/X64 CPER seems to be the same as when it was introduced in
the UEFI 2.1 spec.

Link:
https://lkml.kernel.org/r/20180226193904.20532-1-yazen.ghan...@amd.com

Changes V2 to V3:
* Fix table numbers in commit messages.
* Don't print raw validation bits.
* Only print GUID for unknown error types.

Changes V1 to V2:
* Remove stable request for all patches.
* Address Ard's comments on formatting and other issues.
* In Patch 8, always print context info even if the type is not
  recognized.

Yazen Ghannam (8):
  efi: Fix IA32/X64 Processor Error Record definition
  efi: Decode IA32/X64 Processor Error Section
  efi: Decode IA32/X64 Processor Error Info Structure
  efi: Decode UEFI-defined IA32/X64 Error Structure GUIDs
  efi: Decode IA32/X64 Cache, TLB, and Bus Check structures
  efi: Decode additional IA32/X64 Bus Check fields
  efi: Decode IA32/X64 MS Check structure
  efi: Decode IA32/X64 Context Info structure

 drivers/firmware/efi/Kconfig|   5 +
 drivers/firmware/efi/Makefile   |   1 +
 drivers/firmware/efi/cper-x86.c | 358 
 drivers/firmware/efi/cper.c |  10 ++
 include/linux/cper.h|   4 +-
 5 files changed, 377 insertions(+), 1 deletion(-)
 create mode 100644 drivers/firmware/efi/cper-x86.c

-- 
2.14.1



[PATCH v3 5/8] efi: Decode IA32/X64 Cache, TLB, and Bus Check structures

2018-03-24 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Print the common fields of the Cache, TLB, and Bus check structures.The
fields of these three check types are the same except for a few more
fields in the Bus check structure. The remaining Bus check structure
fields will be decoded in a following patch.

Based on UEFI 2.7,
Table 254. IA32/X64 Cache Check Structure
Table 255. IA32/X64 TLB Check Structure
Table 256. IA32/X64 Bus Check Structure

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180226193904.20532-6-yazen.ghan...@amd.com

v2->v3:
* Fix table numbers in commit message.
* Don't print raw validation bits.

v1->v2:
* Add parantheses around "check" expression in macro.
* Change use of enum type to u8.
* Fix indentation on multi-line statements.

 drivers/firmware/efi/cper-x86.c | 99 -
 1 file changed, 98 insertions(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 57fbea5b3a8c..260e4bf7773c 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -32,6 +32,25 @@
 #define INFO_VALID_RESPONDER_IDBIT_ULL(3)
 #define INFO_VALID_IP  BIT_ULL(4)
 
+#define CHECK_VALID_TRANS_TYPE BIT_ULL(0)
+#define CHECK_VALID_OPERATION  BIT_ULL(1)
+#define CHECK_VALID_LEVEL  BIT_ULL(2)
+#define CHECK_VALID_PCCBIT_ULL(3)
+#define CHECK_VALID_UNCORRECTEDBIT_ULL(4)
+#define CHECK_VALID_PRECISE_IP BIT_ULL(5)
+#define CHECK_VALID_RESTARTABLE_IP BIT_ULL(6)
+#define CHECK_VALID_OVERFLOW   BIT_ULL(7)
+
+#define CHECK_VALID_BITS(check)(((check) & GENMASK_ULL(15, 0)))
+#define CHECK_TRANS_TYPE(check)(((check) & GENMASK_ULL(17, 
16)) >> 16)
+#define CHECK_OPERATION(check) (((check) & GENMASK_ULL(21, 18)) >> 18)
+#define CHECK_LEVEL(check) (((check) & GENMASK_ULL(24, 22)) >> 22)
+#define CHECK_PCC  BIT_ULL(25)
+#define CHECK_UNCORRECTED  BIT_ULL(26)
+#define CHECK_PRECISE_IP   BIT_ULL(27)
+#define CHECK_RESTARTABLE_IP   BIT_ULL(28)
+#define CHECK_OVERFLOW BIT_ULL(29)
+
 enum err_types {
ERR_TYPE_CACHE = 0,
ERR_TYPE_TLB,
@@ -54,11 +73,81 @@ static enum err_types cper_get_err_type(const guid_t 
*err_type)
return N_ERR_TYPES;
 }
 
+static const char * const ia_check_trans_type_strs[] = {
+   "Instruction",
+   "Data Access",
+   "Generic",
+};
+
+static const char * const ia_check_op_strs[] = {
+   "generic error",
+   "generic read",
+   "generic write",
+   "data read",
+   "data write",
+   "instruction fetch",
+   "prefetch",
+   "eviction",
+   "snoop",
+};
+
+static inline void print_bool(char *str, const char *pfx, u64 check, u64 bit)
+{
+   printk("%s%s: %s\n", pfx, str, (check & bit) ? "true" : "false");
+}
+
+static void print_err_info(const char *pfx, u8 err_type, u64 check)
+{
+   u16 validation_bits = CHECK_VALID_BITS(check);
+
+   if (err_type == ERR_TYPE_MS)
+   return;
+
+   if (validation_bits & CHECK_VALID_TRANS_TYPE) {
+   u8 trans_type = CHECK_TRANS_TYPE(check);
+
+   printk("%sTransaction Type: %u, %s\n", pfx, trans_type,
+  trans_type < ARRAY_SIZE(ia_check_trans_type_strs) ?
+  ia_check_trans_type_strs[trans_type] : "unknown");
+   }
+
+   if (validation_bits & CHECK_VALID_OPERATION) {
+   u8 op = CHECK_OPERATION(check);
+
+   /*
+* CACHE has more operation types than TLB or BUS, though the
+* name and the order are the same.
+*/
+   u8 max_ops = (err_type == ERR_TYPE_CACHE) ? 9 : 7;
+
+   printk("%sOperation: %u, %s\n", pfx, op,
+  op < max_ops ? ia_check_op_strs[op] : "unknown");
+   }
+
+   if (validation_bits & CHECK_VALID_LEVEL)
+   printk("%sLevel: %llu\n", pfx, CHECK_LEVEL(check));
+
+   if (validation_bits & CHECK_VALID_PCC)
+   print_bool("Processor Context Corrupt", pfx, check, CHECK_PCC);
+
+   if (validation_bits & CHECK_VALID_UNCORRECTED)
+   print_bool("Uncorrected", pfx, check, CHECK_UNCORRECTED);
+
+   if (validation_bits & CHECK_VALID_PRECISE_IP)
+   print_bool("Precise IP", pfx, check, CHECK_PRECISE_IP);
+
+   if (validation_bits & CHECK_VALID_RESTARTABLE_IP)
+   print_bool("Restartable IP",

[PATCH v3 3/8] efi: Decode IA32/X64 Processor Error Info Structure

2018-03-24 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

Print the fields in the IA32/X64 Processor Error Info Structure.

Based on UEFI 2.7 Table 253. IA32/X64 Processor Error Information
Structure.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180226193904.20532-4-yazen.ghan...@amd.com

v2->v3:
* Fix table number in commit message.
* Don't print raw validation bits.

v1->v2:
* Add parantheses around "bits" expression in macro.
* Fix indentation on multi-line statements.

 drivers/firmware/efi/cper-x86.c | 50 +
 1 file changed, 50 insertions(+)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 863f0cd2a0ff..a9ab3bbf7986 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -3,15 +3,28 @@
 
 #include 
 
+#define INDENT_SP  " "
+
 /*
  * We don't need a "CPER_IA" prefix since these are all locally defined.
  * This will save us a lot of line space.
  */
 #define VALID_LAPIC_ID BIT_ULL(0)
 #define VALID_CPUID_INFO   BIT_ULL(1)
+#define VALID_PROC_ERR_INFO_NUM(bits)  (((bits) & GENMASK_ULL(7, 2)) >> 2)
+
+#define INFO_VALID_CHECK_INFO  BIT_ULL(0)
+#define INFO_VALID_TARGET_ID   BIT_ULL(1)
+#define INFO_VALID_REQUESTOR_IDBIT_ULL(2)
+#define INFO_VALID_RESPONDER_IDBIT_ULL(3)
+#define INFO_VALID_IP  BIT_ULL(4)
 
 void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
 {
+   int i;
+   struct cper_ia_err_info *err_info;
+   char newpfx[64];
+
if (proc->validation_bits & VALID_LAPIC_ID)
printk("%sLocal APIC_ID: 0x%llx\n", pfx, proc->lapic_id);
 
@@ -20,4 +33,41 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
print_hex_dump(pfx, "", DUMP_PREFIX_OFFSET, 16, 4, proc->cpuid,
   sizeof(proc->cpuid), 0);
}
+
+   snprintf(newpfx, sizeof(newpfx), "%s%s", pfx, INDENT_SP);
+
+   err_info = (struct cper_ia_err_info *)(proc + 1);
+   for (i = 0; i < VALID_PROC_ERR_INFO_NUM(proc->validation_bits); i++) {
+   printk("%sError Information Structure %d:\n", pfx, i);
+
+   printk("%sError Structure Type: %pUl\n", newpfx,
+  _info->err_type);
+
+   if (err_info->validation_bits & INFO_VALID_CHECK_INFO) {
+   printk("%sCheck Information: 0x%016llx\n", newpfx,
+  err_info->check_info);
+   }
+
+   if (err_info->validation_bits & INFO_VALID_TARGET_ID) {
+   printk("%sTarget Identifier: 0x%016llx\n",
+  newpfx, err_info->target_id);
+   }
+
+   if (err_info->validation_bits & INFO_VALID_REQUESTOR_ID) {
+   printk("%sRequestor Identifier: 0x%016llx\n",
+  newpfx, err_info->requestor_id);
+   }
+
+   if (err_info->validation_bits & INFO_VALID_RESPONDER_ID) {
+   printk("%sResponder Identifier: 0x%016llx\n",
+  newpfx, err_info->responder_id);
+   }
+
+   if (err_info->validation_bits & INFO_VALID_IP) {
+   printk("%sInstruction Pointer: 0x%016llx\n",
+  newpfx, err_info->ip);
+   }
+
+   err_info++;
+   }
 }
-- 
2.14.1



[PATCH 2/2] x86/MCE: Always save MCA_{ADDR,MISC,SYND} register contents

2018-03-26 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

The Intel SDM and AMD APM both state that the contents of the MCA_ADDR
register should be saved if MCA_STATUS[ADDRV] is set. The same applies
to MCA_MISC and MCA_SYND (on SMCA systems) and their respective valid
bits.

However, the Fam17h Processor Programming Reference states
"Error handlers should save the values in MCA_ADDR, MCA_MISC0, and
MCA_SYND even if MCA_STATUS[AddrV], MCA_STATUS[MiscV], and
MCA_STATUS[SyndV] are zero."

This is to ensure that all MCA state information is collected even if
software cannot act upon it (because the valid bits are cleared).

So always save the auxiliary MCA register contents even if the valid
bits are cleared. This should not affect error processing because
software should still check the valid bits before using the register
contents for error processing.

Also, print MCA_{ADDR,MISC,SYND} even if their valid bits are not set.
Printing from EDAC/mce_amd is included here since we want to do this on
AMD systems.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce.c | 23 +++
 arch/x86/kernel/cpu/mcheck/mce_amd.c | 10 +++---
 drivers/edac/mce_amd.c   | 10 +++---
 3 files changed, 13 insertions(+), 30 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 42cf2880d0ed..a556e1cadfbc 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -248,19 +248,14 @@ static void __print_mce(struct mce *m)
}
 
pr_emerg(HW_ERR "TSC %llx ", m->tsc);
-   if (m->addr)
-   pr_cont("ADDR %llx ", m->addr);
-   if (m->misc)
-   pr_cont("MISC %llx ", m->misc);
+   pr_cont("ADDR %016llx ", m->addr);
+   pr_cont("MISC %016llx\n", m->misc);
 
if (mce_flags.smca) {
-   if (m->synd)
-   pr_cont("SYND %llx ", m->synd);
-   if (m->ipid)
-   pr_cont("IPID %llx ", m->ipid);
+   pr_emerg(HW_ERR "IPID %016llx ", m->ipid);
+   pr_cont("SYND %016llx\n", m->synd);
}
 
-   pr_cont("\n");
/*
 * Note this output is parsed by external tools and old fields
 * should not be changed.
@@ -639,12 +634,10 @@ static struct notifier_block mce_default_nb = {
  */
 static void mce_read_aux(struct mce *m, int i)
 {
-   if (m->status & MCI_STATUS_MISCV)
-   m->misc = mce_rdmsrl(msr_ops.misc(i));
+   m->misc = mce_rdmsrl(msr_ops.misc(i));
+   m->addr = mce_rdmsrl(msr_ops.addr(i));
 
if (m->status & MCI_STATUS_ADDRV) {
-   m->addr = mce_rdmsrl(msr_ops.addr(i));
-
/*
 * Mask the reported address by the reported granularity.
 */
@@ -667,9 +660,7 @@ static void mce_read_aux(struct mce *m, int i)
 
if (mce_flags.smca) {
m->ipid = mce_rdmsrl(MSR_AMD64_SMCA_MCx_IPID(i));
-
-   if (m->status & MCI_STATUS_SYNDV)
-   m->synd = mce_rdmsrl(MSR_AMD64_SMCA_MCx_SYND(i));
+   m->synd = mce_rdmsrl(MSR_AMD64_SMCA_MCx_SYND(i));
}
 }
 
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c 
b/arch/x86/kernel/cpu/mcheck/mce_amd.c
index f7666eef4a87..5a37ae704578 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -799,13 +799,12 @@ static void __log_error(unsigned int bank, u64 status, 
u64 addr, u64 misc)
mce_setup();
 
m.status = status;
+   m.addr   = addr;
m.misc   = misc;
m.bank   = bank;
m.tsc= rdtsc();
 
if (m.status & MCI_STATUS_ADDRV) {
-   m.addr = addr;
-
/*
 * Extract [55:] where lsb is the least significant
 * *valid* bit of the address bits.
@@ -819,9 +818,7 @@ static void __log_error(unsigned int bank, u64 status, u64 
addr, u64 misc)
 
if (mce_flags.smca) {
rdmsrl(MSR_AMD64_SMCA_MCx_IPID(bank), m.ipid);
-
-   if (m.status & MCI_STATUS_SYNDV)
-   rdmsrl(MSR_AMD64_SMCA_MCx_SYND(bank), m.synd);
+   rdmsrl(MSR_AMD64_SMCA_MCx_SYND(bank), m.synd);
}
 
mce_log();
@@ -849,8 +846,7 @@ _log_error_bank(unsigned int bank, u32 msr_stat, u32 
msr_addr, u64 misc)
if (!(status & MCI_STATUS_VAL))
return false;
 
-   if (status & MCI_STATUS_ADDRV)
-   rdmsrl(msr_addr, addr);
+   rdmsrl(msr_addr, addr);
 
__log_error(bank, status, addr, misc);
 
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c
index 2ab4d61ee47e..004425cc8ddf 100644
--- a/drivers/edac/mce_amd.c
+++ b/drivers/edac/mce

[PATCH 1/2] Revert "x86/mce/AMD: Collect error info even if valid bits are not set"

2018-03-26 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

This reverts commit 4b1e84276a6172980c5bf39aa091ba13e90d6dad.

Software uses the valid bits to decide if the values can be used for
further processing or other actions. So setting the valid bits will have
software act on values that it shouldn't be acting on.

The recommendation to save all the register values does not mean that
the values are always valid.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
 arch/x86/kernel/cpu/mcheck/mce.c | 14 --
 1 file changed, 14 deletions(-)

diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 86079b90ebcf..42cf2880d0ed 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -446,20 +446,6 @@ static inline void mce_gather_info(struct mce *m, struct 
pt_regs *regs)
if (mca_cfg.rip_msr)
m->ip = mce_rdmsrl(mca_cfg.rip_msr);
}
-
-   /*
-* Error handlers should save the values in MCA_ADDR, MCA_MISC0, and
-* MCA_SYND even if MCA_STATUS[AddrV], MCA_STATUS[MiscV], and
-* MCA_STATUS[SyndV] are zero.
-*/
-   if (m->cpuvendor == X86_VENDOR_AMD) {
-   u64 status = MCI_STATUS_ADDRV | MCI_STATUS_MISCV;
-
-   if (mce_flags.smca)
-   status |= MCI_STATUS_SYNDV;
-
-   m->status |= status;
-   }
 }
 
 int mce_available(struct cpuinfo_x86 *c)
-- 
2.14.1



[PATCH v4 4/8] efi: Decode UEFI-defined IA32/X64 Error Structure GUIDs

2018-04-02 Thread Yazen Ghannam
From: Yazen Ghannam <yazen.ghan...@amd.com>

For easier handling, match the known IA32/X64 error structure GUIDs to
enums.

Also, print out the name of the matching Error Structure Type.

Only print the GUID for unknown types.

GUIDs taken from UEFI 2.7 section N.2.4.2.1 IA32/X64 Processor Error
Information Structure.

Signed-off-by: Yazen Ghannam <yazen.ghan...@amd.com>
---
Link:
https://lkml.kernel.org/r/20180324184940.19762-5-yazen.ghan...@amd.com

v3->v4:
* No changes.

v2->v3:
* Only print raw GUID for unknown error types.

v1->v2:
* Change use of enum type to u8.
* Fix indentation on multi-line statements.

 drivers/firmware/efi/cper-x86.c | 47 +++--
 1 file changed, 45 insertions(+), 2 deletions(-)

diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index e0633a103fcf..5438097b93ac 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -11,17 +11,53 @@
 #define VALID_CPUID_INFO   BIT_ULL(1)
 #define VALID_PROC_ERR_INFO_NUM(bits)  (((bits) & GENMASK_ULL(7, 2)) >> 2)
 
+#define INFO_ERR_STRUCT_TYPE_CACHE \
+   GUID_INIT(0xA55701F5, 0xE3EF, 0x43DE, 0xAC, 0x72, 0x24, 0x9B,   \
+ 0x57, 0x3F, 0xAD, 0x2C)
+#define INFO_ERR_STRUCT_TYPE_TLB   \
+   GUID_INIT(0xFC06B535, 0x5E1F, 0x4562, 0x9F, 0x25, 0x0A, 0x3B,   \
+ 0x9A, 0xDB, 0x63, 0xC3)
+#define INFO_ERR_STRUCT_TYPE_BUS   \
+   GUID_INIT(0x1CF3F8B3, 0xC5B1, 0x49a2, 0xAA, 0x59, 0x5E, 0xEF,   \
+ 0x92, 0xFF, 0xA6, 0x3C)
+#define INFO_ERR_STRUCT_TYPE_MS
\
+   GUID_INIT(0x48AB7F57, 0xDC34, 0x4f6c, 0xA7, 0xD3, 0xB0, 0xB5,   \
+ 0xB0, 0xA7, 0x43, 0x14)
+
 #define INFO_VALID_CHECK_INFO  BIT_ULL(0)
 #define INFO_VALID_TARGET_ID   BIT_ULL(1)
 #define INFO_VALID_REQUESTOR_IDBIT_ULL(2)
 #define INFO_VALID_RESPONDER_IDBIT_ULL(3)
 #define INFO_VALID_IP  BIT_ULL(4)
 
+enum err_types {
+   ERR_TYPE_CACHE = 0,
+   ERR_TYPE_TLB,
+   ERR_TYPE_BUS,
+   ERR_TYPE_MS,
+   N_ERR_TYPES
+};
+
+static enum err_types cper_get_err_type(const guid_t *err_type)
+{
+   if (guid_equal(err_type, _ERR_STRUCT_TYPE_CACHE))
+   return ERR_TYPE_CACHE;
+   else if (guid_equal(err_type, _ERR_STRUCT_TYPE_TLB))
+   return ERR_TYPE_TLB;
+   else if (guid_equal(err_type, _ERR_STRUCT_TYPE_BUS))
+   return ERR_TYPE_BUS;
+   else if (guid_equal(err_type, _ERR_STRUCT_TYPE_MS))
+   return ERR_TYPE_MS;
+   else
+   return N_ERR_TYPES;
+}
+
 void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
 {
int i;
struct cper_ia_err_info *err_info;
char newpfx[64];
+   u8 err_type;
 
if (proc->validation_bits & VALID_LAPIC_ID)
printk("%sLocal APIC_ID: 0x%llx\n", pfx, proc->lapic_id);
@@ -38,8 +74,15 @@ void cper_print_proc_ia(const char *pfx, const struct 
cper_sec_proc_ia *proc)
for (i = 0; i < VALID_PROC_ERR_INFO_NUM(proc->validation_bits); i++) {
printk("%sError Information Structure %d:\n", pfx, i);
 
-   printk("%sError Structure Type: %pUl\n", newpfx,
-  _info->err_type);
+   err_type = cper_get_err_type(_info->err_type);
+   printk("%sError Structure Type: %s\n", newpfx,
+  err_type < ARRAY_SIZE(cper_proc_error_type_strs) ?
+  cper_proc_error_type_strs[err_type] : "unknown");
+
+   if (err_type >= N_ERR_TYPES) {
+   printk("%sError Structure Type: %pUl\n", newpfx,
+  _info->err_type);
+   }
 
if (err_info->validation_bits & INFO_VALID_CHECK_INFO) {
printk("%sCheck Information: 0x%016llx\n", newpfx,
-- 
2.14.1



  1   2   3   4   5   >