direct-io.hg

changeset 7708:356c175366a1

Allow xen_create_contiguous_region() to fail gracefully if it
cannot allocate a contiguous multi-page extent of memory. This
should avoid unnecessary crashes in the xen-specific skbuff
cache constructor.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Wed Nov 09 14:39:32 2005 +0100 (2005-11-09)
parents 5066d2aa2fb0
children 6b62605e77b5
files linux-2.6-xen-sparse/arch/xen/i386/kernel/pci-dma.c linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c linux-2.6-xen-sparse/arch/xen/kernel/skbuff.c linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypervisor.h
line diff
     1.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/pci-dma.c	Wed Nov 09 13:59:53 2005 +0100
     1.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/pci-dma.c	Wed Nov 09 14:39:32 2005 +0100
     1.3 @@ -152,8 +152,11 @@ void *dma_alloc_coherent(struct device *
     1.4  	ret = (void *)vstart;
     1.5  
     1.6  	if (ret != NULL) {
     1.7 -		xen_create_contiguous_region(vstart, order);
     1.8 -
     1.9 +		/* NB. Hardcode 31 address bits for now: aacraid limitation. */
    1.10 +		if (xen_create_contiguous_region(vstart, order, 31) != 0) {
    1.11 +			free_pages(vstart, order);
    1.12 +			return NULL;
    1.13 +		}
    1.14  		memset(ret, 0, size);
    1.15  		*dma_handle = virt_to_bus(ret);
    1.16  	}
     2.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c	Wed Nov 09 13:59:53 2005 +0100
     2.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/kernel/swiotlb.c	Wed Nov 09 14:39:32 2005 +0100
     2.3 @@ -117,6 +117,7 @@ void
     2.4  swiotlb_init_with_default_size (size_t default_size)
     2.5  {
     2.6  	unsigned long i, bytes;
     2.7 +	int rc;
     2.8  
     2.9  	if (!iotlb_nslabs) {
    2.10  		iotlb_nslabs = (default_size >> IO_TLB_SHIFT);
    2.11 @@ -137,8 +138,10 @@ swiotlb_init_with_default_size (size_t d
    2.12  		      "Use dom0_mem Xen boot parameter to reserve\n"
    2.13  		      "some DMA memory (e.g., dom0_mem=-128M).\n");
    2.14  
    2.15 -	xen_create_contiguous_region(
    2.16 -		(unsigned long)iotlb_virt_start, get_order(bytes));
    2.17 +	/* Hardcode 31 address bits for now: aacraid limitation. */
    2.18 +	rc = xen_create_contiguous_region(
    2.19 +		(unsigned long)iotlb_virt_start, get_order(bytes), 31);
    2.20 +	BUG_ON(rc);
    2.21  
    2.22  	/*
    2.23  	 * Allocate and initialize the free list array.  This array is used
     3.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c	Wed Nov 09 13:59:53 2005 +0100
     3.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c	Wed Nov 09 14:39:32 2005 +0100
     3.3 @@ -314,7 +314,8 @@ static void contiguous_bitmap_clear(
     3.4  }
     3.5  
     3.6  /* Ensure multi-page extents are contiguous in machine memory. */
     3.7 -void xen_create_contiguous_region(unsigned long vstart, unsigned int order)
     3.8 +int xen_create_contiguous_region(
     3.9 +	unsigned long vstart, unsigned int order, unsigned int address_bits)
    3.10  {
    3.11  	pgd_t         *pgd; 
    3.12  	pud_t         *pud; 
    3.13 @@ -349,9 +350,10 @@ void xen_create_contiguous_region(unsign
    3.14  
    3.15  	/* 2. Get a new contiguous memory extent. */
    3.16  	reservation.extent_order = order;
    3.17 -	reservation.address_bits = 31; /* aacraid limitation */
    3.18 -	BUG_ON(HYPERVISOR_memory_op(
    3.19 -		XENMEM_increase_reservation, &reservation) != 1);
    3.20 +	reservation.address_bits = address_bits;
    3.21 +	if (HYPERVISOR_memory_op(XENMEM_increase_reservation,
    3.22 +				 &reservation) != 1)
    3.23 +		goto fail;
    3.24  
    3.25  	/* 3. Map the new extent in place of old pages. */
    3.26  	for (i = 0; i < (1<<order); i++) {
    3.27 @@ -367,6 +369,28 @@ void xen_create_contiguous_region(unsign
    3.28  	contiguous_bitmap_set(__pa(vstart) >> PAGE_SHIFT, 1UL << order);
    3.29  
    3.30  	balloon_unlock(flags);
    3.31 +
    3.32 +	return 0;
    3.33 +
    3.34 + fail:
    3.35 +	reservation.extent_order = 0;
    3.36 +	reservation.address_bits = 0;
    3.37 +
    3.38 +	for (i = 0; i < (1<<order); i++) {
    3.39 +		BUG_ON(HYPERVISOR_memory_op(
    3.40 +			XENMEM_increase_reservation, &reservation) != 1);
    3.41 +		BUG_ON(HYPERVISOR_update_va_mapping(
    3.42 +			vstart + (i*PAGE_SIZE),
    3.43 +			pfn_pte_ma(mfn, PAGE_KERNEL), 0));
    3.44 +		xen_machphys_update(mfn, (__pa(vstart)>>PAGE_SHIFT)+i);
    3.45 +		phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] = mfn;
    3.46 +	}
    3.47 +
    3.48 +	flush_tlb_all();
    3.49 +
    3.50 +	balloon_unlock(flags);
    3.51 +
    3.52 +	return -ENOMEM;
    3.53  }
    3.54  
    3.55  void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
     4.1 --- a/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c	Wed Nov 09 13:59:53 2005 +0100
     4.2 +++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/pgtable.c	Wed Nov 09 14:39:32 2005 +0100
     4.3 @@ -279,8 +279,9 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
     4.4  	unsigned long flags;
     4.5  
     4.6  #ifdef CONFIG_X86_PAE
     4.7 -	/* this gives us a page below 4GB */
     4.8 -	xen_create_contiguous_region((unsigned long)pgd, 0);
     4.9 +	/* Ensure pgd resides below 4GB. */
    4.10 +	int rc = xen_create_contiguous_region((unsigned long)pgd, 0, 32);
    4.11 +	BUG_ON(rc);
    4.12  #endif
    4.13  
    4.14  	if (!HAVE_SHARED_KERNEL_PMD)
     5.1 --- a/linux-2.6-xen-sparse/arch/xen/kernel/skbuff.c	Wed Nov 09 13:59:53 2005 +0100
     5.2 +++ b/linux-2.6-xen-sparse/arch/xen/kernel/skbuff.c	Wed Nov 09 14:39:32 2005 +0100
     5.3 @@ -79,8 +79,10 @@ static void skbuff_ctor(void *buf, kmem_
     5.4  	while (skbuff_order_cachep[order] != cachep)
     5.5  		order++;
     5.6  
     5.7 +	/* Do our best to allocate contiguous memory but fall back to IOMMU. */
     5.8  	if (order != 0)
     5.9 -		xen_create_contiguous_region((unsigned long)buf, order);
    5.10 +		(void)xen_create_contiguous_region(
    5.11 +			(unsigned long)buf, order, 0);
    5.12  
    5.13  	scrub_pages(buf, 1 << order);
    5.14  }
     6.1 --- a/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypervisor.h	Wed Nov 09 13:59:53 2005 +0100
     6.2 +++ b/linux-2.6-xen-sparse/include/asm-xen/asm-i386/hypervisor.h	Wed Nov 09 14:39:32 2005 +0100
     6.3 @@ -129,8 +129,11 @@ void xen_invlpg_mask(cpumask_t *mask, un
     6.4  #define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
     6.5  #endif /* linux < 2.6.0 */
     6.6  
     6.7 -void xen_create_contiguous_region(unsigned long vstart, unsigned int order);
     6.8 -void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
     6.9 +/* Returns zero on success else negative errno. */
    6.10 +int xen_create_contiguous_region(
    6.11 +    unsigned long vstart, unsigned int order, unsigned int address_bits);
    6.12 +void xen_destroy_contiguous_region(
    6.13 +    unsigned long vstart, unsigned int order);
    6.14  
    6.15  #include <asm/hypercall.h>
    6.16