Merge branch 'x86-vmware-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[sfrench/cifs-2.6.git] / arch / parisc / kernel / alternative.c
index ca1f5ca0540a1b603c6377d19f1520151ac8798b..3c66d5c4d90d309eacbc265227ce07fdb2a3625e 100644 (file)
@@ -28,7 +28,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
 
        for (entry = start; entry < end; entry++, index++) {
 
-               u32 *from, len, cond, replacement;
+               u32 *from, cond, replacement;
+               s32 len;
 
                from = (u32 *)((ulong)&entry->orig_offset + entry->orig_offset);
                len = entry->len;
@@ -49,6 +50,8 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
                        continue;
                if ((cond & ALT_COND_NO_ICACHE) && (cache_info.ic_size != 0))
                        continue;
+               if ((cond & ALT_COND_RUN_ON_QEMU) && !running_on_qemu)
+                       continue;
 
                /*
                 * If the PDC_MODEL capabilities has Non-coherent IO-PDIR bit
@@ -74,11 +77,19 @@ void __init_or_module apply_alternatives(struct alt_instr *start,
                if (replacement == INSN_NOP && len > 1)
                        replacement = 0xe8000002 + (len-2)*8; /* "b,n .+8" */
 
-               pr_debug("Do    %d: Cond 0x%x, Replace %02d instructions @ 0x%px with 0x%08x\n",
-                       index, cond, len, from, replacement);
-
-               /* Replace instruction */
-               *from = replacement;
+               pr_debug("ALTERNATIVE %3d: Cond %2x, Replace %2d instructions to 0x%08x @ 0x%px (%pS)\n",
+                       index, cond, len, replacement, from, from);
+
+               if (len < 0) {
+                       /* Replace multiple instruction by new code */
+                       u32 *source;
+                       len = -len;
+                       source = (u32 *)((ulong)&entry->replacement + entry->replacement);
+                       memcpy(from, source, 4 * len);
+               } else {
+                       /* Replace by one instruction */
+                       *from = replacement;
+               }
                applied++;
        }