Merge branch 'for_paulus' of master.kernel.org:/pub/scm/linux/kernel/git/galak/powerpc
[pandora-kernel.git] / kernel / kexec.c
index cdd4dcd..50087ec 100644 (file)
@@ -6,6 +6,7 @@
  * Version 2.  See the file COPYING for more details.
  */
 
+#include <linux/capability.h>
 #include <linux/mm.h>
 #include <linux/file.h>
 #include <linux/slab.h>
@@ -26,6 +27,9 @@
 #include <asm/system.h>
 #include <asm/semaphore.h>
 
+/* Per cpu memory for storing cpu states in case of system crash. */
+note_buf_t* crash_notes;
+
 /* Location of the reserved area for the crash kernel */
 struct resource crashk_res = {
        .name  = "Crash kernel",
@@ -90,7 +94,7 @@ int kexec_should_crash(struct task_struct *p)
 static int kimage_is_destination_range(struct kimage *image,
                                       unsigned long start, unsigned long end);
 static struct page *kimage_alloc_page(struct kimage *image,
-                                      unsigned int gfp_mask,
+                                      gfp_t gfp_mask,
                                       unsigned long dest);
 
 static int do_kimage_alloc(struct kimage **rimage, unsigned long entry,
@@ -326,8 +330,7 @@ static int kimage_is_destination_range(struct kimage *image,
        return 0;
 }
 
-static struct page *kimage_alloc_pages(unsigned int gfp_mask,
-                                       unsigned int order)
+static struct page *kimage_alloc_pages(gfp_t gfp_mask, unsigned int order)
 {
        struct page *pages;
 
@@ -335,7 +338,7 @@ static struct page *kimage_alloc_pages(unsigned int gfp_mask,
        if (pages) {
                unsigned int count, i;
                pages->mapping = NULL;
-               pages->private = order;
+               set_page_private(pages, order);
                count = 1 << order;
                for (i = 0; i < count; i++)
                        SetPageReserved(pages + i);
@@ -348,7 +351,7 @@ static void kimage_free_pages(struct page *page)
 {
        unsigned int order, count, i;
 
-       order = page->private;
+       order = page_private(page);
        count = 1 << order;
        for (i = 0; i < count; i++)
                ClearPageReserved(page + i);
@@ -654,7 +657,7 @@ static kimage_entry_t *kimage_dst_used(struct kimage *image,
 }
 
 static struct page *kimage_alloc_page(struct kimage *image,
-                                       unsigned int gfp_mask,
+                                       gfp_t gfp_mask,
                                        unsigned long destination)
 {
        /*
@@ -899,14 +902,14 @@ static int kimage_load_segment(struct kimage *image,
  * kexec does not sync, or unmount filesystems so if you need
  * that to happen you need to do that yourself.
  */
-struct kimage *kexec_image = NULL;
-static struct kimage *kexec_crash_image = NULL;
+struct kimage *kexec_image;
+struct kimage *kexec_crash_image;
 /*
  * A home grown binary mutex.
  * Nothing can wait so this mutex is safe to use
  * in interrupt context :)
  */
-static int kexec_lock = 0;
+static int kexec_lock;
 
 asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments,
                                struct kexec_segment __user *segments,
@@ -1039,7 +1042,6 @@ asmlinkage long compat_sys_kexec_load(unsigned long entry,
 
 void crash_kexec(struct pt_regs *regs)
 {
-       struct kimage *image;
        int locked;
 
 
@@ -1053,11 +1055,25 @@ void crash_kexec(struct pt_regs *regs)
         */
        locked = xchg(&kexec_lock, 1);
        if (!locked) {
-               image = xchg(&kexec_crash_image, NULL);
-               if (image) {
-                       machine_crash_shutdown(regs);
-                       machine_kexec(image);
+               if (kexec_crash_image) {
+                       struct pt_regs fixed_regs;
+                       crash_setup_regs(&fixed_regs, regs);
+                       machine_crash_shutdown(&fixed_regs);
+                       machine_kexec(kexec_crash_image);
                }
                xchg(&kexec_lock, 0);
        }
 }
+
+static int __init crash_notes_memory_init(void)
+{
+       /* Allocate memory for saving cpu registers. */
+       crash_notes = alloc_percpu(note_buf_t);
+       if (!crash_notes) {
+               printk("Kexec: Memory allocation for saving cpu register"
+               " states failed\n");
+               return -ENOMEM;
+       }
+       return 0;
+}
+module_init(crash_notes_memory_init)