[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [patch] Add kexec_ops & function pointers



Signed-off-by: Gerd Hoffmann <kraxel@xxxxxxx>
---
 linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c   |    2 
 linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c |    2 
 linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c   |   42 +++++++-
 linux-2.6-xen-sparse/include/asm-i386/kexec.h           |   14 --
 linux-2.6-xen-sparse/include/asm-x86_64/kexec.h         |   13 --
 linux-2.6-xen-sparse/include/linux/kexec.h              |   24 ++--
 linux-2.6-xen-sparse/kernel/kexec.c                     |   80 +++++++++++-----
 7 files changed, 110 insertions(+), 67 deletions(-)

Index: 
build-32-unstable-12809/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c
===================================================================
--- 
build-32-unstable-12809.orig/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c
+++ 
build-32-unstable-12809/linux-2.6-xen-sparse/arch/i386/kernel/machine_kexec.c
@@ -92,7 +92,6 @@ void machine_kexec_cleanup(struct kimage
 {
 }
 
-#ifndef CONFIG_XEN
 /*
  * Do not allocate memory (or fail in any way) in machine_kexec().
  * We are past the point of no return, committed to rebooting now.
@@ -126,4 +125,3 @@ NORET_TYPE void machine_kexec(struct kim
        relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
                        image->start, cpu_has_pae);
 }
-#endif
Index: 
build-32-unstable-12809/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c
===================================================================
--- 
build-32-unstable-12809.orig/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c
+++ 
build-32-unstable-12809/linux-2.6-xen-sparse/arch/x86_64/kernel/machine_kexec.c
@@ -237,7 +237,6 @@ void machine_kexec_cleanup(struct kimage
        return;
 }
 
-#ifndef CONFIG_XEN
 /*
  * Do not allocate memory (or fail in any way) in machine_kexec().
  * We are past the point of no return, committed to rebooting now.
@@ -276,4 +275,3 @@ NORET_TYPE void machine_kexec(struct kim
        relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
                        image->start);
 }
-#endif
Index: 
build-32-unstable-12809/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
===================================================================
--- 
build-32-unstable-12809.orig/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
+++ 
build-32-unstable-12809/linux-2.6-xen-sparse/drivers/xen/core/machine_kexec.c
@@ -11,6 +11,7 @@
 
 extern void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, 
                                         struct kimage *image);
+static void xen0_set_hooks(void);
 
 int xen_max_nr_phys_cpus;
 struct resource xen_hypervisor_res;
@@ -93,6 +94,7 @@ void xen_machine_kexec_setup_resources(v
                crashk_res.end = range.start + range.size - 1;
        }
 
+       xen0_set_hooks();
        return;
 
  err:
@@ -130,7 +132,7 @@ static void setup_load_arg(xen_kexec_ima
  * is currently called too early. It might make sense
  * to move prepare, but for now, just add an extra hook.
  */
-int xen_machine_kexec_load(struct kimage *image)
+static int xen0_machine_kexec_load(struct kimage *image)
 {
        xen_kexec_load_t xkl;
 
@@ -146,7 +148,7 @@ int xen_machine_kexec_load(struct kimage
  * is called too late, and its possible xen could try and kdump
  * using resources that have been freed.
  */
-void xen_machine_kexec_unload(struct kimage *image)
+static void xen0_machine_kexec_unload(struct kimage *image)
 {
        xen_kexec_load_t xkl;
 
@@ -163,7 +165,7 @@ void xen_machine_kexec_unload(struct kim
  * stop all CPUs and kexec. That is it combines machine_shutdown()
  * and machine_kexec() in Linux kexec terms.
  */
-NORET_TYPE void machine_kexec(struct kimage *image)
+static NORET_TYPE ATTRIB_NORET void xen0_machine_kexec(struct kimage *image)
 {
        xen_kexec_exec_t xke;
 
@@ -178,6 +180,40 @@ void machine_shutdown(void)
        /* do nothing */
 }
 
+static unsigned long xen0_page_to_pfn(struct page *page)
+{
+       return pfn_to_mfn(page_to_pfn(page));
+}
+
+static struct page* xen0_pfn_to_page(unsigned long pfn)
+{
+       return pfn_to_page(mfn_to_pfn(pfn));
+}
+
+static unsigned long xen0_virt_to_phys(void *addr)
+{
+       return virt_to_machine(addr);
+}
+
+static void* xen0_phys_to_virt(unsigned long addr)
+{
+       return phys_to_virt(machine_to_phys(addr));
+}
+
+
+static void xen0_set_hooks(void)
+{
+       kexec_ops.kpage_to_pfn  = xen0_page_to_pfn;
+       kexec_ops.kpfn_to_page  = xen0_pfn_to_page;
+       kexec_ops.kvirt_to_phys = xen0_virt_to_phys;
+       kexec_ops.kphys_to_virt = xen0_phys_to_virt;
+
+       kexec_ops.kexec         = xen0_machine_kexec;
+       kexec_ops.kexec_load    = xen0_machine_kexec_load;
+       kexec_ops.kexec_unload  = xen0_machine_kexec_unload;
+
+       printk("%s: kexec hook setup done\n", __FUNCTION__);
+}
 
 /*
  * Local variables:
Index: build-32-unstable-12809/linux-2.6-xen-sparse/include/asm-i386/kexec.h
===================================================================
--- build-32-unstable-12809.orig/linux-2.6-xen-sparse/include/asm-i386/kexec.h
+++ build-32-unstable-12809/linux-2.6-xen-sparse/include/asm-i386/kexec.h
@@ -98,20 +98,6 @@ relocate_kernel(unsigned long indirectio
                unsigned long start_address,
                unsigned int has_pae) ATTRIB_NORET;
 
-
-/* Under Xen we need to work with machine addresses. These macros give the
- * machine address of a certain page to the generic kexec code instead of 
- * the pseudo physical address which would be given by the default macros.
- */
-
-#ifdef CONFIG_XEN
-#define KEXEC_ARCH_HAS_PAGE_MACROS
-#define kexec_page_to_pfn(page)  pfn_to_mfn(page_to_pfn(page))
-#define kexec_pfn_to_page(pfn)   pfn_to_page(mfn_to_pfn(pfn))
-#define kexec_virt_to_phys(addr) virt_to_machine(addr)
-#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr))
-#endif
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* _I386_KEXEC_H */
Index: build-32-unstable-12809/linux-2.6-xen-sparse/include/asm-x86_64/kexec.h
===================================================================
--- build-32-unstable-12809.orig/linux-2.6-xen-sparse/include/asm-x86_64/kexec.h
+++ build-32-unstable-12809/linux-2.6-xen-sparse/include/asm-x86_64/kexec.h
@@ -91,19 +91,6 @@ relocate_kernel(unsigned long indirectio
                unsigned long page_list,
                unsigned long start_address) ATTRIB_NORET;
 
-/* Under Xen we need to work with machine addresses. These macros give the
- * machine address of a certain page to the generic kexec code instead of 
- * the pseudo physical address which would be given by the default macros.
- */
-
-#ifdef CONFIG_XEN
-#define KEXEC_ARCH_HAS_PAGE_MACROS
-#define kexec_page_to_pfn(page)  pfn_to_mfn(page_to_pfn(page))
-#define kexec_pfn_to_page(pfn)   pfn_to_page(mfn_to_pfn(pfn))
-#define kexec_virt_to_phys(addr) virt_to_machine(addr)
-#define kexec_phys_to_virt(addr) phys_to_virt(machine_to_phys(addr))
-#endif
-
 #endif /* __ASSEMBLY__ */
 
 #endif /* _X86_64_KEXEC_H */
Index: build-32-unstable-12809/linux-2.6-xen-sparse/include/linux/kexec.h
===================================================================
--- build-32-unstable-12809.orig/linux-2.6-xen-sparse/include/linux/kexec.h
+++ build-32-unstable-12809/linux-2.6-xen-sparse/include/linux/kexec.h
@@ -31,13 +31,6 @@
 #error KEXEC_ARCH not defined
 #endif
 
-#ifndef KEXEC_ARCH_HAS_PAGE_MACROS
-#define kexec_page_to_pfn(page)  page_to_pfn(page)
-#define kexec_pfn_to_page(pfn)   pfn_to_page(pfn)
-#define kexec_virt_to_phys(addr) virt_to_phys(addr)
-#define kexec_phys_to_virt(addr) phys_to_virt(addr)
-#endif
-
 /*
  * This structure is used to hold the arguments that are used when loading
  * kernel binaries.
@@ -92,15 +85,26 @@ struct kimage {
 #define KEXEC_TYPE_CRASH   1
 };
 
+/* kexec interface functions */
+struct kexec_machine_ops {
+    unsigned long (*kpage_to_pfn)(struct page *page);
+    struct page* (*kpfn_to_page)(unsigned long pfn);
+    unsigned long (*kvirt_to_phys)(void *addr);
+    void* (*kphys_to_virt)(unsigned long addr);
 
+    NORET_TYPE void (*kexec)(struct kimage *image) ATTRIB_NORET;
+    int (*kexec_prepare)(struct kimage *image);
+    int (*kexec_load)(struct kimage *image);
+    void (*kexec_unload)(struct kimage *image);
+    void (*kexec_cleanup)(struct kimage *image);
+};
+extern struct kexec_machine_ops kexec_ops;
 
-/* kexec interface functions */
 extern NORET_TYPE void machine_kexec(struct kimage *image) ATTRIB_NORET;
 extern int machine_kexec_prepare(struct kimage *image);
 extern void machine_kexec_cleanup(struct kimage *image);
+
 #ifdef CONFIG_XEN
-extern int xen_machine_kexec_load(struct kimage *image);
-extern void xen_machine_kexec_unload(struct kimage *image);
 extern void xen_machine_kexec_setup_resources(void);
 extern void xen_machine_kexec_register_resources(struct resource *res);
 #endif
Index: build-32-unstable-12809/linux-2.6-xen-sparse/kernel/kexec.c
===================================================================
--- build-32-unstable-12809.orig/linux-2.6-xen-sparse/kernel/kexec.c
+++ build-32-unstable-12809/linux-2.6-xen-sparse/kernel/kexec.c
@@ -27,6 +27,36 @@
 #include <asm/system.h>
 #include <asm/semaphore.h>
 
+static unsigned long default_page_to_pfn(struct page *page)
+{
+       return page_to_pfn(page);
+}
+
+static struct page* default_pfn_to_page(unsigned long pfn)
+{
+       return pfn_to_page(pfn);
+}
+
+static unsigned long default_virt_to_phys(void *addr)
+{
+       return virt_to_phys(addr);
+}
+
+static void* default_phys_to_virt(unsigned long addr)
+{
+       return phys_to_virt(addr);
+}
+
+struct kexec_machine_ops kexec_ops = {
+    .kpage_to_pfn  = default_page_to_pfn,
+    .kpfn_to_page  = default_pfn_to_page,
+    .kvirt_to_phys = default_virt_to_phys,
+    .kphys_to_virt = default_phys_to_virt,
+    .kexec         = machine_kexec,
+    .kexec_prepare = machine_kexec_prepare,
+    .kexec_cleanup = machine_kexec_cleanup,
+};
+
 /* Per cpu memory for storing cpu states in case of system crash. */
 note_buf_t* crash_notes;
 
@@ -403,7 +433,7 @@ static struct page *kimage_alloc_normal_
                pages = kimage_alloc_pages(GFP_KERNEL, order);
                if (!pages)
                        break;
-               pfn   = kexec_page_to_pfn(pages);
+               pfn   = kexec_ops.kpage_to_pfn(pages);
                epfn  = pfn + count;
                addr  = pfn << PAGE_SHIFT;
                eaddr = epfn << PAGE_SHIFT;
@@ -491,7 +521,7 @@ static struct page *kimage_alloc_crash_c
                }
                /* If I don't overlap any segments I have found my hole! */
                if (i == image->nr_segments) {
-                       pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT);
+                       pages = kexec_ops.kpfn_to_page(hole_start >> 
PAGE_SHIFT);
                        break;
                }
        }
@@ -540,7 +570,7 @@ static int kimage_add_entry(struct kimag
                        return -ENOMEM;
 
                ind_page = page_address(page);
-               *image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION;
+               *image->entry = kexec_ops.kvirt_to_phys(ind_page) | 
IND_INDIRECTION;
                image->entry = ind_page;
                image->last_entry = ind_page +
                                      ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
@@ -601,13 +631,13 @@ static int kimage_terminate(struct kimag
 #define for_each_kimage_entry(image, ptr, entry) \
        for (ptr = &image->head; (entry = *ptr) && !(entry & IND_DONE); \
                ptr = (entry & IND_INDIRECTION)? \
-                       kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1)
+                       kexec_ops.kphys_to_virt((entry & PAGE_MASK)): ptr +1)
 
 static void kimage_free_entry(kimage_entry_t entry)
 {
        struct page *page;
 
-       page = kexec_pfn_to_page(entry >> PAGE_SHIFT);
+       page = kexec_ops.kpfn_to_page(entry >> PAGE_SHIFT);
        kimage_free_pages(page);
 }
 
@@ -619,9 +649,8 @@ static void kimage_free(struct kimage *i
        if (!image)
                return;
 
-#ifdef CONFIG_XEN
-       xen_machine_kexec_unload(image);
-#endif
+       if (kexec_ops.kexec_unload)
+               kexec_ops.kexec_unload(image);
 
        kimage_free_extra_pages(image);
        for_each_kimage_entry(image, ptr, entry) {
@@ -642,7 +671,8 @@ static void kimage_free(struct kimage *i
                kimage_free_entry(ind);
 
        /* Handle any machine specific cleanup */
-       machine_kexec_cleanup(image);
+       if (kexec_ops.kexec_cleanup)
+               kexec_ops.kexec_cleanup(image);
 
        /* Free the kexec control pages... */
        kimage_free_page_list(&image->control_pages);
@@ -698,7 +728,7 @@ static struct page *kimage_alloc_page(st
         * have a match.
         */
        list_for_each_entry(page, &image->dest_pages, lru) {
-               addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
+               addr = kexec_ops.kpage_to_pfn(page) << PAGE_SHIFT;
                if (addr == destination) {
                        list_del(&page->lru);
                        return page;
@@ -713,12 +743,12 @@ static struct page *kimage_alloc_page(st
                if (!page)
                        return NULL;
                /* If the page cannot be used file it away */
-               if (kexec_page_to_pfn(page) >
+               if (kexec_ops.kpage_to_pfn(page) >
                                (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
                        list_add(&page->lru, &image->unuseable_pages);
                        continue;
                }
-               addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
+               addr = kexec_ops.kpage_to_pfn(page) << PAGE_SHIFT;
 
                /* If it is the destination page we want use it */
                if (addr == destination)
@@ -741,7 +771,7 @@ static struct page *kimage_alloc_page(st
                        struct page *old_page;
 
                        old_addr = *old & PAGE_MASK;
-                       old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT);
+                       old_page = kexec_ops.kpfn_to_page(old_addr >> 
PAGE_SHIFT);
                        copy_highpage(page, old_page);
                        *old = addr | (*old & ~PAGE_MASK);
 
@@ -791,7 +821,7 @@ static int kimage_load_normal_segment(st
                        result  = -ENOMEM;
                        goto out;
                }
-               result = kimage_add_page(image, kexec_page_to_pfn(page)
+               result = kimage_add_page(image, kexec_ops.kpage_to_pfn(page)
                                                                << PAGE_SHIFT);
                if (result < 0)
                        goto out;
@@ -846,7 +876,7 @@ static int kimage_load_crash_segment(str
                char *ptr;
                size_t uchunk, mchunk;
 
-               page = kexec_pfn_to_page(maddr >> PAGE_SHIFT);
+               page = kexec_ops.kpfn_to_page(maddr >> PAGE_SHIFT);
                if (page == 0) {
                        result  = -ENOMEM;
                        goto out;
@@ -998,9 +1028,11 @@ asmlinkage long sys_kexec_load(unsigned 
                if (result)
                        goto out;
 
-               result = machine_kexec_prepare(image);
-               if (result)
-                       goto out;
+               if (kexec_ops.kexec_prepare) {
+                       result = kexec_ops.kexec_prepare(image);
+                       if (result)
+                               goto out;
+               }
 
                for (i = 0; i < nr_segments; i++) {
                        result = kimage_load_segment(image, &image->segment[i]);
@@ -1011,11 +1043,13 @@ asmlinkage long sys_kexec_load(unsigned 
                if (result)
                        goto out;
        }
-#ifdef CONFIG_XEN
-       result = xen_machine_kexec_load(image);
-       if (result)
-               goto out;
-#endif
+
+       if (kexec_ops.kexec_load) {
+               result = kexec_ops.kexec_load(image);
+               if (result)
+                       goto out;
+       }
+
        /* Install the new kernel, and  Uninstall the old */
        image = xchg(dest_image, image);
 

-- 


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.