aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/parisc/include/asm/elf.h9
-rw-r--r--arch/parisc/include/asm/linkage.h9
-rw-r--r--arch/parisc/include/asm/processor.h6
-rw-r--r--arch/parisc/include/asm/traps.h4
-rw-r--r--arch/parisc/include/asm/unwind.h6
-rw-r--r--arch/parisc/kernel/entry.S79
-rw-r--r--arch/parisc/kernel/processor.c2
-rw-r--r--arch/parisc/kernel/stacktrace.c15
-rw-r--r--arch/parisc/kernel/sys_parisc.c5
-rw-r--r--arch/parisc/kernel/syscall.S35
-rw-r--r--arch/parisc/kernel/traps.c37
-rw-r--r--arch/parisc/kernel/unwind.c43
12 files changed, 113 insertions, 137 deletions
diff --git a/arch/parisc/include/asm/elf.h b/arch/parisc/include/asm/elf.h
index f019d3ec0c1c..d00973aab7f1 100644
--- a/arch/parisc/include/asm/elf.h
+++ b/arch/parisc/include/asm/elf.h
@@ -235,6 +235,7 @@ typedef unsigned long elf_greg_t;
235#define SET_PERSONALITY(ex) \ 235#define SET_PERSONALITY(ex) \
236({ \ 236({ \
237 set_personality((current->personality & ~PER_MASK) | PER_LINUX); \ 237 set_personality((current->personality & ~PER_MASK) | PER_LINUX); \
238 clear_thread_flag(TIF_32BIT); \
238 current->thread.map_base = DEFAULT_MAP_BASE; \ 239 current->thread.map_base = DEFAULT_MAP_BASE; \
239 current->thread.task_size = DEFAULT_TASK_SIZE; \ 240 current->thread.task_size = DEFAULT_TASK_SIZE; \
240 }) 241 })
@@ -243,9 +244,11 @@ typedef unsigned long elf_greg_t;
243 244
244#define COMPAT_SET_PERSONALITY(ex) \ 245#define COMPAT_SET_PERSONALITY(ex) \
245({ \ 246({ \
246 set_thread_flag(TIF_32BIT); \ 247 if ((ex).e_ident[EI_CLASS] == ELFCLASS32) { \
247 current->thread.map_base = DEFAULT_MAP_BASE32; \ 248 set_thread_flag(TIF_32BIT); \
248 current->thread.task_size = DEFAULT_TASK_SIZE32; \ 249 current->thread.map_base = DEFAULT_MAP_BASE32; \
250 current->thread.task_size = DEFAULT_TASK_SIZE32; \
251 } else clear_thread_flag(TIF_32BIT); \
249 }) 252 })
250 253
251/* 254/*
diff --git a/arch/parisc/include/asm/linkage.h b/arch/parisc/include/asm/linkage.h
index 49f6f3d772cc..cd6fe4febead 100644
--- a/arch/parisc/include/asm/linkage.h
+++ b/arch/parisc/include/asm/linkage.h
@@ -22,15 +22,6 @@
22name: ASM_NL\ 22name: ASM_NL\
23 .export name 23 .export name
24 24
25#ifdef CONFIG_64BIT
26#define ENDPROC(name) \
27 END(name)
28#else
29#define ENDPROC(name) \
30 .type name, @function !\
31 END(name)
32#endif
33
34#define ENTRY_CFI(name, ...) \ 25#define ENTRY_CFI(name, ...) \
35 ENTRY(name) ASM_NL\ 26 ENTRY(name) ASM_NL\
36 .proc ASM_NL\ 27 .proc ASM_NL\
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h
index 2dbe5580a1a4..2bd5e695bdad 100644
--- a/arch/parisc/include/asm/processor.h
+++ b/arch/parisc/include/asm/processor.h
@@ -256,11 +256,7 @@ on downward growing arches, it looks like this:
256 * it in here from the current->personality 256 * it in here from the current->personality
257 */ 257 */
258 258
259#ifdef CONFIG_64BIT 259#define USER_WIDE_MODE (!is_32bit_task())
260#define USER_WIDE_MODE (!test_thread_flag(TIF_32BIT))
261#else
262#define USER_WIDE_MODE 0
263#endif
264 260
265#define start_thread(regs, new_pc, new_sp) do { \ 261#define start_thread(regs, new_pc, new_sp) do { \
266 elf_addr_t *sp = (elf_addr_t *)new_sp; \ 262 elf_addr_t *sp = (elf_addr_t *)new_sp; \
diff --git a/arch/parisc/include/asm/traps.h b/arch/parisc/include/asm/traps.h
index e00013248907..8ecc1f0c0483 100644
--- a/arch/parisc/include/asm/traps.h
+++ b/arch/parisc/include/asm/traps.h
@@ -2,7 +2,9 @@
2#ifndef __ASM_TRAPS_H 2#ifndef __ASM_TRAPS_H
3#define __ASM_TRAPS_H 3#define __ASM_TRAPS_H
4 4
5#ifdef __KERNEL__ 5#define PARISC_ITLB_TRAP 6 /* defined by architecture. Do not change. */
6
7#if !defined(__ASSEMBLY__)
6struct pt_regs; 8struct pt_regs;
7 9
8/* traps.c */ 10/* traps.c */
diff --git a/arch/parisc/include/asm/unwind.h b/arch/parisc/include/asm/unwind.h
index f133b7efbebb..9547e5261a8b 100644
--- a/arch/parisc/include/asm/unwind.h
+++ b/arch/parisc/include/asm/unwind.h
@@ -73,8 +73,10 @@ unwind_table_remove(struct unwind_table *table);
73 73
74void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, 74void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t,
75 struct pt_regs *regs); 75 struct pt_regs *regs);
76void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t); 76void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info,
77void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs); 77 struct task_struct *t);
78void unwind_frame_init_task(struct unwind_frame_info *info,
79 struct task_struct *task, struct pt_regs *regs);
78int unwind_once(struct unwind_frame_info *info); 80int unwind_once(struct unwind_frame_info *info);
79int unwind_to_user(struct unwind_frame_info *info); 81int unwind_to_user(struct unwind_frame_info *info);
80 82
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index c7508f5717fb..242c5ab65611 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -36,6 +36,7 @@
36#include <asm/signal.h> 36#include <asm/signal.h>
37#include <asm/unistd.h> 37#include <asm/unistd.h>
38#include <asm/ldcw.h> 38#include <asm/ldcw.h>
39#include <asm/traps.h>
39#include <asm/thread_info.h> 40#include <asm/thread_info.h>
40 41
41#include <linux/linkage.h> 42#include <linux/linkage.h>
@@ -692,7 +693,7 @@ ENTRY(fault_vector_20)
692 def 3 693 def 3
693 extint 4 694 extint 4
694 def 5 695 def 5
695 itlb_20 6 696 itlb_20 PARISC_ITLB_TRAP
696 def 7 697 def 7
697 def 8 698 def 8
698 def 9 699 def 9
@@ -735,7 +736,7 @@ ENTRY(fault_vector_11)
735 def 3 736 def 3
736 extint 4 737 extint 4
737 def 5 738 def 5
738 itlb_11 6 739 itlb_11 PARISC_ITLB_TRAP
739 def 7 740 def 7
740 def 8 741 def 8
741 def 9 742 def 9
@@ -776,7 +777,7 @@ END(fault_vector_11)
776 * copy_thread moved args into task save area. 777 * copy_thread moved args into task save area.
777 */ 778 */
778 779
779ENTRY_CFI(ret_from_kernel_thread) 780ENTRY(ret_from_kernel_thread)
780 /* Call schedule_tail first though */ 781 /* Call schedule_tail first though */
781 BL schedule_tail, %r2 782 BL schedule_tail, %r2
782 nop 783 nop
@@ -791,7 +792,7 @@ ENTRY_CFI(ret_from_kernel_thread)
791 copy %r31, %r2 792 copy %r31, %r2
792 b finish_child_return 793 b finish_child_return
793 nop 794 nop
794ENDPROC_CFI(ret_from_kernel_thread) 795END(ret_from_kernel_thread)
795 796
796 797
797 /* 798 /*
@@ -815,9 +816,8 @@ ENTRY_CFI(_switch_to)
815 LDREG TASK_THREAD_INFO(%r25), %r25 816 LDREG TASK_THREAD_INFO(%r25), %r25
816 bv %r0(%r2) 817 bv %r0(%r2)
817 mtctl %r25,%cr30 818 mtctl %r25,%cr30
818ENDPROC_CFI(_switch_to)
819 819
820ENTRY_CFI(_switch_to_ret) 820ENTRY(_switch_to_ret)
821 mtctl %r0, %cr0 /* Needed for single stepping */ 821 mtctl %r0, %cr0 /* Needed for single stepping */
822 callee_rest 822 callee_rest
823 callee_rest_float 823 callee_rest_float
@@ -825,7 +825,7 @@ ENTRY_CFI(_switch_to_ret)
825 LDREG -RP_OFFSET(%r30), %r2 825 LDREG -RP_OFFSET(%r30), %r2
826 bv %r0(%r2) 826 bv %r0(%r2)
827 copy %r26, %r28 827 copy %r26, %r28
828ENDPROC_CFI(_switch_to_ret) 828ENDPROC_CFI(_switch_to)
829 829
830 /* 830 /*
831 * Common rfi return path for interruptions, kernel execve, and 831 * Common rfi return path for interruptions, kernel execve, and
@@ -886,14 +886,12 @@ ENTRY_CFI(syscall_exit_rfi)
886 STREG %r19,PT_SR5(%r16) 886 STREG %r19,PT_SR5(%r16)
887 STREG %r19,PT_SR6(%r16) 887 STREG %r19,PT_SR6(%r16)
888 STREG %r19,PT_SR7(%r16) 888 STREG %r19,PT_SR7(%r16)
889ENDPROC_CFI(syscall_exit_rfi)
890 889
891ENTRY_CFI(intr_return) 890ENTRY(intr_return)
892 /* check for reschedule */ 891 /* check for reschedule */
893 mfctl %cr30,%r1 892 mfctl %cr30,%r1
894 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */ 893 LDREG TI_FLAGS(%r1),%r19 /* sched.h: TIF_NEED_RESCHED */
895 bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */ 894 bb,<,n %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
896ENDPROC_CFI(intr_return)
897 895
898 .import do_notify_resume,code 896 .import do_notify_resume,code
899intr_check_sig: 897intr_check_sig:
@@ -1049,6 +1047,7 @@ intr_extint:
1049 1047
1050 b do_cpu_irq_mask 1048 b do_cpu_irq_mask
1051 ldo R%intr_return(%r2), %r2 /* return to intr_return, not here */ 1049 ldo R%intr_return(%r2), %r2 /* return to intr_return, not here */
1050ENDPROC_CFI(syscall_exit_rfi)
1052 1051
1053 1052
1054 /* Generic interruptions (illegal insn, unaligned, page fault, etc) */ 1053 /* Generic interruptions (illegal insn, unaligned, page fault, etc) */
@@ -1068,21 +1067,12 @@ ENTRY_CFI(intr_save) /* for os_hpmc */
1068 save_specials %r29 1067 save_specials %r29
1069 1068
1070 /* If this trap is a itlb miss, skip saving/adjusting isr/ior */ 1069 /* If this trap is a itlb miss, skip saving/adjusting isr/ior */
1071 1070 cmpib,COND(=),n PARISC_ITLB_TRAP,%r26,skip_save_ior
1072 /*
1073 * FIXME: 1) Use a #define for the hardwired "6" below (and in
1074 * traps.c.
1075 * 2) Once we start executing code above 4 Gb, we need
1076 * to adjust iasq/iaoq here in the same way we
1077 * adjust isr/ior below.
1078 */
1079
1080 cmpib,COND(=),n 6,%r26,skip_save_ior
1081 1071
1082 1072
1083 mfctl %cr20, %r16 /* isr */ 1073 mfctl %isr, %r16
1084 nop /* serialize mfctl on PA 2.0 to avoid 4 cycle penalty */ 1074 nop /* serialize mfctl on PA 2.0 to avoid 4 cycle penalty */
1085 mfctl %cr21, %r17 /* ior */ 1075 mfctl %ior, %r17
1086 1076
1087 1077
1088#ifdef CONFIG_64BIT 1078#ifdef CONFIG_64BIT
@@ -1094,22 +1084,34 @@ ENTRY_CFI(intr_save) /* for os_hpmc */
1094 extrd,u,*<> %r8,PSW_W_BIT,1,%r0 1084 extrd,u,*<> %r8,PSW_W_BIT,1,%r0
1095 depdi 0,1,2,%r17 1085 depdi 0,1,2,%r17
1096 1086
1097 /* 1087 /* adjust isr/ior: get high bits from isr and deposit in ior */
1098 * FIXME: This code has hardwired assumptions about the split 1088 space_adjust %r16,%r17,%r1
1099 * between space bits and offset bits. This will change
1100 * when we allow alternate page sizes.
1101 */
1102
1103 /* adjust isr/ior. */
1104 extrd,u %r16,63,SPACEID_SHIFT,%r1 /* get high bits from isr for ior */
1105 depd %r1,31,SPACEID_SHIFT,%r17 /* deposit them into ior */
1106 depdi 0,63,SPACEID_SHIFT,%r16 /* clear them from isr */
1107#endif 1089#endif
1108 STREG %r16, PT_ISR(%r29) 1090 STREG %r16, PT_ISR(%r29)
1109 STREG %r17, PT_IOR(%r29) 1091 STREG %r17, PT_IOR(%r29)
1110 1092
1093#if 0 && defined(CONFIG_64BIT)
1094 /* Revisit when we have 64-bit code above 4Gb */
1095 b,n intr_save2
1111 1096
1112skip_save_ior: 1097skip_save_ior:
1098 /* We have a itlb miss, and when executing code above 4 Gb on ILP64, we
1099 * need to adjust iasq/iaoq here in the same way we adjusted isr/ior
1100 * above.
1101 */
1102 extrd,u,* %r8,PSW_W_BIT,1,%r1
1103 cmpib,COND(=),n 1,%r1,intr_save2
1104 LDREG PT_IASQ0(%r29), %r16
1105 LDREG PT_IAOQ0(%r29), %r17
1106 /* adjust iasq/iaoq */
1107 space_adjust %r16,%r17,%r1
1108 STREG %r16, PT_IASQ0(%r29)
1109 STREG %r17, PT_IAOQ0(%r29)
1110#else
1111skip_save_ior:
1112#endif
1113
1114intr_save2:
1113 virt_map 1115 virt_map
1114 save_general %r29 1116 save_general %r29
1115 1117
@@ -1747,7 +1749,7 @@ fork_like fork
1747fork_like vfork 1749fork_like vfork
1748 1750
1749 /* Set the return value for the child */ 1751 /* Set the return value for the child */
1750ENTRY_CFI(child_return) 1752ENTRY(child_return)
1751 BL schedule_tail, %r2 1753 BL schedule_tail, %r2
1752 nop 1754 nop
1753finish_child_return: 1755finish_child_return:
@@ -1759,7 +1761,7 @@ finish_child_return:
1759 reg_restore %r1 1761 reg_restore %r1
1760 b syscall_exit 1762 b syscall_exit
1761 copy %r0,%r28 1763 copy %r0,%r28
1762ENDPROC_CFI(child_return) 1764END(child_return)
1763 1765
1764ENTRY_CFI(sys_rt_sigreturn_wrapper) 1766ENTRY_CFI(sys_rt_sigreturn_wrapper)
1765 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26 1767 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r26
@@ -1791,7 +1793,7 @@ ENTRY_CFI(sys_rt_sigreturn_wrapper)
1791 LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */ 1793 LDREG PT_GR28(%r1),%r28 /* reload original r28 for syscall_exit */
1792ENDPROC_CFI(sys_rt_sigreturn_wrapper) 1794ENDPROC_CFI(sys_rt_sigreturn_wrapper)
1793 1795
1794ENTRY_CFI(syscall_exit) 1796ENTRY(syscall_exit)
1795 /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit 1797 /* NOTE: Not all syscalls exit this way. rt_sigreturn will exit
1796 * via syscall_exit_rfi if the signal was received while the process 1798 * via syscall_exit_rfi if the signal was received while the process
1797 * was running. 1799 * was running.
@@ -1990,15 +1992,13 @@ syscall_do_resched:
1990#else 1992#else
1991 nop 1993 nop
1992#endif 1994#endif
1993ENDPROC_CFI(syscall_exit) 1995END(syscall_exit)
1994 1996
1995 1997
1996#ifdef CONFIG_FUNCTION_TRACER 1998#ifdef CONFIG_FUNCTION_TRACER
1997 1999
1998 .import ftrace_function_trampoline,code 2000 .import ftrace_function_trampoline,code
1999 .align L1_CACHE_BYTES 2001 .align L1_CACHE_BYTES
2000 .globl mcount
2001 .type mcount, @function
2002ENTRY_CFI(mcount, caller) 2002ENTRY_CFI(mcount, caller)
2003_mcount: 2003_mcount:
2004 .export _mcount,data 2004 .export _mcount,data
@@ -2027,8 +2027,6 @@ ENDPROC_CFI(mcount)
2027 2027
2028#ifdef CONFIG_FUNCTION_GRAPH_TRACER 2028#ifdef CONFIG_FUNCTION_GRAPH_TRACER
2029 .align 8 2029 .align 8
2030 .globl return_to_handler
2031 .type return_to_handler, @function
2032ENTRY_CFI(return_to_handler, caller,frame=FRAME_SIZE) 2030ENTRY_CFI(return_to_handler, caller,frame=FRAME_SIZE)
2033 .export parisc_return_to_handler,data 2031 .export parisc_return_to_handler,data
2034parisc_return_to_handler: 2032parisc_return_to_handler:
@@ -2078,6 +2076,7 @@ ENDPROC_CFI(return_to_handler)
2078/* void call_on_stack(unsigned long param1, void *func, 2076/* void call_on_stack(unsigned long param1, void *func,
2079 unsigned long new_stack) */ 2077 unsigned long new_stack) */
2080ENTRY_CFI(call_on_stack, FRAME=2*FRAME_SIZE,CALLS,SAVE_RP,SAVE_SP) 2078ENTRY_CFI(call_on_stack, FRAME=2*FRAME_SIZE,CALLS,SAVE_RP,SAVE_SP)
2079ENTRY(_call_on_stack)
2081 copy %sp, %r1 2080 copy %sp, %r1
2082 2081
2083 /* Regarding the HPPA calling conventions for function pointers, 2082 /* Regarding the HPPA calling conventions for function pointers,
diff --git a/arch/parisc/kernel/processor.c b/arch/parisc/kernel/processor.c
index 45cc65902fce..82bd0d0927ce 100644
--- a/arch/parisc/kernel/processor.c
+++ b/arch/parisc/kernel/processor.c
@@ -288,6 +288,8 @@ void __init collect_boot_cpu_data(void)
288 printk(KERN_INFO "model %s\n", 288 printk(KERN_INFO "model %s\n",
289 boot_cpu_data.pdc.sys_model_name); 289 boot_cpu_data.pdc.sys_model_name);
290 290
291 dump_stack_set_arch_desc("%s", boot_cpu_data.pdc.sys_model_name);
292
291 boot_cpu_data.hversion = boot_cpu_data.pdc.model.hversion; 293 boot_cpu_data.hversion = boot_cpu_data.pdc.model.hversion;
292 boot_cpu_data.sversion = boot_cpu_data.pdc.model.sversion; 294 boot_cpu_data.sversion = boot_cpu_data.pdc.model.sversion;
293 295
diff --git a/arch/parisc/kernel/stacktrace.c b/arch/parisc/kernel/stacktrace.c
index 2fe914c5f533..ec5835e83a7a 100644
--- a/arch/parisc/kernel/stacktrace.c
+++ b/arch/parisc/kernel/stacktrace.c
@@ -16,20 +16,7 @@ static void dump_trace(struct task_struct *task, struct stack_trace *trace)
16{ 16{
17 struct unwind_frame_info info; 17 struct unwind_frame_info info;
18 18
19 /* initialize unwind info */ 19 unwind_frame_init_task(&info, task, NULL);
20 if (task == current) {
21 unsigned long sp;
22 struct pt_regs r;
23HERE:
24 asm volatile ("copy %%r30, %0" : "=r"(sp));
25 memset(&r, 0, sizeof(struct pt_regs));
26 r.iaoq[0] = (unsigned long)&&HERE;
27 r.gr[2] = (unsigned long)__builtin_return_address(0);
28 r.gr[30] = sp;
29 unwind_frame_init(&info, task, &r);
30 } else {
31 unwind_frame_init_from_blocked_task(&info, task);
32 }
33 20
34 /* unwind stack and save entries in stack_trace struct */ 21 /* unwind stack and save entries in stack_trace struct */
35 trace->nr_entries = 0; 22 trace->nr_entries = 0;
diff --git a/arch/parisc/kernel/sys_parisc.c b/arch/parisc/kernel/sys_parisc.c
index 43b308cfdf53..376ea0d1b275 100644
--- a/arch/parisc/kernel/sys_parisc.c
+++ b/arch/parisc/kernel/sys_parisc.c
@@ -156,11 +156,6 @@ arch_get_unmapped_area_topdown(struct file *filp, const unsigned long addr0,
156 int do_color_align, last_mmap; 156 int do_color_align, last_mmap;
157 struct vm_unmapped_area_info info; 157 struct vm_unmapped_area_info info;
158 158
159#ifdef CONFIG_64BIT
160 /* This should only ever run for 32-bit processes. */
161 BUG_ON(!test_thread_flag(TIF_32BIT));
162#endif
163
164 /* requested length too big for entire address space */ 159 /* requested length too big for entire address space */
165 if (len > TASK_SIZE) 160 if (len > TASK_SIZE)
166 return -ENOMEM; 161 return -ENOMEM;
diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S
index 5f7e57fcaeef..f453997a7b8f 100644
--- a/arch/parisc/kernel/syscall.S
+++ b/arch/parisc/kernel/syscall.S
@@ -108,12 +108,8 @@ linux_gateway_entry:
108 mtsp %r0,%sr6 /* get kernel space into sr6 */ 108 mtsp %r0,%sr6 /* get kernel space into sr6 */
109 109
110#ifdef CONFIG_64BIT 110#ifdef CONFIG_64BIT
111 /* for now we can *always* set the W bit on entry to the syscall 111 /* Store W bit on entry to the syscall in case it's a wide userland
112 * since we don't support wide userland processes. We could 112 * process. */
113 * also save the current SM other than in r0 and restore it on
114 * exit from the syscall, and also use that value to know
115 * whether to do narrow or wide syscalls. -PB
116 */
117 ssm PSW_SM_W, %r1 113 ssm PSW_SM_W, %r1
118 extrd,u %r1,PSW_W_BIT,1,%r1 114 extrd,u %r1,PSW_W_BIT,1,%r1
119 /* sp must be aligned on 4, so deposit the W bit setting into 115 /* sp must be aligned on 4, so deposit the W bit setting into
@@ -227,8 +223,7 @@ linux_gateway_entry:
227 or,= %r2,%r2,%r2 223 or,= %r2,%r2,%r2
228 ldo R%sys_call_table64(%r1), %r19 224 ldo R%sys_call_table64(%r1), %r19
229#else 225#else
230 ldil L%sys_call_table, %r1 226 load32 sys_call_table, %r19
231 ldo R%sys_call_table(%r1), %r19
232#endif 227#endif
233 comiclr,>> __NR_Linux_syscalls, %r20, %r0 228 comiclr,>> __NR_Linux_syscalls, %r20, %r0
234 b,n .Lsyscall_nosys 229 b,n .Lsyscall_nosys
@@ -331,8 +326,6 @@ tracesys_next:
331 * task->thread.regs.gr[20] above. 326 * task->thread.regs.gr[20] above.
332 */ 327 */
333 copy %ret0,%r20 328 copy %ret0,%r20
334 ldil L%sys_call_table,%r1
335 ldo R%sys_call_table(%r1), %r19
336 329
337 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */ 330 ldo -THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 /* get task ptr */
338 LDREG TI_TASK(%r1), %r1 331 LDREG TI_TASK(%r1), %r1
@@ -354,6 +347,23 @@ tracesys_next:
354 comiclr,>> __NR_Linux_syscalls, %r20, %r0 347 comiclr,>> __NR_Linux_syscalls, %r20, %r0
355 b,n .Ltracesys_nosys 348 b,n .Ltracesys_nosys
356 349
350 /* Note! We cannot use the syscall table that is mapped
351 nearby since the gateway page is mapped execute-only. */
352
353#ifdef CONFIG_64BIT
354 LDREG TASK_PT_GR30(%r1), %r19 /* get users sp back */
355 extrd,u %r19,63,1,%r2 /* W hidden in bottom bit */
356
357 ldil L%sys_call_table, %r1
358 or,= %r2,%r2,%r2
359 addil L%(sys_call_table64-sys_call_table), %r1
360 ldo R%sys_call_table(%r1), %r19
361 or,= %r2,%r2,%r2
362 ldo R%sys_call_table64(%r1), %r19
363#else
364 load32 sys_call_table, %r19
365#endif
366
357 LDREGX %r20(%r19), %r19 367 LDREGX %r20(%r19), %r19
358 368
359 /* If this is a sys_rt_sigreturn call, and the signal was received 369 /* If this is a sys_rt_sigreturn call, and the signal was received
@@ -464,16 +474,13 @@ tracesys_sigexit:
464lws_start: 474lws_start:
465 475
466#ifdef CONFIG_64BIT 476#ifdef CONFIG_64BIT
467 /* FIXME: If we are a 64-bit kernel just
468 * turn this on unconditionally.
469 */
470 ssm PSW_SM_W, %r1 477 ssm PSW_SM_W, %r1
471 extrd,u %r1,PSW_W_BIT,1,%r1 478 extrd,u %r1,PSW_W_BIT,1,%r1
472 /* sp must be aligned on 4, so deposit the W bit setting into 479 /* sp must be aligned on 4, so deposit the W bit setting into
473 * the bottom of sp temporarily */ 480 * the bottom of sp temporarily */
474 or,ev %r1,%r30,%r30 481 or,ev %r1,%r30,%r30
475 482
476 /* Clip LWS number to a 32-bit value always */ 483 /* Clip LWS number to a 32-bit value for 32-bit processes */
477 depdi 0, 31, 32, %r20 484 depdi 0, 31, 32, %r20
478#endif 485#endif
479 486
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 318815212518..68f10f87073d 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -45,7 +45,7 @@
45 45
46#include "../math-emu/math-emu.h" /* for handle_fpe() */ 46#include "../math-emu/math-emu.h" /* for handle_fpe() */
47 47
48static void parisc_show_stack(struct task_struct *task, unsigned long *sp, 48static void parisc_show_stack(struct task_struct *task,
49 struct pt_regs *regs); 49 struct pt_regs *regs);
50 50
51static int printbinary(char *buf, unsigned long x, int nbits) 51static int printbinary(char *buf, unsigned long x, int nbits)
@@ -152,7 +152,7 @@ void show_regs(struct pt_regs *regs)
152 printk("%s IAOQ[1]: %pS\n", level, (void *) regs->iaoq[1]); 152 printk("%s IAOQ[1]: %pS\n", level, (void *) regs->iaoq[1]);
153 printk("%s RP(r2): %pS\n", level, (void *) regs->gr[2]); 153 printk("%s RP(r2): %pS\n", level, (void *) regs->gr[2]);
154 154
155 parisc_show_stack(current, NULL, regs); 155 parisc_show_stack(current, regs);
156 } 156 }
157} 157}
158 158
@@ -185,44 +185,19 @@ static void do_show_stack(struct unwind_frame_info *info)
185 printk(KERN_CRIT "\n"); 185 printk(KERN_CRIT "\n");
186} 186}
187 187
188static void parisc_show_stack(struct task_struct *task, unsigned long *sp, 188static void parisc_show_stack(struct task_struct *task,
189 struct pt_regs *regs) 189 struct pt_regs *regs)
190{ 190{
191 struct unwind_frame_info info; 191 struct unwind_frame_info info;
192 struct task_struct *t;
193 192
194 t = task ? task : current; 193 unwind_frame_init_task(&info, task, regs);
195 if (regs) {
196 unwind_frame_init(&info, t, regs);
197 goto show_stack;
198 }
199
200 if (t == current) {
201 unsigned long sp;
202
203HERE:
204 asm volatile ("copy %%r30, %0" : "=r"(sp));
205 {
206 struct pt_regs r;
207
208 memset(&r, 0, sizeof(struct pt_regs));
209 r.iaoq[0] = (unsigned long)&&HERE;
210 r.gr[2] = (unsigned long)__builtin_return_address(0);
211 r.gr[30] = sp;
212
213 unwind_frame_init(&info, current, &r);
214 }
215 } else {
216 unwind_frame_init_from_blocked_task(&info, t);
217 }
218 194
219show_stack:
220 do_show_stack(&info); 195 do_show_stack(&info);
221} 196}
222 197
223void show_stack(struct task_struct *t, unsigned long *sp) 198void show_stack(struct task_struct *t, unsigned long *sp)
224{ 199{
225 return parisc_show_stack(t, sp, NULL); 200 parisc_show_stack(t, NULL);
226} 201}
227 202
228int is_valid_bugaddr(unsigned long iaoq) 203int is_valid_bugaddr(unsigned long iaoq)
@@ -557,7 +532,7 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
557 cpu_lpmc(5, regs); 532 cpu_lpmc(5, regs);
558 return; 533 return;
559 534
560 case 6: 535 case PARISC_ITLB_TRAP:
561 /* Instruction TLB miss fault/Instruction page fault */ 536 /* Instruction TLB miss fault/Instruction page fault */
562 fault_address = regs->iaoq[0]; 537 fault_address = regs->iaoq[0];
563 fault_space = regs->iasq[0]; 538 fault_space = regs->iasq[0];
diff --git a/arch/parisc/kernel/unwind.c b/arch/parisc/kernel/unwind.c
index 5cdf13069dd9..f329b466e68f 100644
--- a/arch/parisc/kernel/unwind.c
+++ b/arch/parisc/kernel/unwind.c
@@ -209,6 +209,8 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int
209 * We have to use void * instead of a function pointer, because 209 * We have to use void * instead of a function pointer, because
210 * function pointers aren't a pointer to the function on 64-bit. 210 * function pointers aren't a pointer to the function on 64-bit.
211 * Make them const so the compiler knows they live in .text 211 * Make them const so the compiler knows they live in .text
212 * Note: We could use dereference_kernel_function_descriptor()
213 * instead but we want to keep it simple here.
212 */ 214 */
213 extern void * const handle_interruption; 215 extern void * const handle_interruption;
214 extern void * const ret_from_kernel_thread; 216 extern void * const ret_from_kernel_thread;
@@ -216,7 +218,7 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int
216 extern void * const intr_return; 218 extern void * const intr_return;
217 extern void * const _switch_to_ret; 219 extern void * const _switch_to_ret;
218#ifdef CONFIG_IRQSTACKS 220#ifdef CONFIG_IRQSTACKS
219 extern void * const call_on_stack; 221 extern void * const _call_on_stack;
220#endif /* CONFIG_IRQSTACKS */ 222#endif /* CONFIG_IRQSTACKS */
221 223
222 if (pc == (unsigned long) &handle_interruption) { 224 if (pc == (unsigned long) &handle_interruption) {
@@ -251,7 +253,7 @@ static int unwind_special(struct unwind_frame_info *info, unsigned long pc, int
251 } 253 }
252 254
253#ifdef CONFIG_IRQSTACKS 255#ifdef CONFIG_IRQSTACKS
254 if (pc == (unsigned long) &call_on_stack) { 256 if (pc == (unsigned long) &_call_on_stack) {
255 info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ); 257 info->prev_sp = *(unsigned long *)(info->sp - FRAME_SIZE - REG_SZ);
256 info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET); 258 info->prev_ip = *(unsigned long *)(info->sp - FRAME_SIZE - RP_OFFSET);
257 return 1; 259 return 1;
@@ -403,9 +405,31 @@ void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct
403 kfree(r2); 405 kfree(r2);
404} 406}
405 407
406void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs) 408#define get_parisc_stackpointer() ({ \
409 unsigned long sp; \
410 __asm__("copy %%r30, %0" : "=r"(sp)); \
411 (sp); \
412})
413
414void unwind_frame_init_task(struct unwind_frame_info *info,
415 struct task_struct *task, struct pt_regs *regs)
407{ 416{
408 unwind_frame_init(info, current, regs); 417 task = task ? task : current;
418
419 if (task == current) {
420 struct pt_regs r;
421
422 if (!regs) {
423 memset(&r, 0, sizeof(r));
424 r.iaoq[0] = _THIS_IP_;
425 r.gr[2] = _RET_IP_;
426 r.gr[30] = get_parisc_stackpointer();
427 regs = &r;
428 }
429 unwind_frame_init(info, task, &r);
430 } else {
431 unwind_frame_init_from_blocked_task(info, task);
432 }
409} 433}
410 434
411int unwind_once(struct unwind_frame_info *next_frame) 435int unwind_once(struct unwind_frame_info *next_frame)
@@ -442,19 +466,12 @@ int unwind_to_user(struct unwind_frame_info *info)
442unsigned long return_address(unsigned int level) 466unsigned long return_address(unsigned int level)
443{ 467{
444 struct unwind_frame_info info; 468 struct unwind_frame_info info;
445 struct pt_regs r;
446 unsigned long sp;
447 469
448 /* initialize unwind info */ 470 /* initialize unwind info */
449 asm volatile ("copy %%r30, %0" : "=r"(sp)); 471 unwind_frame_init_task(&info, current, NULL);
450 memset(&r, 0, sizeof(struct pt_regs));
451 r.iaoq[0] = _THIS_IP_;
452 r.gr[2] = _RET_IP_;
453 r.gr[30] = sp;
454 unwind_frame_init(&info, current, &r);
455 472
456 /* unwind stack */ 473 /* unwind stack */
457 ++level; 474 level += 2;
458 do { 475 do {
459 if (unwind_once(&info) < 0 || info.ip == 0) 476 if (unwind_once(&info) < 0 || info.ip == 0)
460 return 0; 477 return 0;