Re: [PATCH 06/11] x86/xen: Add i386 kexec/kdump implementation
From: Daniel Kiper
Date: Mon Oct 01 2012 - 09:16:30 EST
On Fri, Sep 28, 2012 at 12:39:44PM -0400, Konrad Rzeszutek Wilk wrote:
> On Thu, Sep 27, 2012 at 08:06:33PM +0200, Daniel Kiper wrote:
> > Add i386 kexec/kdump implementation.
> >
> > Signed-off-by: Daniel Kiper <daniel.kiper@xxxxxxxxxx>
> > ---
> > arch/x86/xen/machine_kexec_32.c | 245 ++++++++++++++++++++++++++++
> > arch/x86/xen/relocate_kernel_32.S | 323 +++++++++++++++++++++++++++++++++++++
> > 2 files changed, 568 insertions(+), 0 deletions(-)
> > create mode 100644 arch/x86/xen/machine_kexec_32.c
> > create mode 100644 arch/x86/xen/relocate_kernel_32.S
> >
> > diff --git a/arch/x86/xen/machine_kexec_32.c b/arch/x86/xen/machine_kexec_32.c
> > new file mode 100644
> > index 0000000..6b5141e
> > --- /dev/null
> > +++ b/arch/x86/xen/machine_kexec_32.c
> > @@ -0,0 +1,245 @@
> > +/*
> > + * Copyright (c) 2011 Daniel Kiper
> > + * Copyright (c) 2012 Daniel Kiper, Oracle Corporation
> > + *
> > + * kexec/kdump implementation for Xen was written by Daniel Kiper.
> > + * Initial work on it was sponsored by Google under Google Summer
> > + * of Code 2011 program and Citrix. Konrad Rzeszutek Wilk from Oracle
> > + * was the mentor for this project.
> > + *
> > + * Some ideas are taken from:
> > + * - native kexec/kdump implementation,
> > + * - kexec/kdump implementation for Xen Linux Kernel Ver. 2.6.18,
> > + * - PV-GRUB.
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License along
> > + * with this program. If not, see <http://www.gnu.org/licenses/>.
> > + */
> > +
> > +#include <linux/errno.h>
> > +#include <linux/init.h>
> > +#include <linux/kernel.h>
> > +#include <linux/kexec.h>
> > +#include <linux/mm.h>
> > +#include <linux/string.h>
> > +
> > +#include <xen/xen.h>
> > +#include <xen/xen-ops.h>
> > +
> > +#include <asm/xen/hypercall.h>
> > +#include <asm/xen/kexec.h>
> > +#include <asm/xen/page.h>
> > +
> > +#define __ma(vaddr) (virt_to_machine(vaddr).maddr)
> > +
> > +static struct page *kimage_alloc_pages(gfp_t gfp_mask,
> > + unsigned int order,
> > + unsigned long limit)
> > +{
> > + struct page *pages;
> > + unsigned int address_bits, i;
> > +
> > + pages = alloc_pages(gfp_mask, order);
> > +
> > + if (!pages)
> > + return NULL;
> > +
> > + address_bits = (limit == ULONG_MAX) ? BITS_PER_LONG : ilog2(limit);
> > +
> > + /* Relocate set of pages below given limit. */
> > + if (xen_create_contiguous_region((unsigned long)page_address(pages),
> > + order, address_bits)) {
> > + __free_pages(pages, order);
> > + return NULL;
> > + }
> > +
> > + pages->mapping = NULL;
>
> It shouldn't matter (as you did the alloc_page) but could you
> add:
> BUG_ON(PagePrivate(pages))
> in case somebody did do something weird beforehand.
OK.
> > + set_page_private(pages, order);
> > +
> > + for (i = 0; i < (1 << order); ++i)
> > + SetPageReserved(pages + i);
> > +
> > + return pages;
> > +}
> > +
> > +static void kimage_free_pages(struct page *page)
> > +{
> > + unsigned int i, order;
> > +
> > + order = page_private(page);
> > +
> > + for (i = 0; i < (1 << order); ++i)
> > + ClearPageReserved(page + i);
> > +
> > + xen_destroy_contiguous_region((unsigned long)page_address(page), order);
> > + __free_pages(page, order);
> > +}
> > +
> > +static unsigned long xen_page_to_mfn(struct page *page)
> > +{
> > + return pfn_to_mfn(page_to_pfn(page));
> > +}
> > +
> > +static struct page *xen_mfn_to_page(unsigned long mfn)
> > +{
> > + return pfn_to_page(mfn_to_pfn(mfn));
> > +}
> > +
> > +static unsigned long xen_virt_to_machine(volatile void *address)
> > +{
> > + return virt_to_machine(address).maddr;
> > +}
> > +
> > +static void *xen_machine_to_virt(unsigned long address)
> > +{
> > + return phys_to_virt(machine_to_phys(XMADDR(address)).paddr);
> > +}
> > +
> > +static void free_transition_pgtable(struct kimage *image)
> > +{
> > + free_page((unsigned long)image->arch.pgd);
> > + free_page((unsigned long)image->arch.pmd0);
> > + free_page((unsigned long)image->arch.pmd1);
> > + free_page((unsigned long)image->arch.pte0);
> > + free_page((unsigned long)image->arch.pte1);
> > +}
> > +
> > +static int alloc_transition_pgtable(struct kimage *image)
> > +{
> > + image->arch.pgd = (pgd_t *)get_zeroed_page(GFP_KERNEL);
> > +
> > + if (!image->arch.pgd)
> > + goto err;
> > +
> > + image->arch.pmd0 = (pmd_t *)get_zeroed_page(GFP_KERNEL);
> > +
> > + if (!image->arch.pmd0)
> > + goto err;
> > +
> > + image->arch.pmd1 = (pmd_t *)get_zeroed_page(GFP_KERNEL);
> > +
> > + if (!image->arch.pmd1)
> > + goto err;
> > +
> > + image->arch.pte0 = (pte_t *)get_zeroed_page(GFP_KERNEL);
> > +
> > + if (!image->arch.pte0)
> > + goto err;
> > +
> > + image->arch.pte1 = (pte_t *)get_zeroed_page(GFP_KERNEL);
> > +
> > + if (!image->arch.pte1)
> > + goto err;
> > +
> > + return 0;
> > +
> > +err:
> > + free_transition_pgtable(image);
> > +
> > + return -ENOMEM;
> > +}
> > +
> > +static int machine_xen_kexec_prepare(struct kimage *image)
> > +{
> > +#ifdef CONFIG_KEXEC_JUMP
> > + if (image->preserve_context) {
> > + pr_info_once("kexec: Context preservation is not "
> > + "supported in Xen domains.\n");
> > + return -ENOSYS;
> > + }
> > +#endif
> > +
> > + return alloc_transition_pgtable(image);
> > +}
> > +
> > +static int machine_xen_kexec_load(struct kimage *image)
> > +{
> > + void *control_page;
> > + struct xen_kexec_load xkl = {};
> > +
> > + if (!image)
> > + return 0;
>
> Not -EINVAL?
No, if image == NULL then it means that image is unloaded from memory
and there is nothing to do by machine_xen_kexec_load().
Daniel
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/