struct unwind_ctrl_block {
        unsigned long vrs[16];          /* virtual register set */
        const unsigned long *insn;      /* pointer to the current instructions word */
+       unsigned long sp_low;           /* lowest value of sp allowed */
        unsigned long sp_high;          /* highest value of sp allowed */
        /*
         * 1 : check for stack overflow for each register pop.
                mask >>= 1;
                reg++;
        }
-       if (!load_sp)
+       if (!load_sp) {
                ctrl->vrs[SP] = (unsigned long)vsp;
+       } else {
+               ctrl->sp_low = ctrl->vrs[SP];
+               ctrl->sp_high = ALIGN(ctrl->sp_low, THREAD_SIZE);
+       }
 
        return URC_OK;
 }
 
        if ((insn & 0xc0) == 0x00)
                ctrl->vrs[SP] += ((insn & 0x3f) << 2) + 4;
-       else if ((insn & 0xc0) == 0x40)
+       else if ((insn & 0xc0) == 0x40) {
                ctrl->vrs[SP] -= ((insn & 0x3f) << 2) + 4;
-       else if ((insn & 0xf0) == 0x80) {
+               ctrl->sp_low = ctrl->vrs[SP];
+       } else if ((insn & 0xf0) == 0x80) {
                unsigned long mask;
 
                insn = (insn << 8) | unwind_get_byte(ctrl);
                if (ret)
                        goto error;
        } else if ((insn & 0xf0) == 0x90 &&
-                  (insn & 0x0d) != 0x0d)
+                  (insn & 0x0d) != 0x0d) {
                ctrl->vrs[SP] = ctrl->vrs[insn & 0x0f];
-       else if ((insn & 0xf0) == 0xa0) {
+               ctrl->sp_low = ctrl->vrs[SP];
+               ctrl->sp_high = ALIGN(ctrl->sp_low, THREAD_SIZE);
+       } else if ((insn & 0xf0) == 0xa0) {
                ret = unwind_exec_pop_r4_to_rN(ctrl, insn);
                if (ret)
                        goto error;
  */
 int unwind_frame(struct stackframe *frame)
 {
-       unsigned long low;
        const struct unwind_idx *idx;
        struct unwind_ctrl_block ctrl;
 
        /* store the highest address on the stack to avoid crossing it*/
-       low = frame->sp;
-       ctrl.sp_high = ALIGN(low, THREAD_SIZE);
+       ctrl.sp_low = frame->sp;
+       ctrl.sp_high = ALIGN(ctrl.sp_low, THREAD_SIZE);
 
        pr_debug("%s(pc = %08lx lr = %08lx sp = %08lx)\n", __func__,
                 frame->pc, frame->lr, frame->sp);
                urc = unwind_exec_insn(&ctrl);
                if (urc < 0)
                        return urc;
-               if (ctrl.vrs[SP] < low || ctrl.vrs[SP] >= ctrl.sp_high)
+               if (ctrl.vrs[SP] < ctrl.sp_low || ctrl.vrs[SP] > ctrl.sp_high)
                        return -URC_FAILURE;
        }