WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

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

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [patch] Add kexec_ops & function pointers
From: Gerd Hoffmann <kraxel@xxxxxxx>
Date: Fri, 08 Dec 2006 17:17:44 +0100
Cc: magnus.damm@xxxxxxxxx
Delivery-date: Fri, 08 Dec 2006 08:18:05 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: quilt/0.46-14
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