# HG changeset patch # User yamahata@xxxxxxxxxxxxx # Node ID 0ec28d25907df04890586a9ba8d4c0a593b37451 # Parent 6cb524702355fae2d2a324243cf2748e11a34725 This patch is for justifying the previous patch, page_to_bus.patch, by showing how to allow auto translated mode domain to work as back end. not for committing. Don't apply this patch. Only compile test is done. mfn_to_pfn_for_dma() isn't implemented completely, but only a few drivers use it. PATCHNAME: auto_translated_domain_as_backend Signed-off-by: Isaku Yamahata diff -r 6cb524702355 -r 0ec28d25907d linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/agp.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/agp.h Mon Apr 10 16:39:55 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/agp.h Mon Apr 10 16:42:56 2006 +0900 @@ -23,8 +23,8 @@ int unmap_page_from_agp(struct page *pag #define flush_agp_cache() wbinvd() /* Convert a physical address to an address suitable for the GART. */ -#define phys_to_gart(x) phys_to_machine(x) -#define gart_to_phys(x) machine_to_phys(x) +#define phys_to_gart(x) phys_to_machine_for_dma(x) +#define gart_to_phys(x) machine_to_phys_for_dma(x) /* GATT allocation. Returns/accepts GATT kernel virtual address. */ #define alloc_gatt_pages(order) ({ \ diff -r 6cb524702355 -r 0ec28d25907d linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h Mon Apr 10 16:39:55 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/hypervisor.h Mon Apr 10 16:42:56 2006 +0900 @@ -221,4 +221,99 @@ MULTI_update_va_mapping_otherdomain( #endif } +// the following should go to page.h +// But they are here to avoid the header inclusion hell. +#include +static inline unsigned long pfn_to_mfn_for_dma(unsigned long pfn) +{ + if (xen_feature(XENFEAT_auto_translated_physmap)) { + unsigned long mfn; + struct xen_translate_gpfn_list translate = { + .domid = DOMID_SELF, + .nr_gpfns = 1, + .gpfn_list = &pfn, + .mfn_list = &mfn, + }; + long ret; + ret = HYPERVISOR_memory_op(XENMEM_translate_gpfn_list, + &translate); + BUG_ON(ret != 0); + return mfn; + } + return phys_to_machine_mapping[(unsigned int)(pfn)] & + ~FOREIGN_FRAME_BIT; +} + +#ifdef __i386__ +static inline unsigned long mfn_to_pfn_for_dma(unsigned long mfn) +{ + unsigned long pfn; + + if (xen_feature(XENFEAT_auto_translated_physmap)) { + pfn = 0; + //XXX get gpfn + BUG(); + return pfn; + } + + /* + * The array access can fail (e.g., device space beyond end of RAM). + * In such cases it doesn't matter what we return (we return garbage), + * but we must handle the fault without crashing! + */ + asm ( + "1: movl %1,%0\n" + "2:\n" + ".section __ex_table,\"a\"\n" + " .align 4\n" + " .long 1b,2b\n" + ".previous" + : "=r" (pfn) : "m" (machine_to_phys_mapping[mfn]) ); + + return pfn; +} +#else +static inline unsigned long mfn_to_pfn_for_dma(unsigned long mfn) +{ + unsigned long pfn; + + if (xen_feature(XENFEAT_auto_translated_physmap)) { + pfn = 0; + //XXX get gpfn + BUG(); + return pfn; + } + + /* + * The array access can fail (e.g., device space beyond end of RAM). + * In such cases it doesn't matter what we return (we return garbage), + * but we must handle the fault without crashing! + */ + asm ( + "1: movq %1,%0\n" + "2:\n" + ".section __ex_table,\"a\"\n" + " .align 8\n" + " .quad 1b,2b\n" + ".previous" + : "=r" (pfn) : "m" (machine_to_phys_mapping[mfn]) ); + + return pfn; +} +#endif + +static inline maddr_t phys_to_machine_for_dma(paddr_t phys) +{ + maddr_t machine = pfn_to_mfn_for_dma(phys >> PAGE_SHIFT); + machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK); + return machine; +} + +static inline paddr_t machine_to_phys_for_dma(maddr_t machine) +{ + paddr_t phys = mfn_to_pfn_for_dma(machine >> PAGE_SHIFT); + phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK); + return phys; +} + #endif /* __HYPERVISOR_H__ */ diff -r 6cb524702355 -r 0ec28d25907d linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h Mon Apr 10 16:39:55 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/io.h Mon Apr 10 16:42:56 2006 +0900 @@ -102,15 +102,17 @@ static inline void * phys_to_virt(unsign */ #define page_to_pseudophys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) #define page_to_phys(page) (phys_to_machine(page_to_pseudophys(page))) -#define page_to_bus(page) (phys_to_machine(page_to_pseudophys(page))) +#define page_to_bus(page) (phys_to_machine_for_dma(page_to_pseudophys(page))) #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 bvec_to_bus(bv) (page_to_bus((bv)->bv_page) + \ + (unsigned long) (bv)->bv_offset) #define BIOVEC_PHYS_MERGEABLE(vec1, vec2) \ - (((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2))) && \ + (((bvec_to_bus((vec1)) + (vec1)->bv_len) == bvec_to_bus((vec2))) && \ ((bvec_to_pseudophys((vec1)) + (vec1)->bv_len) == \ bvec_to_pseudophys((vec2)))) @@ -162,8 +164,8 @@ extern void bt_iounmap(void *addr, unsig * * Allow them on x86 for legacy drivers, though. */ -#define virt_to_bus(_x) phys_to_machine(__pa(_x)) -#define bus_to_virt(_x) __va(machine_to_phys(_x)) +#define virt_to_bus(_x) phys_to_machine_for_dma(__pa(_x)) +#define bus_to_virt(_x) __va(machine_to_phys_for_dma(_x)) /* * readX/writeX() are used to access memory mapped devices. On some diff -r 6cb524702355 -r 0ec28d25907d linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pci.h --- a/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pci.h Mon Apr 10 16:39:55 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pci.h Mon Apr 10 16:42:56 2006 +0900 @@ -86,14 +86,14 @@ static inline dma64_addr_t static inline dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction) { - return ((dma64_addr_t) page_to_phys(page) + + return ((dma64_addr_t) page_to_bus(page) + (dma64_addr_t) offset); } static inline struct page * pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr) { - return pfn_to_page(dma_addr >> PAGE_SHIFT); + return pfn_to_page(mfn_to_pfn_for_dma(dma_addr >> PAGE_SHIFT)); } static inline unsigned long diff -r 6cb524702355 -r 0ec28d25907d linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h Mon Apr 10 16:39:55 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/io.h Mon Apr 10 16:42:56 2006 +0900 @@ -121,8 +121,8 @@ static inline void * phys_to_virt(unsign return __va(address); } -#define virt_to_bus(_x) phys_to_machine(__pa(_x)) -#define bus_to_virt(_x) __va(machine_to_phys(_x)) +#define virt_to_bus(_x) phys_to_machine_for_dma(__pa(_x)) +#define bus_to_virt(_x) __va(machine_to_phys_for_dma(_x)) #endif /* @@ -130,15 +130,17 @@ static inline void * phys_to_virt(unsign */ #define page_to_pseudophys(page) ((dma_addr_t)page_to_pfn(page) << PAGE_SHIFT) #define page_to_phys(page) (phys_to_machine(page_to_pseudophys(page))) -#define page_to_bus(page) (phys_to_machine(page_to_pseudophys(page))) +#define page_to_bus(page) (phys_to_machine_for_dma(page_to_pseudophys(page))) #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 bvec_to_bus(bv) (page_to_bus((bv)->bv_page) + \ + (unsigned long) (bv)->bv_offset) #define BIOVEC_PHYS_MERGEABLE(vec1, vec2) \ - (((bvec_to_phys((vec1)) + (vec1)->bv_len) == bvec_to_phys((vec2))) && \ + (((bvec_to_bus((vec1)) + (vec1)->bv_len) == bvec_to_bus((vec2))) && \ ((bvec_to_pseudophys((vec1)) + (vec1)->bv_len) == \ bvec_to_pseudophys((vec2)))) @@ -178,8 +180,8 @@ extern void iounmap(volatile void __iome * * Allow them on x86 for legacy drivers, though. */ -#define virt_to_bus(_x) phys_to_machine(__pa(_x)) -#define bus_to_virt(_x) __va(machine_to_phys(_x)) +#define virt_to_bus(_x) phys_to_machine_for_dma(__pa(_x)) +#define bus_to_virt(_x) __va(machine_to_phys_for_dma(_x)) /* * readX/writeX() are used to access memory mapped devices. On some diff -r 6cb524702355 -r 0ec28d25907d linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pci.h --- a/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pci.h Mon Apr 10 16:39:55 2006 +0900 +++ b/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pci.h Mon Apr 10 16:42:56 2006 +0900 @@ -112,14 +112,14 @@ static inline dma64_addr_t static inline dma64_addr_t pci_dac_page_to_dma(struct pci_dev *pdev, struct page *page, unsigned long offset, int direction) { - return ((dma64_addr_t) page_to_phys(page) + + return ((dma64_addr_t) page_to_bus(page) + (dma64_addr_t) offset); } static inline struct page * pci_dac_dma_to_page(struct pci_dev *pdev, dma64_addr_t dma_addr) { - return virt_to_page(__va(dma_addr)); + return virt_to_page(bus_to_virt(dma_addr)); } static inline unsigned long