upgrade to fedora-2.6.12-1.1398.FC4 + vserver 2.0.rc7
[linux-2.6.git] / arch / ia64 / kernel / unwind.c
index 050ae05..2776a07 100644 (file)
@@ -47,8 +47,6 @@
 #include "entry.h"
 #include "unwind_i.h"
 
-#define p5             5
-
 #define UNW_LOG_CACHE_SIZE     7       /* each unw_script is ~256 bytes in size */
 #define UNW_CACHE_SIZE         (1 << UNW_LOG_CACHE_SIZE)
 
@@ -1899,7 +1897,7 @@ unw_unwind (struct unw_frame_info *info)
        num_regs = 0;
        if ((info->flags & UNW_FLAG_INTERRUPT_FRAME)) {
                info->pt = info->sp + 16;
-               if ((pr & (1UL << pNonSys)) != 0)
+               if ((pr & (1UL << PRED_NON_SYSCALL)) != 0)
                        num_regs = *info->cfm_loc & 0x7f;               /* size of frame */
                info->pfs_loc =
                        (unsigned long *) (info->pt + offsetof(struct pt_regs, ar_pfs));
@@ -1945,20 +1943,30 @@ EXPORT_SYMBOL(unw_unwind);
 int
 unw_unwind_to_user (struct unw_frame_info *info)
 {
-       unsigned long ip;
+       unsigned long ip, sp, pr = 0;
 
        while (unw_unwind(info) >= 0) {
-               if (unw_get_rp(info, &ip) < 0) {
-                       unw_get_ip(info, &ip);
-                       UNW_DPRINT(0, "unwind.%s: failed to read return pointer (ip=0x%lx)\n",
-                                  __FUNCTION__, ip);
-                       return -1;
+               unw_get_sp(info, &sp);
+               if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp)
+                   < IA64_PT_REGS_SIZE) {
+                       UNW_DPRINT(0, "unwind.%s: ran off the top of the kernel stack\n",
+                                  __FUNCTION__);
+                       break;
                }
-               if (ip < FIXADDR_USER_END)
+               if (unw_is_intr_frame(info) &&
+                   (pr & (1UL << PRED_USER_STACK)))
                        return 0;
+               if (unw_get_pr (info, &pr) < 0) {
+                       unw_get_rp(info, &ip);
+                       UNW_DPRINT(0, "unwind.%s: failed to read "
+                                  "predicate register (ip=0x%lx)\n",
+                               __FUNCTION__, ip);
+                       return -1;
+               }
        }
        unw_get_ip(info, &ip);
-       UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip);
+       UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n",
+                  __FUNCTION__, ip);
        return -1;
 }
 EXPORT_SYMBOL(unw_unwind_to_user);
@@ -2051,6 +2059,8 @@ unw_init_frame_info (struct unw_frame_info *info, struct task_struct *t, struct
        find_save_locs(info);
 }
 
+EXPORT_SYMBOL(unw_init_frame_info);
+
 void
 unw_init_from_blocked_task (struct unw_frame_info *info, struct task_struct *t)
 {
@@ -2254,7 +2264,7 @@ unw_init (void)
                if (i > 0)
                        unw.cache[i].lru_chain = (i - 1);
                unw.cache[i].coll_chain = -1;
-               unw.cache[i].lock = RW_LOCK_UNLOCKED;
+               rwlock_init(&unw.cache[i].lock);
        }
        unw.lru_head = UNW_CACHE_SIZE - 1;
        unw.lru_tail = 0;