ia64/linux-2.6.18-xen.hg

annotate arch/ia64/xen/xen_dma.c @ 897:329ea0ccb344

balloon: try harder to balloon up under memory pressure.

Currently if the balloon driver is unable to increase the guest's
reservation it assumes the failure was due to reaching its full
allocation, gives up on the ballooning operation and records the limit
it reached as the "hard limit". The driver will not try again until
the target is set again (even to the same value).

However it is possible that ballooning has in fact failed due to
memory pressure in the host and therefore it is desirable to keep
attempting to reach the target in case memory becomes available. The
most likely scenario is that some guests are ballooning down while
others are ballooning up and therefore there is temporary memory
pressure while things stabilise. You would not expect a well behaved
toolstack to ask a domain to balloon to more than its allocation nor
would you expect it to deliberately over-commit memory by setting
balloon targets which exceed the total host memory.

This patch drops the concept of a hard limit and causes the balloon
driver to retry increasing the reservation on a timer in the same
manner as when decreasing the reservation.

Also if we partially succeed in increasing the reservation
(i.e. receive less pages than we asked for) then we may as well keep
those pages rather than returning them to Xen.

Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Fri Jun 05 14:01:20 2009 +0100 (2009-06-05)
parents e410857fd83c
children
rev   line source
ian@26 1 /*
ian@26 2 * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
ian@26 3 * Alex Williamson <alex.williamson@hp.com>
ian@26 4 *
ian@26 5 * Basic DMA mapping services for Xen guests.
ian@26 6 * Based on arch/i386/kernel/pci-dma-xen.c.
ian@26 7 *
ian@26 8 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ian@26 9 * This program is free software; you can redistribute it and/or modify
ian@26 10 * it under the terms of the GNU General Public License as published by
ian@26 11 * the Free Software Foundation; either version 2 of the License, or
ian@26 12 * (at your option) any later version.
ian@26 13 *
ian@26 14 * This program is distributed in the hope that it will be useful,
ian@26 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ian@26 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ian@26 17 * GNU General Public License for more details.
ian@26 18 *
ian@26 19 * You should have received a copy of the GNU General Public License
ian@26 20 * along with this program; if not, write to the Free Software
ian@26 21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
ian@26 22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ian@26 23 */
ian@26 24
alex@43 25 #include <linux/bitops.h>
ian@26 26 #include <linux/dma-mapping.h>
ian@26 27 #include <linux/mm.h>
ian@26 28 #include <asm/scatterlist.h>
alex@47 29 #include <xen/gnttab.h>
alex@47 30 #include <asm/gnttab_dma.h>
ian@26 31
ian@26 32 #define IOMMU_BUG_ON(test) \
ian@26 33 do { \
ian@26 34 if (unlikely(test)) { \
ian@26 35 printk(KERN_ALERT "Fatal DMA error!\n"); \
ian@26 36 BUG(); \
ian@26 37 } \
ian@26 38 } while (0)
ian@26 39
alex@507 40 static int check_pages_physically_contiguous(unsigned long pfn,
alex@507 41 unsigned int offset,
alex@507 42 size_t length)
alex@507 43 {
alex@507 44 unsigned long next_bus;
alex@507 45 int i;
alex@507 46 int nr_pages;
alex@507 47
alex@507 48 next_bus = pfn_to_mfn_for_dma(pfn);
alex@507 49 nr_pages = (offset + length + PAGE_SIZE-1) >> PAGE_SHIFT;
alex@507 50
alex@507 51 for (i = 1; i < nr_pages; i++) {
alex@507 52 if (pfn_to_mfn_for_dma(++pfn) != ++next_bus)
alex@507 53 return 0;
alex@507 54 }
alex@507 55 return 1;
alex@507 56 }
alex@507 57
alex@507 58 int range_straddles_page_boundary(paddr_t p, size_t size)
alex@507 59 {
alex@507 60 unsigned long pfn = p >> PAGE_SHIFT;
alex@507 61 unsigned int offset = p & ~PAGE_MASK;
alex@507 62
alex@507 63 if (!is_running_on_xen())
alex@507 64 return 0;
alex@507 65
alex@507 66 if (offset + size <= PAGE_SIZE)
alex@507 67 return 0;
alex@507 68 if (check_pages_physically_contiguous(pfn, offset, size))
alex@507 69 return 0;
alex@507 70 return 1;
alex@507 71 }
ian@26 72
ian@26 73 /*
ian@26 74 * This should be broken out of swiotlb and put in a common place
ian@26 75 * when merged with upstream Linux.
ian@26 76 */
ian@26 77 static inline int
alex@43 78 address_needs_mapping(struct device *dev, dma_addr_t addr)
ian@26 79 {
ian@26 80 dma_addr_t mask = 0xffffffff;
ian@26 81
ian@26 82 /* If the device has a mask, use it, otherwise default to 32 bits */
alex@43 83 if (dev && dev->dma_mask)
alex@43 84 mask = *dev->dma_mask;
ian@26 85 return (addr & ~mask) != 0;
ian@26 86 }
ian@26 87
ian@26 88 int
alex@43 89 xen_map_sg(struct device *dev, struct scatterlist *sg, int nents,
ian@26 90 int direction)
ian@26 91 {
ian@26 92 int i;
ian@26 93
ian@26 94 for (i = 0 ; i < nents ; i++) {
alex@47 95 sg[i].dma_address = gnttab_dma_map_page(sg[i].page) + sg[i].offset;
ian@26 96 sg[i].dma_length = sg[i].length;
ian@26 97
alex@43 98 IOMMU_BUG_ON(address_needs_mapping(dev, sg[i].dma_address));
alex@126 99 IOMMU_BUG_ON(range_straddles_page_boundary(
alex@126 100 page_to_pseudophys(sg[i].page) + sg[i].offset,
alex@126 101 sg[i].length));
ian@26 102 }
ian@26 103
ian@26 104 return nents;
ian@26 105 }
ian@26 106 EXPORT_SYMBOL(xen_map_sg);
ian@26 107
ian@26 108 void
alex@43 109 xen_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
ian@26 110 int direction)
ian@26 111 {
alex@47 112 int i;
alex@47 113 for (i = 0; i < nents; i++)
alex@47 114 __gnttab_dma_unmap_page(sg[i].page);
ian@26 115 }
ian@26 116 EXPORT_SYMBOL(xen_unmap_sg);
ian@26 117
ian@26 118 int
ian@26 119 xen_dma_mapping_error(dma_addr_t dma_addr)
ian@26 120 {
ian@26 121 return 0;
ian@26 122 }
ian@26 123 EXPORT_SYMBOL(xen_dma_mapping_error);
ian@26 124
ian@26 125 int
ian@26 126 xen_dma_supported(struct device *dev, u64 mask)
ian@26 127 {
ian@26 128 return 1;
ian@26 129 }
ian@26 130 EXPORT_SYMBOL(xen_dma_supported);
ian@26 131
ian@26 132 void *
ian@26 133 xen_alloc_coherent(struct device *dev, size_t size,
ian@26 134 dma_addr_t *dma_handle, gfp_t gfp)
ian@26 135 {
ian@26 136 unsigned long vaddr;
ian@26 137 unsigned int order = get_order(size);
ian@26 138
ian@26 139 vaddr = __get_free_pages(gfp, order);
ian@26 140
ian@26 141 if (!vaddr)
ian@26 142 return NULL;
ian@26 143
ian@26 144 if (xen_create_contiguous_region(vaddr, order,
alex@43 145 fls64(dev->coherent_dma_mask))) {
ian@26 146 free_pages(vaddr, order);
ian@26 147 return NULL;
ian@26 148 }
ian@26 149
ian@26 150 memset((void *)vaddr, 0, size);
ian@26 151 *dma_handle = virt_to_bus((void *)vaddr);
ian@26 152
ian@26 153 return (void *)vaddr;
ian@26 154 }
ian@26 155 EXPORT_SYMBOL(xen_alloc_coherent);
ian@26 156
ian@26 157 void
ian@26 158 xen_free_coherent(struct device *dev, size_t size,
ian@26 159 void *vaddr, dma_addr_t dma_handle)
ian@26 160 {
ian@26 161 unsigned int order = get_order(size);
ian@26 162
ian@26 163 xen_destroy_contiguous_region((unsigned long)vaddr, order);
ian@26 164 free_pages((unsigned long)vaddr, order);
ian@26 165 }
ian@26 166 EXPORT_SYMBOL(xen_free_coherent);
ian@26 167
ian@26 168 dma_addr_t
ian@26 169 xen_map_single(struct device *dev, void *ptr, size_t size,
ian@26 170 int direction)
ian@26 171 {
alex@47 172 dma_addr_t dma_addr = gnttab_dma_map_virt(ptr);
ian@26 173
alex@126 174 IOMMU_BUG_ON(range_straddles_page_boundary(__pa(ptr), size));
ian@26 175 IOMMU_BUG_ON(address_needs_mapping(dev, dma_addr));
ian@26 176
ian@26 177 return dma_addr;
ian@26 178 }
ian@26 179 EXPORT_SYMBOL(xen_map_single);
ian@26 180
ian@26 181 void
ian@26 182 xen_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
ian@26 183 int direction)
ian@26 184 {
alex@47 185 gnttab_dma_unmap_page(dma_addr);
ian@26 186 }
ian@26 187 EXPORT_SYMBOL(xen_unmap_single);