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

Re: [Xen-devel] kexec trouble

  Hi,

> Function pointers sound like the right way to go! Happy hacking!

First step of a cleanup by moving to function pointers.
Compile tested only.

First three attachments replace the patches with identical names in
patches/linux-2.6.  The last should be applied to the sparse tree.

cheers,
  Gerd

-- 
Gerd Hoffmann <kraxel@xxxxxxx>
---
 include/linux/kexec.h |   22 +++++++++++-
 kernel/kexec.c        |   85 ++++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 89 insertions(+), 18 deletions(-)

Index: kexec-2.6.16/include/linux/kexec.h
===================================================================
--- kexec-2.6.16.orig/include/linux/kexec.h
+++ kexec-2.6.16/include/linux/kexec.h
@@ -85,12 +85,30 @@ struct kimage {
 #define KEXEC_TYPE_CRASH   1
 };
 
-
-
 /* kexec interface functions */
+extern unsigned long (*kexec_page_to_pfn)(struct page *page);
+extern struct page* (*kexec_pfn_to_page)(unsigned long pfn);
+extern unsigned long (*kexec_virt_to_phys)(void *addr);
+extern void* (*kexec_phys_to_virt)(unsigned long addr);
+
+#ifdef KEXEC_ARCH_USES_HOOKS
+extern NORET_TYPE void (*machine_kexec)(struct kimage *image) ATTRIB_NORET;
+extern int (*machine_kexec_prepare)(struct kimage *image);
+extern int (*machine_kexec_load)(struct kimage *image);
+extern void (*machine_kexec_unload)(struct kimage *image);
+extern void (*machine_kexec_cleanup)(struct kimage *image);
+#else
 extern NORET_TYPE void machine_kexec(struct kimage *image) ATTRIB_NORET;
 extern int machine_kexec_prepare(struct kimage *image);
+static inline int machine_kexec_load(struct kimage *image) { return 0; }
+static inline void machine_kexec_unload(struct kimage *image) { }
 extern void machine_kexec_cleanup(struct kimage *image);
+#endif
+
+#ifdef CONFIG_XEN
+extern void xen_machine_kexec_setup_resources(void);
+extern void xen_machine_kexec_register_resources(struct resource *res);
+#endif
 extern asmlinkage long sys_kexec_load(unsigned long entry,
                                        unsigned long nr_segments,
                                        struct kexec_segment __user *segments,
Index: kexec-2.6.16/kernel/kexec.c
===================================================================
--- kexec-2.6.16.orig/kernel/kexec.c
+++ kexec-2.6.16/kernel/kexec.c
@@ -27,6 +27,31 @@
 #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);
+}
+
+unsigned long (*kexec_page_to_pfn)(struct page *page) = default_page_to_pfn;
+struct page* (*kexec_pfn_to_page)(unsigned long pfn)  = default_pfn_to_page;
+unsigned long (*kexec_virt_to_phys)(void *addr) = default_virt_to_phys;
+void* (*kexec_phys_to_virt)(unsigned long addr) = default_phys_to_virt;
+
 /* Per cpu memory for storing cpu states in case of system crash. */
 note_buf_t* crash_notes;
 
@@ -403,7 +428,7 @@ static struct page *kimage_alloc_normal_
                pages = kimage_alloc_pages(GFP_KERNEL, order);
                if (!pages)
                        break;
-               pfn   = page_to_pfn(pages);
+               pfn   = kexec_page_to_pfn(pages);
                epfn  = pfn + count;
                addr  = pfn << PAGE_SHIFT;
                eaddr = epfn << PAGE_SHIFT;
@@ -437,6 +462,7 @@ static struct page *kimage_alloc_normal_
        return pages;
 }
 
+#ifndef CONFIG_XEN
 static struct page *kimage_alloc_crash_control_pages(struct kimage *image,
                                                      unsigned int order)
 {
@@ -490,7 +516,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 = pfn_to_page(hole_start >> PAGE_SHIFT);
+                       pages = kexec_pfn_to_page(hole_start >> PAGE_SHIFT);
                        break;
                }
        }
@@ -517,6 +543,13 @@ struct page *kimage_alloc_control_pages(
 
        return pages;
 }
+#else /* !CONFIG_XEN */
+struct page *kimage_alloc_control_pages(struct kimage *image,
+                                        unsigned int order)
+{
+       return kimage_alloc_normal_control_pages(image, order);
+}
+#endif
 
 static int kimage_add_entry(struct kimage *image, kimage_entry_t entry)
 {
@@ -532,7 +565,7 @@ static int kimage_add_entry(struct kimag
                        return -ENOMEM;
 
                ind_page = page_address(page);
-               *image->entry = virt_to_phys(ind_page) | IND_INDIRECTION;
+               *image->entry = kexec_virt_to_phys(ind_page) | IND_INDIRECTION;
                image->entry = ind_page;
                image->last_entry = ind_page +
                                      ((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
@@ -593,13 +626,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)? \
-                       phys_to_virt((entry & PAGE_MASK)): ptr +1)
+                       kexec_phys_to_virt((entry & PAGE_MASK)): ptr +1)
 
 static void kimage_free_entry(kimage_entry_t entry)
 {
        struct page *page;
 
-       page = pfn_to_page(entry >> PAGE_SHIFT);
+       page = kexec_pfn_to_page(entry >> PAGE_SHIFT);
        kimage_free_pages(page);
 }
 
@@ -611,6 +644,9 @@ static void kimage_free(struct kimage *i
        if (!image)
                return;
 
+       if (machine_kexec_unload)
+               machine_kexec_unload(image);
+
        kimage_free_extra_pages(image);
        for_each_kimage_entry(image, ptr, entry) {
                if (entry & IND_INDIRECTION) {
@@ -630,7 +666,8 @@ static void kimage_free(struct kimage *i
                kimage_free_entry(ind);
 
        /* Handle any machine specific cleanup */
-       machine_kexec_cleanup(image);
+       if (machine_kexec_cleanup)
+               machine_kexec_cleanup(image);
 
        /* Free the kexec control pages... */
        kimage_free_page_list(&image->control_pages);
@@ -686,7 +723,7 @@ static struct page *kimage_alloc_page(st
         * have a match.
         */
        list_for_each_entry(page, &image->dest_pages, lru) {
-               addr = page_to_pfn(page) << PAGE_SHIFT;
+               addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
                if (addr == destination) {
                        list_del(&page->lru);
                        return page;
@@ -701,12 +738,12 @@ static struct page *kimage_alloc_page(st
                if (!page)
                        return NULL;
                /* If the page cannot be used file it away */
-               if (page_to_pfn(page) >
+               if (kexec_page_to_pfn(page) >
                                (KEXEC_SOURCE_MEMORY_LIMIT >> PAGE_SHIFT)) {
                        list_add(&page->lru, &image->unuseable_pages);
                        continue;
                }
-               addr = page_to_pfn(page) << PAGE_SHIFT;
+               addr = kexec_page_to_pfn(page) << PAGE_SHIFT;
 
                /* If it is the destination page we want use it */
                if (addr == destination)
@@ -729,7 +766,7 @@ static struct page *kimage_alloc_page(st
                        struct page *old_page;
 
                        old_addr = *old & PAGE_MASK;
-                       old_page = pfn_to_page(old_addr >> PAGE_SHIFT);
+                       old_page = kexec_pfn_to_page(old_addr >> PAGE_SHIFT);
                        copy_highpage(page, old_page);
                        *old = addr | (*old & ~PAGE_MASK);
 
@@ -779,7 +816,7 @@ static int kimage_load_normal_segment(st
                        result  = -ENOMEM;
                        goto out;
                }
-               result = kimage_add_page(image, page_to_pfn(page)
+               result = kimage_add_page(image, kexec_page_to_pfn(page)
                                                                << PAGE_SHIFT);
                if (result < 0)
                        goto out;
@@ -811,6 +848,7 @@ out:
        return result;
 }
 
+#ifndef CONFIG_XEN
 static int kimage_load_crash_segment(struct kimage *image,
                                        struct kexec_segment *segment)
 {
@@ -833,7 +871,7 @@ static int kimage_load_crash_segment(str
                char *ptr;
                size_t uchunk, mchunk;
 
-               page = pfn_to_page(maddr >> PAGE_SHIFT);
+               page = kexec_pfn_to_page(maddr >> PAGE_SHIFT);
                if (page == 0) {
                        result  = -ENOMEM;
                        goto out;
@@ -881,6 +919,13 @@ static int kimage_load_segment(struct ki
 
        return result;
 }
+#else /* CONFIG_XEN */
+static int kimage_load_segment(struct kimage *image,
+                               struct kexec_segment *segment)
+{
+       return kimage_load_normal_segment(image, segment);
+}
+#endif
 
 /*
  * Exec Kernel system call: for obvious reasons only root may call it.
@@ -978,9 +1023,11 @@ asmlinkage long sys_kexec_load(unsigned 
                if (result)
                        goto out;
 
-               result = machine_kexec_prepare(image);
-               if (result)
-                       goto out;
+               if (machine_kexec_prepare) {
+                       result = machine_kexec_prepare(image);
+                       if (result)
+                               goto out;
+               }
 
                for (i = 0; i < nr_segments; i++) {
                        result = kimage_load_segment(image, &image->segment[i]);
@@ -991,6 +1038,13 @@ asmlinkage long sys_kexec_load(unsigned 
                if (result)
                        goto out;
        }
+
+       if (machine_kexec_load) {
+               result = machine_kexec_load(image);
+               if (result)
+                       goto out;
+       }
+
        /* Install the new kernel, and  Uninstall the old */
        image = xchg(dest_image, image);
 
@@ -1045,7 +1099,6 @@ void crash_kexec(struct pt_regs *regs)
        struct kimage *image;
        int locked;
 
-
        /* Take the kexec_lock here to prevent sys_kexec_load
         * running on one cpu from replacing the crash kernel
         * we are using after a panic on a different cpu.
---
 arch/i386/kernel/crash.c         |    4 ++
 arch/i386/kernel/machine_kexec.c |   65 +++++++++++++++++++++++++--------------
 include/asm-i386/kexec.h         |    3 +
 3 files changed, 49 insertions(+), 23 deletions(-)

Index: kexec-2.6.16/arch/i386/kernel/crash.c
===================================================================
--- kexec-2.6.16.orig/arch/i386/kernel/crash.c
+++ kexec-2.6.16/arch/i386/kernel/crash.c
@@ -90,6 +90,7 @@ static void crash_save_self(struct pt_re
        crash_save_this_cpu(regs, cpu);
 }
 
+#ifndef CONFIG_XEN
 #ifdef CONFIG_SMP
 static atomic_t waiting_for_crash_ipi;
 
@@ -158,6 +159,7 @@ static void nmi_shootdown_cpus(void)
        /* There are no cpus to shootdown */
 }
 #endif
+#endif /* CONFIG_XEN */
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
@@ -174,10 +176,12 @@ void machine_crash_shutdown(struct pt_re
 
        /* Make a note of crashing cpu. Will be used in NMI callback.*/
        crashing_cpu = smp_processor_id();
+#ifndef CONFIG_XEN
        nmi_shootdown_cpus();
        lapic_shutdown();
 #if defined(CONFIG_X86_IO_APIC)
        disable_IO_APIC();
 #endif
+#endif /* CONFIG_XEN */
        crash_save_self(regs);
 }
Index: kexec-2.6.16/arch/i386/kernel/machine_kexec.c
===================================================================
--- kexec-2.6.16.orig/arch/i386/kernel/machine_kexec.c
+++ kexec-2.6.16/arch/i386/kernel/machine_kexec.c
@@ -19,6 +19,10 @@
 #include <asm/desc.h>
 #include <asm/system.h>
 
+#ifdef CONFIG_XEN
+#include <xen/interface/kexec.h>
+#endif
+
 #define PAGE_ALIGNED __attribute__ ((__aligned__(PAGE_SIZE)))
 static u32 kexec_pgd[1024] PAGE_ALIGNED;
 #ifdef CONFIG_X86_PAE
@@ -28,37 +32,45 @@ static u32 kexec_pmd1[1024] PAGE_ALIGNED
 static u32 kexec_pte0[1024] PAGE_ALIGNED;
 static u32 kexec_pte1[1024] PAGE_ALIGNED;
 
-/*
- * A architecture hook called to validate the
- * proposed image and prepare the control pages
- * as needed.  The pages for KEXEC_CONTROL_CODE_SIZE
- * have been allocated, but the segments have yet
- * been copied into the kernel.
- *
- * Do what every setup is needed on image and the
- * reboot code buffer to allow us to avoid allocations
- * later.
- *
- * Currently nothing.
- */
-int machine_kexec_prepare(struct kimage *image)
-{
-       return 0;
-}
+#ifdef CONFIG_XEN
 
-/*
- * Undo anything leftover by machine_kexec_prepare
- * when an image is freed.
- */
-void machine_kexec_cleanup(struct kimage *image)
+#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT)
+
+#if PAGES_NR > KEXEC_XEN_NO_PAGES
+#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break
+#endif
+
+#if PA_CONTROL_PAGE != 0
+#error PA_CONTROL_PAGE is non zero - Xen support will break
+#endif
+
+void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
 {
+       void *control_page;
+
+       memset(xki->page_list, 0, sizeof(xki->page_list));
+
+       control_page = page_address(image->control_code_page);
+       memcpy(control_page, relocate_kernel, PAGE_SIZE);
+
+       xki->page_list[PA_CONTROL_PAGE] = __ma(control_page);
+       xki->page_list[PA_PGD] = __ma(kexec_pgd);
+#ifdef CONFIG_X86_PAE
+       xki->page_list[PA_PMD_0] = __ma(kexec_pmd0);
+       xki->page_list[PA_PMD_1] = __ma(kexec_pmd1);
+#endif
+       xki->page_list[PA_PTE_0] = __ma(kexec_pte0);
+       xki->page_list[PA_PTE_1] = __ma(kexec_pte1);
+
 }
 
+#endif /* 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.
  */
-NORET_TYPE void machine_kexec(struct kimage *image)
+static NORET_TYPE ATTRIB_NORET void native_machine_kexec(struct kimage *image)
 {
        unsigned long page_list[PAGES_NR];
        void *control_page;
@@ -87,3 +99,10 @@ NORET_TYPE void machine_kexec(struct kim
        relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
                        image->start, cpu_has_pae);
 }
+
+NORET_TYPE void (*machine_kexec)(struct kimage *image) ATTRIB_NORET
+       = native_machine_kexec;
+int (*machine_kexec_prepare)(struct kimage *image)  = NULL;
+int (*machine_kexec_load)(struct kimage *image)     = NULL;
+void (*machine_kexec_unload)(struct kimage *image)  = NULL;
+void (*machine_kexec_cleanup)(struct kimage *image) = NULL;
Index: kexec-2.6.16/include/asm-i386/kexec.h
===================================================================
--- kexec-2.6.16.orig/include/asm-i386/kexec.h
+++ kexec-2.6.16/include/asm-i386/kexec.h
@@ -98,6 +98,9 @@ relocate_kernel(unsigned long indirectio
                unsigned long start_address,
                unsigned int has_pae) ATTRIB_NORET;
 
+
+#define KEXEC_ARCH_USES_HOOKS 1
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _I386_KEXEC_H */
---
 arch/x86_64/kernel/crash.c         |    6 +
 arch/x86_64/kernel/machine_kexec.c |  133 +++++++++++++++++++++++++++++++++----
 include/asm-x86_64/kexec.h         |    7 +
 3 files changed, 132 insertions(+), 14 deletions(-)

Index: kexec-2.6.16/arch/x86_64/kernel/crash.c
===================================================================
--- kexec-2.6.16.orig/arch/x86_64/kernel/crash.c
+++ kexec-2.6.16/arch/x86_64/kernel/crash.c
@@ -92,6 +92,7 @@ static void crash_save_self(struct pt_re
        crash_save_this_cpu(regs, cpu);
 }
 
+#ifndef CONFIG_XEN
 #ifdef CONFIG_SMP
 static atomic_t waiting_for_crash_ipi;
 
@@ -156,6 +157,7 @@ static void nmi_shootdown_cpus(void)
        /* There are no cpus to shootdown */
 }
 #endif
+#endif /* CONFIG_XEN */
 
 void machine_crash_shutdown(struct pt_regs *regs)
 {
@@ -173,6 +175,8 @@ void machine_crash_shutdown(struct pt_re
 
        /* Make a note of crashing cpu. Will be used in NMI callback.*/
        crashing_cpu = smp_processor_id();
+
+#ifndef CONFIG_XEN
        nmi_shootdown_cpus();
 
        if(cpu_has_apic)
@@ -181,6 +185,6 @@ void machine_crash_shutdown(struct pt_re
 #if defined(CONFIG_X86_IO_APIC)
        disable_IO_APIC();
 #endif
-
+#endif /* CONFIG_XEN */
        crash_save_self(regs);
 }
Index: kexec-2.6.16/arch/x86_64/kernel/machine_kexec.c
===================================================================
--- kexec-2.6.16.orig/arch/x86_64/kernel/machine_kexec.c
+++ kexec-2.6.16/arch/x86_64/kernel/machine_kexec.c
@@ -24,6 +24,104 @@ static u64 kexec_pud1[512] PAGE_ALIGNED;
 static u64 kexec_pmd1[512] PAGE_ALIGNED;
 static u64 kexec_pte1[512] PAGE_ALIGNED;
 
+#ifdef CONFIG_XEN
+
+/* In the case of Xen, override hypervisor functions to be able to create
+ * a regular identity mapping page table...
+ */
+
+#include <xen/interface/kexec.h>
+#include <xen/interface/memory.h>
+
+#define x__pmd(x) ((pmd_t) { (x) } )
+#define x__pud(x) ((pud_t) { (x) } )
+#define x__pgd(x) ((pgd_t) { (x) } )
+
+#define x_pmd_val(x)   ((x).pmd)
+#define x_pud_val(x)   ((x).pud)
+#define x_pgd_val(x)   ((x).pgd)
+
+static inline void x_set_pmd(pmd_t *dst, pmd_t val)
+{
+       x_pmd_val(*dst) = x_pmd_val(val);
+}
+
+static inline void x_set_pud(pud_t *dst, pud_t val)
+{
+       x_pud_val(*dst) = phys_to_machine(x_pud_val(val));
+}
+
+static inline void x_pud_clear (pud_t *pud)
+{
+       x_pud_val(*pud) = 0;
+}
+
+static inline void x_set_pgd(pgd_t *dst, pgd_t val)
+{
+       x_pgd_val(*dst) = phys_to_machine(x_pgd_val(val));
+}
+
+static inline void x_pgd_clear (pgd_t * pgd)
+{
+       x_pgd_val(*pgd) = 0;
+}
+
+#define X__PAGE_KERNEL_LARGE_EXEC \
+         _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_PSE
+#define X_KERNPG_TABLE _PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY
+
+#define __ma(x) (pfn_to_mfn(__pa((x)) >> PAGE_SHIFT) << PAGE_SHIFT)
+
+#if PAGES_NR > KEXEC_XEN_NO_PAGES
+#error PAGES_NR is greater than KEXEC_XEN_NO_PAGES - Xen support will break
+#endif
+
+#if PA_CONTROL_PAGE != 0
+#error PA_CONTROL_PAGE is non zero - Xen support will break
+#endif
+
+void machine_kexec_setup_load_arg(xen_kexec_image_t *xki, struct kimage *image)
+{
+       void *control_page;
+       void *table_page;
+
+       memset(xki->page_list, 0, sizeof(xki->page_list));
+
+       control_page = page_address(image->control_code_page) + PAGE_SIZE;
+       memcpy(control_page, relocate_kernel, PAGE_SIZE);
+
+       table_page = page_address(image->control_code_page);
+
+       xki->page_list[PA_CONTROL_PAGE] = __ma(control_page);
+       xki->page_list[PA_TABLE_PAGE] = __ma(table_page);
+
+       xki->page_list[PA_PGD] = __ma(kexec_pgd);
+       xki->page_list[PA_PUD_0] = __ma(kexec_pud0);
+       xki->page_list[PA_PUD_1] = __ma(kexec_pud1);
+       xki->page_list[PA_PMD_0] = __ma(kexec_pmd0);
+       xki->page_list[PA_PMD_1] = __ma(kexec_pmd1);
+       xki->page_list[PA_PTE_0] = __ma(kexec_pte0);
+       xki->page_list[PA_PTE_1] = __ma(kexec_pte1);
+}
+
+#else /* CONFIG_XEN */
+
+#define x__pmd(x) __pmd(x)
+#define x__pud(x) __pud(x)
+#define x__pgd(x) __pgd(x)
+
+#define x_set_pmd(x, y) set_pmd(x, y)
+#define x_set_pud(x, y) set_pud(x, y)
+#define x_set_pgd(x, y) set_pgd(x, y)
+
+#define x_pud_clear(x) pud_clear(x)
+#define x_pgd_clear(x) pgd_clear(x)
+
+#define X__PAGE_KERNEL_LARGE_EXEC __PAGE_KERNEL_LARGE_EXEC
+#define X_KERNPG_TABLE _KERNPG_TABLE
+
+#endif /* CONFIG_XEN */
+
 static void init_level2_page(pmd_t *level2p, unsigned long addr)
 {
        unsigned long end_addr;
@@ -31,7 +129,7 @@ static void init_level2_page(pmd_t *leve
        addr &= PAGE_MASK;
        end_addr = addr + PUD_SIZE;
        while (addr < end_addr) {
-               set_pmd(level2p++, __pmd(addr | __PAGE_KERNEL_LARGE_EXEC));
+               x_set_pmd(level2p++, x__pmd(addr | X__PAGE_KERNEL_LARGE_EXEC));
                addr += PMD_SIZE;
        }
 }
@@ -56,12 +154,12 @@ static int init_level3_page(struct kimag
                }
                level2p = (pmd_t *)page_address(page);
                init_level2_page(level2p, addr);
-               set_pud(level3p++, __pud(__pa(level2p) | _KERNPG_TABLE));
+               x_set_pud(level3p++, x__pud(__pa(level2p) | X_KERNPG_TABLE));
                addr += PUD_SIZE;
        }
        /* clear the unused entries */
        while (addr < end_addr) {
-               pud_clear(level3p++);
+               x_pud_clear(level3p++);
                addr += PUD_SIZE;
        }
 out:
@@ -92,12 +190,12 @@ static int init_level4_page(struct kimag
                if (result) {
                        goto out;
                }
-               set_pgd(level4p++, __pgd(__pa(level3p) | _KERNPG_TABLE));
+               x_set_pgd(level4p++, x__pgd(__pa(level3p) | X_KERNPG_TABLE));
                addr += PGDIR_SIZE;
        }
        /* clear the unused entries */
        while (addr < end_addr) {
-               pgd_clear(level4p++);
+               x_pgd_clear(level4p++);
                addr += PGDIR_SIZE;
        }
 out:
@@ -108,11 +206,17 @@ out:
 static int init_pgtable(struct kimage *image, unsigned long start_pgtable)
 {
        pgd_t *level4p;
+       unsigned long x_end_pfn = end_pfn;
+
+#ifdef CONFIG_XEN
+       x_end_pfn = HYPERVISOR_memory_op(XENMEM_maximum_ram_page, NULL);
+#endif
+
        level4p = (pgd_t *)__va(start_pgtable);
-       return init_level4_page(image, level4p, 0, end_pfn << PAGE_SHIFT);
+       return init_level4_page(image, level4p, 0, x_end_pfn << PAGE_SHIFT);
 }
 
-int machine_kexec_prepare(struct kimage *image)
+static int native_machine_kexec_prepare(struct kimage *image)
 {
        unsigned long start_pgtable;
        int result;
@@ -128,16 +232,11 @@ int machine_kexec_prepare(struct kimage 
        return 0;
 }
 
-void machine_kexec_cleanup(struct kimage *image)
-{
-       return;
-}
-
 /*
  * 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)
+static NORET_TYPE ATTRIB_NORET void native_machine_kexec(struct kimage *image)
 {
        unsigned long page_list[PAGES_NR];
        void *control_page;
@@ -171,3 +270,11 @@ NORET_TYPE void machine_kexec(struct kim
        relocate_kernel((unsigned long)image->head, (unsigned long)page_list,
                        image->start);
 }
+
+NORET_TYPE void (*machine_kexec)(struct kimage *image) ATTRIB_NORET
+       = native_machine_kexec;
+int (*machine_kexec_prepare)(struct kimage *image)
+       = native_machine_kexec_prepare;
+int (*machine_kexec_load)(struct kimage *image)     = NULL;
+void (*machine_kexec_unload)(struct kimage *image)  = NULL;
+void (*machine_kexec_cleanup)(struct kimage *image) = NULL;
Index: kexec-2.6.16/include/asm-x86_64/kexec.h
===================================================================
--- kexec-2.6.16.orig/include/asm-x86_64/kexec.h
+++ kexec-2.6.16/include/asm-x86_64/kexec.h
@@ -91,6 +91,13 @@ 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.
+ */
+
+#define KEXEC_ARCH_USES_HOOKS 1
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _X86_64_KEXEC_H */
---
 drivers/xen/core/machine_kexec.c |   42 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 39 insertions(+), 3 deletions(-)

Index: kexec-2.6.16/drivers/xen/core/machine_kexec.c
===================================================================
--- kexec-2.6.16.orig/drivers/xen/core/machine_kexec.c
+++ kexec-2.6.16/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;
@@ -24,6 +25,7 @@ void xen_machine_kexec_setup_resources(v
 
        if (!is_initial_xendomain())
                return;
+       xen0_set_hooks();
 
        /* determine maximum number of physical cpus */
 
@@ -124,7 +126,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;
 
@@ -140,7 +142,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;
 
@@ -157,7 +159,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 xen_machine_kexec(struct kimage *image)
+static NORET_TYPE void xen0_machine_kexec(struct kimage *image)
 {
        xen_kexec_exec_t xke;
 
@@ -172,6 +174,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_page_to_pfn  = xen0_page_to_pfn;
+       kexec_pfn_to_page  = xen0_pfn_to_page;
+       kexec_virt_to_phys = xen0_virt_to_phys;
+       kexec_phys_to_virt = xen0_phys_to_virt;
+
+       machine_kexec_load   = xen0_machine_kexec_load;
+       machine_kexec_unload = xen0_machine_kexec_unload;
+       machine_kexec        = xen0_machine_kexec;
+
+       printk("%s: kexec hook setup done\n", __FUNCTION__);
+}
 
 /*
  * Local variables:
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel