# 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
|