]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/x86/kernel/alternative.c
Merge branch 'x86/asm' into x86/atomic
[karo-tx-linux.git] / arch / x86 / kernel / alternative.c
index 1a160d5d44d0bd0f47b0b88b9e6a98f4b9b7f2b3..70237732a6c7c5f62f941d5df0594f7386ca6a10 100644 (file)
@@ -194,7 +194,7 @@ static void __init_or_module add_nops(void *insns, unsigned int len)
 }
 
 extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
-extern u8 *__smp_locks[], *__smp_locks_end[];
+extern s32 __smp_locks[], __smp_locks_end[];
 static void *text_poke_early(void *addr, const void *opcode, size_t len);
 
 /* Replace instructions with better alternatives for this CPU type.
@@ -235,37 +235,41 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
 
 #ifdef CONFIG_SMP
 
-static void alternatives_smp_lock(u8 **start, u8 **end, u8 *text, u8 *text_end)
+static void alternatives_smp_lock(const s32 *start, const s32 *end,
+                                 u8 *text, u8 *text_end)
 {
-       u8 **ptr;
+       const s32 *poff;
 
        mutex_lock(&text_mutex);
-       for (ptr = start; ptr < end; ptr++) {
-               if (*ptr < text)
-                       continue;
-               if (*ptr > text_end)
+       for (poff = start; poff < end; poff++) {
+               u8 *ptr = (u8 *)poff + *poff;
+
+               if (!*poff || ptr < text || ptr >= text_end)
                        continue;
                /* turn DS segment override prefix into lock prefix */
-               text_poke(*ptr, ((unsigned char []){0xf0}), 1);
+               if (*ptr == 0x3e)
+                       text_poke(ptr, ((unsigned char []){0xf0}), 1);
        };
        mutex_unlock(&text_mutex);
 }
 
-static void alternatives_smp_unlock(u8 **start, u8 **end, u8 *text, u8 *text_end)
+static void alternatives_smp_unlock(const s32 *start, const s32 *end,
+                                   u8 *text, u8 *text_end)
 {
-       u8 **ptr;
+       const s32 *poff;
 
        if (noreplace_smp)
                return;
 
        mutex_lock(&text_mutex);
-       for (ptr = start; ptr < end; ptr++) {
-               if (*ptr < text)
-                       continue;
-               if (*ptr > text_end)
+       for (poff = start; poff < end; poff++) {
+               u8 *ptr = (u8 *)poff + *poff;
+
+               if (!*poff || ptr < text || ptr >= text_end)
                        continue;
                /* turn lock prefix into DS segment override prefix */
-               text_poke(*ptr, ((unsigned char []){0x3E}), 1);
+               if (*ptr == 0xf0)
+                       text_poke(ptr, ((unsigned char []){0x3E}), 1);
        };
        mutex_unlock(&text_mutex);
 }
@@ -276,8 +280,8 @@ struct smp_alt_module {
        char            *name;
 
        /* ptrs to lock prefixes */
-       u8              **locks;
-       u8              **locks_end;
+       const s32       *locks;
+       const s32       *locks_end;
 
        /* .text segment, needed to avoid patching init code ;) */
        u8              *text;
@@ -398,16 +402,19 @@ void alternatives_smp_switch(int smp)
 int alternatives_text_reserved(void *start, void *end)
 {
        struct smp_alt_module *mod;
-       u8 **ptr;
+       const s32 *poff;
        u8 *text_start = start;
        u8 *text_end = end;
 
        list_for_each_entry(mod, &smp_alt_modules, next) {
                if (mod->text > text_end || mod->text_end < text_start)
                        continue;
-               for (ptr = mod->locks; ptr < mod->locks_end; ptr++)
-                       if (text_start <= *ptr && text_end >= *ptr)
+               for (poff = mod->locks; poff < mod->locks_end; poff++) {
+                       const u8 *ptr = (const u8 *)poff + *poff;
+
+                       if (text_start <= ptr && text_end > ptr)
                                return 1;
+               }
        }
 
        return 0;