mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
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:
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>
|
||||
|
||||
|
||||