aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2018-06-04 23:26:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2018-06-04 23:26:07 -0400
commit0ef283d4c7808cb264f904de5e29a0b661747fc4 (patch)
tree2bab8ce30de851b87af4d4877fc46c8d7df9e6b8
parentdb020be9f7a0eb667761f0b762c1aadef2d7bd24 (diff)
parentfbf96cf904dc154a28338fe68f72902e9af57afc (diff)
Merge branch 'ras-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 RAS updates from Thomas Gleixner: - Fix a stack out of bounds write in the MCE error injection code. - Avoid IPIs during CPU hotplug to read the MCx_MISC block address from a remote CPU. That's fragile and pointless because the block addresses are the same on all CPUs. So they can be read once and local. - Add support for MCE broadcasting on newer VIA Centaur CPUs. * 'ras-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/MCE/AMD: Read MCx_MISC block addresses on any CPU x86/MCE: Fix stack out-of-bounds write in mce-inject.c: Flags_read() x86/MCE: Enable MCE broadcasting on new Centaur CPUs
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce-inject.c2
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c18
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce_amd.c15
3 files changed, 26 insertions, 9 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce-inject.c b/arch/x86/kernel/cpu/mcheck/mce-inject.c
index 475cb4f5f14f..c805a06e14c3 100644
--- a/arch/x86/kernel/cpu/mcheck/mce-inject.c
+++ b/arch/x86/kernel/cpu/mcheck/mce-inject.c
@@ -48,7 +48,7 @@ static struct dentry *dfs_inj;
48 48
49static u8 n_banks; 49static u8 n_banks;
50 50
51#define MAX_FLAG_OPT_SIZE 3 51#define MAX_FLAG_OPT_SIZE 4
52#define NBCFG 0x44 52#define NBCFG 0x44
53 53
54enum injection_type { 54enum injection_type {
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index 42cf2880d0ed..cd76380af79f 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -1727,6 +1727,21 @@ static void __mcheck_cpu_init_early(struct cpuinfo_x86 *c)
1727 } 1727 }
1728} 1728}
1729 1729
1730static void mce_centaur_feature_init(struct cpuinfo_x86 *c)
1731{
1732 struct mca_config *cfg = &mca_cfg;
1733
1734 /*
1735 * All newer Centaur CPUs support MCE broadcasting. Enable
1736 * synchronization with a one second timeout.
1737 */
1738 if ((c->x86 == 6 && c->x86_model == 0xf && c->x86_stepping >= 0xe) ||
1739 c->x86 > 6) {
1740 if (cfg->monarch_timeout < 0)
1741 cfg->monarch_timeout = USEC_PER_SEC;
1742 }
1743}
1744
1730static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c) 1745static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
1731{ 1746{
1732 switch (c->x86_vendor) { 1747 switch (c->x86_vendor) {
@@ -1739,6 +1754,9 @@ static void __mcheck_cpu_init_vendor(struct cpuinfo_x86 *c)
1739 mce_amd_feature_init(c); 1754 mce_amd_feature_init(c);
1740 break; 1755 break;
1741 } 1756 }
1757 case X86_VENDOR_CENTAUR:
1758 mce_centaur_feature_init(c);
1759 break;
1742 1760
1743 default: 1761 default:
1744 break; 1762 break;
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