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>
This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2005-11-09 14:39:32 +01:00
1 parent b99415e527
commit 4b6d60a8f0
6 files changed
+49 -13

No files matched your search

@@ -152,8 +152,11 @@ void *dma_alloc_coherent(struct device *dev, size_t size,
ret = (void *)vstart;
if (ret != NULL) {
xen_create_contiguous_region(vstart, order);
/* NB. Hardcode 31 address bits for now: aacraid limitation. */
if (xen_create_contiguous_region(vstart, order, 31) != 0) {
free_pages(vstart, order);
return NULL;
}
memset(ret, 0, size);
*dma_handle = virt_to_bus(ret);
}
@@ -117,6 +117,7 @@ void
swiotlb_init_with_default_size (size_t default_size)
{
unsigned long i, bytes;
int rc;
if (!iotlb_nslabs) {
iotlb_nslabs = (default_size >> IO_TLB_SHIFT);
@@ -137,8 +138,10 @@ swiotlb_init_with_default_size (size_t default_size)
"Use dom0_mem Xen boot parameter to reserve\n"
"some DMA memory (e.g., dom0_mem=-128M).\n");
xen_create_contiguous_region(
(unsigned long)iotlb_virt_start, get_order(bytes));
/* Hardcode 31 address bits for now: aacraid limitation. */
rc = xen_create_contiguous_region(
(unsigned long)iotlb_virt_start, get_order(bytes), 31);
BUG_ON(rc);
/*
* Allocate and initialize the free list array. This array is used
@@ -314,7 +314,8 @@ static void contiguous_bitmap_clear(
}
/* Ensure multi-page extents are contiguous in machine memory. */
void xen_create_contiguous_region(unsigned long vstart, unsigned int order)
int xen_create_contiguous_region(
unsigned long vstart, unsigned int order, unsigned int address_bits)
{
pgd_t *pgd;
pud_t *pud;
@@ -349,9 +350,10 @@ void xen_create_contiguous_region(unsigned long vstart, unsigned int order)
/* 2. Get a new contiguous memory extent. */
reservation.extent_order = order;
reservation.address_bits = 31; /* aacraid limitation */
BUG_ON(HYPERVISOR_memory_op(
XENMEM_increase_reservation, &reservation) != 1);
reservation.address_bits = address_bits;
if (HYPERVISOR_memory_op(XENMEM_increase_reservation,
&reservation) != 1)
goto fail;
/* 3. Map the new extent in place of old pages. */
for (i = 0; i < (1<<order); i++) {
@@ -367,6 +369,28 @@ void xen_create_contiguous_region(unsigned long vstart, unsigned int order)
contiguous_bitmap_set(__pa(vstart) >> PAGE_SHIFT, 1UL << order);
balloon_unlock(flags);
return 0;
fail:
reservation.extent_order = 0;
reservation.address_bits = 0;
for (i = 0; i < (1<<order); i++) {
BUG_ON(HYPERVISOR_memory_op(
XENMEM_increase_reservation, &reservation) != 1);
BUG_ON(HYPERVISOR_update_va_mapping(
vstart + (i*PAGE_SIZE),
pfn_pte_ma(mfn, PAGE_KERNEL), 0));
xen_machphys_update(mfn, (__pa(vstart)>>PAGE_SHIFT)+i);
phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] = mfn;
}
flush_tlb_all();
balloon_unlock(flags);
return -ENOMEM;
}
void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
@@ -279,8 +279,9 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
unsigned long flags;
#ifdef CONFIG_X86_PAE
/* this gives us a page below 4GB */
xen_create_contiguous_region((unsigned long)pgd, 0);
/* Ensure pgd resides below 4GB. */
int rc = xen_create_contiguous_region((unsigned long)pgd, 0, 32);
BUG_ON(rc);
#endif
if (!HAVE_SHARED_KERNEL_PMD)
@@ -79,8 +79,10 @@ static void skbuff_ctor(void *buf, kmem_cache_t *cachep, unsigned long unused)
while (skbuff_order_cachep[order] != cachep)
order++;
/* Do our best to allocate contiguous memory but fall back to IOMMU. */
if (order != 0)
xen_create_contiguous_region((unsigned long)buf, order);
(void)xen_create_contiguous_region(
(unsigned long)buf, order, 0);
scrub_pages(buf, 1 << order);
}
@@ -129,8 +129,11 @@ void xen_invlpg_mask(cpumask_t *mask, unsigned long ptr);
#define EXPORT_PER_CPU_SYMBOL_GPL(var) EXPORT_SYMBOL_GPL(per_cpu__##var)
#endif /* linux < 2.6.0 */
void xen_create_contiguous_region(unsigned long vstart, unsigned int order);
void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
/* Returns zero on success else negative errno. */
int xen_create_contiguous_region(
unsigned long vstart, unsigned int order, unsigned int address_bits);
void xen_destroy_contiguous_region(
unsigned long vstart, unsigned int order);
#include <asm/hypercall.h>
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.