aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64/kernel
diff options
context:
space:
mode:
authorKeith Owens <kaos@sgi.com>2005-04-25 14:45:26 -0400
committerTony Luck <tony.luck@intel.com>2005-04-25 14:45:26 -0400
commite8d1cb2f280aa53e1c75c8b5fcbf80b3481d0caa (patch)
tree832d5f4beabfc1c075dd54eebe343ad10c611c73 /arch/ia64/kernel
parent8297511530b0d2a281c796e738683951a59a020c (diff)
[IA64] Tighten up unw_unwind_to_user check
Detect user space by the unwind frame with predicate PRED_USER_STACK set, instead of a user space IP. Tighten up the last ditch check for running off the top of the kernel stack. Based on a suggestion by David Mosberger, reworked to fit the current tree. This survives my stress test which used to break 2.6.9 kernels. Unlike 2.6.11, the stress test now unwinds to the correct point, so gdb can get the user space registers. Signed-off-by: Keith Owens <kaos@sgi.com> Signed-off-by: Tony Luck <tony.luck@intel.com>
Diffstat (limited to 'arch/ia64/kernel')
-rw-r--r--arch/ia64/kernel/unwind.c27
1 files changed, 17 insertions, 10 deletions
diff --git a/arch/ia64/kernel/unwind.c b/arch/ia64/kernel/unwind.c
index d494ff647cac..2776a074c6f1 100644
--- a/arch/ia64/kernel/unwind.c
+++ b/arch/ia64/kernel/unwind.c
@@ -1943,23 +1943,30 @@ EXPORT_SYMBOL(unw_unwind);
1943int 1943int
1944unw_unwind_to_user (struct unw_frame_info *info) 1944unw_unwind_to_user (struct unw_frame_info *info)
1945{ 1945{
1946 unsigned long ip, sp; 1946 unsigned long ip, sp, pr = 0;
1947 1947
1948 while (unw_unwind(info) >= 0) { 1948 while (unw_unwind(info) >= 0) {
1949 if (unw_get_rp(info, &ip) < 0) {
1950 unw_get_ip(info, &ip);
1951 UNW_DPRINT(0, "unwind.%s: failed to read return pointer (ip=0x%lx)\n",
1952 __FUNCTION__, ip);
1953 return -1;
1954 }
1955 unw_get_sp(info, &sp); 1949 unw_get_sp(info, &sp);
1956 if (sp >= (unsigned long)info->task + IA64_STK_OFFSET) 1950 if ((long)((unsigned long)info->task + IA64_STK_OFFSET - sp)
1951 < IA64_PT_REGS_SIZE) {
1952 UNW_DPRINT(0, "unwind.%s: ran off the top of the kernel stack\n",
1953 __FUNCTION__);
1957 break; 1954 break;
1958 if (ip < FIXADDR_USER_END) 1955 }
1956 if (unw_is_intr_frame(info) &&
1957 (pr & (1UL << PRED_USER_STACK)))
1959 return 0; 1958 return 0;
1959 if (unw_get_pr (info, &pr) < 0) {
1960 unw_get_rp(info, &ip);
1961 UNW_DPRINT(0, "unwind.%s: failed to read "
1962 "predicate register (ip=0x%lx)\n",
1963 __FUNCTION__, ip);
1964 return -1;
1965 }
1960 } 1966 }
1961 unw_get_ip(info, &ip); 1967 unw_get_ip(info, &ip);
1962 UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n", __FUNCTION__, ip); 1968 UNW_DPRINT(0, "unwind.%s: failed to unwind to user-level (ip=0x%lx)\n",
1969 __FUNCTION__, ip);
1963 return -1; 1970 return -1;
1964} 1971}
1965EXPORT_SYMBOL(unw_unwind_to_user); 1972EXPORT_SYMBOL(unw_unwind_to_user);