aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBorislav Petkov <bp@suse.de>2018-05-17 12:32:33 -0400
committerThomas Gleixner <tglx@linutronix.de>2018-05-19 09:21:46 -0400
commitfbf96cf904dc154a28338fe68f72902e9af57afc (patch)
tree882a87cc70d8b4c4261c4bce51047efee78a2714
parent95b5c0a592c712496dce6c1ed772d5f9026b5ed3 (diff)
x86/MCE/AMD: Read MCx_MISC block addresses on any CPU
We used rdmsr_safe_on_cpu() to make sure we're reading the proper CPU's MISC block addresses. However, that caused trouble with CPU hotplug due to the _on_cpu() helper issuing an IPI while IRQs are disabled. But we don't have to do that: the block addresses are the same on any CPU so we can read them on any CPU. (What practically happens is, we read them on the BSP and cache them, and for later reads, we service them from the cache). Suggested-by: Yazen Ghannam <Yazen.Ghannam@amd.com> Signed-off-by: Borislav Petkov <bp@suse.de> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c15
1 files 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 c8e038800591..f591b01930db 100644
--- a/arch/x86/kernel/cpu/mcheck/mce_amd.c
+++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c
@@ -436,8 +436,7 @@ static void deferred_error_interrupt_enable(struct cpuinfo_x86 *c)
436 wrmsr(MSR_CU_DEF_ERR, low, high); 436 wrmsr(MSR_CU_DEF_ERR, low, high);
437} 437}
438 438
439static u32 smca_get_block_address(unsigned int cpu, unsigned int bank, 439static u32 smca_get_block_address(unsigned int bank, unsigned int block)
440 unsigned int block)
441{ 440{
442 u32 low, high; 441 u32 low, high;
443 u32 addr = 0; 442 u32 addr = 0;
@@ -456,13 +455,13 @@ static u32 smca_get_block_address(unsigned int cpu, unsigned int bank,
456 * For SMCA enabled processors, BLKPTR field of the first MISC register 455 * For SMCA enabled processors, BLKPTR field of the first MISC register
457 * (MCx_MISC0) indicates presence of additional MISC regs set (MISC1-4). 456 * (MCx_MISC0) indicates presence of additional MISC regs set (MISC1-4).
458 */ 457 */
459 if (rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_CONFIG(bank), &low, &high)) 458 if (rdmsr_safe(MSR_AMD64_SMCA_MCx_CONFIG(bank), &low, &high))
460 goto out; 459 goto out;
461 460
462 if (!(low & MCI_CONFIG_MCAX)) 461 if (!(low & MCI_CONFIG_MCAX))
463 goto out; 462 goto out;
464 463
465 if (!rdmsr_safe_on_cpu(cpu, MSR_AMD64_SMCA_MCx_MISC(bank), &low, &high) && 464 if (!rdmsr_safe(MSR_AMD64_SMCA_MCx_MISC(bank), &low, &high) &&
466 (low & MASK_BLKPTR_LO)) 465 (low & MASK_BLKPTR_LO))
467 addr = MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1); 466 addr = MSR_AMD64_SMCA_MCx_MISCy(bank, block - 1);
468 467
@@ -471,7 +470,7 @@ out:
471 return addr; 470 return addr;
472} 471}
473 472
474static u32 get_block_address(unsigned int cpu, u32 current_addr, u32 low, u32 high, 473static u32 get_block_address(u32 current_addr, u32 low, u32 high,
475 unsigned int bank, unsigned int block) 474 unsigned int bank, unsigned int block)
476{ 475{
477 u32 addr = 0, offset = 0; 476 u32 addr = 0, offset = 0;
@@ -480,7 +479,7 @@ static u32 get_block_address(unsigned int cpu, u32 current_addr, u32 low, u32 hi
480 return addr; 479 return addr;
481 480
482 if (mce_flags.smca) 481 if (mce_flags.smca)
483 return smca_get_block_address(cpu, bank, block); 482 return smca_get_block_address(bank, block);
484 483
485 /* Fall back to method we used for older processors: */ 484 /* Fall back to method we used for older processors: */
486 switch (block) { 485 switch (block) {
@@ -558,7 +557,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c)
558 smca_configure(bank, cpu); 557 smca_configure(bank, cpu);
559 558
560 for (block = 0; block < NR_BLOCKS; ++block) { 559 for (block = 0; block < NR_BLOCKS; ++block) {
561 address = get_block_address(cpu, address, low, high, bank, block); 560 address = get_block_address(address, low, high, bank, block);
562 if (!address) 561 if (!address)
563 break; 562 break;
564 563
@@ -1175,7 +1174,7 @@ static int allocate_threshold_blocks(unsigned int cpu, unsigned int bank,
1175 if (err) 1174 if (err)
1176 goto out_free; 1175 goto out_free;
1177recurse: 1176recurse:
1178 address = get_block_address(cpu, address, low, high, bank, ++block); 1177 address = get_block_address(address, low, high, bank, ++block);
1179 if (!address) 1178 if (!address)
1180 return 0; 1179 return 0;
1181 1180