Index: /trunk/source/lisp-kernel/arm-exceptions.c
===================================================================
--- /trunk/source/lisp-kernel/arm-exceptions.c	(revision 14790)
+++ /trunk/source/lisp-kernel/arm-exceptions.c	(revision 14791)
@@ -1545,5 +1545,7 @@
   egc_rplacd,
   egc_set_hash_key_conditional,
-  egc_set_hash_key_conditional_test;
+  egc_set_hash_key_conditional_test,
+  swap_lr_lisp_frame_temp0,
+  swap_lr_lisp_frame_arg_z;
 
 
@@ -1720,6 +1722,29 @@
         xpGPR(xp,allocptr) = VOID_ALLOCPTR;
       }
+      return;
     }
     return;
+  }
+  {
+    lisp_frame *swap_frame = NULL;
+    pc base = &swap_lr_lisp_frame_temp0;
+    
+    if ((program_counter >base)             /* sic */
+        && (program_counter < (base+3))) {
+      swap_frame = (lisp_frame *)xpGPR(xp,temp0);
+    } else {
+      base = &swap_lr_lisp_frame_arg_z;
+      if ((program_counter > base) && (program_counter < (base+3))) { 
+        swap_frame = (lisp_frame *)xpGPR(xp,arg_z);
+      }
+    }
+    if (swap_frame) {
+      if (program_counter == (base+1)) {
+        swap_frame->savelr = xpGPR(xp,Rlr);
+      }
+      xpGPR(xp,Rlr) = xpGPR(xp,imm0);
+      xpPC(xp) = base+3;
+      return;
+    }
   }
 }
Index: /trunk/source/lisp-kernel/arm-spentry.s
===================================================================
--- /trunk/source/lisp-kernel/arm-spentry.s	(revision 14790)
+++ /trunk/source/lisp-kernel/arm-spentry.s	(revision 14791)
@@ -4010,6 +4010,14 @@
         /* protect.  (Clever, eh ?)  */
         __(add sp,sp,#catch_frame.size)
-        /* swp is deprecated on ARMv6+.  It's not useful as a basis
-           for synchronization, but that's not why we're using it here. */
+        /* We used to use a swp instruction to exchange the lr with
+        the lisp_frame.savelr field of the lisp frame that temp0 addresses.
+        Multicore ARMv7 machines include the ability to disable the swp
+        instruction, and some Linux kernels do so and emulate the instruction.
+        There seems to be evidence that they sometimes do so incorrectly,
+        so we stopped using swp.
+        pc_luser_xp() needs to do some extra work if the thread is interrupted
+        in the midst of the three-instruction sequence at
+	swap_lr_lisp_frame_temp0.
+        */
         __(mov imm1,#0)
         __(mov temp0,sp)
@@ -4017,6 +4025,12 @@
         __(orr imm0,imm0,#subtag_simple_vector)
         __(stmdb sp!,{imm0,imm1,arg_z,temp2})
-        __(add imm0,temp0,#lisp_frame.savelr)
-        __(swp lr,lr,[imm0])
+        .globl C(swap_lr_lisp_frame_temp0)
+        .globl C(swap_lr_lisp_frame_temp0_end)
+        /* This instruction sequence needs support from pc_luser_xp() */
+C(swap_lr_lisp_frame_temp0):            
+        __(ldr imm0,[temp0,#lisp_frame.savelr])
+        __(str lr,[temp0,#lisp_frame.savelr])
+        __(mov lr,imm0)
+C(swap_lr_lisp_frame_temp0_end):            
         __(ldr nfn,[temp0,#lisp_frame.savefn])
         __(str fn,[temp0,#lisp_frame.savefn])
@@ -4105,6 +4119,12 @@
         __(bge local_label(nthrownv_tpushloop))
         __(mov imm1,#0)
-        __(add imm0,arg_z,#lisp_frame.savelr)
-        __(swp lr,lr,[imm0])
+        /* This instruction sequence needs support from pc_luser_xp() */
+        .globl C(swap_lr_lisp_frame_arg_z)
+        .globl C(swap_lr_lisp_frame_arg_z_end)
+C(swap_lr_lisp_frame_arg_z):                   
+        __(ldr imm0,[arg_z,#lisp_frame.savelr])
+        __(str lr,[arg_z,#lisp_frame.savelr])
+        __(mov lr,imm0)
+C(swap_lr_lisp_frame_arg_z_end):                   
         __(ldr nfn,[arg_z,#lisp_frame.savefn])
         __(str fn,[arg_z,#lisp_frame.savefn])
