WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [IA64] dma paravirtualization, Xen patchbot -unstable <=