diff options
-rw-r--r-- | arch/parisc/include/asm/elf.h | 9 | ||||
-rw-r--r-- | arch/parisc/include/asm/linkage.h | 9 | ||||
-rw-r--r-- | arch/parisc/include/asm/processor.h | 6 | ||||
-rw-r--r-- | arch/parisc/include/asm/traps.h | 4 | ||||
-rw-r--r-- | arch/parisc/include/asm/unwind.h | 6 | ||||
-rw-r--r-- | arch/parisc/kernel/entry.S | 79 | ||||
-rw-r--r-- | arch/parisc/kernel/processor.c | 2 | ||||
-rw-r--r-- | arch/parisc/kernel/stacktrace.c | 15 | ||||
-rw-r--r-- | arch/parisc/kernel/sys_parisc.c | 5 | ||||
-rw-r--r-- | arch/parisc/kernel/syscall.S | 35 | ||||
-rw-r--r-- | arch/parisc/kernel/traps.c | 37 | ||||
-rw-r--r-- | arch/parisc/kernel/unwind.c | 43 |
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 @@ | |||
22 | name: ASM_NL\ | 22 | name: 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__) | ||
6 | struct pt_regs; | 8 | struct 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 | ||
74 | void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, | 74 | void unwind_frame_init(struct unwind_frame_info *info, struct task_struct *t, |
75 | struct pt_regs *regs); | 75 | struct pt_regs *regs); |
76 | void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, struct task_struct *t); | 76 | void unwind_frame_init_from_blocked_task(struct unwind_frame_info *info, |
77 | void unwind_frame_init_running(struct unwind_frame_info *info, struct pt_regs *regs); | 77 | struct task_struct *t); |
78 | void unwind_frame_init_task(struct unwind_frame_info *info, | ||
79 | struct task_struct *task, struct pt_regs *regs); | ||
78 | int unwind_once(struct unwind_frame_info *info); | 80 | int unwind_once(struct unwind_frame_info *info); |
79 | int unwind_to_user(struct unwind_frame_info *info); | 81 | int 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 | ||
779 | ENTRY_CFI(ret_from_kernel_thread) | 780 | ENTRY(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 |
794 | ENDPROC_CFI(ret_from_kernel_thread) | 795 | END(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 |
818 | ENDPROC_CFI(_switch_to) | ||
819 | 819 | ||
820 | ENTRY_CFI(_switch_to_ret) | 820 | ENTRY(_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 |
828 | ENDPROC_CFI(_switch_to_ret) | 828 | ENDPROC_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) |
889 | ENDPROC_CFI(syscall_exit_rfi) | ||
890 | 889 | ||
891 | ENTRY_CFI(intr_return) | 890 | ENTRY(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 */ |
896 | ENDPROC_CFI(intr_return) | ||
897 | 895 | ||
898 | .import do_notify_resume,code | 896 | .import do_notify_resume,code |
899 | intr_check_sig: | 897 | intr_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 */ |
1050 | ENDPROC_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 | ||
1112 | skip_save_ior: | 1097 | skip_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 | ||
1111 | skip_save_ior: | ||
1112 | #endif | ||
1113 | |||
1114 | intr_save2: | ||
1113 | virt_map | 1115 | virt_map |
1114 | save_general %r29 | 1116 | save_general %r29 |
1115 | 1117 | ||
@@ -1747,7 +1749,7 @@ fork_like fork | |||
1747 | fork_like vfork | 1749 | fork_like vfork |
1748 | 1750 | ||
1749 | /* Set the return value for the child */ | 1751 | /* Set the return value for the child */ |
1750 | ENTRY_CFI(child_return) | 1752 | ENTRY(child_return) |
1751 | BL schedule_tail, %r2 | 1753 | BL schedule_tail, %r2 |
1752 | nop | 1754 | nop |
1753 | finish_child_return: | 1755 | finish_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 |
1762 | ENDPROC_CFI(child_return) | 1764 | END(child_return) |
1763 | 1765 | ||
1764 | ENTRY_CFI(sys_rt_sigreturn_wrapper) | 1766 | ENTRY_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 */ |
1792 | ENDPROC_CFI(sys_rt_sigreturn_wrapper) | 1794 | ENDPROC_CFI(sys_rt_sigreturn_wrapper) |
1793 | 1795 | ||
1794 | ENTRY_CFI(syscall_exit) | 1796 | ENTRY(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 |
1993 | ENDPROC_CFI(syscall_exit) | 1995 | END(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 | ||
2002 | ENTRY_CFI(mcount, caller) | 2002 | ENTRY_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 | ||
2032 | ENTRY_CFI(return_to_handler, caller,frame=FRAME_SIZE) | 2030 | ENTRY_CFI(return_to_handler, caller,frame=FRAME_SIZE) |
2033 | .export parisc_return_to_handler,data | 2031 | .export parisc_return_to_handler,data |
2034 | parisc_return_to_handler: | 2032 | parisc_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) */ |
2080 | ENTRY_CFI(call_on_stack, FRAME=2*FRAME_SIZE,CALLS,SAVE_RP,SAVE_SP) | 2078 | ENTRY_CFI(call_on_stack, FRAME=2*FRAME_SIZE,CALLS,SAVE_RP,SAVE_SP) |
2079 | ENTRY(_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; | ||
23 | HERE: | ||
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: | |||
464 | lws_start: | 474 | lws_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 | ||
48 | static void parisc_show_stack(struct task_struct *task, unsigned long *sp, | 48 | static void parisc_show_stack(struct task_struct *task, |
49 | struct pt_regs *regs); | 49 | struct pt_regs *regs); |
50 | 50 | ||
51 | static int printbinary(char *buf, unsigned long x, int nbits) | 51 | static 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 | ||
188 | static void parisc_show_stack(struct task_struct *task, unsigned long *sp, | 188 | static 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 | |||
203 | HERE: | ||
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 | ||
219 | show_stack: | ||
220 | do_show_stack(&info); | 195 | do_show_stack(&info); |
221 | } | 196 | } |
222 | 197 | ||
223 | void show_stack(struct task_struct *t, unsigned long *sp) | 198 | void 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 | ||
228 | int is_valid_bugaddr(unsigned long iaoq) | 203 | int 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 | ||
406 | void 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 | |||
414 | void 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 | ||
411 | int unwind_once(struct unwind_frame_info *next_frame) | 435 | int unwind_once(struct unwind_frame_info *next_frame) |
@@ -442,19 +466,12 @@ int unwind_to_user(struct unwind_frame_info *info) | |||
442 | unsigned long return_address(unsigned int level) | 466 | unsigned 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; |