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

Re: [Xen-devel] Xen with dom0 pvops on ultra-recent "git tip"kernel on x

To: Jeremy Fitzhardinge <jeremy@xxxxxxxx>, xen-devel <xen-devel@xxxxxxxxxxxxxxxxxxx>
Subject: Re: [Xen-devel] Xen with dom0 pvops on ultra-recent "git tip"kernel on x86_64
From: Christophe Saout <christophe@xxxxxxxx>
Date: Mon, 19 Jan 2009 13:33:58 +0100
Cc:
Delivery-date: Mon, 19 Jan 2009 04:34:24 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <1232358735.4651.15.camel@xxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <C5996017.186D%keir.fraser@xxxxxxxxxxxxx> <1232358735.4651.15.camel@xxxxxxxxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
Hi again,

ok, to my astonishment this seem to be actually working.

My X server is coming up and seems usable (until my hard disk stops
working after some minutes again :-)).

Here's the patch that's doing the trick for me (the Xen implementation
is mostly copied over from the 2.6.27 SuSE Xen kernel):


Subject: [PATCH] Make io_remap_pfn_range a paravirt operation and have a special
 implementation for it in Xen.

---
 arch/x86/include/asm/paravirt.h   |   12 ++++
 arch/x86/include/asm/pgtable_32.h |    4 ++
 arch/x86/include/asm/pgtable_64.h |    4 ++
 arch/x86/kernel/paravirt.c        |    1 +
 arch/x86/xen/enlighten.c          |    1 +
 arch/x86/xen/mmu.c                |  103 +++++++++++++++++++++++++++++++++++++
 arch/x86/xen/mmu.h                |    4 ++
 7 files changed, 129 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index 40795f4..d2a7298 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -39,6 +39,7 @@ struct desc_ptr;
 struct tss_struct;
 struct mm_struct;
 struct desc_struct;
+struct vm_area_struct;
 
 /* general info */
 struct pv_info {
@@ -326,6 +327,10 @@ struct pv_mmu_ops {
                           unsigned long phys, pgprot_t flags);
 
        int (*page_is_ram)(unsigned long pfn);
+
+       int (*io_remap_pfn_range)(struct vm_area_struct *vma,
+                                 unsigned long address, unsigned long mfn,
+                                 unsigned long size, pgprot_t prot);
 };
 
 struct raw_spinlock;
@@ -1402,6 +1407,13 @@ static inline int page_is_ram(unsigned long pfn)
        return PVOP_CALL1(int, pv_mmu_ops.page_is_ram, pfn);
 }
 
+static inline int io_remap_pfn_range(struct vm_area_struct *vma,
+                                     unsigned long vaddr, unsigned long pfn,
+                                     unsigned long size, pgprot_t prot)
+{
+       return pv_mmu_ops.io_remap_pfn_range(vma, vaddr, pfn, size, prot);
+}
+
 void _paravirt_nop(void);
 #define paravirt_nop   ((void *)_paravirt_nop)
 
diff --git a/arch/x86/include/asm/pgtable_32.h 
b/arch/x86/include/asm/pgtable_32.h
index 56e1560..ab2419b 100644
--- a/arch/x86/include/asm/pgtable_32.h
+++ b/arch/x86/include/asm/pgtable_32.h
@@ -182,7 +182,11 @@ do {                                               \
 #define kern_addr_valid(kaddr) (0)
 #endif
 
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)        \
        remap_pfn_range(vma, vaddr, pfn, size, prot)
+#endif
 
 #endif /* _ASM_X86_PGTABLE_32_H */
diff --git a/arch/x86/include/asm/pgtable_64.h 
b/arch/x86/include/asm/pgtable_64.h
index 537081e..293570f 100644
--- a/arch/x86/include/asm/pgtable_64.h
+++ b/arch/x86/include/asm/pgtable_64.h
@@ -272,8 +272,12 @@ extern int direct_gbpages;
 extern int kern_addr_valid(unsigned long addr);
 extern void cleanup_highmap(void);
 
+#ifdef CONFIG_PARAVIRT
+#include <asm/paravirt.h>
+#else
 #define io_remap_pfn_range(vma, vaddr, pfn, size, prot)        \
        remap_pfn_range(vma, vaddr, pfn, size, prot)
+#endif
 
 #define HAVE_ARCH_UNMAPPED_AREA
 #define HAVE_ARCH_UNMAPPED_AREA_TOPDOWN
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 602edc0..81c2e15 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -453,6 +453,7 @@ struct pv_mmu_ops pv_mmu_ops = {
 
        .set_fixmap = native_set_fixmap,
        .page_is_ram = native_page_is_ram,
+       .io_remap_pfn_range = remap_pfn_range
 };
 
 EXPORT_SYMBOL_GPL(pv_time_ops);
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 360f04b..643d00f 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1401,6 +1401,7 @@ static const struct pv_mmu_ops xen_mmu_ops __initdata = {
 
        .set_fixmap = xen_set_fixmap,
        .page_is_ram = xen_page_is_ram,
+       .io_remap_pfn_range = xen_io_remap_pfn_range
 };
 
 static void xen_reboot(int reason)
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index 72069b1..d0a9348 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -1441,6 +1441,109 @@ void xen_destroy_contiguous_region(unsigned long 
vstart, unsigned int order)
 }
 EXPORT_SYMBOL_GPL(xen_destroy_contiguous_region);
 
+static inline pte_t pfn_pte_ma(unsigned long page_nr, pgprot_t pgprot)
+{
+       pgprotval_t prot = pgprot_val(pgprot);
+
+       if (prot & _PAGE_PRESENT)
+               prot &= __supported_pte_mask;
+       return __pte_ma(((phys_addr_t)page_nr << PAGE_SHIFT) | prot);
+}
+                                        
+static int direct_remap_area_pte_fn(pte_t *pte,
+                                   struct page *pmd_page,
+                                   unsigned long address,
+                                   void *data)
+{
+       struct mmu_update **v = (struct mmu_update **)data;
+
+       BUG_ON(!pte_none(*pte));
+
+       (*v)->ptr = ((u64)pfn_to_mfn(page_to_pfn(pmd_page)) <<
+                    PAGE_SHIFT) | ((unsigned long)pte & ~PAGE_MASK);
+       (*v)++;
+
+       return 0;
+}
+
+static int __direct_remap_pfn_range(struct mm_struct *mm,
+                                   unsigned long address,
+                                   unsigned long mfn,
+                                   unsigned long size,
+                                   pgprot_t prot,
+                                   domid_t  domid)
+{
+       int rc;
+       unsigned long i, start_address;
+       struct mmu_update *u, *v, *w;
+
+       u = v = w = (struct mmu_update 
*)__get_free_page(GFP_KERNEL|__GFP_REPEAT);
+       if (u == NULL)
+               return -ENOMEM;
+
+       start_address = address;
+
+       flush_cache_all();
+
+       for (i = 0; i < size; i += PAGE_SIZE) {
+               if ((v - u) == (PAGE_SIZE / sizeof(struct mmu_update))) {
+                       /* Flush a full batch after filling in the PTE ptrs. */
+                       rc = apply_to_page_range(mm, start_address,
+                                                address - start_address,
+                                                direct_remap_area_pte_fn, &w);
+                       if (rc)
+                               goto out;
+                       rc = -EFAULT;
+                       if (HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0)
+                               goto out;
+                       v = w = u;
+                       start_address = address;
+               }
+
+               /*
+                * Fill in the machine address: PTE ptr is done later by
+                * apply_to_page_range().
+                */
+                v->val = pfn_pte_ma(mfn, prot).pte
+                         | _PAGE_SPECIAL | _PAGE_IOMAP;
+
+               mfn++;
+               address += PAGE_SIZE;
+               v++;
+       }
+
+       if (v != u) {
+               /* Final batch. */
+               rc = apply_to_page_range(mm, start_address,
+                                        address - start_address,
+                                        direct_remap_area_pte_fn, &w);
+               if (rc)
+                       goto out;
+               rc = -EFAULT;
+               if (unlikely(HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0))
+                       goto out;
+       }
+
+       rc = 0;
+
+ out:
+       flush_tlb_all();
+
+       free_page((unsigned long)u);
+
+       return rc;
+}
+
+int xen_io_remap_pfn_range(struct vm_area_struct *vma,
+                           unsigned long address, unsigned long mfn,
+                           unsigned long size, pgprot_t prot)
+{
+       vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP;
+
+       return __direct_remap_pfn_range(
+               vma->vm_mm, address, mfn, size, prot, DOMID_IO);
+}
+
 #ifdef CONFIG_XEN_DEBUG_FS
 
 static struct dentry *d_mmu_debug;
diff --git a/arch/x86/xen/mmu.h b/arch/x86/xen/mmu.h
index 98d7165..e1c8321 100644
--- a/arch/x86/xen/mmu.h
+++ b/arch/x86/xen/mmu.h
@@ -54,4 +54,8 @@ pte_t xen_ptep_modify_prot_start(struct mm_struct *mm, 
unsigned long addr, pte_t
 void  xen_ptep_modify_prot_commit(struct mm_struct *mm, unsigned long addr,
                                  pte_t *ptep, pte_t pte);
 
+int xen_io_remap_pfn_range(struct vm_area_struct *vma,
+                           unsigned long address, unsigned long mfn,
+                           unsigned long size, pgprot_t prot);
+
 #endif /* _XEN_MMU_H */
-- 
1.6.1




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

<Prev in Thread] Current Thread [Next in Thread>