Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

parisc: provide macro to create exception table entries

Provide a macro ASM_EXCEPTIONTABLE_ENTRY() to create exception table
entries and convert all open-coded places to use that macro.

This patch is a first step toward creating a exception table which only
holds 32bit pointers even on a 64bit kernel. That way in my own kernel
I was able to reduce the in-kernel exception table from 44kB to 22kB.

Signed-off-by: Helge Deller <deller@gmx.de>

+27 -14
+12
arch/parisc/include/asm/assembly.h
··· 515 515 nop /* 7 */ 516 516 .endm 517 517 518 + /* 519 + * ASM_EXCEPTIONTABLE_ENTRY 520 + * 521 + * Creates an exception table entry. 522 + * Do not convert to a assembler macro. This won't work. 523 + */ 524 + #define ASM_EXCEPTIONTABLE_ENTRY(fault_addr, except_addr) \ 525 + .section __ex_table,"aw" ! \ 526 + ASM_ULONG_INSN fault_addr, except_addr ! \ 527 + .previous 528 + 529 + 518 530 #endif /* __ASSEMBLY__ */ 519 531 #endif
+4 -3
arch/parisc/include/asm/uaccess.h
··· 59 59 /* 60 60 * The exception table contains two values: the first is an address 61 61 * for an instruction that is allowed to fault, and the second is 62 - * the address to the fixup routine. 62 + * the address to the fixup routine. Even on a 64bit kernel we could 63 + * use a 32bit (unsigned int) address here. 63 64 */ 64 65 65 66 struct exception_table_entry { 66 - unsigned long insn; /* address of insn that is allowed to fault. */ 67 - long fixup; /* fixup routine */ 67 + unsigned long insn; /* address of insn that is allowed to fault. */ 68 + unsigned long fixup; /* fixup routine */ 68 69 }; 69 70 70 71 #define ASM_EXCEPTIONTABLE_ENTRY( fault_addr, except_addr )\
+2 -4
arch/parisc/kernel/syscall.S
··· 649 649 /* Two exception table entries, one for the load, 650 650 the other for the store. Either return -EFAULT. 651 651 Each of the entries must be relocated. */ 652 - .section __ex_table,"aw" 653 - ASM_ULONG_INSN (1b - linux_gateway_page), (3b - linux_gateway_page) 654 - ASM_ULONG_INSN (2b - linux_gateway_page), (3b - linux_gateway_page) 655 - .previous 652 + ASM_EXCEPTIONTABLE_ENTRY(1b-linux_gateway_page, 3b-linux_gateway_page) 653 + ASM_EXCEPTIONTABLE_ENTRY(2b-linux_gateway_page, 3b-linux_gateway_page) 656 654 657 655 658 656 /* Make sure nothing else is placed on this page */
+3 -7
arch/parisc/lib/lusercopy.S
··· 88 88 ldo 1(%r25),%r25 89 89 .previous 90 90 91 - .section __ex_table,"aw" 92 - ASM_ULONG_INSN 1b,2b 93 - .previous 91 + ASM_EXCEPTIONTABLE_ENTRY(1b,2b) 94 92 95 93 .procend 96 94 ··· 127 129 copy %r24,%r26 /* reset r26 so 0 is returned on fault */ 128 130 .previous 129 131 130 - .section __ex_table,"aw" 131 - ASM_ULONG_INSN 1b,3b 132 - ASM_ULONG_INSN 2b,3b 133 - .previous 132 + ASM_EXCEPTIONTABLE_ENTRY(1b,3b) 133 + ASM_EXCEPTIONTABLE_ENTRY(2b,3b) 134 134 135 135 .procend 136 136
+6
arch/parisc/mm/fault.c
··· 142 142 { 143 143 const struct exception_table_entry *fix; 144 144 145 + /* If we only stored 32bit addresses in the exception table we can drop 146 + * out if we faulted on a 64bit address. */ 147 + if ((sizeof(regs->iaoq[0]) > sizeof(fix->insn)) 148 + && (regs->iaoq[0] >> 32)) 149 + return 0; 150 + 145 151 fix = search_exception_tables(regs->iaoq[0]); 146 152 if (fix) { 147 153 struct exception_data *d;