aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2007-02-13 07:26:23 -0500
committerAndi Kleen <andi@basil.nowhere.org>2007-02-13 07:26:23 -0500
commit24ce0e96f2dea558762c994d054ea2f3c01fa95a (patch)
tree59a4a538e6d67d0a15751095c6b191010be04f4f
parent9b355897562fe2291248a7aec8e479c2c98cf117 (diff)
[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: Andi Kleen <ak@suse.de>
-rw-r--r--arch/x86_64/kernel/mce_amd.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/arch/x86_64/kernel/mce_amd.c b/arch/x86_64/kernel/mce_amd.c
index 93c707257637..cd8dbe57b33a 100644
--- a/arch/x86_64/kernel/mce_amd.c
+++ b/arch/x86_64/kernel/mce_amd.c
@@ -37,6 +37,8 @@
37#define THRESHOLD_MAX 0xFFF 37#define THRESHOLD_MAX 0xFFF
38#define INT_TYPE_APIC 0x00020000 38#define INT_TYPE_APIC 0x00020000
39#define MASK_VALID_HI 0x80000000 39#define MASK_VALID_HI 0x80000000
40#define MASK_CNTP_HI 0x40000000
41#define MASK_LOCKED_HI 0x20000000
40#define MASK_LVTOFF_HI 0x00F00000 42#define MASK_LVTOFF_HI 0x00F00000
41#define MASK_COUNT_EN_HI 0x00080000 43#define MASK_COUNT_EN_HI 0x00080000
42#define MASK_INT_TYPE_HI 0x00060000 44#define MASK_INT_TYPE_HI 0x00060000
@@ -122,14 +124,17 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
122 for (block = 0; block < NR_BLOCKS; ++block) { 124 for (block = 0; block < NR_BLOCKS; ++block) {
123 if (block == 0) 125 if (block == 0)
124 address = MSR_IA32_MC0_MISC + bank * 4; 126 address = MSR_IA32_MC0_MISC + bank * 4;
125 else if (block == 1) 127 else if (block == 1) {
126 address = MCG_XBLK_ADDR 128 address = (low & MASK_BLKPTR_LO) >> 21;
127 + ((low & MASK_BLKPTR_LO) >> 21); 129 if (!address)
130 break;
131 address += MCG_XBLK_ADDR;
132 }
128 else 133 else
129 ++address; 134 ++address;
130 135
131 if (rdmsr_safe(address, &low, &high)) 136 if (rdmsr_safe(address, &low, &high))
132 continue; 137 break;
133 138
134 if (!(high & MASK_VALID_HI)) { 139 if (!(high & MASK_VALID_HI)) {
135 if (block) 140 if (block)
@@ -138,8 +143,8 @@ void __cpuinit mce_amd_feature_init(struct cpuinfo_x86 *c)
138 break; 143 break;
139 } 144 }
140 145
141 if (!(high & MASK_VALID_HI >> 1) || 146 if (!(high & MASK_CNTP_HI) ||
142 (high & MASK_VALID_HI >> 2)) 147 (high & MASK_LOCKED_HI))
143 continue; 148 continue;
144 149
145 if (!block) 150 if (!block)
@@ -187,17 +192,22 @@ asmlinkage void mce_threshold_interrupt(void)
187 192
188 /* assume first bank caused it */ 193 /* assume first bank caused it */
189 for (bank = 0; bank < NR_BANKS; ++bank) { 194 for (bank = 0; bank < NR_BANKS; ++bank) {
195 if (!(per_cpu(bank_map, m.cpu) & (1 << bank)))
196 continue;
190 for (block = 0; block < NR_BLOCKS; ++block) { 197 for (block = 0; block < NR_BLOCKS; ++block) {
191 if (block == 0) 198 if (block == 0)
192 address = MSR_IA32_MC0_MISC + bank * 4; 199 address = MSR_IA32_MC0_MISC + bank * 4;
193 else if (block == 1) 200 else if (block == 1) {
194 address = MCG_XBLK_ADDR 201 address = (low & MASK_BLKPTR_LO) >> 21;
195 + ((low & MASK_BLKPTR_LO) >> 21); 202 if (!address)
203 break;
204 address += MCG_XBLK_ADDR;
205 }
196 else 206 else
197 ++address; 207 ++address;
198 208
199 if (rdmsr_safe(address, &low, &high)) 209 if (rdmsr_safe(address, &low, &high))
200 continue; 210 break;
201 211
202 if (!(high & MASK_VALID_HI)) { 212 if (!(high & MASK_VALID_HI)) {
203 if (block) 213 if (block)
@@ -206,8 +216,8 @@ asmlinkage void mce_threshold_interrupt(void)
206 break; 216 break;
207 } 217 }
208 218
209 if (!(high & MASK_VALID_HI >> 1) || 219 if (!(high & MASK_CNTP_HI) ||
210 (high & MASK_VALID_HI >> 2)) 220 (high & MASK_LOCKED_HI))
211 continue; 221 continue;
212 222
213 if (high & MASK_OVERFLOW_HI) { 223 if (high & MASK_OVERFLOW_HI) {
@@ -385,7 +395,7 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
385 return 0; 395 return 0;
386 396
387 if (rdmsr_safe(address, &low, &high)) 397 if (rdmsr_safe(address, &low, &high))
388 goto recurse; 398 return 0;
389 399
390 if (!(high & MASK_VALID_HI)) { 400 if (!(high & MASK_VALID_HI)) {
391 if (block) 401 if (block)
@@ -394,8 +404,8 @@ static __cpuinit int allocate_threshold_blocks(unsigned int cpu,
394 return 0; 404 return 0;
395 } 405 }
396 406
397 if (!(high & MASK_VALID_HI >> 1) || 407 if (!(high & MASK_CNTP_HI) ||
398 (high & MASK_VALID_HI >> 2)) 408 (high & MASK_LOCKED_HI))
399 goto recurse; 409 goto recurse;
400 410
401 b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL); 411 b = kzalloc(sizeof(struct threshold_block), GFP_KERNEL);