diff options
-rw-r--r-- | arch/x86/include/asm/alternative-asm.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/alternative.h | 4 | ||||
-rw-r--r-- | arch/x86/kernel/alternative.c | 45 |
3 files changed, 29 insertions, 24 deletions
diff --git a/arch/x86/include/asm/alternative-asm.h b/arch/x86/include/asm/alternative-asm.h index b97f786a48d5..a63a68be1cce 100644 --- a/arch/x86/include/asm/alternative-asm.h +++ b/arch/x86/include/asm/alternative-asm.h | |||
@@ -6,8 +6,8 @@ | |||
6 | .macro LOCK_PREFIX | 6 | .macro LOCK_PREFIX |
7 | 1: lock | 7 | 1: lock |
8 | .section .smp_locks,"a" | 8 | .section .smp_locks,"a" |
9 | _ASM_ALIGN | 9 | .balign 4 |
10 | _ASM_PTR 1b | 10 | .long 1b - . |
11 | .previous | 11 | .previous |
12 | .endm | 12 | .endm |
13 | #else | 13 | #else |
diff --git a/arch/x86/include/asm/alternative.h b/arch/x86/include/asm/alternative.h index b09ec55650b3..714bf2417284 100644 --- a/arch/x86/include/asm/alternative.h +++ b/arch/x86/include/asm/alternative.h | |||
@@ -30,8 +30,8 @@ | |||
30 | #ifdef CONFIG_SMP | 30 | #ifdef CONFIG_SMP |
31 | #define LOCK_PREFIX \ | 31 | #define LOCK_PREFIX \ |
32 | ".section .smp_locks,\"a\"\n" \ | 32 | ".section .smp_locks,\"a\"\n" \ |
33 | _ASM_ALIGN "\n" \ | 33 | ".balign 4\n" \ |
34 | _ASM_PTR "661f\n" /* address */ \ | 34 | ".long 661f - .\n" /* offset */ \ |
35 | ".previous\n" \ | 35 | ".previous\n" \ |
36 | "661:\n\tlock; " | 36 | "661:\n\tlock; " |
37 | 37 | ||
diff --git a/arch/x86/kernel/alternative.c b/arch/x86/kernel/alternative.c index 1a160d5d44d0..936738427223 100644 --- a/arch/x86/kernel/alternative.c +++ b/arch/x86/kernel/alternative.c | |||
@@ -194,7 +194,7 @@ static void __init_or_module add_nops(void *insns, unsigned int len) | |||
194 | } | 194 | } |
195 | 195 | ||
196 | extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; | 196 | extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; |
197 | extern u8 *__smp_locks[], *__smp_locks_end[]; | 197 | extern s32 __smp_locks[], __smp_locks_end[]; |
198 | static void *text_poke_early(void *addr, const void *opcode, size_t len); | 198 | static void *text_poke_early(void *addr, const void *opcode, size_t len); |
199 | 199 | ||
200 | /* Replace instructions with better alternatives for this CPU type. | 200 | /* Replace instructions with better alternatives for this CPU type. |
@@ -235,37 +235,39 @@ void __init_or_module apply_alternatives(struct alt_instr *start, | |||
235 | 235 | ||
236 | #ifdef CONFIG_SMP | 236 | #ifdef CONFIG_SMP |
237 | 237 | ||
238 | static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) | 238 | static void alternatives_smp_lock(const s32 *start, const s32 *end, |
239 | u8 *text, u8 *text_end) | ||
239 | { | 240 | { |
240 | u8 **ptr; | 241 | const s32 *poff; |
241 | 242 | ||
242 | mutex_lock(&text_mutex); | 243 | mutex_lock(&text_mutex); |
243 | for (ptr = start; ptr < end; ptr++) { | 244 | for (poff = start; poff < end; poff++) { |
244 | if (*ptr < text) | 245 | u8 *ptr = (u8 *)poff + *poff; |
245 | continue; | 246 | |
246 | if (*ptr > text_end) | 247 | if (!*poff || ptr < text || ptr >= text_end) |
247 | continue; | 248 | continue; |
248 | /* turn DS segment override prefix into lock prefix */ | 249 | /* turn DS segment override prefix into lock prefix */ |
249 | text_poke(*ptr, ((unsigned char []){0xf0}), 1); | 250 | text_poke(ptr, ((unsigned char []){0xf0}), 1); |
250 | }; | 251 | }; |
251 | mutex_unlock(&text_mutex); | 252 | mutex_unlock(&text_mutex); |
252 | } | 253 | } |
253 | 254 | ||
254 | static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) | 255 | static void alternatives_smp_unlock(const s32 *start, const s32 *end, |
256 | u8 *text, u8 *text_end) | ||
255 | { | 257 | { |
256 | u8 **ptr; | 258 | const s32 *poff; |
257 | 259 | ||
258 | if (noreplace_smp) | 260 | if (noreplace_smp) |
259 | return; | 261 | return; |
260 | 262 | ||
261 | mutex_lock(&text_mutex); | 263 | mutex_lock(&text_mutex); |
262 | for (ptr = start; ptr < end; ptr++) { | 264 | for (poff = start; poff < end; poff++) { |
263 | if (*ptr < text) | 265 | u8 *ptr = (u8 *)poff + *poff; |
264 | continue; | 266 | |
265 | if (*ptr > text_end) | 267 | if (!*poff || ptr < text || ptr >= text_end) |
266 | continue; | 268 | continue; |
267 | /* turn lock prefix into DS segment override prefix */ | 269 | /* turn lock prefix into DS segment override prefix */ |
268 | text_poke(*ptr, ((unsigned char []){0x3E}), 1); | 270 | text_poke(ptr, ((unsigned char []){0x3E}), 1); |
269 | }; | 271 | }; |
270 | mutex_unlock(&text_mutex); | 272 | mutex_unlock(&text_mutex); |
271 | } | 273 | } |
@@ -276,8 +278,8 @@ struct smp_alt_module { | |||
276 | char *name; | 278 | char *name; |
277 | 279 | ||
278 | /* ptrs to lock prefixes */ | 280 | /* ptrs to lock prefixes */ |
279 | u8 **locks; | 281 | const s32 *locks; |
280 | u8 **locks_end; | 282 | const s32 *locks_end; |
281 | 283 | ||
282 | /* .text segment, needed to avoid patching init code ;) */ | 284 | /* .text segment, needed to avoid patching init code ;) */ |
283 | u8 *text; | 285 | u8 *text; |
@@ -398,16 +400,19 @@ void alternatives_smp_switch(int smp) | |||
398 | int alternatives_text_reserved(void *start, void *end) | 400 | int alternatives_text_reserved(void *start, void *end) |
399 | { | 401 | { |
400 | struct smp_alt_module *mod; | 402 | struct smp_alt_module *mod; |
401 | u8 **ptr; | 403 | const s32 *poff; |
402 | u8 *text_start = start; | 404 | u8 *text_start = start; |
403 | u8 *text_end = end; | 405 | u8 *text_end = end; |
404 | 406 | ||
405 | list_for_each_entry(mod, &smp_alt_modules, next) { | 407 | list_for_each_entry(mod, &smp_alt_modules, next) { |
406 | if (mod->text > text_end || mod->text_end < text_start) | 408 | if (mod->text > text_end || mod->text_end < text_start) |
407 | continue; | 409 | continue; |
408 | for (ptr = mod->locks; ptr < mod->locks_end; ptr++) | 410 | for (poff = mod->locks; poff < mod->locks_end; poff++) { |
409 | if (text_start <= *ptr && text_end >= *ptr) | 411 | const u8 *ptr = (const u8 *)poff + *poff; |
412 | |||
413 | if (text_start <= ptr && text_end > ptr) | ||
410 | return 1; | 414 | return 1; |
415 | } | ||
411 | } | 416 | } |
412 | 417 | ||
413 | return 0; | 418 | return 0; |