Commit eb608fb366de123a97227437e5306f731f4a63c5
Committed by
Martin Schwidefsky
1 parent
24996edce5
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
s390/exceptions: switch to relative exception table entries
This is the s390 port of 70627654 "x86, extable: Switch to relative exception table entries". Reduces the size of our exception tables by 50% on 64 bit builds. Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Showing 10 changed files with 132 additions and 33 deletions Side-by-side Diff
arch/s390/include/asm/processor.h
... | ... | @@ -11,6 +11,8 @@ |
11 | 11 | #ifndef __ASM_S390_PROCESSOR_H |
12 | 12 | #define __ASM_S390_PROCESSOR_H |
13 | 13 | |
14 | +#ifndef __ASSEMBLY__ | |
15 | + | |
14 | 16 | #include <linux/linkage.h> |
15 | 17 | #include <linux/irqflags.h> |
16 | 18 | #include <asm/cpu.h> |
... | ... | @@ -348,23 +350,6 @@ |
348 | 350 | |
349 | 351 | #define ARCH_LOW_ADDRESS_LIMIT 0x7fffffffUL |
350 | 352 | |
351 | -/* | |
352 | - * Helper macro for exception table entries | |
353 | - */ | |
354 | -#ifndef CONFIG_64BIT | |
355 | -#define EX_TABLE(_fault,_target) \ | |
356 | - ".section __ex_table,\"a\"\n" \ | |
357 | - " .align 4\n" \ | |
358 | - " .long " #_fault "," #_target "\n" \ | |
359 | - ".previous\n" | |
360 | -#else | |
361 | -#define EX_TABLE(_fault,_target) \ | |
362 | - ".section __ex_table,\"a\"\n" \ | |
363 | - " .align 8\n" \ | |
364 | - " .quad " #_fault "," #_target "\n" \ | |
365 | - ".previous\n" | |
366 | -#endif | |
367 | - | |
368 | 353 | extern int memcpy_real(void *, void *, size_t); |
369 | 354 | extern void memcpy_absolute(void *, void *, size_t); |
370 | 355 | |
... | ... | @@ -375,5 +360,26 @@ |
375 | 360 | memcpy_absolute(&(dest), &__tmp, sizeof(__tmp)); \ |
376 | 361 | } |
377 | 362 | |
378 | -#endif /* __ASM_S390_PROCESSOR_H */ | |
363 | +/* | |
364 | + * Helper macro for exception table entries | |
365 | + */ | |
366 | +#define EX_TABLE(_fault, _target) \ | |
367 | + ".section __ex_table,\"a\"\n" \ | |
368 | + ".align 4\n" \ | |
369 | + ".long (" #_fault ") - .\n" \ | |
370 | + ".long (" #_target ") - .\n" \ | |
371 | + ".previous\n" | |
372 | + | |
373 | +#else /* __ASSEMBLY__ */ | |
374 | + | |
375 | +#define EX_TABLE(_fault, _target) \ | |
376 | + .section __ex_table,"a" ; \ | |
377 | + .align 4 ; \ | |
378 | + .long (_fault) - . ; \ | |
379 | + .long (_target) - . ; \ | |
380 | + .previous | |
381 | + | |
382 | +#endif /* __ASSEMBLY__ */ | |
383 | + | |
384 | +#endif /* __ASM_S390_PROCESSOR_H */ |
arch/s390/include/asm/uaccess.h
... | ... | @@ -76,8 +76,21 @@ |
76 | 76 | |
77 | 77 | struct exception_table_entry |
78 | 78 | { |
79 | - unsigned long insn, fixup; | |
79 | + int insn, fixup; | |
80 | 80 | }; |
81 | + | |
82 | +static inline unsigned long extable_insn(const struct exception_table_entry *x) | |
83 | +{ | |
84 | + return (unsigned long)&x->insn + x->insn; | |
85 | +} | |
86 | + | |
87 | +static inline unsigned long extable_fixup(const struct exception_table_entry *x) | |
88 | +{ | |
89 | + return (unsigned long)&x->fixup + x->fixup; | |
90 | +} | |
91 | + | |
92 | +#define ARCH_HAS_SORT_EXTABLE | |
93 | +#define ARCH_HAS_SEARCH_EXTABLE | |
81 | 94 | |
82 | 95 | struct uaccess_ops { |
83 | 96 | size_t (*copy_from_user)(size_t, const void __user *, void *); |
arch/s390/kernel/early.c
... | ... | @@ -255,14 +255,14 @@ |
255 | 255 | |
256 | 256 | static void early_pgm_check_handler(void) |
257 | 257 | { |
258 | - unsigned long addr; | |
259 | 258 | const struct exception_table_entry *fixup; |
259 | + unsigned long addr; | |
260 | 260 | |
261 | 261 | addr = S390_lowcore.program_old_psw.addr; |
262 | 262 | fixup = search_exception_tables(addr & PSW_ADDR_INSN); |
263 | 263 | if (!fixup) |
264 | 264 | disabled_wait(0); |
265 | - S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE; | |
265 | + S390_lowcore.program_old_psw.addr = extable_fixup(fixup)|PSW_ADDR_AMODE; | |
266 | 266 | } |
267 | 267 | |
268 | 268 | static noinline __init void setup_lowcore_early(void) |
arch/s390/kernel/entry64.S
... | ... | @@ -10,6 +10,7 @@ |
10 | 10 | |
11 | 11 | #include <linux/init.h> |
12 | 12 | #include <linux/linkage.h> |
13 | +#include <asm/processor.h> | |
13 | 14 | #include <asm/cache.h> |
14 | 15 | #include <asm/errno.h> |
15 | 16 | #include <asm/ptrace.h> |
... | ... | @@ -1008,9 +1009,7 @@ |
1008 | 1009 | .Lhost_id: |
1009 | 1010 | .quad 0 |
1010 | 1011 | |
1011 | - .section __ex_table,"a" | |
1012 | - .quad sie_loop,sie_fault | |
1013 | - .previous | |
1012 | + EX_TABLE(sie_loop,sie_fault) | |
1014 | 1013 | #endif |
1015 | 1014 | |
1016 | 1015 | .section .rodata, "a" |
arch/s390/kernel/kprobes.c
arch/s390/kernel/traps.c
... | ... | @@ -322,7 +322,7 @@ |
322 | 322 | const struct exception_table_entry *fixup; |
323 | 323 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); |
324 | 324 | if (fixup) |
325 | - regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; | |
325 | + regs->psw.addr = extable_fixup(fixup) | PSW_ADDR_AMODE; | |
326 | 326 | else { |
327 | 327 | enum bug_trap_type btt; |
328 | 328 |
arch/s390/mm/Makefile
arch/s390/mm/extable.c
1 | +#include <linux/module.h> | |
2 | +#include <linux/sort.h> | |
3 | +#include <asm/uaccess.h> | |
4 | + | |
5 | +/* | |
6 | + * Search one exception table for an entry corresponding to the | |
7 | + * given instruction address, and return the address of the entry, | |
8 | + * or NULL if none is found. | |
9 | + * We use a binary search, and thus we assume that the table is | |
10 | + * already sorted. | |
11 | + */ | |
12 | +const struct exception_table_entry * | |
13 | +search_extable(const struct exception_table_entry *first, | |
14 | + const struct exception_table_entry *last, | |
15 | + unsigned long value) | |
16 | +{ | |
17 | + const struct exception_table_entry *mid; | |
18 | + unsigned long addr; | |
19 | + | |
20 | + while (first <= last) { | |
21 | + mid = ((last - first) >> 1) + first; | |
22 | + addr = extable_insn(mid); | |
23 | + if (addr < value) | |
24 | + first = mid + 1; | |
25 | + else if (addr > value) | |
26 | + last = mid - 1; | |
27 | + else | |
28 | + return mid; | |
29 | + } | |
30 | + return NULL; | |
31 | +} | |
32 | + | |
33 | +/* | |
34 | + * The exception table needs to be sorted so that the binary | |
35 | + * search that we use to find entries in it works properly. | |
36 | + * This is used both for the kernel exception table and for | |
37 | + * the exception tables of modules that get loaded. | |
38 | + * | |
39 | + */ | |
40 | +static int cmp_ex(const void *a, const void *b) | |
41 | +{ | |
42 | + const struct exception_table_entry *x = a, *y = b; | |
43 | + | |
44 | + /* This compare is only valid after normalization. */ | |
45 | + return x->insn - y->insn; | |
46 | +} | |
47 | + | |
48 | +void sort_extable(struct exception_table_entry *start, | |
49 | + struct exception_table_entry *finish) | |
50 | +{ | |
51 | + struct exception_table_entry *p; | |
52 | + int i; | |
53 | + | |
54 | + /* Normalize entries to being relative to the start of the section */ | |
55 | + for (p = start, i = 0; p < finish; p++, i += 8) | |
56 | + p->insn += i; | |
57 | + sort(start, finish - start, sizeof(*start), cmp_ex, NULL); | |
58 | + /* Denormalize all entries */ | |
59 | + for (p = start, i = 0; p < finish; p++, i += 8) | |
60 | + p->insn -= i; | |
61 | +} | |
62 | + | |
63 | +#ifdef CONFIG_MODULES | |
64 | +/* | |
65 | + * If the exception table is sorted, any referring to the module init | |
66 | + * will be at the beginning or the end. | |
67 | + */ | |
68 | +void trim_init_extable(struct module *m) | |
69 | +{ | |
70 | + /* Trim the beginning */ | |
71 | + while (m->num_exentries && | |
72 | + within_module_init(extable_insn(&m->extable[0]), m)) { | |
73 | + m->extable++; | |
74 | + m->num_exentries--; | |
75 | + } | |
76 | + /* Trim the end */ | |
77 | + while (m->num_exentries && | |
78 | + within_module_init(extable_insn(&m->extable[m->num_exentries-1]), m)) | |
79 | + m->num_exentries--; | |
80 | +} | |
81 | +#endif /* CONFIG_MODULES */ |
arch/s390/mm/fault.c
... | ... | @@ -163,7 +163,7 @@ |
163 | 163 | /* Are we prepared to handle this kernel fault? */ |
164 | 164 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); |
165 | 165 | if (fixup) { |
166 | - regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; | |
166 | + regs->psw.addr = extable_fixup(fixup) | PSW_ADDR_AMODE; | |
167 | 167 | return; |
168 | 168 | } |
169 | 169 |
scripts/sortextable.c
... | ... | @@ -161,7 +161,7 @@ |
161 | 161 | #define SORTEXTABLE_64 |
162 | 162 | #include "sortextable.h" |
163 | 163 | |
164 | -static int compare_x86_table(const void *a, const void *b) | |
164 | +static int compare_relative_table(const void *a, const void *b) | |
165 | 165 | { |
166 | 166 | int32_t av = (int32_t)r(a); |
167 | 167 | int32_t bv = (int32_t)r(b); |
... | ... | @@ -173,7 +173,7 @@ |
173 | 173 | return 0; |
174 | 174 | } |
175 | 175 | |
176 | -static void sort_x86_table(char *extab_image, int image_size) | |
176 | +static void sort_relative_table(char *extab_image, int image_size) | |
177 | 177 | { |
178 | 178 | int i; |
179 | 179 | |
... | ... | @@ -188,7 +188,7 @@ |
188 | 188 | i += 4; |
189 | 189 | } |
190 | 190 | |
191 | - qsort(extab_image, image_size / 8, 8, compare_x86_table); | |
191 | + qsort(extab_image, image_size / 8, 8, compare_relative_table); | |
192 | 192 | |
193 | 193 | /* Now denormalize. */ |
194 | 194 | i = 0; |
195 | 195 | |
... | ... | @@ -245,9 +245,9 @@ |
245 | 245 | break; |
246 | 246 | case EM_386: |
247 | 247 | case EM_X86_64: |
248 | - custom_sort = sort_x86_table; | |
249 | - break; | |
250 | 248 | case EM_S390: |
249 | + custom_sort = sort_relative_table; | |
250 | + break; | |
251 | 251 | case EM_MIPS: |
252 | 252 | break; |
253 | 253 | } /* end switch */ |