diff options
36 files changed, 256 insertions, 262 deletions
diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c index 62dc379d301a..813c9b63c0e1 100644 --- a/arch/alpha/mm/extable.c +++ b/arch/alpha/mm/extable.c | |||
@@ -48,6 +48,27 @@ void sort_extable(struct exception_table_entry *start, | |||
48 | cmp_ex, swap_ex); | 48 | cmp_ex, swap_ex); |
49 | } | 49 | } |
50 | 50 | ||
51 | #ifdef CONFIG_MODULES | ||
52 | /* | ||
53 | * Any entry referring to the module init will be at the beginning or | ||
54 | * the end. | ||
55 | */ | ||
56 | void trim_init_extable(struct module *m) | ||
57 | { | ||
58 | /*trim the beginning*/ | ||
59 | while (m->num_exentries && | ||
60 | within_module_init(ex_to_addr(&m->extable[0]), m)) { | ||
61 | m->extable++; | ||
62 | m->num_exentries--; | ||
63 | } | ||
64 | /*trim the end*/ | ||
65 | while (m->num_exentries && | ||
66 | within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]), | ||
67 | m)) | ||
68 | m->num_exentries--; | ||
69 | } | ||
70 | #endif /* CONFIG_MODULES */ | ||
71 | |||
51 | const struct exception_table_entry * | 72 | const struct exception_table_entry * |
52 | search_extable(const struct exception_table_entry *first, | 73 | search_extable(const struct exception_table_entry *first, |
53 | const struct exception_table_entry *last, | 74 | const struct exception_table_entry *last, |
diff --git a/arch/avr32/kernel/module.c b/arch/avr32/kernel/module.c index 1167fe9cf6c4..98f94d041d9c 100644 --- a/arch/avr32/kernel/module.c +++ b/arch/avr32/kernel/module.c | |||
@@ -32,8 +32,6 @@ void module_free(struct module *mod, void *module_region) | |||
32 | mod->arch.syminfo = NULL; | 32 | mod->arch.syminfo = NULL; |
33 | 33 | ||
34 | vfree(module_region); | 34 | vfree(module_region); |
35 | /* FIXME: if module_region == mod->init_region, trim exception | ||
36 | * table entries. */ | ||
37 | } | 35 | } |
38 | 36 | ||
39 | static inline int check_rela(Elf32_Rela *rela, struct module *module, | 37 | static inline int check_rela(Elf32_Rela *rela, struct module *module, |
diff --git a/arch/cris/kernel/module.c b/arch/cris/kernel/module.c index a187833febc8..abc13e368b90 100644 --- a/arch/cris/kernel/module.c +++ b/arch/cris/kernel/module.c | |||
@@ -48,8 +48,6 @@ void *module_alloc(unsigned long size) | |||
48 | void module_free(struct module *mod, void *module_region) | 48 | void module_free(struct module *mod, void *module_region) |
49 | { | 49 | { |
50 | FREE_MODULE(module_region); | 50 | FREE_MODULE(module_region); |
51 | /* FIXME: If module_region == mod->init_region, trim exception | ||
52 | table entries. */ | ||
53 | } | 51 | } |
54 | 52 | ||
55 | /* We don't need anything special. */ | 53 | /* We don't need anything special. */ |
diff --git a/arch/frv/kernel/module.c b/arch/frv/kernel/module.c index 850d168f69fc..711763c8a6f3 100644 --- a/arch/frv/kernel/module.c +++ b/arch/frv/kernel/module.c | |||
@@ -35,8 +35,6 @@ void *module_alloc(unsigned long size) | |||
35 | void module_free(struct module *mod, void *module_region) | 35 | void module_free(struct module *mod, void *module_region) |
36 | { | 36 | { |
37 | vfree(module_region); | 37 | vfree(module_region); |
38 | /* FIXME: If module_region == mod->init_region, trim exception | ||
39 | table entries. */ | ||
40 | } | 38 | } |
41 | 39 | ||
42 | /* We don't need anything special. */ | 40 | /* We don't need anything special. */ |
diff --git a/arch/h8300/kernel/module.c b/arch/h8300/kernel/module.c index cfc9127d2ced..0865e291c20d 100644 --- a/arch/h8300/kernel/module.c +++ b/arch/h8300/kernel/module.c | |||
@@ -23,8 +23,6 @@ void *module_alloc(unsigned long size) | |||
23 | void module_free(struct module *mod, void *module_region) | 23 | void module_free(struct module *mod, void *module_region) |
24 | { | 24 | { |
25 | vfree(module_region); | 25 | vfree(module_region); |
26 | /* FIXME: If module_region == mod->init_region, trim exception | ||
27 | table entries. */ | ||
28 | } | 26 | } |
29 | 27 | ||
30 | /* We don't need anything special. */ | 28 | /* We don't need anything special. */ |
diff --git a/arch/ia64/mm/extable.c b/arch/ia64/mm/extable.c index 71c50dd8f870..e95d5ad9285d 100644 --- a/arch/ia64/mm/extable.c +++ b/arch/ia64/mm/extable.c | |||
@@ -53,6 +53,32 @@ void sort_extable (struct exception_table_entry *start, | |||
53 | cmp_ex, swap_ex); | 53 | cmp_ex, swap_ex); |
54 | } | 54 | } |
55 | 55 | ||
56 | static inline unsigned long ex_to_addr(const struct exception_table_entry *x) | ||
57 | { | ||
58 | return (unsigned long)&x->insn + x->insn; | ||
59 | } | ||
60 | |||
61 | #ifdef CONFIG_MODULES | ||
62 | /* | ||
63 | * Any entry referring to the module init will be at the beginning or | ||
64 | * the end. | ||
65 | */ | ||
66 | void trim_init_extable(struct module *m) | ||
67 | { | ||
68 | /*trim the beginning*/ | ||
69 | while (m->num_exentries && | ||
70 | within_module_init(ex_to_addr(&m->extable[0]), m)) { | ||
71 | m->extable++; | ||
72 | m->num_exentries--; | ||
73 | } | ||
74 | /*trim the end*/ | ||
75 | while (m->num_exentries && | ||
76 | within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]), | ||
77 | m)) | ||
78 | m->num_exentries--; | ||
79 | } | ||
80 | #endif /* CONFIG_MODULES */ | ||
81 | |||
56 | const struct exception_table_entry * | 82 | const struct exception_table_entry * |
57 | search_extable (const struct exception_table_entry *first, | 83 | search_extable (const struct exception_table_entry *first, |
58 | const struct exception_table_entry *last, | 84 | const struct exception_table_entry *last, |
diff --git a/arch/m32r/kernel/module.c b/arch/m32r/kernel/module.c index 8d4205794380..cb5f37d78d49 100644 --- a/arch/m32r/kernel/module.c +++ b/arch/m32r/kernel/module.c | |||
@@ -44,8 +44,6 @@ void *module_alloc(unsigned long size) | |||
44 | void module_free(struct module *mod, void *module_region) | 44 | void module_free(struct module *mod, void *module_region) |
45 | { | 45 | { |
46 | vfree(module_region); | 46 | vfree(module_region); |
47 | /* FIXME: If module_region == mod->init_region, trim exception | ||
48 | table entries. */ | ||
49 | } | 47 | } |
50 | 48 | ||
51 | /* We don't need anything special. */ | 49 | /* We don't need anything special. */ |
diff --git a/arch/m68k/kernel/module.c b/arch/m68k/kernel/module.c index 774862bc6977..cd6bcb1c957e 100644 --- a/arch/m68k/kernel/module.c +++ b/arch/m68k/kernel/module.c | |||
@@ -31,8 +31,6 @@ void *module_alloc(unsigned long size) | |||
31 | void module_free(struct module *mod, void *module_region) | 31 | void module_free(struct module *mod, void *module_region) |
32 | { | 32 | { |
33 | vfree(module_region); | 33 | vfree(module_region); |
34 | /* FIXME: If module_region == mod->init_region, trim exception | ||
35 | table entries. */ | ||
36 | } | 34 | } |
37 | 35 | ||
38 | /* We don't need anything special. */ | 36 | /* We don't need anything special. */ |
diff --git a/arch/m68knommu/kernel/module.c b/arch/m68knommu/kernel/module.c index 3b1a2ff61ddc..d11ffae7956a 100644 --- a/arch/m68knommu/kernel/module.c +++ b/arch/m68knommu/kernel/module.c | |||
@@ -23,8 +23,6 @@ void *module_alloc(unsigned long size) | |||
23 | void module_free(struct module *mod, void *module_region) | 23 | void module_free(struct module *mod, void *module_region) |
24 | { | 24 | { |
25 | vfree(module_region); | 25 | vfree(module_region); |
26 | /* FIXME: If module_region == mod->init_region, trim exception | ||
27 | table entries. */ | ||
28 | } | 26 | } |
29 | 27 | ||
30 | /* We don't need anything special. */ | 28 | /* We don't need anything special. */ |
diff --git a/arch/mips/kernel/module.c b/arch/mips/kernel/module.c index 1f60e27523d9..3e9100dcc12d 100644 --- a/arch/mips/kernel/module.c +++ b/arch/mips/kernel/module.c | |||
@@ -68,8 +68,6 @@ void *module_alloc(unsigned long size) | |||
68 | void module_free(struct module *mod, void *module_region) | 68 | void module_free(struct module *mod, void *module_region) |
69 | { | 69 | { |
70 | vfree(module_region); | 70 | vfree(module_region); |
71 | /* FIXME: If module_region == mod->init_region, trim exception | ||
72 | table entries. */ | ||
73 | } | 71 | } |
74 | 72 | ||
75 | int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, | 73 | int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, |
diff --git a/arch/mn10300/kernel/module.c b/arch/mn10300/kernel/module.c index 6b287f2e8e84..4fa0e3648d8e 100644 --- a/arch/mn10300/kernel/module.c +++ b/arch/mn10300/kernel/module.c | |||
@@ -48,8 +48,6 @@ void *module_alloc(unsigned long size) | |||
48 | void module_free(struct module *mod, void *module_region) | 48 | void module_free(struct module *mod, void *module_region) |
49 | { | 49 | { |
50 | vfree(module_region); | 50 | vfree(module_region); |
51 | /* FIXME: If module_region == mod->init_region, trim exception | ||
52 | * table entries. */ | ||
53 | } | 51 | } |
54 | 52 | ||
55 | /* | 53 | /* |
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c index ecd1c5024447..ef5caf2e6ed0 100644 --- a/arch/parisc/kernel/module.c +++ b/arch/parisc/kernel/module.c | |||
@@ -267,8 +267,6 @@ void module_free(struct module *mod, void *module_region) | |||
267 | mod->arch.section = NULL; | 267 | mod->arch.section = NULL; |
268 | 268 | ||
269 | vfree(module_region); | 269 | vfree(module_region); |
270 | /* FIXME: If module_region == mod->init_region, trim exception | ||
271 | table entries. */ | ||
272 | } | 270 | } |
273 | 271 | ||
274 | /* Additional bytes needed in front of individual sections */ | 272 | /* Additional bytes needed in front of individual sections */ |
diff --git a/arch/powerpc/kernel/module.c b/arch/powerpc/kernel/module.c index 43e7e3a7f130..477c663e0140 100644 --- a/arch/powerpc/kernel/module.c +++ b/arch/powerpc/kernel/module.c | |||
@@ -43,8 +43,6 @@ void *module_alloc(unsigned long size) | |||
43 | void module_free(struct module *mod, void *module_region) | 43 | void module_free(struct module *mod, void *module_region) |
44 | { | 44 | { |
45 | vfree(module_region); | 45 | vfree(module_region); |
46 | /* FIXME: If module_region == mod->init_region, trim exception | ||
47 | table entries. */ | ||
48 | } | 46 | } |
49 | 47 | ||
50 | static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, | 48 | static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, |
diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index eed4a00cb676..ab2e3ed28abc 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c | |||
@@ -56,8 +56,6 @@ void *module_alloc(unsigned long size) | |||
56 | void module_free(struct module *mod, void *module_region) | 56 | void module_free(struct module *mod, void *module_region) |
57 | { | 57 | { |
58 | vfree(module_region); | 58 | vfree(module_region); |
59 | /* FIXME: If module_region == mod->init_region, trim exception | ||
60 | table entries. */ | ||
61 | } | 59 | } |
62 | 60 | ||
63 | static void | 61 | static void |
diff --git a/arch/sh/kernel/module.c b/arch/sh/kernel/module.c index c19b0f7d2cc1..c2efdcde266f 100644 --- a/arch/sh/kernel/module.c +++ b/arch/sh/kernel/module.c | |||
@@ -46,8 +46,6 @@ void *module_alloc(unsigned long size) | |||
46 | void module_free(struct module *mod, void *module_region) | 46 | void module_free(struct module *mod, void *module_region) |
47 | { | 47 | { |
48 | vfree(module_region); | 48 | vfree(module_region); |
49 | /* FIXME: If module_region == mod->init_region, trim exception | ||
50 | table entries. */ | ||
51 | } | 49 | } |
52 | 50 | ||
53 | /* We don't need anything special. */ | 51 | /* We don't need anything special. */ |
diff --git a/arch/sparc/include/asm/uaccess_32.h b/arch/sparc/include/asm/uaccess_32.h index 47d5619d43fa..8303ac481034 100644 --- a/arch/sparc/include/asm/uaccess_32.h +++ b/arch/sparc/include/asm/uaccess_32.h | |||
@@ -17,6 +17,9 @@ | |||
17 | 17 | ||
18 | #ifndef __ASSEMBLY__ | 18 | #ifndef __ASSEMBLY__ |
19 | 19 | ||
20 | #define ARCH_HAS_SORT_EXTABLE | ||
21 | #define ARCH_HAS_SEARCH_EXTABLE | ||
22 | |||
20 | /* Sparc is not segmented, however we need to be able to fool access_ok() | 23 | /* Sparc is not segmented, however we need to be able to fool access_ok() |
21 | * when doing system calls from kernel mode legitimately. | 24 | * when doing system calls from kernel mode legitimately. |
22 | * | 25 | * |
diff --git a/arch/sparc/kernel/module.c b/arch/sparc/kernel/module.c index 90273765e81f..0ee642f63234 100644 --- a/arch/sparc/kernel/module.c +++ b/arch/sparc/kernel/module.c | |||
@@ -75,8 +75,6 @@ void *module_alloc(unsigned long size) | |||
75 | void module_free(struct module *mod, void *module_region) | 75 | void module_free(struct module *mod, void *module_region) |
76 | { | 76 | { |
77 | vfree(module_region); | 77 | vfree(module_region); |
78 | /* FIXME: If module_region == mod->init_region, trim exception | ||
79 | table entries. */ | ||
80 | } | 78 | } |
81 | 79 | ||
82 | /* Make generic code ignore STT_REGISTER dummy undefined symbols. */ | 80 | /* Make generic code ignore STT_REGISTER dummy undefined symbols. */ |
diff --git a/arch/sparc/mm/extable.c b/arch/sparc/mm/extable.c index 16cc28935e39..a61c349448e1 100644 --- a/arch/sparc/mm/extable.c +++ b/arch/sparc/mm/extable.c | |||
@@ -28,6 +28,10 @@ search_extable(const struct exception_table_entry *start, | |||
28 | * word 3: last insn address + 4 bytes | 28 | * word 3: last insn address + 4 bytes |
29 | * word 4: fixup code address | 29 | * word 4: fixup code address |
30 | * | 30 | * |
31 | * Deleted entries are encoded as: | ||
32 | * word 1: unused | ||
33 | * word 2: -1 | ||
34 | * | ||
31 | * See asm/uaccess.h for more details. | 35 | * See asm/uaccess.h for more details. |
32 | */ | 36 | */ |
33 | 37 | ||
@@ -39,6 +43,10 @@ search_extable(const struct exception_table_entry *start, | |||
39 | continue; | 43 | continue; |
40 | } | 44 | } |
41 | 45 | ||
46 | /* A deleted entry; see trim_init_extable */ | ||
47 | if (walk->fixup == -1) | ||
48 | continue; | ||
49 | |||
42 | if (walk->insn == value) | 50 | if (walk->insn == value) |
43 | return walk; | 51 | return walk; |
44 | } | 52 | } |
@@ -57,6 +65,27 @@ search_extable(const struct exception_table_entry *start, | |||
57 | return NULL; | 65 | return NULL; |
58 | } | 66 | } |
59 | 67 | ||
68 | #ifdef CONFIG_MODULES | ||
69 | /* We could memmove them around; easier to mark the trimmed ones. */ | ||
70 | void trim_init_extable(struct module *m) | ||
71 | { | ||
72 | unsigned int i; | ||
73 | bool range; | ||
74 | |||
75 | for (i = 0; i < m->num_exentries; i += range ? 2 : 1) { | ||
76 | range = m->extable[i].fixup == 0; | ||
77 | |||
78 | if (within_module_init(m->extable[i].insn, m)) { | ||
79 | m->extable[i].fixup = -1; | ||
80 | if (range) | ||
81 | m->extable[i+1].fixup = -1; | ||
82 | } | ||
83 | if (range) | ||
84 | i++; | ||
85 | } | ||
86 | } | ||
87 | #endif /* CONFIG_MODULES */ | ||
88 | |||
60 | /* Special extable search, which handles ranges. Returns fixup */ | 89 | /* Special extable search, which handles ranges. Returns fixup */ |
61 | unsigned long search_extables_range(unsigned long addr, unsigned long *g2) | 90 | unsigned long search_extables_range(unsigned long addr, unsigned long *g2) |
62 | { | 91 | { |
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h index 58da2480a7f4..9ce3f165111a 100644 --- a/arch/um/include/asm/pgtable.h +++ b/arch/um/include/asm/pgtable.h | |||
@@ -53,16 +53,21 @@ extern unsigned long end_iomem; | |||
53 | #else | 53 | #else |
54 | # define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) | 54 | # define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE) |
55 | #endif | 55 | #endif |
56 | #define MODULES_VADDR VMALLOC_START | ||
57 | #define MODULES_END VMALLOC_END | ||
58 | #define MODULES_LEN (MODULES_VADDR - MODULES_END) | ||
56 | 59 | ||
57 | #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) | 60 | #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) |
58 | #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) | 61 | #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) |
59 | #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) | 62 | #define _PAGE_CHG_MASK (PAGE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) |
60 | 63 | #define __PAGE_KERNEL_EXEC \ | |
64 | (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) | ||
61 | #define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) | 65 | #define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) |
62 | #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) | 66 | #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) |
63 | #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) | 67 | #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) |
64 | #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) | 68 | #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) |
65 | #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) | 69 | #define PAGE_KERNEL __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED) |
70 | #define PAGE_KERNEL_EXEC __pgprot(__PAGE_KERNEL_EXEC) | ||
66 | 71 | ||
67 | /* | 72 | /* |
68 | * The i386 can't do page protection for execute, and considers that the same | 73 | * The i386 can't do page protection for execute, and considers that the same |
diff --git a/arch/um/sys-i386/Makefile b/arch/um/sys-i386/Makefile index 598b5c1903af..1b549bca4645 100644 --- a/arch/um/sys-i386/Makefile +++ b/arch/um/sys-i386/Makefile | |||
@@ -8,7 +8,7 @@ obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \ | |||
8 | 8 | ||
9 | subarch-obj-y = lib/semaphore_32.o lib/string_32.o | 9 | subarch-obj-y = lib/semaphore_32.o lib/string_32.o |
10 | subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o | 10 | subarch-obj-$(CONFIG_HIGHMEM) += mm/highmem_32.o |
11 | subarch-obj-$(CONFIG_MODULES) += kernel/module_32.o | 11 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o |
12 | 12 | ||
13 | USER_OBJS := bugs.o ptrace_user.o fault.o | 13 | USER_OBJS := bugs.o ptrace_user.o fault.o |
14 | 14 | ||
diff --git a/arch/um/sys-x86_64/Makefile b/arch/um/sys-x86_64/Makefile index c8b4cce9cfe1..2201e9c20e4a 100644 --- a/arch/um/sys-x86_64/Makefile +++ b/arch/um/sys-x86_64/Makefile | |||
@@ -8,10 +8,8 @@ obj-y = bug.o bugs.o delay.o fault.o ldt.o mem.o ptrace.o ptrace_user.o \ | |||
8 | setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \ | 8 | setjmp.o signal.o stub.o stub_segv.o syscalls.o syscall_table.o \ |
9 | sysrq.o ksyms.o tls.o | 9 | sysrq.o ksyms.o tls.o |
10 | 10 | ||
11 | obj-$(CONFIG_MODULES) += um_module.o | ||
12 | |||
13 | subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o | 11 | subarch-obj-y = lib/csum-partial_64.o lib/memcpy_64.o lib/thunk_64.o |
14 | subarch-obj-$(CONFIG_MODULES) += kernel/module_64.o | 12 | subarch-obj-$(CONFIG_MODULES) += kernel/module.o |
15 | 13 | ||
16 | ldt-y = ../sys-i386/ldt.o | 14 | ldt-y = ../sys-i386/ldt.o |
17 | 15 | ||
diff --git a/arch/um/sys-x86_64/um_module.c b/arch/um/sys-x86_64/um_module.c deleted file mode 100644 index 3dead392a415..000000000000 --- a/arch/um/sys-x86_64/um_module.c +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
1 | #include <linux/vmalloc.h> | ||
2 | #include <linux/moduleloader.h> | ||
3 | |||
4 | /* Copied from i386 arch/i386/kernel/module.c */ | ||
5 | void *module_alloc(unsigned long size) | ||
6 | { | ||
7 | if (size == 0) | ||
8 | return NULL; | ||
9 | return vmalloc_exec(size); | ||
10 | } | ||
11 | |||
12 | /* Free memory returned from module_alloc */ | ||
13 | void module_free(struct module *mod, void *module_region) | ||
14 | { | ||
15 | vfree(module_region); | ||
16 | /* | ||
17 | * FIXME: If module_region == mod->init_region, trim exception | ||
18 | * table entries. | ||
19 | */ | ||
20 | } | ||
21 | |||
diff --git a/arch/x86/include/asm/pgtable_32_types.h b/arch/x86/include/asm/pgtable_32_types.h index 2733fad45f98..5e67c1532314 100644 --- a/arch/x86/include/asm/pgtable_32_types.h +++ b/arch/x86/include/asm/pgtable_32_types.h | |||
@@ -46,6 +46,10 @@ extern bool __vmalloc_start_set; /* set once high_memory is set */ | |||
46 | # define VMALLOC_END (FIXADDR_START - 2 * PAGE_SIZE) | 46 | # define VMALLOC_END (FIXADDR_START - 2 * PAGE_SIZE) |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #define MODULES_VADDR VMALLOC_START | ||
50 | #define MODULES_END VMALLOC_END | ||
51 | #define MODULES_LEN (MODULES_VADDR - MODULES_END) | ||
52 | |||
49 | #define MAXMEM (VMALLOC_END - PAGE_OFFSET - __VMALLOC_RESERVE) | 53 | #define MAXMEM (VMALLOC_END - PAGE_OFFSET - __VMALLOC_RESERVE) |
50 | 54 | ||
51 | #endif /* _ASM_X86_PGTABLE_32_DEFS_H */ | 55 | #endif /* _ASM_X86_PGTABLE_32_DEFS_H */ |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 4f78bd682125..f3477bb84566 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -73,7 +73,7 @@ obj-$(CONFIG_KEXEC) += machine_kexec_$(BITS).o | |||
73 | obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o | 73 | obj-$(CONFIG_KEXEC) += relocate_kernel_$(BITS).o crash.o |
74 | obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o | 74 | obj-$(CONFIG_CRASH_DUMP) += crash_dump_$(BITS).o |
75 | obj-$(CONFIG_KPROBES) += kprobes.o | 75 | obj-$(CONFIG_KPROBES) += kprobes.o |
76 | obj-$(CONFIG_MODULES) += module_$(BITS).o | 76 | obj-$(CONFIG_MODULES) += module.o |
77 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o | 77 | obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o |
78 | obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o | 78 | obj-$(CONFIG_DOUBLEFAULT) += doublefault_32.o |
79 | obj-$(CONFIG_KGDB) += kgdb.o | 79 | obj-$(CONFIG_KGDB) += kgdb.o |
diff --git a/arch/x86/kernel/module_64.c b/arch/x86/kernel/module.c index c23880b90b5c..89f386f044e4 100644 --- a/arch/x86/kernel/module_64.c +++ b/arch/x86/kernel/module.c | |||
@@ -1,6 +1,5 @@ | |||
1 | /* Kernel module help for x86-64 | 1 | /* Kernel module help for x86. |
2 | Copyright (C) 2001 Rusty Russell. | 2 | Copyright (C) 2001 Rusty Russell. |
3 | Copyright (C) 2002,2003 Andi Kleen, SuSE Labs. | ||
4 | 3 | ||
5 | This program is free software; you can redistribute it and/or modify | 4 | This program is free software; you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by | 5 | it under the terms of the GNU General Public License as published by |
@@ -22,23 +21,18 @@ | |||
22 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
23 | #include <linux/string.h> | 22 | #include <linux/string.h> |
24 | #include <linux/kernel.h> | 23 | #include <linux/kernel.h> |
25 | #include <linux/mm.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/bug.h> | 24 | #include <linux/bug.h> |
25 | #include <linux/mm.h> | ||
28 | 26 | ||
29 | #include <asm/system.h> | 27 | #include <asm/system.h> |
30 | #include <asm/page.h> | 28 | #include <asm/page.h> |
31 | #include <asm/pgtable.h> | 29 | #include <asm/pgtable.h> |
32 | 30 | ||
31 | #if 0 | ||
32 | #define DEBUGP printk | ||
33 | #else | ||
33 | #define DEBUGP(fmt...) | 34 | #define DEBUGP(fmt...) |
34 | 35 | #endif | |
35 | #ifndef CONFIG_UML | ||
36 | void module_free(struct module *mod, void *module_region) | ||
37 | { | ||
38 | vfree(module_region); | ||
39 | /* FIXME: If module_region == mod->init_region, trim exception | ||
40 | table entries. */ | ||
41 | } | ||
42 | 36 | ||
43 | void *module_alloc(unsigned long size) | 37 | void *module_alloc(unsigned long size) |
44 | { | 38 | { |
@@ -54,9 +48,15 @@ void *module_alloc(unsigned long size) | |||
54 | if (!area) | 48 | if (!area) |
55 | return NULL; | 49 | return NULL; |
56 | 50 | ||
57 | return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL_EXEC); | 51 | return __vmalloc_area(area, GFP_KERNEL | __GFP_HIGHMEM, |
52 | PAGE_KERNEL_EXEC); | ||
53 | } | ||
54 | |||
55 | /* Free memory returned from module_alloc */ | ||
56 | void module_free(struct module *mod, void *module_region) | ||
57 | { | ||
58 | vfree(module_region); | ||
58 | } | 59 | } |
59 | #endif | ||
60 | 60 | ||
61 | /* We don't need anything special. */ | 61 | /* We don't need anything special. */ |
62 | int module_frob_arch_sections(Elf_Ehdr *hdr, | 62 | int module_frob_arch_sections(Elf_Ehdr *hdr, |
@@ -67,6 +67,58 @@ int module_frob_arch_sections(Elf_Ehdr *hdr, | |||
67 | return 0; | 67 | return 0; |
68 | } | 68 | } |
69 | 69 | ||
70 | #ifdef CONFIG_X86_32 | ||
71 | int apply_relocate(Elf32_Shdr *sechdrs, | ||
72 | const char *strtab, | ||
73 | unsigned int symindex, | ||
74 | unsigned int relsec, | ||
75 | struct module *me) | ||
76 | { | ||
77 | unsigned int i; | ||
78 | Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; | ||
79 | Elf32_Sym *sym; | ||
80 | uint32_t *location; | ||
81 | |||
82 | DEBUGP("Applying relocate section %u to %u\n", relsec, | ||
83 | sechdrs[relsec].sh_info); | ||
84 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
85 | /* This is where to make the change */ | ||
86 | location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
87 | + rel[i].r_offset; | ||
88 | /* This is the symbol it is referring to. Note that all | ||
89 | undefined symbols have been resolved. */ | ||
90 | sym = (Elf32_Sym *)sechdrs[symindex].sh_addr | ||
91 | + ELF32_R_SYM(rel[i].r_info); | ||
92 | |||
93 | switch (ELF32_R_TYPE(rel[i].r_info)) { | ||
94 | case R_386_32: | ||
95 | /* We add the value into the location given */ | ||
96 | *location += sym->st_value; | ||
97 | break; | ||
98 | case R_386_PC32: | ||
99 | /* Add the value, subtract its postition */ | ||
100 | *location += sym->st_value - (uint32_t)location; | ||
101 | break; | ||
102 | default: | ||
103 | printk(KERN_ERR "module %s: Unknown relocation: %u\n", | ||
104 | me->name, ELF32_R_TYPE(rel[i].r_info)); | ||
105 | return -ENOEXEC; | ||
106 | } | ||
107 | } | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | int apply_relocate_add(Elf32_Shdr *sechdrs, | ||
112 | const char *strtab, | ||
113 | unsigned int symindex, | ||
114 | unsigned int relsec, | ||
115 | struct module *me) | ||
116 | { | ||
117 | printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", | ||
118 | me->name); | ||
119 | return -ENOEXEC; | ||
120 | } | ||
121 | #else /*X86_64*/ | ||
70 | int apply_relocate_add(Elf64_Shdr *sechdrs, | 122 | int apply_relocate_add(Elf64_Shdr *sechdrs, |
71 | const char *strtab, | 123 | const char *strtab, |
72 | unsigned int symindex, | 124 | unsigned int symindex, |
@@ -147,6 +199,8 @@ int apply_relocate(Elf_Shdr *sechdrs, | |||
147 | return -ENOSYS; | 199 | return -ENOSYS; |
148 | } | 200 | } |
149 | 201 | ||
202 | #endif | ||
203 | |||
150 | int module_finalize(const Elf_Ehdr *hdr, | 204 | int module_finalize(const Elf_Ehdr *hdr, |
151 | const Elf_Shdr *sechdrs, | 205 | const Elf_Shdr *sechdrs, |
152 | struct module *me) | 206 | struct module *me) |
diff --git a/arch/x86/kernel/module_32.c b/arch/x86/kernel/module_32.c deleted file mode 100644 index 0edd819050e7..000000000000 --- a/arch/x86/kernel/module_32.c +++ /dev/null | |||
@@ -1,152 +0,0 @@ | |||
1 | /* Kernel module help for i386. | ||
2 | Copyright (C) 2001 Rusty Russell. | ||
3 | |||
4 | This program is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 2 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program; if not, write to the Free Software | ||
16 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | */ | ||
18 | #include <linux/moduleloader.h> | ||
19 | #include <linux/elf.h> | ||
20 | #include <linux/vmalloc.h> | ||
21 | #include <linux/fs.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/kernel.h> | ||
24 | #include <linux/bug.h> | ||
25 | |||
26 | #if 0 | ||
27 | #define DEBUGP printk | ||
28 | #else | ||
29 | #define DEBUGP(fmt...) | ||
30 | #endif | ||
31 | |||
32 | void *module_alloc(unsigned long size) | ||
33 | { | ||
34 | if (size == 0) | ||
35 | return NULL; | ||
36 | return vmalloc_exec(size); | ||
37 | } | ||
38 | |||
39 | |||
40 | /* Free memory returned from module_alloc */ | ||
41 | void module_free(struct module *mod, void *module_region) | ||
42 | { | ||
43 | vfree(module_region); | ||
44 | /* FIXME: If module_region == mod->init_region, trim exception | ||
45 | table entries. */ | ||
46 | } | ||
47 | |||
48 | /* We don't need anything special. */ | ||
49 | int module_frob_arch_sections(Elf_Ehdr *hdr, | ||
50 | Elf_Shdr *sechdrs, | ||
51 | char *secstrings, | ||
52 | struct module *mod) | ||
53 | { | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | int apply_relocate(Elf32_Shdr *sechdrs, | ||
58 | const char *strtab, | ||
59 | unsigned int symindex, | ||
60 | unsigned int relsec, | ||
61 | struct module *me) | ||
62 | { | ||
63 | unsigned int i; | ||
64 | Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; | ||
65 | Elf32_Sym *sym; | ||
66 | uint32_t *location; | ||
67 | |||
68 | DEBUGP("Applying relocate section %u to %u\n", relsec, | ||
69 | sechdrs[relsec].sh_info); | ||
70 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | ||
71 | /* This is where to make the change */ | ||
72 | location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr | ||
73 | + rel[i].r_offset; | ||
74 | /* This is the symbol it is referring to. Note that all | ||
75 | undefined symbols have been resolved. */ | ||
76 | sym = (Elf32_Sym *)sechdrs[symindex].sh_addr | ||
77 | + ELF32_R_SYM(rel[i].r_info); | ||
78 | |||
79 | switch (ELF32_R_TYPE(rel[i].r_info)) { | ||
80 | case R_386_32: | ||
81 | /* We add the value into the location given */ | ||
82 | *location += sym->st_value; | ||
83 | break; | ||
84 | case R_386_PC32: | ||
85 | /* Add the value, subtract its postition */ | ||
86 | *location += sym->st_value - (uint32_t)location; | ||
87 | break; | ||
88 | default: | ||
89 | printk(KERN_ERR "module %s: Unknown relocation: %u\n", | ||
90 | me->name, ELF32_R_TYPE(rel[i].r_info)); | ||
91 | return -ENOEXEC; | ||
92 | } | ||
93 | } | ||
94 | return 0; | ||
95 | } | ||
96 | |||
97 | int apply_relocate_add(Elf32_Shdr *sechdrs, | ||
98 | const char *strtab, | ||
99 | unsigned int symindex, | ||
100 | unsigned int relsec, | ||
101 | struct module *me) | ||
102 | { | ||
103 | printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n", | ||
104 | me->name); | ||
105 | return -ENOEXEC; | ||
106 | } | ||
107 | |||
108 | int module_finalize(const Elf_Ehdr *hdr, | ||
109 | const Elf_Shdr *sechdrs, | ||
110 | struct module *me) | ||
111 | { | ||
112 | const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, | ||
113 | *para = NULL; | ||
114 | char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | ||
115 | |||
116 | for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { | ||
117 | if (!strcmp(".text", secstrings + s->sh_name)) | ||
118 | text = s; | ||
119 | if (!strcmp(".altinstructions", secstrings + s->sh_name)) | ||
120 | alt = s; | ||
121 | if (!strcmp(".smp_locks", secstrings + s->sh_name)) | ||
122 | locks = s; | ||
123 | if (!strcmp(".parainstructions", secstrings + s->sh_name)) | ||
124 | para = s; | ||
125 | } | ||
126 | |||
127 | if (alt) { | ||
128 | /* patch .altinstructions */ | ||
129 | void *aseg = (void *)alt->sh_addr; | ||
130 | apply_alternatives(aseg, aseg + alt->sh_size); | ||
131 | } | ||
132 | if (locks && text) { | ||
133 | void *lseg = (void *)locks->sh_addr; | ||
134 | void *tseg = (void *)text->sh_addr; | ||
135 | alternatives_smp_module_add(me, me->name, | ||
136 | lseg, lseg + locks->sh_size, | ||
137 | tseg, tseg + text->sh_size); | ||
138 | } | ||
139 | |||
140 | if (para) { | ||
141 | void *pseg = (void *)para->sh_addr; | ||
142 | apply_paravirt(pseg, pseg + para->sh_size); | ||
143 | } | ||
144 | |||
145 | return module_bug_finalize(hdr, sechdrs, me); | ||
146 | } | ||
147 | |||
148 | void module_arch_cleanup(struct module *mod) | ||
149 | { | ||
150 | alternatives_smp_module_del(mod); | ||
151 | module_bug_cleanup(mod); | ||
152 | } | ||
diff --git a/arch/xtensa/kernel/module.c b/arch/xtensa/kernel/module.c index 3981a466c779..c1accea8cb56 100644 --- a/arch/xtensa/kernel/module.c +++ b/arch/xtensa/kernel/module.c | |||
@@ -34,8 +34,6 @@ void *module_alloc(unsigned long size) | |||
34 | void module_free(struct module *mod, void *module_region) | 34 | void module_free(struct module *mod, void *module_region) |
35 | { | 35 | { |
36 | vfree(module_region); | 36 | vfree(module_region); |
37 | /* FIXME: If module_region == mod->init_region, trim exception | ||
38 | table entries. */ | ||
39 | } | 37 | } |
40 | 38 | ||
41 | int module_frob_arch_sections(Elf32_Ehdr *hdr, | 39 | int module_frob_arch_sections(Elf32_Ehdr *hdr, |
diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 35e8eb02b9e9..e4e4d433b007 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c | |||
@@ -354,7 +354,7 @@ static int default_crt_on __devinitdata = 0; | |||
354 | static int default_lcd_on __devinitdata = 1; | 354 | static int default_lcd_on __devinitdata = 1; |
355 | 355 | ||
356 | #ifdef CONFIG_MTRR | 356 | #ifdef CONFIG_MTRR |
357 | static int mtrr = 1; | 357 | static bool mtrr = true; |
358 | #endif | 358 | #endif |
359 | 359 | ||
360 | #ifdef CONFIG_PMAC_BACKLIGHT | 360 | #ifdef CONFIG_PMAC_BACKLIGHT |
diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index 83c5cefc266c..da7c01b39be2 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c | |||
@@ -1736,10 +1736,8 @@ static int __init cyber2000fb_init(void) | |||
1736 | 1736 | ||
1737 | #ifdef CONFIG_ARCH_SHARK | 1737 | #ifdef CONFIG_ARCH_SHARK |
1738 | err = cyberpro_vl_probe(); | 1738 | err = cyberpro_vl_probe(); |
1739 | if (!err) { | 1739 | if (!err) |
1740 | ret = 0; | 1740 | ret = 0; |
1741 | __module_get(THIS_MODULE); | ||
1742 | } | ||
1743 | #endif | 1741 | #endif |
1744 | #ifdef CONFIG_PCI | 1742 | #ifdef CONFIG_PCI |
1745 | err = pci_register_driver(&cyberpro_driver); | 1743 | err = pci_register_driver(&cyberpro_driver); |
@@ -1749,14 +1747,15 @@ static int __init cyber2000fb_init(void) | |||
1749 | 1747 | ||
1750 | return ret ? err : 0; | 1748 | return ret ? err : 0; |
1751 | } | 1749 | } |
1750 | module_init(cyber2000fb_init); | ||
1752 | 1751 | ||
1752 | #ifndef CONFIG_ARCH_SHARK | ||
1753 | static void __exit cyberpro_exit(void) | 1753 | static void __exit cyberpro_exit(void) |
1754 | { | 1754 | { |
1755 | pci_unregister_driver(&cyberpro_driver); | 1755 | pci_unregister_driver(&cyberpro_driver); |
1756 | } | 1756 | } |
1757 | |||
1758 | module_init(cyber2000fb_init); | ||
1759 | module_exit(cyberpro_exit); | 1757 | module_exit(cyberpro_exit); |
1758 | #endif | ||
1760 | 1759 | ||
1761 | MODULE_AUTHOR("Russell King"); | 1760 | MODULE_AUTHOR("Russell King"); |
1762 | MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver"); | 1761 | MODULE_DESCRIPTION("CyberPro 2000, 2010 and 5000 framebuffer driver"); |
diff --git a/drivers/video/uvesafb.c b/drivers/video/uvesafb.c index 421770b5e6ab..ca5b4643a401 100644 --- a/drivers/video/uvesafb.c +++ b/drivers/video/uvesafb.c | |||
@@ -45,7 +45,7 @@ static struct fb_fix_screeninfo uvesafb_fix __devinitdata = { | |||
45 | static int mtrr __devinitdata = 3; /* enable mtrr by default */ | 45 | static int mtrr __devinitdata = 3; /* enable mtrr by default */ |
46 | static int blank = 1; /* enable blanking by default */ | 46 | static int blank = 1; /* enable blanking by default */ |
47 | static int ypan = 1; /* 0: scroll, 1: ypan, 2: ywrap */ | 47 | static int ypan = 1; /* 0: scroll, 1: ypan, 2: ywrap */ |
48 | static int pmi_setpal __devinitdata = 1; /* use PMI for palette changes */ | 48 | static bool pmi_setpal __devinitdata = true; /* use PMI for palette changes */ |
49 | static int nocrtc __devinitdata; /* ignore CRTC settings */ | 49 | static int nocrtc __devinitdata; /* ignore CRTC settings */ |
50 | static int noedid __devinitdata; /* don't try DDC transfers */ | 50 | static int noedid __devinitdata; /* don't try DDC transfers */ |
51 | static int vram_remap __devinitdata; /* set amt. of memory to be used */ | 51 | static int vram_remap __devinitdata; /* set amt. of memory to be used */ |
@@ -2002,11 +2002,7 @@ static void __devexit uvesafb_exit(void) | |||
2002 | 2002 | ||
2003 | module_exit(uvesafb_exit); | 2003 | module_exit(uvesafb_exit); |
2004 | 2004 | ||
2005 | static int param_get_scroll(char *buffer, struct kernel_param *kp) | 2005 | #define param_get_scroll NULL |
2006 | { | ||
2007 | return 0; | ||
2008 | } | ||
2009 | |||
2010 | static int param_set_scroll(const char *val, struct kernel_param *kp) | 2006 | static int param_set_scroll(const char *val, struct kernel_param *kp) |
2011 | { | 2007 | { |
2012 | ypan = 0; | 2008 | ypan = 0; |
@@ -2017,6 +2013,8 @@ static int param_set_scroll(const char *val, struct kernel_param *kp) | |||
2017 | ypan = 1; | 2013 | ypan = 1; |
2018 | else if (!strcmp(val, "ywrap")) | 2014 | else if (!strcmp(val, "ywrap")) |
2019 | ypan = 2; | 2015 | ypan = 2; |
2016 | else | ||
2017 | return -EINVAL; | ||
2020 | 2018 | ||
2021 | return 0; | 2019 | return 0; |
2022 | } | 2020 | } |
diff --git a/include/linux/compiler.h b/include/linux/compiler.h index 37bcb50a4d7c..04fb5135b4e1 100644 --- a/include/linux/compiler.h +++ b/include/linux/compiler.h | |||
@@ -261,6 +261,11 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); | |||
261 | # define __section(S) __attribute__ ((__section__(#S))) | 261 | # define __section(S) __attribute__ ((__section__(#S))) |
262 | #endif | 262 | #endif |
263 | 263 | ||
264 | /* Are two types/vars the same type (ignoring qualifiers)? */ | ||
265 | #ifndef __same_type | ||
266 | # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) | ||
267 | #endif | ||
268 | |||
264 | /* | 269 | /* |
265 | * Prevent the compiler from merging or refetching accesses. The compiler | 270 | * Prevent the compiler from merging or refetching accesses. The compiler |
266 | * is also forbidden from reordering successive instances of ACCESS_ONCE(), | 271 | * is also forbidden from reordering successive instances of ACCESS_ONCE(), |
diff --git a/include/linux/module.h b/include/linux/module.h index a8f2c0aa4c32..a7bc6e7b43a7 100644 --- a/include/linux/module.h +++ b/include/linux/module.h | |||
@@ -77,6 +77,7 @@ search_extable(const struct exception_table_entry *first, | |||
77 | void sort_extable(struct exception_table_entry *start, | 77 | void sort_extable(struct exception_table_entry *start, |
78 | struct exception_table_entry *finish); | 78 | struct exception_table_entry *finish); |
79 | void sort_main_extable(void); | 79 | void sort_main_extable(void); |
80 | void trim_init_extable(struct module *m); | ||
80 | 81 | ||
81 | #ifdef MODULE | 82 | #ifdef MODULE |
82 | #define MODULE_GENERIC_TABLE(gtype,name) \ | 83 | #define MODULE_GENERIC_TABLE(gtype,name) \ |
diff --git a/include/linux/moduleparam.h b/include/linux/moduleparam.h index a4f0b931846c..6547c3cdbc4c 100644 --- a/include/linux/moduleparam.h +++ b/include/linux/moduleparam.h | |||
@@ -36,9 +36,14 @@ typedef int (*param_set_fn)(const char *val, struct kernel_param *kp); | |||
36 | /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ | 36 | /* Returns length written or -errno. Buffer is 4k (ie. be short!) */ |
37 | typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp); | 37 | typedef int (*param_get_fn)(char *buffer, struct kernel_param *kp); |
38 | 38 | ||
39 | /* Flag bits for kernel_param.flags */ | ||
40 | #define KPARAM_KMALLOCED 1 | ||
41 | #define KPARAM_ISBOOL 2 | ||
42 | |||
39 | struct kernel_param { | 43 | struct kernel_param { |
40 | const char *name; | 44 | const char *name; |
41 | unsigned int perm; | 45 | u16 perm; |
46 | u16 flags; | ||
42 | param_set_fn set; | 47 | param_set_fn set; |
43 | param_get_fn get; | 48 | param_get_fn get; |
44 | union { | 49 | union { |
@@ -79,7 +84,7 @@ struct kparam_array | |||
79 | parameters. perm sets the visibility in sysfs: 000 means it's | 84 | parameters. perm sets the visibility in sysfs: 000 means it's |
80 | not there, read bits mean it's readable, write bits mean it's | 85 | not there, read bits mean it's readable, write bits mean it's |
81 | writable. */ | 86 | writable. */ |
82 | #define __module_param_call(prefix, name, set, get, arg, perm) \ | 87 | #define __module_param_call(prefix, name, set, get, arg, isbool, perm) \ |
83 | /* Default value instead of permissions? */ \ | 88 | /* Default value instead of permissions? */ \ |
84 | static int __param_perm_check_##name __attribute__((unused)) = \ | 89 | static int __param_perm_check_##name __attribute__((unused)) = \ |
85 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ | 90 | BUILD_BUG_ON_ZERO((perm) < 0 || (perm) > 0777 || ((perm) & 2)) \ |
@@ -88,10 +93,13 @@ struct kparam_array | |||
88 | static struct kernel_param __moduleparam_const __param_##name \ | 93 | static struct kernel_param __moduleparam_const __param_##name \ |
89 | __used \ | 94 | __used \ |
90 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ | 95 | __attribute__ ((unused,__section__ ("__param"),aligned(sizeof(void *)))) \ |
91 | = { __param_str_##name, perm, set, get, { arg } } | 96 | = { __param_str_##name, perm, isbool ? KPARAM_ISBOOL : 0, \ |
97 | set, get, { arg } } | ||
92 | 98 | ||
93 | #define module_param_call(name, set, get, arg, perm) \ | 99 | #define module_param_call(name, set, get, arg, perm) \ |
94 | __module_param_call(MODULE_PARAM_PREFIX, name, set, get, arg, perm) | 100 | __module_param_call(MODULE_PARAM_PREFIX, \ |
101 | name, set, get, arg, \ | ||
102 | __same_type(*(arg), bool), perm) | ||
95 | 103 | ||
96 | /* Helper functions: type is byte, short, ushort, int, uint, long, | 104 | /* Helper functions: type is byte, short, ushort, int, uint, long, |
97 | ulong, charp, bool or invbool, or XXX if you define param_get_XXX, | 105 | ulong, charp, bool or invbool, or XXX if you define param_get_XXX, |
@@ -120,15 +128,16 @@ struct kparam_array | |||
120 | #define core_param(name, var, type, perm) \ | 128 | #define core_param(name, var, type, perm) \ |
121 | param_check_##type(name, &(var)); \ | 129 | param_check_##type(name, &(var)); \ |
122 | __module_param_call("", name, param_set_##type, param_get_##type, \ | 130 | __module_param_call("", name, param_set_##type, param_get_##type, \ |
123 | &var, perm) | 131 | &var, __same_type(var, bool), perm) |
124 | #endif /* !MODULE */ | 132 | #endif /* !MODULE */ |
125 | 133 | ||
126 | /* Actually copy string: maxlen param is usually sizeof(string). */ | 134 | /* Actually copy string: maxlen param is usually sizeof(string). */ |
127 | #define module_param_string(name, string, len, perm) \ | 135 | #define module_param_string(name, string, len, perm) \ |
128 | static const struct kparam_string __param_string_##name \ | 136 | static const struct kparam_string __param_string_##name \ |
129 | = { len, string }; \ | 137 | = { len, string }; \ |
130 | module_param_call(name, param_set_copystring, param_get_string, \ | 138 | __module_param_call(MODULE_PARAM_PREFIX, name, \ |
131 | .str = &__param_string_##name, perm); \ | 139 | param_set_copystring, param_get_string, \ |
140 | .str = &__param_string_##name, 0, perm); \ | ||
132 | __MODULE_PARM_TYPE(name, "string") | 141 | __MODULE_PARM_TYPE(name, "string") |
133 | 142 | ||
134 | /* Called on module insert or kernel boot */ | 143 | /* Called on module insert or kernel boot */ |
@@ -186,21 +195,30 @@ extern int param_set_charp(const char *val, struct kernel_param *kp); | |||
186 | extern int param_get_charp(char *buffer, struct kernel_param *kp); | 195 | extern int param_get_charp(char *buffer, struct kernel_param *kp); |
187 | #define param_check_charp(name, p) __param_check(name, p, char *) | 196 | #define param_check_charp(name, p) __param_check(name, p, char *) |
188 | 197 | ||
198 | /* For historical reasons "bool" parameters can be (unsigned) "int". */ | ||
189 | extern int param_set_bool(const char *val, struct kernel_param *kp); | 199 | extern int param_set_bool(const char *val, struct kernel_param *kp); |
190 | extern int param_get_bool(char *buffer, struct kernel_param *kp); | 200 | extern int param_get_bool(char *buffer, struct kernel_param *kp); |
191 | #define param_check_bool(name, p) __param_check(name, p, int) | 201 | #define param_check_bool(name, p) \ |
202 | static inline void __check_##name(void) \ | ||
203 | { \ | ||
204 | BUILD_BUG_ON(!__same_type(*(p), bool) && \ | ||
205 | !__same_type(*(p), unsigned int) && \ | ||
206 | !__same_type(*(p), int)); \ | ||
207 | } | ||
192 | 208 | ||
193 | extern int param_set_invbool(const char *val, struct kernel_param *kp); | 209 | extern int param_set_invbool(const char *val, struct kernel_param *kp); |
194 | extern int param_get_invbool(char *buffer, struct kernel_param *kp); | 210 | extern int param_get_invbool(char *buffer, struct kernel_param *kp); |
195 | #define param_check_invbool(name, p) __param_check(name, p, int) | 211 | #define param_check_invbool(name, p) __param_check(name, p, bool) |
196 | 212 | ||
197 | /* Comma-separated array: *nump is set to number they actually specified. */ | 213 | /* Comma-separated array: *nump is set to number they actually specified. */ |
198 | #define module_param_array_named(name, array, type, nump, perm) \ | 214 | #define module_param_array_named(name, array, type, nump, perm) \ |
199 | static const struct kparam_array __param_arr_##name \ | 215 | static const struct kparam_array __param_arr_##name \ |
200 | = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type,\ | 216 | = { ARRAY_SIZE(array), nump, param_set_##type, param_get_##type,\ |
201 | sizeof(array[0]), array }; \ | 217 | sizeof(array[0]), array }; \ |
202 | module_param_call(name, param_array_set, param_array_get, \ | 218 | __module_param_call(MODULE_PARAM_PREFIX, name, \ |
203 | .arr = &__param_arr_##name, perm); \ | 219 | param_array_set, param_array_get, \ |
220 | .arr = &__param_arr_##name, \ | ||
221 | __same_type(array[0], bool), perm); \ | ||
204 | __MODULE_PARM_TYPE(name, "array of " #type) | 222 | __MODULE_PARM_TYPE(name, "array of " #type) |
205 | 223 | ||
206 | #define module_param_array(name, type, nump, perm) \ | 224 | #define module_param_array(name, type, nump, perm) \ |
diff --git a/kernel/module.c b/kernel/module.c index 35f7de00bf0d..e4ab36ce7672 100644 --- a/kernel/module.c +++ b/kernel/module.c | |||
@@ -2455,6 +2455,7 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, | |||
2455 | mutex_lock(&module_mutex); | 2455 | mutex_lock(&module_mutex); |
2456 | /* Drop initial reference. */ | 2456 | /* Drop initial reference. */ |
2457 | module_put(mod); | 2457 | module_put(mod); |
2458 | trim_init_extable(mod); | ||
2458 | module_free(mod, mod->module_init); | 2459 | module_free(mod, mod->module_init); |
2459 | mod->module_init = NULL; | 2460 | mod->module_init = NULL; |
2460 | mod->init_size = 0; | 2461 | mod->init_size = 0; |
diff --git a/kernel/params.c b/kernel/params.c index de273ec85bd2..7f6912ced2ba 100644 --- a/kernel/params.c +++ b/kernel/params.c | |||
@@ -24,9 +24,6 @@ | |||
24 | #include <linux/err.h> | 24 | #include <linux/err.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | 26 | ||
27 | /* We abuse the high bits of "perm" to record whether we kmalloc'ed. */ | ||
28 | #define KPARAM_KMALLOCED 0x80000000 | ||
29 | |||
30 | #if 0 | 27 | #if 0 |
31 | #define DEBUGP printk | 28 | #define DEBUGP printk |
32 | #else | 29 | #else |
@@ -220,13 +217,13 @@ int param_set_charp(const char *val, struct kernel_param *kp) | |||
220 | return -ENOSPC; | 217 | return -ENOSPC; |
221 | } | 218 | } |
222 | 219 | ||
223 | if (kp->perm & KPARAM_KMALLOCED) | 220 | if (kp->flags & KPARAM_KMALLOCED) |
224 | kfree(*(char **)kp->arg); | 221 | kfree(*(char **)kp->arg); |
225 | 222 | ||
226 | /* This is a hack. We can't need to strdup in early boot, and we | 223 | /* This is a hack. We can't need to strdup in early boot, and we |
227 | * don't need to; this mangled commandline is preserved. */ | 224 | * don't need to; this mangled commandline is preserved. */ |
228 | if (slab_is_available()) { | 225 | if (slab_is_available()) { |
229 | kp->perm |= KPARAM_KMALLOCED; | 226 | kp->flags |= KPARAM_KMALLOCED; |
230 | *(char **)kp->arg = kstrdup(val, GFP_KERNEL); | 227 | *(char **)kp->arg = kstrdup(val, GFP_KERNEL); |
231 | if (!kp->arg) | 228 | if (!kp->arg) |
232 | return -ENOMEM; | 229 | return -ENOMEM; |
@@ -241,44 +238,63 @@ int param_get_charp(char *buffer, struct kernel_param *kp) | |||
241 | return sprintf(buffer, "%s", *((char **)kp->arg)); | 238 | return sprintf(buffer, "%s", *((char **)kp->arg)); |
242 | } | 239 | } |
243 | 240 | ||
241 | /* Actually could be a bool or an int, for historical reasons. */ | ||
244 | int param_set_bool(const char *val, struct kernel_param *kp) | 242 | int param_set_bool(const char *val, struct kernel_param *kp) |
245 | { | 243 | { |
244 | bool v; | ||
245 | |||
246 | /* No equals means "set"... */ | 246 | /* No equals means "set"... */ |
247 | if (!val) val = "1"; | 247 | if (!val) val = "1"; |
248 | 248 | ||
249 | /* One of =[yYnN01] */ | 249 | /* One of =[yYnN01] */ |
250 | switch (val[0]) { | 250 | switch (val[0]) { |
251 | case 'y': case 'Y': case '1': | 251 | case 'y': case 'Y': case '1': |
252 | *(int *)kp->arg = 1; | 252 | v = true; |
253 | return 0; | 253 | break; |
254 | case 'n': case 'N': case '0': | 254 | case 'n': case 'N': case '0': |
255 | *(int *)kp->arg = 0; | 255 | v = false; |
256 | return 0; | 256 | break; |
257 | default: | ||
258 | return -EINVAL; | ||
257 | } | 259 | } |
258 | return -EINVAL; | 260 | |
261 | if (kp->flags & KPARAM_ISBOOL) | ||
262 | *(bool *)kp->arg = v; | ||
263 | else | ||
264 | *(int *)kp->arg = v; | ||
265 | return 0; | ||
259 | } | 266 | } |
260 | 267 | ||
261 | int param_get_bool(char *buffer, struct kernel_param *kp) | 268 | int param_get_bool(char *buffer, struct kernel_param *kp) |
262 | { | 269 | { |
270 | bool val; | ||
271 | if (kp->flags & KPARAM_ISBOOL) | ||
272 | val = *(bool *)kp->arg; | ||
273 | else | ||
274 | val = *(int *)kp->arg; | ||
275 | |||
263 | /* Y and N chosen as being relatively non-coder friendly */ | 276 | /* Y and N chosen as being relatively non-coder friendly */ |
264 | return sprintf(buffer, "%c", (*(int *)kp->arg) ? 'Y' : 'N'); | 277 | return sprintf(buffer, "%c", val ? 'Y' : 'N'); |
265 | } | 278 | } |
266 | 279 | ||
280 | /* This one must be bool. */ | ||
267 | int param_set_invbool(const char *val, struct kernel_param *kp) | 281 | int param_set_invbool(const char *val, struct kernel_param *kp) |
268 | { | 282 | { |
269 | int boolval, ret; | 283 | int ret; |
284 | bool boolval; | ||
270 | struct kernel_param dummy; | 285 | struct kernel_param dummy; |
271 | 286 | ||
272 | dummy.arg = &boolval; | 287 | dummy.arg = &boolval; |
288 | dummy.flags = KPARAM_ISBOOL; | ||
273 | ret = param_set_bool(val, &dummy); | 289 | ret = param_set_bool(val, &dummy); |
274 | if (ret == 0) | 290 | if (ret == 0) |
275 | *(int *)kp->arg = !boolval; | 291 | *(bool *)kp->arg = !boolval; |
276 | return ret; | 292 | return ret; |
277 | } | 293 | } |
278 | 294 | ||
279 | int param_get_invbool(char *buffer, struct kernel_param *kp) | 295 | int param_get_invbool(char *buffer, struct kernel_param *kp) |
280 | { | 296 | { |
281 | return sprintf(buffer, "%c", (*(int *)kp->arg) ? 'N' : 'Y'); | 297 | return sprintf(buffer, "%c", (*(bool *)kp->arg) ? 'N' : 'Y'); |
282 | } | 298 | } |
283 | 299 | ||
284 | /* We break the rule and mangle the string. */ | 300 | /* We break the rule and mangle the string. */ |
@@ -591,7 +607,7 @@ void destroy_params(const struct kernel_param *params, unsigned num) | |||
591 | unsigned int i; | 607 | unsigned int i; |
592 | 608 | ||
593 | for (i = 0; i < num; i++) | 609 | for (i = 0; i < num; i++) |
594 | if (params[i].perm & KPARAM_KMALLOCED) | 610 | if (params[i].flags & KPARAM_KMALLOCED) |
595 | kfree(*(char **)params[i].arg); | 611 | kfree(*(char **)params[i].arg); |
596 | } | 612 | } |
597 | 613 | ||
diff --git a/lib/extable.c b/lib/extable.c index 179c08745595..4cac81ec225e 100644 --- a/lib/extable.c +++ b/lib/extable.c | |||
@@ -39,7 +39,26 @@ void sort_extable(struct exception_table_entry *start, | |||
39 | sort(start, finish - start, sizeof(struct exception_table_entry), | 39 | sort(start, finish - start, sizeof(struct exception_table_entry), |
40 | cmp_ex, NULL); | 40 | cmp_ex, NULL); |
41 | } | 41 | } |
42 | #endif | 42 | |
43 | #ifdef CONFIG_MODULES | ||
44 | /* | ||
45 | * If the exception table is sorted, any referring to the module init | ||
46 | * will be at the beginning or the end. | ||
47 | */ | ||
48 | void trim_init_extable(struct module *m) | ||
49 | { | ||
50 | /*trim the beginning*/ | ||
51 | while (m->num_exentries && within_module_init(m->extable[0].insn, m)) { | ||
52 | m->extable++; | ||
53 | m->num_exentries--; | ||
54 | } | ||
55 | /*trim the end*/ | ||
56 | while (m->num_exentries && | ||
57 | within_module_init(m->extable[m->num_exentries-1].insn, m)) | ||
58 | m->num_exentries--; | ||
59 | } | ||
60 | #endif /* CONFIG_MODULES */ | ||
61 | #endif /* !ARCH_HAS_SORT_EXTABLE */ | ||
43 | 62 | ||
44 | #ifndef ARCH_HAS_SEARCH_EXTABLE | 63 | #ifndef ARCH_HAS_SEARCH_EXTABLE |
45 | /* | 64 | /* |