aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/alternative-asm.h4
-rw-r--r--arch/x86/include/asm/alternative.h4
-rw-r--r--arch/x86/kernel/alternative.c45
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
71: lock 71: 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
196extern struct alt_instr __alt_instructions[], __alt_instructions_end[]; 196extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
197extern u8 *__smp_locks[], *__smp_locks_end[]; 197extern s32 __smp_locks[], __smp_locks_end[];
198static void *text_poke_early(void *addr, const void *opcode, size_t len); 198static 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
238static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end) 238static 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
254static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end) 255static 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)
398int alternatives_text_reserved(void *start, void *end) 400int 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;