#include <linux/init.h>
 #include <linux/list.h>
 
-#define CALL_BACK              5
+#include <asm/alternative.h>
 
-#define JMPFWD                 0x03eb
+#define CALL_BACK              5
 
-static unsigned short ftrace_jmp = JMPFWD;
+/* Long is fine, even if it is only 4 bytes ;-) */
+static long *ftrace_nop;
 
 struct ftrace_record {
        struct dyn_ftrace       rec;
 notrace struct dyn_ftrace *ftrace_alloc_shutdown_node(unsigned long ip)
 {
        struct ftrace_record *rec;
-       unsigned short save;
+       unsigned long save;
 
        ip -= CALL_BACK;
-       save = *(short *)ip;
+       save = *(long *)ip;
 
        /* If this was already converted, skip it */
-       if (save == JMPFWD)
+       if (save == *ftrace_nop)
                return NULL;
 
        if (ftrace_pages->index == ENTRIES_PER_PAGE) {
 ftrace_modify_code(unsigned long ip, unsigned char *old_code,
                   unsigned char *new_code)
 {
-       unsigned short old = *(unsigned short *)old_code;
-       unsigned short new = *(unsigned short *)new_code;
-       unsigned short replaced;
+       unsigned replaced;
+       unsigned old = *(unsigned *)old_code; /* 4 bytes */
+       unsigned new = *(unsigned *)new_code; /* 4 bytes */
+       unsigned char newch = new_code[4];
        int faulted = 0;
 
        /*
         */
        asm volatile (
                "1: lock\n"
-               "   cmpxchg %w3, (%2)\n"
+               "   cmpxchg %3, (%2)\n"
+               "   jnz 2f\n"
+               "   movb %b4, 4(%2)\n"
                "2:\n"
                ".section .fixup, \"ax\"\n"
                "       movl $1, %0\n"
                ".previous\n"
                _ASM_EXTABLE(1b, 3b)
                : "=r"(faulted), "=a"(replaced)
-               : "r"(ip), "r"(new), "0"(faulted), "a"(old)
+               : "r"(ip), "r"(new), "r"(newch),
+                 "0"(faulted), "a"(old)
                : "memory");
        sync_core();
 
-       if (replaced != old)
+       if (replaced != old && replaced != new)
                faulted = 2;
 
        return faulted;
        /* move the IP back to the start of the call */
        ip -= CALL_BACK;
 
-       r->failed = ftrace_modify_code(ip, save.code, (char *)&ftrace_jmp);
+       r->failed = ftrace_modify_code(ip, save.code, (char *)ftrace_nop);
 }
 
 static void notrace ftrace_replace_code(int saved)
        int i;
 
        if (saved)
-               old = (char *)&ftrace_jmp;
+               old = (char *)ftrace_nop;
        else
-               new = (char *)&ftrace_jmp;
+               new = (char *)ftrace_nop;
 
        for (pg = ftrace_pages_start; pg; pg = pg->next) {
                for (i = 0; i < pg->index; i++) {
        ftrace_pages->next = (void *)get_zeroed_page(GFP_KERNEL);
 }
 
-notrace int ftrace_shutdown_arch_init(void)
+notrace int __init ftrace_shutdown_arch_init(void)
 {
+       const unsigned char *const *noptable = find_nop_table();
        struct ftrace_page *pg;
        int cnt;
        int i;
 
+       ftrace_nop = (unsigned long *)noptable[CALL_BACK];
+
        /* allocate a few pages */
        ftrace_pages_start = (void *)get_zeroed_page(GFP_KERNEL);
        if (!ftrace_pages_start)