diff mbox series

[v5] cper, apei, mce: Pass x86 CPER through the MCA handling chain

Message ID 20201103164952.5126-1-Smita.KoralahalliChannabasappa@amd.com (mailing list archive)
State New, archived
Headers show
Series [v5] cper, apei, mce: Pass x86 CPER through the MCA handling chain | expand

Commit Message

Smita Koralahalli Nov. 3, 2020, 4:49 p.m. UTC
Linux Kernel uses ACPI Boot Error Record Table (BERT) to report fatal
errors that occurred in a previous boot. The MCA errors in the BERT are
reported using the x86 Processor Error Common Platform Error Record (CPER)
format. Currently, the record prints out the raw MSR values and AMD relies
on the raw record to provide MCA information.

Extract the raw MSR values of MCA registers from the BERT and feed it into
the standard mce_log() function through the existing x86/MCA RAS
infrastructure. This will result in better decoding from the EDAC MCE
decoder or the default notifier.

The implementation is SMCA specific as the raw MCA register values are
given in the register offset order of the MCAX address space.

[ Fix a build breakage in patch v1. ]
Reported-by: kernel test robot <lkp@intel.com>
Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>
---
Link:
https://lkml.kernel.org/r/20200904140444.161291-1-Smita.KoralahalliChannabasappa@amd.com

v5:
	Included check to determine if register array size is large
	enough to hold all the registers which we want to extract.
	Used already defined MSR_AMD64_SMCA_MC0_STATUS.
v4:
	Included what kernel test robot reported.
	Changed function name from apei_mce_report_x86_error ->
	apei_smca_report_x86_error.
	Added comment for MASK_MCA_STATUS definition.
	Wrapped apei_smca_report_x86_error() with CONFIG_X86_MCE in
	arch/x86/include/asm/mce.h
v3:
	Moved arch specific declarations from generic headers to arch
	specific headers.
	Cleaned additional declarations which are unnecessary.
	Included the check for context type.
	Added additional check to verify for appropriate MSR address in
	the register layout.
v2:
	Fixed build error reported by kernel test robot.
	Passed struct variable as function argument instead of entire struct.
---
 arch/x86/include/asm/acpi.h     | 11 +++++++
 arch/x86/include/asm/mce.h      |  6 ++++
 arch/x86/kernel/acpi/apei.c     |  5 +++
 arch/x86/kernel/cpu/mce/apei.c  | 56 +++++++++++++++++++++++++++++++++
 drivers/firmware/efi/cper-x86.c | 11 +++++--
 5 files changed, 86 insertions(+), 3 deletions(-)

Comments

Punit Agrawal Nov. 6, 2020, 5:36 a.m. UTC | #1
Hi Smita,

Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com> writes:

> Linux Kernel uses ACPI Boot Error Record Table (BERT) to report fatal
> errors that occurred in a previous boot. The MCA errors in the BERT are
> reported using the x86 Processor Error Common Platform Error Record (CPER)
> format. Currently, the record prints out the raw MSR values and AMD relies
> on the raw record to provide MCA information.
>
> Extract the raw MSR values of MCA registers from the BERT and feed it into
> the standard mce_log() function through the existing x86/MCA RAS
> infrastructure. This will result in better decoding from the EDAC MCE
> decoder or the default notifier.
>
> The implementation is SMCA specific as the raw MCA register values are
> given in the register offset order of the MCAX address space.
>
> [ Fix a build breakage in patch v1. ]
> Reported-by: kernel test robot <lkp@intel.com>
> Signed-off-by: Smita Koralahalli <Smita.KoralahalliChannabasappa@amd.com>

[...]

> diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
> index 2531de49f56c..438ed9eff6d0 100644
> --- a/drivers/firmware/efi/cper-x86.c
> +++ b/drivers/firmware/efi/cper-x86.c
> @@ -2,6 +2,7 @@
>  // Copyright (C) 2018, Advanced Micro Devices, Inc.
>  
>  #include <linux/cper.h>
> +#include <linux/acpi.h>

Did you mean to include <asm/acpi.h>?

>  
>  /*
>   * We don't need a "CPER_IA" prefix since these are all locally defined.
> @@ -347,9 +348,13 @@ void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
>  			       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);
> +		if (ctx_info->reg_ctx_type != CTX_TYPE_MSR ||
> +		    arch_apei_report_x86_error(ctx_info, proc->lapic_id)) {
> +			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);
>  	}

With that addressed,

FWIW,

Reviewed-by: Punit Agrawal <punit1.agrawal@toshiba.co.jp>

Thanks,
Punit
Borislav Petkov Nov. 6, 2020, 12:09 p.m. UTC | #2
On Tue, Nov 03, 2020 at 10:49:52AM -0600, Smita Koralahalli wrote:
> diff --git a/arch/x86/kernel/cpu/mce/apei.c b/arch/x86/kernel/cpu/mce/apei.c
> index af8d37962586..f56f0bc147e2 100644
> --- a/arch/x86/kernel/cpu/mce/apei.c
> +++ b/arch/x86/kernel/cpu/mce/apei.c
> @@ -51,6 +51,62 @@ void apei_mce_report_mem_error(int severity, struct cper_sec_mem_err *mem_err)
>  }
>  EXPORT_SYMBOL_GPL(apei_mce_report_mem_error);
>  
> +int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info, u64 lapic_id)
> +{
> +	const u64 *i_mce = ((const u64 *) (ctx_info + 1));
> +	unsigned int cpu;
> +	struct mce m;
> +
> +	if (!boot_cpu_has(X86_FEATURE_SMCA))
> +		return -EINVAL;
> +
> +	/*
> +	 * The starting address of the Register Array extracted from BERT
> +	 * must match with the first expected register in the register
> +	 * layout of MCAX address space. In SMCA systems this address
> +	 * corresponds to banks's MCA_STATUS register.

So which is it "MCAX" or "SMCA"? They both denote the same thing but
let's stick to one to avoid unnecessary confusion. I'm guessing to
"SMCA" because it is more wide-spread in the kernel...

> +	 *
> +	 * The Register array size must be large enough to include all
> +	 * the SMCA registers which we want to extract.
> +	 *
> +	 * The number of registers in the Register Array is determined
> +	 * by Register Array Size/8 as defined in UEFI spec v2.8, sec
> +	 * N.2.4.2.2. The register layout is fixed and currently the raw
> +	 * data in the register array includes 6 SMCA registers which the
> +	 * kernel can extract.
> +	 */
> +
> +	if ((ctx_info->msr_addr & MSR_AMD64_SMCA_MC0_STATUS) !=
> +	    MSR_AMD64_SMCA_MC0_STATUS || ctx_info->reg_arr_size < 48)
> +		return -EINVAL;

Split that if in two consecutive if-statements.

Also, why the ANDing and not simply do:

	if (ctx_info->msr_addr == MSR_AMD64_SMCA_MC0_STATUS)

?

I'm guessing you wanna match *all* MCi_STATUS MSRs - not only MC0, yes?

If so, document that with in the comment above it.

Thx.
Borislav Petkov Nov. 6, 2020, 12:09 p.m. UTC | #3
On Fri, Nov 06, 2020 at 02:36:46PM +0900, Punit Agrawal wrote:
> > diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
> > index 2531de49f56c..438ed9eff6d0 100644
> > --- a/drivers/firmware/efi/cper-x86.c
> > +++ b/drivers/firmware/efi/cper-x86.c
> > @@ -2,6 +2,7 @@
> >  // Copyright (C) 2018, Advanced Micro Devices, Inc.
> >  
> >  #include <linux/cper.h>
> > +#include <linux/acpi.h>
> 
> Did you mean to include <asm/acpi.h>?

Why?
Punit Agrawal Nov. 9, 2020, 1:18 a.m. UTC | #4
Borislav Petkov <bp@alien8.de> writes:

> On Fri, Nov 06, 2020 at 02:36:46PM +0900, Punit Agrawal wrote:
>> > diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
>> > index 2531de49f56c..438ed9eff6d0 100644
>> > --- a/drivers/firmware/efi/cper-x86.c
>> > +++ b/drivers/firmware/efi/cper-x86.c
>> > @@ -2,6 +2,7 @@
>> >  // Copyright (C) 2018, Advanced Micro Devices, Inc.
>> >  
>> >  #include <linux/cper.h>
>> > +#include <linux/acpi.h>
>> 
>> Did you mean to include <asm/acpi.h>?
>
> Why?

Because arch_apei_report_x86_error() used in the patch is defined
there. The indirect include works but pulls in additional definitions
not needed by the patch.

Do you prefer the more generic include?

Thanks,
Punit
Koralahalli Channabasappa, Smita Nov. 9, 2020, 6:36 p.m. UTC | #5
On 11/6/20 6:09 AM, Borislav Petkov wrote:

> On Tue, Nov 03, 2020 at 10:49:52AM -0600, Smita Koralahalli wrote:
>> diff --git a/arch/x86/kernel/cpu/mce/apei.c b/arch/x86/kernel/cpu/mce/apei.c
>> index af8d37962586..f56f0bc147e2 100644
>> --- a/arch/x86/kernel/cpu/mce/apei.c
>> +++ b/arch/x86/kernel/cpu/mce/apei.c
>> @@ -51,6 +51,62 @@ void apei_mce_report_mem_error(int severity, struct cper_sec_mem_err *mem_err)
>>   }
>>   EXPORT_SYMBOL_GPL(apei_mce_report_mem_error);
>>   
>> +int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info, u64 lapic_id)
>> +{
>> +	const u64 *i_mce = ((const u64 *) (ctx_info + 1));
>> +	unsigned int cpu;
>> +	struct mce m;
>> +
>> +	if (!boot_cpu_has(X86_FEATURE_SMCA))
>> +		return -EINVAL;
>> +
>> +	/*
>> +	 * The starting address of the Register Array extracted from BERT
>> +	 * must match with the first expected register in the register
>> +	 * layout of MCAX address space. In SMCA systems this address
>> +	 * corresponds to banks's MCA_STATUS register.
> So which is it "MCAX" or "SMCA"? They both denote the same thing but
> let's stick to one to avoid unnecessary confusion. I'm guessing to
> "SMCA" because it is more wide-spread in the kernel...

Okay I will change it to SMCA.

>> +	 *
>> +	 * The Register array size must be large enough to include all
>> +	 * the SMCA registers which we want to extract.
>> +	 *
>> +	 * The number of registers in the Register Array is determined
>> +	 * by Register Array Size/8 as defined in UEFI spec v2.8, sec
>> +	 * N.2.4.2.2. The register layout is fixed and currently the raw
>> +	 * data in the register array includes 6 SMCA registers which the
>> +	 * kernel can extract.
>> +	 */
>> +
>> +	if ((ctx_info->msr_addr & MSR_AMD64_SMCA_MC0_STATUS) !=
>> +	    MSR_AMD64_SMCA_MC0_STATUS || ctx_info->reg_arr_size < 48)
>> +		return -EINVAL;
> Split that if in two consecutive if-statements.

Okay.

>
> Also, why the ANDing and not simply do:
>
> 	if (ctx_info->msr_addr == MSR_AMD64_SMCA_MC0_STATUS)
>
> ?
>
> I'm guessing you wanna match *all* MCi_STATUS MSRs - not only MC0, yes?
>
> If so, document that with in the comment above it.
>
> Thx.

ANDing with MC0 avoids bank check by turning off the bits corresponding
to the bank number.

For example: MCA_STATUS in SMCA space is 0xC0002YY1 where YY is the bank
number. The bank number is "Dont care" so ANDing with MC0_STATUS
(0xC0002001) should match on any MCi_STATUS MSR.

I will include that in comments above it.

Thanks,

>
Koralahalli Channabasappa, Smita Nov. 9, 2020, 7:05 p.m. UTC | #6
On 11/8/20 7:18 PM, Punit Agrawal wrote:

> Borislav Petkov <bp@alien8.de> writes:
>
>> On Fri, Nov 06, 2020 at 02:36:46PM +0900, Punit Agrawal wrote:
>>>> diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
>>>> index 2531de49f56c..438ed9eff6d0 100644
>>>> --- a/drivers/firmware/efi/cper-x86.c
>>>> +++ b/drivers/firmware/efi/cper-x86.c
>>>> @@ -2,6 +2,7 @@
>>>>   // Copyright (C) 2018, Advanced Micro Devices, Inc.
>>>>   
>>>>   #include <linux/cper.h>
>>>> +#include <linux/acpi.h>
>>> Did you mean to include <asm/acpi.h>?
>> Why?
> Because arch_apei_report_x86_error() used in the patch is defined
> there. The indirect include works but pulls in additional definitions
> not needed by the patch.
>
> Do you prefer the more generic include?

Okay.

I agree, it's generally a good practice to avoid pulling up additional
definitions. I had this when I made the declaration in generic header
file and may be I did not consider it changing initially as my build
didn't break after moving the declaration from generic header to arch
specific header file.

I will take care henceforth and make the changes as required.

Thanks,
Koralahalli Channabasappa, Smita Nov. 11, 2020, 8:37 p.m. UTC | #7
Punit,

On 11/9/20 1:05 PM, Smita Koralahalli Channabasappa wrote:

> On 11/8/20 7:18 PM, Punit Agrawal wrote:
>> Borislav Petkov <bp@alien8.de> writes:
>>> On Fri, Nov 06, 2020 at 02:36:46PM +0900, Punit Agrawal wrote:
>>>>> diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
>>>>> index 2531de49f56c..438ed9eff6d0 100644
>>>>> --- a/drivers/firmware/efi/cper-x86.c
>>>>> +++ b/drivers/firmware/efi/cper-x86.c
>>>>> @@ -2,6 +2,7 @@
>>>>>    // Copyright (C) 2018, Advanced Micro Devices, Inc.
>>>>>      #include <linux/cper.h>
>>>>> +#include <linux/acpi.h>
>>>> Did you mean to include <asm/acpi.h>?
>>> Why?
>> Because arch_apei_report_x86_error() used in the patch is defined
>> there. The indirect include works but pulls in additional definitions
>> not needed by the patch.
>>
>> Do you prefer the more generic include?
> I agree, it's generally a good practice to avoid pulling up additional
> definitions. I had this when I made the declaration in generic header
> file and may be I did not consider it changing initially as my build
> didn't break after moving the declaration from generic header to arch
> specific header file.
> I will take care henceforth and make the changes as required.

The asm specific include throws out a warning when I run checkpatch.pl

WARNING: Use #include <linux/acpi.h> instead of <asm/acpi.h>
#215: FILE: drivers/firmware/efi/cper-x86.c:5:
+#include <asm/acpi.h>

Should I just keep the generic include?

Thanks,
Smita
Punit Agrawal Nov. 13, 2020, 1:40 a.m. UTC | #8
Smita Koralahalli Channabasappa <skoralah@amd.com> writes:

> Punit,
>
> On 11/9/20 1:05 PM, Smita Koralahalli Channabasappa wrote:
>
>> On 11/8/20 7:18 PM, Punit Agrawal wrote:
>>> Borislav Petkov <bp@alien8.de> writes:
>>>> On Fri, Nov 06, 2020 at 02:36:46PM +0900, Punit Agrawal wrote:
>>>>>> diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
>>>>>> index 2531de49f56c..438ed9eff6d0 100644
>>>>>> --- a/drivers/firmware/efi/cper-x86.c
>>>>>> +++ b/drivers/firmware/efi/cper-x86.c
>>>>>> @@ -2,6 +2,7 @@
>>>>>>    // Copyright (C) 2018, Advanced Micro Devices, Inc.
>>>>>>      #include <linux/cper.h>
>>>>>> +#include <linux/acpi.h>
>>>>> Did you mean to include <asm/acpi.h>?
>>>> Why?
>>> Because arch_apei_report_x86_error() used in the patch is defined
>>> there. The indirect include works but pulls in additional definitions
>>> not needed by the patch.
>>>
>>> Do you prefer the more generic include?
>> I agree, it's generally a good practice to avoid pulling up additional
>> definitions. I had this when I made the declaration in generic header
>> file and may be I did not consider it changing initially as my build
>> didn't break after moving the declaration from generic header to arch
>> specific header file.
>> I will take care henceforth and make the changes as required.
>
> The asm specific include throws out a warning when I run checkpatch.pl
>
> WARNING: Use #include <linux/acpi.h> instead of <asm/acpi.h>
> #215: FILE: drivers/firmware/efi/cper-x86.c:5:
> +#include <asm/acpi.h>
>
> Should I just keep the generic include?

Thanks for checking.

I had a quick look at checkpatch to understand the reason for the
warning. It seems to warn when "asm" includes are used when a suitable
"linux" include exists[0].

I am not convinced that the rationale for that check applies in this
case as the function being used is indeed an architecture specific one
but also don't feel strongly enough to object.

Feel free to pick up the "Reviewed-by" tag in either case.

Thanks,
Punit

[0] https://github.com/torvalds/linux/blob/master/scripts/checkpatch.pl#L5333
diff mbox series

Patch

diff --git a/arch/x86/include/asm/acpi.h b/arch/x86/include/asm/acpi.h
index 6d2df1ee427b..65064d9f7fa6 100644
--- a/arch/x86/include/asm/acpi.h
+++ b/arch/x86/include/asm/acpi.h
@@ -159,6 +159,8 @@  static inline u64 x86_default_get_root_pointer(void)
 extern int x86_acpi_numa_init(void);
 #endif /* CONFIG_ACPI_NUMA */
 
+struct cper_ia_proc_ctx;
+
 #ifdef CONFIG_ACPI_APEI
 static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
 {
@@ -177,6 +179,15 @@  static inline pgprot_t arch_apei_get_mem_attribute(phys_addr_t addr)
 	 */
 	return PAGE_KERNEL_NOENC;
 }
+
+int arch_apei_report_x86_error(struct cper_ia_proc_ctx *ctx_info,
+			       u64 lapic_id);
+#else
+static inline int arch_apei_report_x86_error(struct cper_ia_proc_ctx *ctx_info,
+					     u64 lapic_id)
+{
+	return -EINVAL;
+}
 #endif
 
 #define ACPI_TABLE_UPGRADE_MAX_PHYS (max_low_pfn_mapped << PAGE_SHIFT)
diff --git a/arch/x86/include/asm/mce.h b/arch/x86/include/asm/mce.h
index a0f147893a04..07eedfd6ec38 100644
--- a/arch/x86/include/asm/mce.h
+++ b/arch/x86/include/asm/mce.h
@@ -198,16 +198,22 @@  static inline void enable_copy_mc_fragile(void)
 }
 #endif
 
+struct cper_ia_proc_ctx;
+
 #ifdef CONFIG_X86_MCE
 int mcheck_init(void);
 void mcheck_cpu_init(struct cpuinfo_x86 *c);
 void mcheck_cpu_clear(struct cpuinfo_x86 *c);
 void mcheck_vendor_init_severity(void);
+int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info,
+			       u64 lapic_id);
 #else
 static inline int mcheck_init(void) { return 0; }
 static inline void mcheck_cpu_init(struct cpuinfo_x86 *c) {}
 static inline void mcheck_cpu_clear(struct cpuinfo_x86 *c) {}
 static inline void mcheck_vendor_init_severity(void) {}
+static inline int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info,
+					     u64 lapic_id) { return -EINVAL; }
 #endif
 
 #ifdef CONFIG_X86_ANCIENT_MCE
diff --git a/arch/x86/kernel/acpi/apei.c b/arch/x86/kernel/acpi/apei.c
index c22fb55abcfd..0916f00a992e 100644
--- a/arch/x86/kernel/acpi/apei.c
+++ b/arch/x86/kernel/acpi/apei.c
@@ -43,3 +43,8 @@  void arch_apei_report_mem_error(int sev, struct cper_sec_mem_err *mem_err)
 	apei_mce_report_mem_error(sev, mem_err);
 #endif
 }
+
+int arch_apei_report_x86_error(struct cper_ia_proc_ctx *ctx_info, u64 lapic_id)
+{
+	return apei_smca_report_x86_error(ctx_info, lapic_id);
+}
diff --git a/arch/x86/kernel/cpu/mce/apei.c b/arch/x86/kernel/cpu/mce/apei.c
index af8d37962586..f56f0bc147e2 100644
--- a/arch/x86/kernel/cpu/mce/apei.c
+++ b/arch/x86/kernel/cpu/mce/apei.c
@@ -51,6 +51,62 @@  void apei_mce_report_mem_error(int severity, struct cper_sec_mem_err *mem_err)
 }
 EXPORT_SYMBOL_GPL(apei_mce_report_mem_error);
 
+int apei_smca_report_x86_error(struct cper_ia_proc_ctx *ctx_info, u64 lapic_id)
+{
+	const u64 *i_mce = ((const u64 *) (ctx_info + 1));
+	unsigned int cpu;
+	struct mce m;
+
+	if (!boot_cpu_has(X86_FEATURE_SMCA))
+		return -EINVAL;
+
+	/*
+	 * The starting address of the Register Array extracted from BERT
+	 * must match with the first expected register in the register
+	 * layout of MCAX address space. In SMCA systems this address
+	 * corresponds to banks's MCA_STATUS register.
+	 *
+	 * The Register array size must be large enough to include all
+	 * the SMCA registers which we want to extract.
+	 *
+	 * The number of registers in the Register Array is determined
+	 * by Register Array Size/8 as defined in UEFI spec v2.8, sec
+	 * N.2.4.2.2. The register layout is fixed and currently the raw
+	 * data in the register array includes 6 SMCA registers which the
+	 * kernel can extract.
+	 */
+
+	if ((ctx_info->msr_addr & MSR_AMD64_SMCA_MC0_STATUS) !=
+	    MSR_AMD64_SMCA_MC0_STATUS || ctx_info->reg_arr_size < 48)
+		return -EINVAL;
+
+	mce_setup(&m);
+
+	m.extcpu = -1;
+	m.socketid = -1;
+
+	for_each_possible_cpu(cpu) {
+		if (cpu_data(cpu).initial_apicid == lapic_id) {
+			m.extcpu = cpu;
+			m.socketid = cpu_data(m.extcpu).phys_proc_id;
+			break;
+		}
+	}
+
+	m.apicid = lapic_id;
+	m.bank = (ctx_info->msr_addr >> 4) & 0xFF;
+	m.status = *i_mce;
+	m.addr = *(i_mce + 1);
+	m.misc = *(i_mce + 2);
+	/* Skipping MCA_CONFIG */
+	m.ipid = *(i_mce + 4);
+	m.synd = *(i_mce + 5);
+
+	mce_log(&m);
+
+	return 0;
+}
+
 #define CPER_CREATOR_MCE						\
 	GUID_INIT(0x75a574e3, 0x5052, 0x4b29, 0x8a, 0x8e, 0xbe, 0x2c,	\
 		  0x64, 0x90, 0xb8, 0x9d)
diff --git a/drivers/firmware/efi/cper-x86.c b/drivers/firmware/efi/cper-x86.c
index 2531de49f56c..438ed9eff6d0 100644
--- a/drivers/firmware/efi/cper-x86.c
+++ b/drivers/firmware/efi/cper-x86.c
@@ -2,6 +2,7 @@ 
 // Copyright (C) 2018, Advanced Micro Devices, Inc.
 
 #include <linux/cper.h>
+#include <linux/acpi.h>
 
 /*
  * We don't need a "CPER_IA" prefix since these are all locally defined.
@@ -347,9 +348,13 @@  void cper_print_proc_ia(const char *pfx, const struct cper_sec_proc_ia *proc)
 			       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);
+		if (ctx_info->reg_ctx_type != CTX_TYPE_MSR ||
+		    arch_apei_report_x86_error(ctx_info, proc->lapic_id)) {
+			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);
 	}