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

[Xen-devel] [PATCH v2 2/2] xen: use multicalls for m2p override grant ta

From: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>

Replace the HYPERVISOR_grant_table_op hypercalls with multicalls.

Use the kmap_op pointer directly as argument to do the mapping as it is
guaranteed to be present up until the unmapping is done.
The mapping can be done either by m2p_add_override, in case of
!PageHighMem, or in __xen_set_pte otherwise.

Before issuing any unmapping multicalls, we need to make sure that the
mapping has already being done, because we need the kmap->handle to be
set correctly.
Also we need to do the unmapping before the page is removed from the m2p
override, so we force the unmapping in m2p_remove_override even if
PageHighMem. The value of map_op->host_addr can be used to know if the
unmapping has already happened.

Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>
---
 arch/x86/xen/mmu.c |   49 +++++++++++++++++++++++++++++-------------
 arch/x86/xen/p2m.c |   60 ++++++++++++++++++++++++++++++++-------------------
 2 files changed, 72 insertions(+), 37 deletions(-)

diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c
index e80dad5..b142315 100644
--- a/arch/x86/xen/mmu.c
+++ b/arch/x86/xen/mmu.c
@@ -317,18 +317,36 @@ static int xen_unmap_granted_page(pte_t *ptep)
        mfn = (ptep->pte & PTE_PFN_MASK) >> PAGE_SHIFT;
        page = m2p_find_override(mfn);
        if (page != NULL && (page->private & GRANT_FRAME_BIT)) {
-               int ret;
-               struct gnttab_unmap_grant_ref kunmap_op;
                struct gnttab_map_grant_ref *kmap_op =
                        (struct gnttab_map_grant_ref *) page->index;
-               kunmap_op.host_addr = kmap_op->host_addr;
-               kunmap_op.handle = kmap_op->handle;
-               kunmap_op.dev_bus_addr = 0;
-               ret = HYPERVISOR_grant_table_op(
-                               GNTTABOP_unmap_grant_ref, &kunmap_op, 1);
-               WARN(ret, "m2p_remove_override: pfn %lx mfn %lx, failed to "
-                       "modify kernel mappings", page_to_pfn(page), mfn);
-               return ret;
+               struct multicall_space mcs =
+                       xen_mc_entry(sizeof(struct gnttab_unmap_grant_ref));
+               struct gnttab_unmap_grant_ref *kunmap_op = mcs.args;
+
+               if (kmap_op->host_addr == 0)
+                       return 0;
+               /* 
+                * Has the grant_op mapping multicall being issued? If not,
+                * make sure it is called now.
+                */
+               if (kmap_op->handle == -1)
+                       xen_mc_flush();
+               if (kmap_op->handle == -1) {
+                       printk(KERN_WARNING "xen_unmap_granted_page: mfn %lx, "
+                                       "failed to modify kernel mappings", 
mfn);
+                       return -1;
+               }
+
+               kunmap_op->host_addr = kmap_op->host_addr;
+               kunmap_op->handle = kmap_op->handle;
+               kunmap_op->dev_bus_addr = 0;
+
+               MULTI_grant_table_op(mcs.mc,
+                               GNTTABOP_unmap_grant_ref, kunmap_op, 1);
+
+               xen_mc_issue(PARAVIRT_LAZY_MMU);
+               kmap_op->host_addr = 0;
+               return 0;
        }
        return 1;
 }
@@ -345,7 +363,6 @@ static inline void __xen_set_pte(pte_t *ptep, pte_t pteval)
        xen_unmap_granted_page(ptep);
 
        if (!(pte_flags(pteval) & _PAGE_USER)) {
-               int ret;
                struct page *page;
                unsigned long mfn = (pteval.pte & PTE_PFN_MASK) >> PAGE_SHIFT;
                page = m2p_find_override(mfn);
@@ -354,17 +371,19 @@ static inline void __xen_set_pte(pte_t *ptep, pte_t 
pteval)
                 * hypercall to map it instead
                 */
                if (page != NULL && (page->private & GRANT_FRAME_BIT)) {
+                       struct multicall_space mcs =
+                               xen_mc_entry(sizeof(struct 
gnttab_unmap_grant_ref));
                        struct gnttab_map_grant_ref *kmap_op =
                                (struct gnttab_map_grant_ref *) page->index;
                        unsigned long old_mfn = kmap_op->dev_bus_addr;
                        kmap_op->host_addr =
                                arbitrary_virt_to_machine(ptep).maddr;
                        kmap_op->dev_bus_addr = 0;
-                       ret = HYPERVISOR_grant_table_op(
+
+                       MULTI_grant_table_op(mcs.mc,
                                        GNTTABOP_map_grant_ref, kmap_op, 1);
-                       WARN(ret, "xen_set_pte: pfn %lx mfn %lx, failed to "
-                               "modify kernel mappings",
-                               page_to_pfn(page), mfn);
+
+                       xen_mc_issue(PARAVIRT_LAZY_MMU);
                        kmap_op->dev_bus_addr = old_mfn;
                        return;
                }
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c
index 1c4d2b5..287fa77 100644
--- a/arch/x86/xen/p2m.c
+++ b/arch/x86/xen/p2m.c
@@ -163,6 +163,7 @@
 #include <asm/xen/hypervisor.h>
 #include <xen/grant_table.h>
 
+#include "multicalls.h"
 #include "xen-ops.h"
 
 static void __init m2p_override_init(void);
@@ -703,10 +704,12 @@ int m2p_add_override(unsigned long mfn, struct page *page,
 
        if (kmap_op != NULL) {
                if (!PageHighMem(page)) {
-                       int ret = HYPERVISOR_grant_table_op(
+                       struct multicall_space mcs = 
xen_mc_entry(sizeof(*kmap_op));
+
+                       MULTI_grant_table_op(mcs.mc,
                                        GNTTABOP_map_grant_ref, kmap_op, 1);
-                       WARN(ret, "m2p_add_override: pfn %lx mfn %lx, "
-                               "failed to modify kernel mappings", pfn, mfn);
+
+                       xen_mc_issue(PARAVIRT_LAZY_MMU);
                }
                page->private |= GRANT_FRAME_BIT;
                /* let's use dev_bus_addr to record the old mfn instead */
@@ -734,15 +737,6 @@ int m2p_remove_override(struct page *page, bool clear_pte)
        if (mfn == INVALID_P2M_ENTRY || !(mfn & FOREIGN_FRAME_BIT))
                return -EINVAL;
 
-       if (!PageHighMem(page)) {
-               address = (unsigned long)__va(pfn << PAGE_SHIFT);
-               ptep = lookup_address(address, &level);
-
-               if (WARN(ptep == NULL || level != PG_LEVEL_4K,
-                                       "m2p_remove_override: pfn %lx not 
mapped", pfn))
-                       return -EINVAL;
-       }
-
        spin_lock_irqsave(&m2p_override_lock, flags);
        list_del(&page->lru);
        spin_unlock_irqrestore(&m2p_override_lock, flags);
@@ -751,16 +745,38 @@ int m2p_remove_override(struct page *page, bool clear_pte)
                struct gnttab_map_grant_ref *map_op =
                        (struct gnttab_map_grant_ref *) page->index;
                set_phys_to_machine(pfn, map_op->dev_bus_addr);
-               if (!PageHighMem(page)) {
-                       int ret;
-                       struct gnttab_unmap_grant_ref unmap_op;
-                       unmap_op.host_addr = map_op->host_addr;
-                       unmap_op.handle = map_op->handle;
-                       unmap_op.dev_bus_addr = 0;
-                       ret = HYPERVISOR_grant_table_op(
-                                       GNTTABOP_unmap_grant_ref, &unmap_op, 1);
-                       WARN(ret, "m2p_remove_override: pfn %lx mfn %lx, "
-                               "failed to modify kernel mappings", pfn, mfn);
+               if (map_op->host_addr != 0) {
+                       struct multicall_space mcs =
+                               xen_mc_entry(sizeof(struct 
gnttab_unmap_grant_ref));
+                       struct gnttab_unmap_grant_ref *unmap_op = mcs.args;
+
+                       /* 
+                        * Has the grant_op mapping multicall being issued? If 
not,
+                        * make sure it is called now.
+                        */
+                       if (map_op->handle == -1)
+                               xen_mc_flush();
+                       if (map_op->handle == -1) {
+                               printk(KERN_WARNING "m2p_remove_override: pfn 
%lx mfn %lx, "
+                                               "failed to modify kernel 
mappings", pfn, mfn);
+                               return -1;
+                       }
+
+                       unmap_op->host_addr = map_op->host_addr;
+                       unmap_op->handle = map_op->handle;
+                       unmap_op->dev_bus_addr = 0;
+
+                       MULTI_grant_table_op(mcs.mc,
+                                       GNTTABOP_unmap_grant_ref, unmap_op, 1);
+
+                       xen_mc_issue(PARAVIRT_LAZY_MMU);
+
+                       map_op->host_addr = 0;
+                       address = (unsigned long)__va(pfn << PAGE_SHIFT);
+                       ptep = lookup_address(address, &level);
+                       if (WARN(ptep == NULL || level != PG_LEVEL_4K,
+                                               "m2p_remove_override: pfn %lx 
not mapped", pfn))
+                               return -2;
                        set_pte_at(&init_mm, address, ptep,
                                        pfn_pte(pfn, PAGE_KERNEL));
                        __flush_tlb_single(address);
-- 
1.7.2.3


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

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