]> err.no Git - linux-2.6/commitdiff
[PATCH] s390: instruction processing damage handling
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Fri, 28 Apr 2006 01:40:23 +0000 (18:40 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Fri, 28 Apr 2006 15:33:48 +0000 (08:33 -0700)
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>
drivers/s390/s390mach.c

index 3bf466603512a32f2c6a933525492eed58963f33..5ae14803091f580412d77d76109e3efa306d9332 100644 (file)
@@ -362,12 +362,19 @@ s390_revalidate_registers(struct mci *mci)
        return kill_task;
 }
 
+#define MAX_IPD_COUNT  29
+#define MAX_IPD_TIME   (5 * 60 * 100 * 1000) /* 5 minutes */
+
 /*
  * machine check handler.
  */
 void
 s390_do_machine_check(struct pt_regs *regs)
 {
+       static DEFINE_SPINLOCK(ipd_lock);
+       static unsigned long long last_ipd;
+       static int ipd_count;
+       unsigned long long tmp;
        struct mci *mci;
        struct mcck_struct *mcck;
        int umode;
@@ -404,11 +411,27 @@ s390_do_machine_check(struct pt_regs *regs)
                                s390_handle_damage("processing backup machine "
                                                   "check with damage.");
                        }
-                       if (!umode)
-                               s390_handle_damage("processing backup machine "
-                                                  "check in kernel mode.");
-                       mcck->kill_task = 1;
-                       mcck->mcck_code = *(unsigned long long *) mci;
+
+                       /*
+                        * Nullifying exigent condition, therefore we might
+                        * retry this instruction.
+                        */
+
+                       spin_lock(&ipd_lock);
+
+                       tmp = get_clock();
+
+                       if (((tmp - last_ipd) >> 12) < MAX_IPD_TIME)
+                               ipd_count++;
+                       else
+                               ipd_count = 1;
+
+                       last_ipd = tmp;
+
+                       if (ipd_count == MAX_IPD_COUNT)
+                               s390_handle_damage("too many ipd retries.");
+
+                       spin_unlock(&ipd_lock);
                }
                else {
                        /* Processing damage -> stopping machine */