diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-22 17:06:37 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-08-22 17:06:37 -0400 |
| commit | 45b74a65b9934d5e1520d97aa4e09cf2b8c69ac0 (patch) | |
| tree | 7c451271a6c274da9b7f37fcb2592d4cfc972644 | |
| parent | 433bcf67370bc170a345634aa1be4ee8ac905de9 (diff) | |
| parent | dbf2a4b1ffab2867505be3b24221d5efa2200c91 (diff) | |
Merge branch 'parisc-4.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull more parisc updates from Helge Deller:
- fix boot failure of 64-bit kernel. It got broken by the unwind
optimization commit in merge window.
- fix 64-bit userspace support (static 64-bit applications only, e.g.
we don't yet have 64-bit userspace support in glibc).
- consolidate unwind initialization code.
- add machine model description to stack trace.
* 'parisc-4.19-2' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
parisc: Add hardware description to stack traces
parisc: Fix boot failure of 64-bit kernel
parisc: Consolidate unwind initialization calls
parisc: Update comments in syscall.S regarding wide userland
parisc: Fix ptraced 64-bit applications to call 64-bit syscalls
parisc: Restore possibility to execute 64-bit applications
| -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; |
