diff options
| author | Andi Kleen <ak@linux.intel.com> | 2009-04-29 13:29:12 -0400 |
|---|---|---|
| committer | H. Peter Anvin <hpa@zytor.com> | 2009-05-28 12:24:14 -0400 |
| commit | 5f8c1a54cab6f449fe04d42d0661bc796fa4e73e (patch) | |
| tree | 3e08602a41c9c7bb08cc20f650e884cd94c031e8 | |
| parent | a9862e0560866eadbc59b84867492004da436516 (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.c | 37 |
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 */ | ||
| 198 | static u64 mce_rdmsrl(u32 msr) | ||
| 199 | { | ||
| 200 | u64 v; | ||
| 201 | rdmsrl(msr, v); | ||
| 202 | return v; | ||
| 203 | } | ||
| 204 | |||
| 205 | static void mce_wrmsrl(u32 msr, u64 v) | ||
| 206 | { | ||
| 207 | wrmsrl(msr, v); | ||
| 208 | } | ||
| 209 | |||
| 197 | int mce_available(struct cpuinfo_x86 *c) | 210 | int 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 | } |
