Commit 24ce0e96 authored by Jan Beulich's avatar Jan Beulich Committed by Andi Kleen

[PATCH] x86-64: Tighten mce_amd driver MSR reads

while debugging an unrelated problem in Xen, I noticed odd reads from
non-existent MSRs. Having now found time to look why these happen, I
came up with below patch, which
- prevents accessing MCi_MISCj with j > 0 when the block pointer in
MCi_MISC0 is zero
- accesses only contiguous MCi_MISCj until a non-implemented one is
found
- doesn't touch unimplemented blocks in mce_threshold_interrupt at all
- gives names to two bits previously derived from MASK_VALID_HI (it
took me some time to understand the code without this)

The first three items, besides being apparently closer to the spec, should
namely help cutting down on the time mce_threshold_interrupt() takes.
Signed-off-by: default avatarAndi Kleen <ak@suse.de>
parent 9b355897
...@@ -37,6 +37,8 @@ ...@@ -37,6 +37,8 @@
#define THRESHOLD_MAX 0xFFF #define THRESHOLD_MAX 0xFFF
#define INT_TYPE_APIC 0x00020000 #define INT_TYPE_APIC 0x00020000
#define MASK_VALID_HI 0x80000000 #define MASK_VALID_HI 0x80000000
#define MASK_CNTP_HI 0x40000000
#define MASK_LOCKED_HI 0x20000000
#define MASK_LVTOFF_HI 0x00F00000 #define MASK_LVTOFF_HI 0x00F00000
#define MASK_COUNT_EN_HI 0x00080000 #define MASK_COUNT_EN_HI 0x00080000
#define MASK_INT_TYPE_HI 0x00060000 #define MASK_INT_TYPE_HI 0x00060000
...@@ -122,14 +124,17 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c) ...@@ -122,14 +124,17 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
for (block = 0; block < NR_BLOCKS; ++block) { for (block = 0; block < NR_BLOCKS; ++block) {
if (block == 0) if (block == 0)
address = MSR_IA32_MC0_MISC + bank * 4; address = MSR_IA32_MC0_MISC + bank * 4;
else if (block == 1) else if (block == 1) {
address = MCG_XBLK_ADDR address = (low & MASK_BLKPTR_LO) >> 21;
+ ((low & MASK_BLKPTR_LO) >> 21); if (!address)
break;
address += MCG_XBLK_ADDR;
}
else else
++address; ++address;
if (rdmsr_safe(address, &low, &high)) if (rdmsr_safe(address, &low, &high))
continue; break;
if (!(high & MASK_VALID_HI)) { if (!(high & MASK_VALID_HI)) {
if (block) if (block)
...@@ -138,8 +143,8 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c) ...@@ -138,8 +143,8 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
break; break;
} }
if (!(high & MASK_VALID_HI >> 1) || if (!(high & MASK_CNTP_HI) ||
(high & MASK_VALID_HI >> 2)) (high & MASK_LOCKED_HI))
continue; continue;
if (!block) if (!block)
...@@ -187,17 +192,22 @@ asmlinkage void mce_threshold_interrupt(void) ...@@ -187,17 +192,22 @@ asmlinkage void mce_threshold_interrupt(void)
/* assume first bank caused it */ /* assume first bank caused it */
for (bank = 0; bank < NR_BANKS; ++bank) { for (bank = 0; bank < NR_BANKS; ++bank) {
if (!(per_cpu(bank_map, m.cpu) & (1 << bank)))
continue;
for (block = 0; block < NR_BLOCKS; ++block) { for (block = 0; block < NR_BLOCKS; ++block) {
if (block == 0) if (block == 0)
address = MSR_IA32_MC0_MISC + bank * 4; address = MSR_IA32_MC0_MISC + bank * 4;
else if (block == 1) else if (block == 1) {
address = MCG_XBLK_ADDR address = (low & MASK_BLKPTR_LO) >> 21;
+ ((low & MASK_BLKPTR_LO) >> 21); if (!address)
break;
address += MCG_XBLK_ADDR;
}
else else
++address; ++address;
if (rdmsr_safe(address, &low, &high)) if (rdmsr_safe(address, &low, &high))
continue; break;
if (!(high & MASK_VALID_HI)) { if (!(high & MASK_VALID_HI)) {
if (block) if (block)
...@@ -206,8 +216,8 @@ asmlinkage void mce_threshold_interrupt(void) ...@@ -206,8 +216,8 @@ asmlinkage void mce_threshold_interrupt(void)
break; break;
} }
if (!(high & MASK_VALID_HI >> 1) || if (!(high & MASK_CNTP_HI) ||
(high & MASK_VALID_HI >> 2)) (high & MASK_LOCKED_HI))
continue; continue;
if (high & MASK_OVERFLOW_HI) { if (high & MASK_OVERFLOW_HI) {
...@@ -385,7 +395,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu, ...@@ -385,7 +395,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
return 0; return 0;
if (rdmsr_safe(address, &low, &high)) if (rdmsr_safe(address, &low, &high))
goto recurse; return 0;
if (!(high & MASK_VALID_HI)) { if (!(high & MASK_VALID_HI)) {
if (block) if (block)
...@@ -394,8 +404,8 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu, ...@@ -394,8 +404,8 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
return 0; return 0;
} }
if (!(high & MASK_VALID_HI >> 1) || if (!(high & MASK_CNTP_HI) ||
(high & MASK_VALID_HI >> 2)) (high & MASK_LOCKED_HI))
goto recurse; goto recurse;
b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL); b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment