[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [IA64] dma paravirtualization



# HG changeset patch
# User awilliam@localhost
# Node ID a3cc276f2e87320e032bc4ba998844808550a05b
# Parent  d63c6ba11c6590600b223533ffaa673f1af7bfcf
[IA64] dma paravirtualization

Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>

diff -r d63c6ba11c65 -r a3cc276f2e87 
linux-2.6-xen-sparse/arch/ia64/kernel/setup.c
--- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c     Tue Apr 25 14:02:21 
2006 -0600
+++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c     Tue Apr 25 16:53:27 
2006 -0600
@@ -64,6 +64,7 @@
 #ifdef CONFIG_XEN
 #include <asm/hypervisor.h>
 #endif
+#include <linux/dma-mapping.h>
 
 #if defined(CONFIG_SMP) && (IA64_CPU_SIZE > PAGE_SIZE)
 # error "struct cpuinfo_ia64 too big!"
@@ -534,6 +535,7 @@ setup_arch (char **cmdline_p)
 
        platform_setup(cmdline_p);
        paging_init();
+       contiguous_bitmap_init(max_pfn);
 }
 
 /*
diff -r d63c6ba11c65 -r a3cc276f2e87 linux-2.6-xen-sparse/include/asm-ia64/agp.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/agp.h       Tue Apr 25 14:02:21 
2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/agp.h       Tue Apr 25 16:53:27 
2006 -0600
@@ -19,13 +19,44 @@
 #define flush_agp_cache()              mb()
 
 /* Convert a physical address to an address suitable for the GART. */
+#ifndef CONFIG_XEN_IA64_DOM0_VP
 #define phys_to_gart(x) (x)
 #define gart_to_phys(x) (x)
+#else
+#define phys_to_gart(x) phys_to_machine_for_dma(x)
+#define gart_to_phys(x) machine_to_phys_for_dma(x)
+#endif
 
 /* GATT allocation. Returns/accepts GATT kernel virtual address. */
+#ifndef CONFIG_XEN_IA64_DOM0_VP
 #define alloc_gatt_pages(order)                \
        ((char *)__get_free_pages(GFP_KERNEL, (order)))
 #define free_gatt_pages(table, order)  \
        free_pages((unsigned long)(table), (order))
+#else
+#include <asm/hypervisor.h>
+static inline char*
+alloc_gatt_pages(unsigned int order)
+{
+       unsigned long error;
+       unsigned long ret = __get_free_pages(GFP_KERNEL, (order));
+       if (ret == 0) {
+               goto out;
+       }
+       error = xen_create_contiguous_region(ret, order, 0);
+       if (error) {
+               free_pages(ret, order);
+               ret = 0;
+       }
+out:
+       return (char*)ret;
+}
+static inline void
+free_gatt_pages(void* table, unsigned int order)
+{
+       xen_destroy_contiguous_region((unsigned long)table, order);
+       free_pages((unsigned long)table, order);
+}
+#endif /* CONFIG_XEN_IA64_DOM0_VP */
 
 #endif /* _ASM_IA64_AGP_H */
diff -r d63c6ba11c65 -r a3cc276f2e87 
linux-2.6-xen-sparse/include/asm-ia64/dma-mapping.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/dma-mapping.h       Tue Apr 25 
14:02:21 2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/dma-mapping.h       Tue Apr 25 
16:53:27 2006 -0600
@@ -7,7 +7,13 @@
  */
 #include <linux/config.h>
 #include <asm/machvec.h>
+#ifdef CONFIG_XEN_IA64_DOM0_VP
+#include <asm/hypervisor.h> //XXX to compile arch/i386/kernel/swiotlb.c
+                            //    and arch/i386/kernel/pci-dma-xen.c
+#include <asm-i386/mach-xen/asm/swiotlb.h> //XXX to compile 
arch/i386/kernel/swiotlb.c
+#endif
 
+#ifndef CONFIG_XEN_IA64_DOM0_VP
 #define dma_alloc_coherent     platform_dma_alloc_coherent
 #define dma_alloc_noncoherent  platform_dma_alloc_coherent     /* coherent 
mem. is cheap */
 #define dma_free_coherent      platform_dma_free_coherent
@@ -21,6 +27,46 @@
 #define dma_sync_single_for_device platform_dma_sync_single_for_device
 #define dma_sync_sg_for_device platform_dma_sync_sg_for_device
 #define dma_mapping_error      platform_dma_mapping_error
+#else
+int dma_map_sg(struct device *hwdev, struct scatterlist *sg, int nents,
+               enum dma_data_direction direction);
+void dma_unmap_sg(struct device *hwdev, struct scatterlist *sg, int nents,
+                  enum dma_data_direction direction);
+int dma_supported(struct device *dev, u64 mask);
+void *dma_alloc_coherent(struct device *dev, size_t size,
+                         dma_addr_t *dma_handle, gfp_t gfp);
+void dma_free_coherent(struct device *dev, size_t size, void *vaddr,
+                       dma_addr_t dma_handle);
+dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
+                          enum dma_data_direction direction);
+void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size,
+                      enum dma_data_direction direction);
+void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
+                             size_t size, enum dma_data_direction direction);
+void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
+                                size_t size,
+                                enum dma_data_direction direction);
+int dma_mapping_error(dma_addr_t dma_addr);
+
+#define flush_write_buffers()  do { } while (0)
+static inline void
+dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
+                    enum dma_data_direction direction)
+{
+       if (swiotlb)
+               swiotlb_sync_sg_for_cpu(dev,sg,nelems,direction);
+       flush_write_buffers();
+}
+
+static inline void
+dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
+                       enum dma_data_direction direction)
+{
+       if (swiotlb)
+               swiotlb_sync_sg_for_device(dev,sg,nelems,direction);
+       flush_write_buffers();
+}
+#endif
 
 #define dma_map_page(dev, pg, off, size, dir)                          \
        dma_map_single(dev, page_address(pg) + (off), (size), (dir))
@@ -62,4 +108,29 @@ dma_cache_sync (void *vaddr, size_t size
 
 #define dma_is_consistent(dma_handle)  (1)     /* all we do is coherent 
memory... */
 
+#ifdef CONFIG_XEN_IA64_DOM0_VP
+// arch/i386/kernel/swiotlb.o requires
+void contiguous_bitmap_init(unsigned long end_pfn);
+
+static inline int
+address_needs_mapping(struct device *hwdev, dma_addr_t addr)
+{
+       dma_addr_t mask = DMA_64BIT_MASK;
+       /* If the device has a mask, use it, otherwise default to 64 bits */
+       if (hwdev && hwdev->dma_mask)
+               mask = *hwdev->dma_mask;
+       return (addr & ~mask) != 0;
+}
+
+static inline int
+range_straddles_page_boundary(void *p, size_t size)
+{
+       extern unsigned long *contiguous_bitmap;
+       return (((((unsigned long)p & ~PAGE_MASK) + size) > PAGE_SIZE) &&
+               !test_bit(__pa(p) >> PAGE_SHIFT, contiguous_bitmap));
+}
+#else
+#define contiguous_bitmap_init(end_pfn)        ((void)end_pfn)
+#endif
+
 #endif /* _ASM_IA64_DMA_MAPPING_H */
diff -r d63c6ba11c65 -r a3cc276f2e87 
linux-2.6-xen-sparse/include/asm-ia64/hypercall.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Tue Apr 25 14:02:21 
2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypercall.h Tue Apr 25 16:53:27 
2006 -0600
@@ -36,13 +36,6 @@
 #ifndef __HYPERVISOR_H__
 # error "please don't include this file directly"
 #endif
-
-/* FIXME: temp place to hold these page related macros */
-#include <asm/page.h>
-#define virt_to_machine(v) __pa(v)
-#define machine_to_virt(m) __va(m)
-#define virt_to_mfn(v) ((__pa(v)) >> PAGE_SHIFT)
-#define mfn_to_virt(m) (__va((m) << PAGE_SHIFT))
 
 /*
  * Assembler stubs for hyper-calls.
diff -r d63c6ba11c65 -r a3cc276f2e87 
linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h        Tue Apr 25 
14:02:21 2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/hypervisor.h        Tue Apr 25 
16:53:27 2006 -0600
@@ -41,6 +41,7 @@
 #include <xen/interface/xen.h>
 #include <xen/interface/dom0_ops.h>
 #include <xen/interface/sched.h>
+#include <asm/hypercall.h>
 #include <asm/ptrace.h>
 #include <asm/page.h>
 #include <asm/xen/privop.h> // for running_on_xen
@@ -54,8 +55,6 @@ int xen_init(void);
 
 /* Turn jiffies into Xen system time. XXX Implement me. */
 #define jiffies_to_st(j)       0
-
-#include <asm/hypercall.h>
 
 static inline int
 HYPERVISOR_yield(
@@ -117,9 +116,11 @@ HYPERVISOR_poll(
 
 // for drivers/xen/privcmd/privcmd.c
 #define direct_remap_pfn_range(a,b,c,d,e,f) remap_pfn_range(a,b,c,d,e)
+#define machine_to_phys_mapping 0
+#ifndef CONFIG_XEN_IA64_DOM0_VP
 #define        pfn_to_mfn(x)   (x)
 #define        mfn_to_pfn(x)   (x)
-#define machine_to_phys_mapping 0
+#endif
 
 // for drivers/xen/balloon/balloon.c
 #ifdef CONFIG_XEN_SCRUB_PAGES
@@ -128,12 +129,44 @@ HYPERVISOR_poll(
 #define scrub_pages(_p,_n) ((void)0)
 #endif
 #define        pte_mfn(_x)     pte_pfn(_x)
-#define INVALID_P2M_ENTRY      (~0UL)
 #define __pte_ma(_x)   ((pte_t) {(_x)})
 #define phys_to_machine_mapping_valid(_x)      (1)
 #define        kmap_flush_unused()     do {} while (0)
+#define pfn_pte_ma(_x,_y)      __pte_ma(0)
+#ifndef CONFIG_XEN_IA64_DOM0_VP //XXX
 #define set_phys_to_machine(_x,_y)     do {} while (0)
 #define xen_machphys_update(_x,_y)     do {} while (0)
-#define pfn_pte_ma(_x,_y)      __pte_ma(0)
+#endif
+
+#ifdef CONFIG_XEN_IA64_DOM0_VP
+int __xen_create_contiguous_region(unsigned long vstart, unsigned int order, 
unsigned int address_bits);
+static inline int
+xen_create_contiguous_region(unsigned long vstart,
+                             unsigned int order, unsigned int address_bits)
+{
+       int ret = 0;
+       if (running_on_xen) {
+               ret = __xen_create_contiguous_region(vstart, order,
+                                                    address_bits);
+       }
+       return ret;
+}
+
+void __xen_destroy_contiguous_region(unsigned long vstart, unsigned int order);
+static inline void
+xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
+{
+       if (running_on_xen)
+               __xen_destroy_contiguous_region(vstart, order);
+}
+#else
+#define xen_create_contiguous_region(vstart, order, address_bits)      ({0;})
+#define xen_destroy_contiguous_region(vstart, order)   do {} while (0)
+#endif
+
+// for debug
+asmlinkage int xprintk(const char *fmt, ...);
+#define xprintd(fmt, ...)      xprintk("%s:%d " fmt, __func__, __LINE__, \
+                                       ##__VA_ARGS__)
 
 #endif /* __HYPERVISOR_H__ */
diff -r d63c6ba11c65 -r a3cc276f2e87 linux-2.6-xen-sparse/include/asm-ia64/io.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/io.h        Tue Apr 25 14:02:21 
2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/io.h        Tue Apr 25 16:53:27 
2006 -0600
@@ -71,6 +71,10 @@ extern unsigned int num_io_spaces;
 #include <asm/page.h>
 #include <asm/system.h>
 #include <asm-generic/iomap.h>
+#ifdef CONFIG_XEN
+#include <asm/privop.h>
+#include <asm/hypervisor.h>
+#endif
 
 /*
  * Change virtual addresses to physical addresses and vv.
@@ -95,9 +99,39 @@ extern int valid_mmap_phys_addr_range (u
  * The following two macros are deprecated and scheduled for removal.
  * Please use the PCI-DMA interface defined in <asm/pci.h> instead.
  */
+#ifndef CONFIG_XEN_IA64_DOM0_VP
 #define bus_to_virt    phys_to_virt
 #define virt_to_bus    virt_to_phys
 #define page_to_bus    page_to_phys
+#define page_to_phys(page)     (page_to_pfn(page) << PAGE_SHIFT)
+#define page_to_pseudophys(page)       page_to_phys(page)
+#else
+#define bus_to_virt(bus)       \
+       phys_to_virt(machine_to_phys_for_dma(bus))
+#define virt_to_bus(virt)      \
+       phys_to_machine_for_dma(virt_to_phys(virt))
+#define page_to_bus(page)      \
+       phys_to_machine_for_dma(page_to_pseudophys(page))
+
+#define page_to_pseudophys(page) \
+       ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT)
+// XXX
+// the following drivers are broken because they use page_to_phys() to
+// get bus address. fix them.
+// drivers/ide/cris/ide-cris.c
+// drivers/scsi/dec_esp.c
+#define page_to_phys(page)     (page_to_pseudophys(page))
+#define bvec_to_bus(bv)                (page_to_bus((bv)->bv_page) + \
+                               (unsigned long) (bv)->bv_offset)
+#define bio_to_pseudophys(bio) (page_to_pseudophys(bio_page((bio))) +  \
+                                (unsigned long) bio_offset((bio)))
+#define bvec_to_pseudophys(bv)  (page_to_pseudophys((bv)->bv_page) +   \
+                                (unsigned long) (bv)->bv_offset)
+#define BIOVEC_PHYS_MERGEABLE(vec1, vec2)                              \
+       (((bvec_to_bus((vec1)) + (vec1)->bv_len) == bvec_to_bus((vec2))) && \
+        ((bvec_to_pseudophys((vec1)) + (vec1)->bv_len) ==              \
+         bvec_to_pseudophys((vec2))))
+#endif
 
 # endif /* KERNEL */
 
@@ -425,6 +459,9 @@ static inline void __iomem *
 static inline void __iomem *
 ioremap (unsigned long offset, unsigned long size)
 {
+#ifdef CONFIG_XEN
+       offset = HYPERVISOR_ioremap(offset, size);
+#endif
        return (void __iomem *) (__IA64_UNCACHED_OFFSET | (offset));
 }
 
diff -r d63c6ba11c65 -r a3cc276f2e87 
linux-2.6-xen-sparse/include/asm-ia64/machvec.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/machvec.h   Tue Apr 25 14:02:21 
2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/machvec.h   Tue Apr 25 16:53:27 
2006 -0600
@@ -247,6 +247,21 @@ extern void machvec_init (const char *na
 #  error Unknown configuration.  Update asm-ia64/machvec.h.
 # endif /* CONFIG_IA64_GENERIC */
 
+#ifdef CONFIG_XEN_IA64_DOM0_VP
+# define platform_dma_map_sg           dma_map_sg
+# define platform_dma_unmap_sg         dma_unmap_sg
+# define platform_dma_mapping_error    dma_mapping_error
+# define platform_dma_supported                dma_supported
+# define platform_dma_alloc_coherent   dma_alloc_coherent
+# define platform_dma_free_coherent    dma_free_coherent
+# define platform_dma_map_single       dma_map_single
+# define platform_dma_unmap_single     dma_unmap_single
+# define platform_dma_sync_single_for_cpu \
+                                       dma_sync_single_for_cpu
+# define platform_dma_sync_single_for_device \
+                                       dma_sync_single_for_device
+#endif
+
 /*
  * Declare default routines which aren't declared anywhere else:
  */
diff -r d63c6ba11c65 -r a3cc276f2e87 
linux-2.6-xen-sparse/include/asm-ia64/page.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/page.h      Tue Apr 25 14:02:21 
2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/page.h      Tue Apr 25 16:53:27 
2006 -0600
@@ -117,7 +117,6 @@ extern unsigned long max_low_pfn;
 # define pfn_to_page(pfn)      (vmem_map + (pfn))
 #endif
 
-#define page_to_phys(page)     (page_to_pfn(page) << PAGE_SHIFT)
 #define virt_to_page(kaddr)    pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
 #define pfn_to_kaddr(pfn)      __va((pfn) << PAGE_SHIFT)
 
@@ -219,4 +218,75 @@ get_order (unsigned long size)
                                         (((current->personality & 
READ_IMPLIES_EXEC) != 0)     \
                                          ? VM_EXEC : 0))
 
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_XEN
+
+#define INVALID_P2M_ENTRY      (~0UL)
+
+#ifndef CONFIG_XEN_IA64_DOM0_VP
+
+#define virt_to_machine(v) __pa(v)
+#define machine_to_virt(m) __va(m)
+#define virt_to_mfn(v) ((__pa(v)) >> PAGE_SHIFT)
+#define mfn_to_virt(m) (__va((m) << PAGE_SHIFT))
+
+#else
+
+#include <linux/kernel.h>
+#include <asm/hypervisor.h>
+
+//XXX xen page size != page size
+
+static inline unsigned long
+pfn_to_mfn_for_dma(unsigned long pfn)
+{
+       unsigned long mfn;
+       mfn = HYPERVISOR_phystomach(pfn);
+       BUG_ON(mfn == 0); // XXX
+       BUG_ON(mfn == INVALID_P2M_ENTRY); // XXX
+       BUG_ON(mfn == INVALID_MFN);
+       return mfn;
+}
+
+static inline unsigned long
+phys_to_machine_for_dma(unsigned long phys)
+{
+       unsigned long machine =
+                     pfn_to_mfn_for_dma(phys >> PAGE_SHIFT) << PAGE_SHIFT;
+       machine |= (phys & ~PAGE_MASK);
+       return machine;
+}
+
+static inline unsigned long
+mfn_to_pfn_for_dma(unsigned long mfn)
+{
+       unsigned long pfn;
+       pfn = HYPERVISOR_machtophys(mfn);
+       BUG_ON(pfn == 0);
+       //BUG_ON(pfn == INVALID_M2P_ENTRY);
+       return pfn;
+}
+
+static inline unsigned long
+machine_to_phys_for_dma(unsigned long machine)
+{
+       unsigned long phys =
+                     mfn_to_pfn_for_dma(machine >> PAGE_SHIFT) << PAGE_SHIFT;
+       phys |= (machine & ~PAGE_MASK);
+       return phys;
+}
+
+#define set_phys_to_machine(pfn, mfn) do { } while (0)
+#define xen_machphys_update(mfn, pfn) do { } while (0)
+
+#define mfn_to_pfn(mfn)                        ({(mfn);})
+#define mfn_to_virt(mfn)               ({__va((mfn) << PAGE_SHIFT);})
+#define pfn_to_mfn(pfn)                        ({(pfn);})
+#define virt_to_mfn(virt)              ({__pa(virt) >> PAGE_SHIFT;})
+#define virt_to_machine(virt)          ({__pa(virt);}) // for tpmfront.c
+
+#endif /* CONFIG_XEN_IA64_DOM0_VP */
+#endif /* CONFIG_XEN */
+#endif /* __ASSEMBLY__ */
+
 #endif /* _ASM_IA64_PAGE_H */
diff -r d63c6ba11c65 -r a3cc276f2e87 
linux-2.6-xen-sparse/include/asm-ia64/pgalloc.h
--- a/linux-2.6-xen-sparse/include/asm-ia64/pgalloc.h   Tue Apr 25 14:02:21 
2006 -0600
+++ b/linux-2.6-xen-sparse/include/asm-ia64/pgalloc.h   Tue Apr 25 16:53:27 
2006 -0600
@@ -126,7 +126,7 @@ static inline void
 static inline void
 pmd_populate(struct mm_struct *mm, pmd_t * pmd_entry, struct page *pte)
 {
-       pmd_val(*pmd_entry) = page_to_phys(pte);
+       pmd_val(*pmd_entry) = page_to_pseudophys(pte);
 }
 
 static inline void
diff -r d63c6ba11c65 -r a3cc276f2e87 
linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c   Tue Apr 25 16:53:27 
2006 -0600
@@ -0,0 +1,234 @@
+/******************************************************************************
+ * include/asm-ia64/shadow.h
+ *
+ * Copyright (c) 2006 Isaku Yamahata <yamahata at valinux co jp>
+ *                    VA Linux Systems Japan K.K.
+ *
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+//#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bootmem.h>
+#include <asm/page.h>
+#include <asm/hypervisor.h>
+#include <asm/hypercall.h>
+
+#define XEN_IA64_BALLOON_IS_NOT_YET
+#ifndef XEN_IA64_BALLOON_IS_NOT_YET
+#include <xen/balloon.h>
+#else
+#define balloon_lock(flags)    ((void)flags)
+#define balloon_unlock(flags)  ((void)flags)
+#endif
+
+
+//XXX same as i386, x86_64 contiguous_bitmap_set(), contiguous_bitmap_clear()
+// move those to lib/contiguous_bitmap?
+//XXX discontigmem/sparsemem
+
+/*
+ * Bitmap is indexed by page number. If bit is set, the page is part of a
+ * xen_create_contiguous_region() area of memory.
+ */
+unsigned long *contiguous_bitmap;
+
+void
+contiguous_bitmap_init(unsigned long end_pfn)
+{
+       unsigned long size = (end_pfn + 2 * BITS_PER_LONG) >> 3;
+       contiguous_bitmap = alloc_bootmem_low_pages(size);
+       BUG_ON(!contiguous_bitmap);
+       memset(contiguous_bitmap, 0, size);
+}
+
+#if 0
+int
+contiguous_bitmap_test(void* p)
+{
+       return test_bit(__pa(p) >> PAGE_SHIFT, contiguous_bitmap);
+}
+#endif
+
+static void contiguous_bitmap_set(
+       unsigned long first_page, unsigned long nr_pages)
+{
+       unsigned long start_off, end_off, curr_idx, end_idx;
+
+       curr_idx  = first_page / BITS_PER_LONG;
+       start_off = first_page & (BITS_PER_LONG-1);
+       end_idx   = (first_page + nr_pages) / BITS_PER_LONG;
+       end_off   = (first_page + nr_pages) & (BITS_PER_LONG-1);
+
+       if (curr_idx == end_idx) {
+               contiguous_bitmap[curr_idx] |=
+                       ((1UL<<end_off)-1) & -(1UL<<start_off);
+       } else {
+               contiguous_bitmap[curr_idx] |= -(1UL<<start_off);
+               while ( ++curr_idx < end_idx )
+                       contiguous_bitmap[curr_idx] = ~0UL;
+               contiguous_bitmap[curr_idx] |= (1UL<<end_off)-1;
+       }
+}
+
+static void contiguous_bitmap_clear(
+       unsigned long first_page, unsigned long nr_pages)
+{
+       unsigned long start_off, end_off, curr_idx, end_idx;
+
+       curr_idx  = first_page / BITS_PER_LONG;
+       start_off = first_page & (BITS_PER_LONG-1);
+       end_idx   = (first_page + nr_pages) / BITS_PER_LONG;
+       end_off   = (first_page + nr_pages) & (BITS_PER_LONG-1);
+
+       if (curr_idx == end_idx) {
+               contiguous_bitmap[curr_idx] &=
+                       -(1UL<<end_off) | ((1UL<<start_off)-1);
+       } else {
+               contiguous_bitmap[curr_idx] &= (1UL<<start_off)-1;
+               while ( ++curr_idx != end_idx )
+                       contiguous_bitmap[curr_idx] = 0;
+               contiguous_bitmap[curr_idx] &= -(1UL<<end_off);
+       }
+}
+
+/* Ensure multi-page extents are contiguous in machine memory. */
+int
+__xen_create_contiguous_region(unsigned long vstart,
+                              unsigned int order, unsigned int address_bits)
+{
+       unsigned long error = 0;
+       unsigned long gphys = __pa(vstart);
+       unsigned long start_gpfn = gphys >> PAGE_SHIFT;
+       unsigned long num_pfn = 1 << order;
+       unsigned long i;
+       unsigned long flags;
+
+       scrub_pages(vstart, 1 << order);
+
+       balloon_lock(flags);
+
+       //XXX order
+       for (i = 0; i < num_pfn; i++) {
+               error = HYPERVISOR_zap_physmap(start_gpfn + i, 0);
+               if (error) {
+                       goto out;
+               }
+       }
+
+       error = HYPERVISOR_populate_physmap(start_gpfn, order, address_bits);
+       contiguous_bitmap_set(start_gpfn, 1UL << order);
+#if 0
+       {
+       unsigned long mfn;
+       unsigned long mfn_prev = ~0UL;
+       for (i = 0; i < 1 << order; i++) {
+               mfn = pfn_to_mfn_for_dma(start_gpfn + i);
+               if (mfn_prev != ~0UL && mfn != mfn_prev + 1) {
+                       xprintk("\n");
+                       xprintk("%s:%d order %d "
+                               "start 0x%lx bus 0x%lx machine 0x%lx\n",
+                               __func__, __LINE__, order,
+                               vstart, virt_to_bus((void*)vstart),
+                               phys_to_machine_for_dma(gphys));
+                       xprintk("mfn: ");
+                       for (i = 0; i < 1 << order; i++) {
+                               mfn = pfn_to_mfn_for_dma(start_gpfn + i);
+                               xprintk("0x%lx ", mfn);
+                       }
+                       xprintk("\n");
+                       goto out;
+               }
+               mfn_prev = mfn;
+       }
+       }
+#endif
+out:
+       balloon_unlock(flags);
+       return error;
+}
+
+void
+__xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
+{
+       unsigned long error = 0;
+       unsigned long gphys = __pa(vstart);
+       unsigned long start_gpfn = gphys >> PAGE_SHIFT;
+       unsigned long num_pfn = 1 << order;
+       unsigned long i;
+       unsigned long flags;
+
+       scrub_pages(vstart, 1 << order);
+
+       balloon_lock(flags);
+
+       contiguous_bitmap_clear(start_gpfn, 1UL << order);
+
+       //XXX order
+       for (i = 0; i < num_pfn; i++) {
+               error = HYPERVISOR_zap_physmap(start_gpfn + i, 0);
+               if (error) {
+                       goto out;
+               }
+       }
+
+       for (i = 0; i < num_pfn; i++) {
+               error = HYPERVISOR_populate_physmap(start_gpfn + i, 0, 0);
+               if (error) {
+                       goto out;
+               }
+       }
+
+out:
+       balloon_unlock(flags);
+       if (error) {
+               //XXX
+       }
+}
+
+
+///////////////////////////////////////////////////////////////////////////
+//XXX taken from balloon.c
+//    temporal hack until balloon driver support.
+#include <linux/module.h>
+
+struct page *balloon_alloc_empty_page_range(unsigned long nr_pages)
+{
+       unsigned long vstart;
+       unsigned int  order = get_order(nr_pages * PAGE_SIZE);
+
+       vstart = __get_free_pages(GFP_KERNEL, order);
+       if (vstart == 0)
+               return NULL;
+
+       return virt_to_page(vstart);
+}
+
+void balloon_dealloc_empty_page_range(
+       struct page *page, unsigned long nr_pages)
+{
+       __free_pages(page, get_order(nr_pages * PAGE_SIZE));
+}
+
+void balloon_update_driver_allowance(long delta)
+{
+}
+
+EXPORT_SYMBOL(balloon_alloc_empty_page_range);
+EXPORT_SYMBOL(balloon_dealloc_empty_page_range);
+EXPORT_SYMBOL(balloon_update_driver_allowance);
+
+

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.