[S390] pm: fix build error for !SMP
[safe/jmp/linux-2.6] / arch / sh / kernel / machine_kexec.c
index 6bcd8d9..7ea2704 100644 (file)
 #include <linux/kexec.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
+#include <linux/numa.h>
+#include <linux/ftrace.h>
+#include <linux/suspend.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
 #include <asm/mmu_context.h>
 #include <asm/io.h>
 #include <asm/cacheflush.h>
 
-typedef NORET_TYPE void (*relocate_new_kernel_t)(
-                               unsigned long indirection_page,
-                               unsigned long reboot_code_buffer,
-                               unsigned long start_address,
-                               unsigned long vbr_reg) ATTRIB_NORET;
+typedef void (*relocate_new_kernel_t)(unsigned long indirection_page,
+                                     unsigned long reboot_code_buffer,
+                                     unsigned long start_address);
 
 extern const unsigned char relocate_new_kernel[];
 extern const unsigned int relocate_new_kernel_size;
 extern void *gdb_vbr_vector;
-
-/*
- * Provide a dummy crash_notes definition while crash dump arrives to ppc.
- * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
- */
-void *crash_notes = NULL;
+extern void *vbr_base;
 
 void machine_shutdown(void)
 {
@@ -50,6 +46,12 @@ void machine_crash_shutdown(struct pt_regs *regs)
  */
 int machine_kexec_prepare(struct kimage *image)
 {
+       /* older versions of kexec-tools are passing
+        * the zImage entry point as a virtual address.
+        */
+       if (image->start != PHYSADDR(image->start))
+               return -EINVAL; /* upgrade your kexec-tools */
+
        return 0;
 }
 
@@ -65,30 +67,46 @@ static void kexec_info(struct kimage *image)
                printk("  segment[%d]: 0x%08x - 0x%08x (0x%08x)\n",
                       i,
                       (unsigned int)image->segment[i].mem,
-                      (unsigned int)image->segment[i].mem + image->segment[i].memsz,
+                      (unsigned int)image->segment[i].mem +
+                                    image->segment[i].memsz,
                       (unsigned int)image->segment[i].memsz);
-       }
+       }
        printk("  start     : 0x%08x\n\n", (unsigned int)image->start);
 }
 
-
 /*
  * Do not allocate memory (or fail in any way) in machine_kexec().
  * We are past the point of no return, committed to rebooting now.
  */
-NORET_TYPE void machine_kexec(struct kimage *image)
+void machine_kexec(struct kimage *image)
 {
-
        unsigned long page_list;
        unsigned long reboot_code_buffer;
-       unsigned long vbr_reg;
        relocate_new_kernel_t rnk;
-
-#if defined(CONFIG_SH_STANDARD_BIOS)
-       vbr_reg = ((unsigned long )gdb_vbr_vector) - 0x100;
-#else
-       vbr_reg = 0x80000000;  // dummy
+       unsigned long entry;
+       unsigned long *ptr;
+       int save_ftrace_enabled;
+
+       /*
+        * Nicked from the mips version of machine_kexec():
+        * The generic kexec code builds a page list with physical
+        * addresses. Use phys_to_virt() to convert them to virtual.
+        */
+       for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE);
+            ptr = (entry & IND_INDIRECTION) ?
+              phys_to_virt(entry & PAGE_MASK) : ptr + 1) {
+               if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION ||
+                   *ptr & IND_DESTINATION)
+                       *ptr = (unsigned long) phys_to_virt(*ptr);
+       }
+
+#ifdef CONFIG_KEXEC_JUMP
+       if (image->preserve_context)
+               save_processor_state();
 #endif
+
+       save_ftrace_enabled = __ftrace_enabled_save();
+
        /* Interrupts aren't acceptable while we reboot */
        local_irq_disable();
 
@@ -102,11 +120,43 @@ NORET_TYPE void machine_kexec(struct kimage *image)
        memcpy((void *)reboot_code_buffer, relocate_new_kernel,
                                                relocate_new_kernel_size);
 
-        kexec_info(image);
+       kexec_info(image);
        flush_cache_all();
 
+#if defined(CONFIG_SH_STANDARD_BIOS)
+       asm volatile("ldc %0, vbr" :
+                    : "r" (((unsigned long) gdb_vbr_vector) - 0x100)
+                    : "memory");
+#endif
+
        /* now call it */
        rnk = (relocate_new_kernel_t) reboot_code_buffer;
-               (*rnk)(page_list, reboot_code_buffer, image->start, vbr_reg);
+       (*rnk)(page_list, reboot_code_buffer,
+              (unsigned long)phys_to_virt(image->start));
+
+#ifdef CONFIG_KEXEC_JUMP
+       asm volatile("ldc %0, vbr" : : "r" (&vbr_base) : "memory");
+
+       if (image->preserve_context)
+               restore_processor_state();
+
+       /* Convert page list back to physical addresses, what a mess. */
+       for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE);
+            ptr = (*ptr & IND_INDIRECTION) ?
+              phys_to_virt(*ptr & PAGE_MASK) : ptr + 1) {
+               if (*ptr & IND_SOURCE || *ptr & IND_INDIRECTION ||
+                   *ptr & IND_DESTINATION)
+                       *ptr = virt_to_phys(*ptr);
+       }
+#endif
+
+       __ftrace_enabled_restore(save_ftrace_enabled);
 }
 
+void arch_crash_save_vmcoreinfo(void)
+{
+#ifdef CONFIG_NUMA
+       VMCOREINFO_SYMBOL(node_data);
+       VMCOREINFO_LENGTH(node_data, MAX_NUMNODES);
+#endif
+}