diff options
Diffstat (limited to 'arch')
-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 | } |