aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2009-04-29 13:29:12 -0400
committerH. Peter Anvin <hpa@zytor.com>2009-05-28 12:24:14 -0400
commit5f8c1a54cab6f449fe04d42d0661bc796fa4e73e (patch)
tree3e08602a41c9c7bb08cc20f650e884cd94c031e8
parenta9862e0560866eadbc59b84867492004da436516 (diff)
x86, mce: add MSR read wrappers for easier error injection
This will be used by future patches to allow machine check error injection. Right now it's a nop, except for adding some wrappers around the MSR reads. This is early in the sequence to avoid too many conflicts. Signed-off-by: Andi Kleen <ak@linux.intel.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com> Signed-off-by: Hidetoshi Seto <seto.hidetoshi@jp.fujitsu.com> Signed-off-by: H. Peter Anvin <hpa@zytor.com>
-rw-r--r--arch/x86/kernel/cpu/mcheck/mce.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index e193de44ef19..e755c95674dc 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -194,6 +194,19 @@ static void mce_panic(char *msg, struct mce *backup, u64 start)
194 panic(msg); 194 panic(msg);
195} 195}
196 196
197/* MSR access wrappers used for error injection */
198static u64 mce_rdmsrl(u32 msr)
199{
200 u64 v;
201 rdmsrl(msr, v);
202 return v;
203}
204
205static void mce_wrmsrl(u32 msr, u64 v)
206{
207 wrmsrl(msr, v);
208}
209
197int mce_available(struct cpuinfo_x86 *c) 210int mce_available(struct cpuinfo_x86 *c)
198{ 211{
199 if (mce_disabled) 212 if (mce_disabled)
@@ -213,7 +226,7 @@ static inline void mce_get_rip(struct mce *m, struct pt_regs *regs)
213 if (rip_msr) { 226 if (rip_msr) {
214 /* Assume the RIP in the MSR is exact. Is this true? */ 227 /* Assume the RIP in the MSR is exact. Is this true? */
215 m->mcgstatus |= MCG_STATUS_EIPV; 228 m->mcgstatus |= MCG_STATUS_EIPV;
216 rdmsrl(rip_msr, m->ip); 229 m->ip = mce_rdmsrl(rip_msr);
217 m->cs = 0; 230 m->cs = 0;
218 } 231 }
219} 232}
@@ -231,7 +244,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
231 244
232 mce_setup(&m); 245 mce_setup(&m);
233 246
234 rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus); 247 m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
235 for (i = 0; i < banks; i++) { 248 for (i = 0; i < banks; i++) {
236 if (!bank[i] || !test_bit(i, *b)) 249 if (!bank[i] || !test_bit(i, *b))
237 continue; 250 continue;
@@ -242,7 +255,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
242 m.tsc = 0; 255 m.tsc = 0;
243 256
244 barrier(); 257 barrier();
245 rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status); 258 m.status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4);
246 if (!(m.status & MCI_STATUS_VAL)) 259 if (!(m.status & MCI_STATUS_VAL))
247 continue; 260 continue;
248 261
@@ -257,9 +270,9 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
257 continue; 270 continue;
258 271
259 if (m.status & MCI_STATUS_MISCV) 272 if (m.status & MCI_STATUS_MISCV)
260 rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc); 273 m.misc = mce_rdmsrl(MSR_IA32_MC0_MISC + i*4);
261 if (m.status & MCI_STATUS_ADDRV) 274 if (m.status & MCI_STATUS_ADDRV)
262 rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr); 275 m.addr = mce_rdmsrl(MSR_IA32_MC0_ADDR + i*4);
263 276
264 if (!(flags & MCP_TIMESTAMP)) 277 if (!(flags & MCP_TIMESTAMP))
265 m.tsc = 0; 278 m.tsc = 0;
@@ -275,7 +288,7 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
275 /* 288 /*
276 * Clear state for this bank. 289 * Clear state for this bank.
277 */ 290 */
278 wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); 291 mce_wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
279 } 292 }
280 293
281 /* 294 /*
@@ -320,7 +333,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
320 333
321 mce_setup(&m); 334 mce_setup(&m);
322 335
323 rdmsrl(MSR_IA32_MCG_STATUS, m.mcgstatus); 336 m.mcgstatus = mce_rdmsrl(MSR_IA32_MCG_STATUS);
324 337
325 /* if the restart IP is not valid, we're done for */ 338 /* if the restart IP is not valid, we're done for */
326 if (!(m.mcgstatus & MCG_STATUS_RIPV)) 339 if (!(m.mcgstatus & MCG_STATUS_RIPV))
@@ -338,7 +351,7 @@ void do_machine_check(struct pt_regs *regs, long error_code)
338 m.addr = 0; 351 m.addr = 0;
339 m.bank = i; 352 m.bank = i;
340 353
341 rdmsrl(MSR_IA32_MC0_STATUS + i*4, m.status); 354 m.status = mce_rdmsrl(MSR_IA32_MC0_STATUS + i*4);
342 if ((m.status & MCI_STATUS_VAL) == 0) 355 if ((m.status & MCI_STATUS_VAL) == 0)
343 continue; 356 continue;
344 357
@@ -378,9 +391,9 @@ void do_machine_check(struct pt_regs *regs, long error_code)
378 } 391 }
379 392
380 if (m.status & MCI_STATUS_MISCV) 393 if (m.status & MCI_STATUS_MISCV)
381 rdmsrl(MSR_IA32_MC0_MISC + i*4, m.misc); 394 m.misc = mce_rdmsrl(MSR_IA32_MC0_MISC + i*4);
382 if (m.status & MCI_STATUS_ADDRV) 395 if (m.status & MCI_STATUS_ADDRV)
383 rdmsrl(MSR_IA32_MC0_ADDR + i*4, m.addr); 396 m.addr = mce_rdmsrl(MSR_IA32_MC0_ADDR + i*4);
384 397
385 mce_get_rip(&m, regs); 398 mce_get_rip(&m, regs);
386 mce_log(&m); 399 mce_log(&m);
@@ -449,9 +462,9 @@ void do_machine_check(struct pt_regs *regs, long error_code)
449 /* the last thing we do is clear state */ 462 /* the last thing we do is clear state */
450 for (i = 0; i < banks; i++) { 463 for (i = 0; i < banks; i++) {
451 if (test_bit(i, toclear)) 464 if (test_bit(i, toclear))
452 wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0); 465 mce_wrmsrl(MSR_IA32_MC0_STATUS+4*i, 0);
453 } 466 }
454 wrmsrl(MSR_IA32_MCG_STATUS, 0); 467 mce_wrmsrl(MSR_IA32_MCG_STATUS, 0);
455 out2: 468 out2:
456 atomic_dec(&mce_entry); 469 atomic_dec(&mce_entry);
457} 470}