Merge branch 'parisc-4.6-3' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux

Pull parisc fixes from Helge Deller:
"Since commit 0de798584bde ("parisc: Use generic extable search and
sort routines") module loading is boken on parisc, because the parisc
module loader wasn't prepared for the new R_PARISC_PCREL32 relocations.

In addition, due to that breakage, Mikulas Patocka noticed that
handling exceptions from modules probably never worked on parisc. It
was just masked by the fact that exceptions from modules don't happen
during normal use.

This patch series fixes those issues and survives the tests of the
lib/test_user_copy kernel module test. Some patches are tagged for
stable"

* 'parisc-4.6-3' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
parisc: Update comment regarding relative extable support
parisc: Unbreak handling exceptions from kernel modules
parisc: Fix kernel crash with reversed copy_from_user()
parisc: Avoid function pointers for kernel exception routines
parisc: Handle R_PARISC_PCREL32 relocations in kernel modules

Changed files
+29 -11
arch
+5 -6
arch/parisc/include/asm/uaccess.h
··· 44 44 #define LDD_USER(ptr) BUILD_BUG() 45 45 #define STD_KERNEL(x, ptr) __put_kernel_asm64(x, ptr) 46 46 #define STD_USER(x, ptr) __put_user_asm64(x, ptr) 47 - #define ASM_WORD_INSN ".word\t" 48 47 #else 49 48 #define LDD_KERNEL(ptr) __get_kernel_asm("ldd", ptr) 50 49 #define LDD_USER(ptr) __get_user_asm("ldd", ptr) 51 50 #define STD_KERNEL(x, ptr) __put_kernel_asm("std", x, ptr) 52 51 #define STD_USER(x, ptr) __put_user_asm("std", x, ptr) 53 - #define ASM_WORD_INSN ".dword\t" 54 52 #endif 55 53 56 54 /* 57 - * The exception table contains two values: the first is an address 58 - * for an instruction that is allowed to fault, and the second is 59 - * the address to the fixup routine. Even on a 64bit kernel we could 60 - * use a 32bit (unsigned int) address here. 55 + * The exception table contains two values: the first is the relative offset to 56 + * the address of the instruction that is allowed to fault, and the second is 57 + * the relative offset to the address of the fixup routine. Since relative 58 + * addresses are used, 32bit values are sufficient even on 64bit kernel. 61 59 */ 62 60 63 61 #define ARCH_HAS_RELATIVE_EXTABLE ··· 75 77 */ 76 78 struct exception_data { 77 79 unsigned long fault_ip; 80 + unsigned long fault_gp; 78 81 unsigned long fault_space; 79 82 unsigned long fault_addr; 80 83 };
+1
arch/parisc/kernel/asm-offsets.c
··· 299 299 #endif 300 300 BLANK(); 301 301 DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip)); 302 + DEFINE(EXCDATA_GP, offsetof(struct exception_data, fault_gp)); 302 303 DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space)); 303 304 DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr)); 304 305 BLANK();
+8
arch/parisc/kernel/module.c
··· 660 660 } 661 661 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); 662 662 break; 663 + case R_PARISC_PCREL32: 664 + /* 32-bit PC relative address */ 665 + *loc = val - dot - 8 + addend; 666 + break; 663 667 664 668 default: 665 669 printk(KERN_ERR "module %s: Unknown relocation: %u\n", ··· 791 787 val = (val - dot - 8)/4; 792 788 CHECK_RELOC(val, 22); 793 789 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); 790 + break; 791 + case R_PARISC_PCREL32: 792 + /* 32-bit PC relative address */ 793 + *loc = val - dot - 8 + addend; 794 794 break; 795 795 case R_PARISC_DIR64: 796 796 /* 64-bit effective address */
+5 -5
arch/parisc/kernel/parisc_ksyms.c
··· 47 47 EXPORT_SYMBOL(lclear_user); 48 48 EXPORT_SYMBOL(lstrnlen_user); 49 49 50 - /* Global fixups */ 51 - extern void fixup_get_user_skip_1(void); 52 - extern void fixup_get_user_skip_2(void); 53 - extern void fixup_put_user_skip_1(void); 54 - extern void fixup_put_user_skip_2(void); 50 + /* Global fixups - defined as int to avoid creation of function pointers */ 51 + extern int fixup_get_user_skip_1; 52 + extern int fixup_get_user_skip_2; 53 + extern int fixup_put_user_skip_1; 54 + extern int fixup_put_user_skip_2; 55 55 EXPORT_SYMBOL(fixup_get_user_skip_1); 56 56 EXPORT_SYMBOL(fixup_get_user_skip_2); 57 57 EXPORT_SYMBOL(fixup_put_user_skip_1);
+3
arch/parisc/kernel/traps.c
··· 795 795 796 796 if (fault_space == 0 && !faulthandler_disabled()) 797 797 { 798 + /* Clean up and return if in exception table. */ 799 + if (fixup_exception(regs)) 800 + return; 798 801 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); 799 802 parisc_terminate("Kernel Fault", regs, code, fault_address); 800 803 }
+6
arch/parisc/lib/fixup.S
··· 26 26 27 27 #ifdef CONFIG_SMP 28 28 .macro get_fault_ip t1 t2 29 + loadgp 29 30 addil LT%__per_cpu_offset,%r27 30 31 LDREG RT%__per_cpu_offset(%r1),\t1 31 32 /* t2 = smp_processor_id() */ ··· 41 40 LDREG RT%exception_data(%r1),\t1 42 41 /* t1 = this_cpu_ptr(&exception_data) */ 43 42 add,l \t1,\t2,\t1 43 + /* %r27 = t1->fault_gp - restore gp */ 44 + LDREG EXCDATA_GP(\t1), %r27 44 45 /* t1 = t1->fault_ip */ 45 46 LDREG EXCDATA_IP(\t1), \t1 46 47 .endm 47 48 #else 48 49 .macro get_fault_ip t1 t2 50 + loadgp 49 51 /* t1 = this_cpu_ptr(&exception_data) */ 50 52 addil LT%exception_data,%r27 51 53 LDREG RT%exception_data(%r1),\t2 54 + /* %r27 = t2->fault_gp - restore gp */ 55 + LDREG EXCDATA_GP(\t2), %r27 52 56 /* t1 = t2->fault_ip */ 53 57 LDREG EXCDATA_IP(\t2), \t1 54 58 .endm
+1
arch/parisc/mm/fault.c
··· 145 145 struct exception_data *d; 146 146 d = this_cpu_ptr(&exception_data); 147 147 d->fault_ip = regs->iaoq[0]; 148 + d->fault_gp = regs->gr[27]; 148 149 d->fault_space = regs->isr; 149 150 d->fault_addr = regs->ior; 150 151