]> git.zerfleddert.de Git - ms2-kexec/blobdiff - machine_kexec.c
update kexec to 2.6.39 version, still doesn't work...
[ms2-kexec] / machine_kexec.c
index 598ca61e7bca8496a853128a433dc7d1dfba0edf..531120f6769ec3ed24b409b365f4fcb56b636e96 100644 (file)
@@ -23,6 +23,8 @@ extern unsigned long kexec_indirection_page;
 extern unsigned long kexec_mach_type;
 extern unsigned long kexec_boot_atags;
 
+static atomic_t waiting_for_crash_ipi;
+
 /*
  * Provide a dummy crash_notes definition while crash dump arrives to arm.
  * This prevents breakage of crash_notes attribute in kernel/ksysfs.c.
@@ -37,14 +39,47 @@ void machine_kexec_cleanup(struct kimage *image)
 {
 }
 
-void machine_shutdown(void)
+void machine_crash_nonpanic_core(void *unused)
 {
+       struct pt_regs regs;
+
+       crash_setup_regs(&regs, NULL);
+       printk(KERN_DEBUG "CPU %u will stop doing anything useful since another CPU has crashed\n",
+              smp_processor_id());
+       crash_save_cpu(&regs, smp_processor_id());
+       flush_cache_all();
+
+       atomic_dec(&waiting_for_crash_ipi);
+       while (1)
+               cpu_relax();
 }
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
+       unsigned long msecs;
+
+       local_irq_disable();
+
+       atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
+       smp_call_function(machine_crash_nonpanic_core, NULL, false);
+       msecs = 1000; /* Wait at most a second for the other cpus to stop */
+       while ((atomic_read(&waiting_for_crash_ipi) > 0) && msecs) {
+               mdelay(1);
+               msecs--;
+       }
+       if (atomic_read(&waiting_for_crash_ipi) > 0)
+               printk(KERN_WARNING "Non-crashing CPUs did not react to IPI\n");
+
+       crash_save_cpu(regs, smp_processor_id());
+
+       printk(KERN_INFO "Loading crashdump kernel...\n");
 }
 
+/*
+ * Function pointer to optional machine-specific reinitialization
+ */
+void (*kexec_reinit)(void);
+
 void machine_kexec(struct kimage *image)
 {
        unsigned long page_list;
@@ -74,7 +109,20 @@ void machine_kexec(struct kimage *image)
                           (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
        printk(KERN_INFO "Bye!\n");
 
-       cpu_proc_fin();
+       if (kexec_reinit)
+               kexec_reinit();
+       local_irq_disable();
+       local_fiq_disable();
        setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
+       flush_cache_all();
+#if 0
+       outer_flush_all();
+       outer_disable();
+#endif
+       cpu_proc_fin();
+#if 0
+       outer_inv_all();
+#endif
+       flush_cache_all();
        cpu_reset(reboot_code_buffer_phys);
 }
Impressum, Datenschutz