diff options
Diffstat (limited to 'arch/x86_64/kernel/module.c')
-rw-r--r-- | arch/x86_64/kernel/module.c | 38 |
1 files changed, 25 insertions, 13 deletions
diff --git a/arch/x86_64/kernel/module.c b/arch/x86_64/kernel/module.c index bac195c74bcc..9d0958ff547f 100644 --- a/arch/x86_64/kernel/module.c +++ b/arch/x86_64/kernel/module.c | |||
@@ -145,26 +145,38 @@ int apply_relocate(Elf_Shdr *sechdrs, | |||
145 | return -ENOSYS; | 145 | return -ENOSYS; |
146 | } | 146 | } |
147 | 147 | ||
148 | extern void apply_alternatives(void *start, void *end); | ||
149 | |||
150 | int module_finalize(const Elf_Ehdr *hdr, | 148 | int module_finalize(const Elf_Ehdr *hdr, |
151 | const Elf_Shdr *sechdrs, | 149 | const Elf_Shdr *sechdrs, |
152 | struct module *me) | 150 | struct module *me) |
153 | { | 151 | { |
154 | const Elf_Shdr *s; | 152 | const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL; |
155 | char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; | 153 | char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; |
156 | 154 | ||
157 | /* look for .altinstructions to patch */ | 155 | for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { |
158 | for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { | 156 | if (!strcmp(".text", secstrings + s->sh_name)) |
159 | void *seg; | 157 | text = s; |
160 | if (strcmp(".altinstructions", secstrings + s->sh_name)) | 158 | if (!strcmp(".altinstructions", secstrings + s->sh_name)) |
161 | continue; | 159 | alt = s; |
162 | seg = (void *)s->sh_addr; | 160 | if (!strcmp(".smp_locks", secstrings + s->sh_name)) |
163 | apply_alternatives(seg, seg + s->sh_size); | 161 | locks= s; |
164 | } | 162 | } |
163 | |||
164 | if (alt) { | ||
165 | /* patch .altinstructions */ | ||
166 | void *aseg = (void *)alt->sh_addr; | ||
167 | apply_alternatives(aseg, aseg + alt->sh_size); | ||
168 | } | ||
169 | if (locks && text) { | ||
170 | void *lseg = (void *)locks->sh_addr; | ||
171 | void *tseg = (void *)text->sh_addr; | ||
172 | alternatives_smp_module_add(me, me->name, | ||
173 | lseg, lseg + locks->sh_size, | ||
174 | tseg, tseg + text->sh_size); | ||
175 | } | ||
165 | return 0; | 176 | return 0; |
166 | } | 177 | } |
167 | 178 | ||
168 | void module_arch_cleanup(struct module *mod) | 179 | void module_arch_cleanup(struct module *mod) |
169 | { | 180 | { |
181 | alternatives_smp_module_del(mod); | ||
170 | } | 182 | } |