In current code, only one bit (bit 0) is used in rmap, this patch export
more bits from rmap, during pte add/remove, it only touches bit 0 and other
bits are keeped

Signed-off-by: Xiao Guangrong <xiaoguangr...@linux.vnet.ibm.com>
---
 arch/x86/kvm/mmu.c |  143 +++++++++++++++++++++++++++++++++-------------------
 1 files changed, 91 insertions(+), 52 deletions(-)

diff --git a/arch/x86/kvm/mmu.c b/arch/x86/kvm/mmu.c
index bb4d292..84b9775 100644
--- a/arch/x86/kvm/mmu.c
+++ b/arch/x86/kvm/mmu.c
@@ -796,6 +796,17 @@ static int mapping_level(struct kvm_vcpu *vcpu, gfn_t 
large_gfn)
        return level - 1;
 }

+#define PTE_LIST_DESC          (0x1ull)
+#define PTE_LIST_FLAG_MASK     (0x3ull)
+
+static void
+pte_list_decode(const unsigned long *pte_list, unsigned long *map,
+               unsigned long *flags)
+{
+       *map = *pte_list & (~PTE_LIST_FLAG_MASK);
+       *flags = *pte_list & PTE_LIST_FLAG_MASK;
+}
+
 /*
  * Pte mapping structures:
  *
@@ -812,50 +823,67 @@ static int pte_list_add(struct kvm_vcpu *vcpu, u64 *spte,
                        unsigned long *pte_list)
 {
        struct pte_list_desc *desc;
+       unsigned long map, flags;
        int i, count = 0;

-       if (!*pte_list) {
+       pte_list_decode(pte_list, &map, &flags);
+
+       if (!map) {
                rmap_printk("pte_list_add: %p %llx 0->1\n", spte, *spte);
-               *pte_list = (unsigned long)spte;
-       } else if (!(*pte_list & 1)) {
+               WARN_ON(flags & PTE_LIST_DESC);
+               *pte_list = (unsigned long)spte | flags ;
+
+               return 0;
+       }
+
+       if (!(flags & PTE_LIST_DESC)) {
                rmap_printk("pte_list_add: %p %llx 1->many\n", spte, *spte);
                desc = mmu_alloc_pte_list_desc(vcpu);
-               desc->sptes[0] = (u64 *)*pte_list;
+               desc->sptes[0] = (u64 *)map;
                desc->sptes[1] = spte;
-               *pte_list = (unsigned long)desc | 1;
-               ++count;
-       } else {
-               rmap_printk("pte_list_add: %p %llx many->many\n", spte, *spte);
-               desc = (struct pte_list_desc *)(*pte_list & ~1ul);
-               while (desc->sptes[PTE_LIST_EXT-1] && desc->more) {
-                       desc = desc->more;
-                       count += PTE_LIST_EXT;
-               }
-               if (desc->sptes[PTE_LIST_EXT-1]) {
-                       desc->more = mmu_alloc_pte_list_desc(vcpu);
-                       desc = desc->more;
-               }
-               for (i = 0; desc->sptes[i]; ++i)
-                       ++count;
-               desc->sptes[i] = spte;
+               *pte_list = (unsigned long)desc | flags | PTE_LIST_DESC;
+
+               return 1;
+       }
+
+       rmap_printk("pte_list_add: %p %llx many->many\n", spte, *spte);
+       desc = (struct pte_list_desc *)map;
+       while (desc->sptes[PTE_LIST_EXT - 1] && desc->more) {
+               desc = desc->more;
+               count += PTE_LIST_EXT;
+       }
+
+       if (desc->sptes[PTE_LIST_EXT - 1]) {
+               desc->more = mmu_alloc_pte_list_desc(vcpu);
+               desc = desc->more;
        }
+
+       for (i = 0; desc->sptes[i]; ++i)
+               ++count;
+       desc->sptes[i] = spte;
+
        return count;
 }

 static u64 *pte_list_next(unsigned long *pte_list, u64 *spte)
 {
        struct pte_list_desc *desc;
+       unsigned long map, flags;
        u64 *prev_spte;
        int i;

-       if (!*pte_list)
+       pte_list_decode(pte_list, &map, &flags);
+
+       if (!map)
                return NULL;
-       else if (!(*pte_list & 1)) {
+
+       if (!(flags & PTE_LIST_DESC)) {
                if (!spte)
-                       return (u64 *)*pte_list;
+                       return (u64 *)map;
                return NULL;
        }
-       desc = (struct pte_list_desc *)(*pte_list & ~1ul);
+
+       desc = (struct pte_list_desc *)map;
        prev_spte = NULL;
        while (desc) {
                for (i = 0; i < PTE_LIST_EXT && desc->sptes[i]; ++i) {
@@ -870,7 +898,8 @@ static u64 *pte_list_next(unsigned long *pte_list, u64 
*spte)

 static void
 pte_list_desc_remove_entry(unsigned long *pte_list, struct pte_list_desc *desc,
-                          int i, struct pte_list_desc *prev_desc)
+                          int i, struct pte_list_desc *prev_desc,
+                          unsigned long flags)
 {
        int j;

@@ -881,12 +910,13 @@ pte_list_desc_remove_entry(unsigned long *pte_list, 
struct pte_list_desc *desc,
        if (j != 0)
                return;
        if (!prev_desc && !desc->more)
-               *pte_list = (unsigned long)desc->sptes[0];
+               *pte_list = (unsigned long)desc->sptes[0] |
+                                       (flags & (~PTE_LIST_DESC)) ;
        else
                if (prev_desc)
                        prev_desc->more = desc->more;
                else
-                       *pte_list = (unsigned long)desc->more | 1;
+                       *pte_list = (unsigned long)desc->more | flags;
        mmu_free_pte_list_desc(desc);
 }

@@ -894,51 +924,60 @@ static void pte_list_remove(u64 *spte, unsigned long 
*pte_list)
 {
        struct pte_list_desc *desc;
        struct pte_list_desc *prev_desc;
+       unsigned long map, flags;
        int i;

-       if (!*pte_list) {
+       pte_list_decode(pte_list, &map, &flags);
+
+       if (!map) {
                printk(KERN_ERR "pte_list_remove: %p 0->BUG\n", spte);
                BUG();
-       } else if (!(*pte_list & 1)) {
+               return;
+       }
+
+       if (!(flags & PTE_LIST_DESC)) {
                rmap_printk("pte_list_remove:  %p 1->0\n", spte);
-               if ((u64 *)*pte_list != spte) {
+               if ((u64 *)map != spte) {
                        printk(KERN_ERR "pte_list_remove:  %p 1->BUG\n", spte);
                        BUG();
                }
-               *pte_list = 0;
-       } else {
-               rmap_printk("pte_list_remove:  %p many->many\n", spte);
-               desc = (struct pte_list_desc *)(*pte_list & ~1ul);
-               prev_desc = NULL;
-               while (desc) {
-                       for (i = 0; i < PTE_LIST_EXT && desc->sptes[i]; ++i)
-                               if (desc->sptes[i] == spte) {
-                                       pte_list_desc_remove_entry(pte_list,
-                                                              desc, i,
-                                                              prev_desc);
-                                       return;
-                               }
-                       prev_desc = desc;
-                       desc = desc->more;
-               }
-               pr_err("pte_list_remove: %p many->many\n", spte);
-               BUG();
+               *pte_list = flags;
+               return;
+       }
+
+       rmap_printk("pte_list_remove:  %p many->many\n", spte);
+       desc = (struct pte_list_desc *)map;
+       prev_desc = NULL;
+       while (desc) {
+               for (i = 0; i < PTE_LIST_EXT && desc->sptes[i]; ++i)
+                       if (desc->sptes[i] == spte) {
+                               pte_list_desc_remove_entry(pte_list,
+                                               desc, i, prev_desc, flags);
+                               return;
+                       }
+               prev_desc = desc;
+               desc = desc->more;
        }
+       pr_err("pte_list_remove: %p many->many\n", spte);
+       BUG();
 }

 typedef void (*pte_list_walk_fn) (u64 *spte);
 static void pte_list_walk(unsigned long *pte_list, pte_list_walk_fn fn)
 {
        struct pte_list_desc *desc;
+       unsigned long map, flags;
        int i;

-       if (!*pte_list)
+       pte_list_decode(pte_list, &map, &flags);
+
+       if (!map)
                return;

-       if (!(*pte_list & 1))
-               return fn((u64 *)*pte_list);
+       if (!(flags & PTE_LIST_DESC))
+               return fn((u64 *)map);

-       desc = (struct pte_list_desc *)(*pte_list & ~1ul);
+       desc = (struct pte_list_desc *)map;
        while (desc) {
                for (i = 0; i < PTE_LIST_EXT && desc->sptes[i]; ++i)
                        fn(desc->sptes[i]);
-- 
1.7.7.6

--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to