Magnus Damm wrote:
> I think using a structure for all callbacks will result in cleaner
> code. This is sort of a nitpick because it does not really matter
> function wise, but it sounded earlier like you were aiming for
> something that would be directly acceptable by the kexec and kdump
> community. And I'm all for cleanliness.
>
> Personally I would go with changing the code in kernel/kexec.c to
> instead of calling machine_kexec() call kexec_ops.machine_kexec().
> This regardless of the use of KEXEC_ARCH_USES_HOOKS. Then I would have
> a single global instance of the structure kexec_ops declared in
> kernel/kexec.c, and it would by default fill in
> kexec_ops.machine_kexec() to machine_kexec. That way you won't have to
> rename the arch-specific functions and there is no need to declare the
> hooks in the arch-specific files. Maybe you won't need
> KEXEC_ARCH_USES_HOOKS at all.
Yep, good idea, that works without the hooks define (and also without
touching all architectures which I want to avoid too).
> The load and unload code may be broken today if KEXEC_ARCH_USES_HOOKS
> is unset - can you really check if machine_kexec_load is non-NULL if
> it is inline?
Didn't check what gcc made out of it. It's a moot point now anyway with
the switch to a ops struct.
> The reason why I did put the page-macros in arch-specific header files
> was because they need to be different on ia64. So your unification in
> drivers/xen/core/machine_kexec.c may be ok for now (if our goal is x86
> only), but in the future we need to figure out how to change them
> nicely on ia64.
I simply wasn't aware of the ia64 issue. Well, maybe we should simply
create a arch/$arch/kernel/machine_kexec_xen0.c file with that kind of
code placed into. And maybe move the arch-independant xen bits in
driver/xen/core/machine_kexec.c to bits to kernel/kexec_xen0, but I
think that discussion better should be defered until we are actually
seeking mainline merge. Maybe we get our own subdirectory below kernel/
for that kind of stuff. There is some more code which is arch-specific
on native but simply a hypercall on xen, smpboot.c for example.
> You probably remember that I was kind of negative to trying to solve
> mainline merge issues at the same time as implementing this "switch".
> This was because I remembered that paravirt allowed patching of inline
> machine code. At least that's the impression I got from a presentation
> given here in Tokyo by Rusty. I think the page macros ideally should
> be patched in, but it's kind of hard trying to do that without
> paravirt..
Yep, there is, to get some percent performace improvements for hot path
code. Which IMHO isn't true for the kexec bits. It isn't performance
critical, usually you load a kexec kernel only once, I don't think it is
worth the trouble.
> Finally, we should get rid of the #ifdef CONFIG_XEN left here and
> there. My main concern is the code in crash.c which need to be
> replaced with runtime checks if we are aiming for a single binary for
> both native and dom0. I left out domU because it doesn't do crash,
> right?
I expect *lots* of changes in that area (apic/smp) anyway when we
upgrade the xen linux tree to be based on 2.6.20-rc1 or newer. paravirt
infrastructure is in Linus' tree now. I'd wait until that is done then
look again.
> If you have an updated snapshot (or a replay saying I should use this
> version) then I'll try out the code the first thing next week.
Updated patches attached.
cheers,
Gerd
--
Gerd Hoffmann <kraxel@xxxxxxx>
---
include/linux/kexec.h | 19 ++++++++++
kernel/kexec.c | 90 +++++++++++++++++++++++++++++++++++++++++---------
2 files changed, 92 insertions(+), 17 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,29 @@ 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 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,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 = page_to_pfn(pages);
+ pfn = kexec_ops.kpage_to_pfn(pages);
epfn = pfn + count;
addr = pfn << PAGE_SHIFT;
eaddr = epfn << PAGE_SHIFT;
@@ -437,6 +467,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 +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 = pfn_to_page(hole_start >> PAGE_SHIFT);
+ pages = kexec_ops.kpfn_to_page(hole_start >>
PAGE_SHIFT);
break;
}
}
@@ -517,6 +548,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 +570,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_ops.kvirt_to_phys(ind_page) |
IND_INDIRECTION;
image->entry = ind_page;
image->last_entry = ind_page +
((PAGE_SIZE/sizeof(kimage_entry_t)) - 1);
@@ -593,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)? \
- 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 = pfn_to_page(entry >> PAGE_SHIFT);
+ page = kexec_ops.kpfn_to_page(entry >> PAGE_SHIFT);
kimage_free_pages(page);
}
@@ -611,6 +649,9 @@ static void kimage_free(struct kimage *i
if (!image)
return;
+ if (kexec_ops.kexec_unload)
+ kexec_ops.kexec_unload(image);
+
kimage_free_extra_pages(image);
for_each_kimage_entry(image, ptr, entry) {
if (entry & IND_INDIRECTION) {
@@ -630,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);
@@ -686,7 +728,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_ops.kpage_to_pfn(page) << PAGE_SHIFT;
if (addr == destination) {
list_del(&page->lru);
return page;
@@ -701,12 +743,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_ops.kpage_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_ops.kpage_to_pfn(page) << PAGE_SHIFT;
/* If it is the destination page we want use it */
if (addr == destination)
@@ -729,7 +771,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_ops.kpfn_to_page(old_addr >>
PAGE_SHIFT);
copy_highpage(page, old_page);
*old = addr | (*old & ~PAGE_MASK);
@@ -779,7 +821,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_ops.kpage_to_pfn(page)
<< PAGE_SHIFT);
if (result < 0)
goto out;
@@ -811,6 +853,7 @@ out:
return result;
}
+#ifndef CONFIG_XEN
static int kimage_load_crash_segment(struct kimage *image,
struct kexec_segment *segment)
{
@@ -833,7 +876,7 @@ static int kimage_load_crash_segment(str
char *ptr;
size_t uchunk, mchunk;
- page = pfn_to_page(maddr >> PAGE_SHIFT);
+ page = kexec_ops.kpfn_to_page(maddr >> PAGE_SHIFT);
if (page == 0) {
result = -ENOMEM;
goto out;
@@ -881,6 +924,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 +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]);
@@ -991,6 +1043,13 @@ asmlinkage long sys_kexec_load(unsigned
if (result)
goto out;
}
+
+ 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);
@@ -1045,7 +1104,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 | 38 ++++++++++++++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
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
@@ -54,6 +58,40 @@ void machine_kexec_cleanup(struct kimage
{
}
+#ifdef CONFIG_XEN
+
+#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.
---
arch/x86_64/kernel/crash.c | 6 +
arch/x86_64/kernel/machine_kexec.c | 116 +++++++++++++++++++++++++++++++++++--
2 files changed, 115 insertions(+), 7 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,8 +206,14 @@ 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)
---
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 ATTRIB_NORET 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_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:
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|