Skip to content

Commit f9bbb8a

Browse files
yghannambp3tk0v
authored andcommitted
x86/mce: Define mce_prep_record() helpers for common and per-CPU fields
Generally, MCA information for an error is gathered on the CPU that reported the error. In this case, CPU-specific information from the running CPU will be correct. However, this will be incorrect if the MCA information is gathered while running on a CPU that didn't report the error. One example is creating an MCA record using mce_prep_record() for errors reported from ACPI. Split mce_prep_record() so that there is a helper function to gather common, i.e. not CPU-specific, information and another helper for CPU-specific information. Leave mce_prep_record() defined as-is for the common case when running on the reporting CPU. Get MCG_CAP in the global helper even though the register is per-CPU. This value is not already cached per-CPU like other values. And it does not assist with any per-CPU decoding or handling. Signed-off-by: Yazen Ghannam <[email protected]> Signed-off-by: Borislav Petkov (AMD) <[email protected]> Reviewed-by: Nikolay Borisov <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Borislav Petkov (AMD) <[email protected]>
1 parent 5ad21a2 commit f9bbb8a

File tree

2 files changed

+25
-11
lines changed

2 files changed

+25
-11
lines changed

arch/x86/kernel/cpu/mce/core.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -117,20 +117,32 @@ static struct irq_work mce_irq_work;
117117
*/
118118
BLOCKING_NOTIFIER_HEAD(x86_mce_decoder_chain);
119119

120-
/* Do initial initialization of a struct mce */
121-
void mce_prep_record(struct mce *m)
120+
void mce_prep_record_common(struct mce *m)
122121
{
123122
memset(m, 0, sizeof(struct mce));
124-
m->cpu = m->extcpu = smp_processor_id();
123+
124+
m->cpuid = cpuid_eax(1);
125+
m->cpuvendor = boot_cpu_data.x86_vendor;
126+
m->mcgcap = __rdmsr(MSR_IA32_MCG_CAP);
125127
/* need the internal __ version to avoid deadlocks */
126-
m->time = __ktime_get_real_seconds();
127-
m->cpuvendor = boot_cpu_data.x86_vendor;
128-
m->cpuid = cpuid_eax(1);
129-
m->socketid = cpu_data(m->extcpu).topo.pkg_id;
130-
m->apicid = cpu_data(m->extcpu).topo.initial_apicid;
131-
m->mcgcap = __rdmsr(MSR_IA32_MCG_CAP);
132-
m->ppin = cpu_data(m->extcpu).ppin;
133-
m->microcode = boot_cpu_data.microcode;
128+
m->time = __ktime_get_real_seconds();
129+
}
130+
131+
void mce_prep_record_per_cpu(unsigned int cpu, struct mce *m)
132+
{
133+
m->cpu = cpu;
134+
m->extcpu = cpu;
135+
m->apicid = cpu_data(cpu).topo.initial_apicid;
136+
m->microcode = cpu_data(cpu).microcode;
137+
m->ppin = topology_ppin(cpu);
138+
m->socketid = topology_physical_package_id(cpu);
139+
}
140+
141+
/* Do initial initialization of a struct mce */
142+
void mce_prep_record(struct mce *m)
143+
{
144+
mce_prep_record_common(m);
145+
mce_prep_record_per_cpu(smp_processor_id(), m);
134146
}
135147

136148
DEFINE_PER_CPU(struct mce, injectm);

arch/x86/kernel/cpu/mce/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ enum mca_msr {
261261

262262
/* Decide whether to add MCE record to MCE event pool or filter it out. */
263263
extern bool filter_mce(struct mce *m);
264+
void mce_prep_record_common(struct mce *m);
265+
void mce_prep_record_per_cpu(unsigned int cpu, struct mce *m);
264266

265267
#ifdef CONFIG_X86_MCE_AMD
266268
extern bool amd_filter_mce(struct mce *m);

0 commit comments

Comments
 (0)