aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/s390
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2006-04-27 21:40:23 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-04-28 11:33:48 -0400
commitb73d40c6178f2c8b2d574db566b47f36e3d12072 (patch)
tree5f0f10ee010f06d359dbbf33dd2160f34d770ea2 /drivers/s390
parent9b5dec1aa08b77c4217cd5fcaf1e4e177f659b2e (diff)
[PATCH] s390: instruction processing damage handling
In case of an instruction processing damage (IPD) machine check in kernel mode the resulting action is always to stop the kernel. This is not necessarily the best solution since a retry of the failing instruction might succeed. Add logic to retry the instruction if no more than 30 instruction processing damage checks occured in the last 5 minutes. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'drivers/s390')
-rw-r--r--drivers/s390/s390mach.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/drivers/s390/s390mach.c b/drivers/s390/s390mach.c
index 3bf466603512..5ae14803091f 100644
--- a/drivers/s390/s390mach.c
+++ b/drivers/s390/s390mach.c
@@ -362,12 +362,19 @@ s390_revalidate_registers(struct mci *mci)
362 return kill_task; 362 return kill_task;
363} 363}
364 364
365#define MAX_IPD_COUNT 29
366#define MAX_IPD_TIME (5 * 60 * 100 * 1000) /* 5 minutes */
367
365/* 368/*
366 * machine check handler. 369 * machine check handler.
367 */ 370 */
368void 371void
369s390_do_machine_check(struct pt_regs *regs) 372s390_do_machine_check(struct pt_regs *regs)
370{ 373{
374 static DEFINE_SPINLOCK(ipd_lock);
375 static unsigned long long last_ipd;
376 static int ipd_count;
377 unsigned long long tmp;
371 struct mci *mci; 378 struct mci *mci;
372 struct mcck_struct *mcck; 379 struct mcck_struct *mcck;
373 int umode; 380 int umode;
@@ -404,11 +411,27 @@ s390_do_machine_check(struct pt_regs *regs)
404 s390_handle_damage("processing backup machine " 411 s390_handle_damage("processing backup machine "
405 "check with damage."); 412 "check with damage.");
406 } 413 }
407 if (!umode) 414
408 s390_handle_damage("processing backup machine " 415 /*
409 "check in kernel mode."); 416 * Nullifying exigent condition, therefore we might
410 mcck->kill_task = 1; 417 * retry this instruction.
411 mcck->mcck_code = *(unsigned long long *) mci; 418 */
419
420 spin_lock(&ipd_lock);
421
422 tmp = get_clock();
423
424 if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME)
425 ipd_count++;
426 else
427 ipd_count = 1;
428
429 last_ipd = tmp;
430
431 if (ipd_count == MAX_IPD_COUNT)
432 s390_handle_damage("too many ipd retries.");
433
434 spin_unlock(&ipd_lock);
412 } 435 }
413 else { 436 else {
414 /* Processing damage -> stopping machine */ 437 /* Processing damage -> stopping machine */