[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH RFC v2 4/9] xen/arm: Implement get_maximum_gpfn hypercall for arm



From: Alexey Sokolov <sokolov.a@xxxxxxxxxxx>

Since we do not know the maximum gpfn size for guest domain,
we walk the page table of guest in order to see the maximum size
of gpfn.

Singed-off-by: Alexey Sokolov <sokolov.a@xxxxxxxxxxx>
---
 xen/arch/arm/mm.c             |  3 +-
 xen/arch/arm/p2m.c            | 69 +++++++++++++++++++++++++++++++++++++++++++
 xen/include/asm-arm/p2m.h     |  3 ++
 xen/include/public/arch-arm.h |  6 ++++
 4 files changed, 80 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index d1290cd..650b1fc 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -762,7 +762,8 @@ int page_is_ram_type(unsigned long mfn, unsigned long 
mem_type)
 
 unsigned long domain_get_maximum_gpfn(struct domain *d)
 {
-    return -ENOSYS;
+    xen_pfn_t result = p2m_get_next_non_used_gpfn(d, GUEST_RAM_BASE >> 
PAGE_SHIFT);
+    return result;
 }
 
 void share_xen_page_with_guest(struct page_info *page,
diff --git a/xen/arch/arm/p2m.c b/xen/arch/arm/p2m.c
index 9fc5534..8bf7eb7 100644
--- a/xen/arch/arm/p2m.c
+++ b/xen/arch/arm/p2m.c
@@ -5,6 +5,75 @@
 #include <xen/domain_page.h>
 #include <asm/flushtlb.h>
 #include <asm/gic.h>
+#include <xen/guest_access.h>
+
+/* 
+ * walk the guest page table to find out the next non-used gpfn 
+ */
+xen_pfn_t p2m_get_next_non_used_gpfn(struct domain *d, xen_pfn_t start)
+{
+    struct p2m_domain *p2m = &d->arch.p2m;
+    paddr_t start_addr = start << PAGE_SHIFT;
+    int first_index = first_table_offset(start_addr);
+    int second_index = second_table_offset(start_addr);
+    int third_index = third_table_offset(start_addr);
+    lpae_t *first = __map_domain_page(p2m->first_level);
+    lpae_t *second = NULL;
+    lpae_t *third = NULL;
+
+    BUG_ON(!first && "Can't map first level p2m");
+
+    spin_lock(&p2m->lock);
+
+    while (first_index < LPAE_ENTRIES*2)
+    {
+        lpae_walk_t first_pte = first[first_index].walk;
+        if (!first_pte.valid || !first_pte.table)
+        {
+            goto out;
+        }
+        second = map_domain_page(first_pte.base);
+        BUG_ON(!second && "Can't map second level p2m");
+        while (second_index < LPAE_ENTRIES)
+        {
+            lpae_walk_t second_pte = second[second_index].walk;
+            if (!second_pte.valid || !second_pte.table)
+            {
+                goto out;
+            }
+            third = map_domain_page(second_pte.base);
+            BUG_ON(!third && "Can't map third level p2m");
+            while (third_index < LPAE_ENTRIES)
+            {
+                lpae_walk_t third_pte = third[third_index].walk;
+                if (!third_pte.valid)
+                {
+                    goto out;
+                }
+                third_index++;
+            }
+            unmap_domain_page(third); third = NULL;
+            second_index++;
+            third_index = 0;
+        }
+        unmap_domain_page(second); second = NULL;
+        first_index++;
+        second_index = 0;
+        third_index = 0;
+    }
+
+out:
+    if (third) unmap_domain_page(third);
+    if (second) unmap_domain_page(second);
+    if (first) unmap_domain_page(first);
+
+    spin_unlock(&p2m->lock);
+
+    return ( ((xen_pfn_t)first_index << FIRST_SHIFT) |
+             (second_index << SECOND_SHIFT)          |
+             (third_index << THIRD_SHIFT)
+           )  >> PAGE_SHIFT;
+}
 
 void dump_p2m_lookup(struct domain *d, paddr_t addr)
 {
diff --git a/xen/include/asm-arm/p2m.h b/xen/include/asm-arm/p2m.h
index a00069b..379c453 100644
--- a/xen/include/asm-arm/p2m.h
+++ b/xen/include/asm-arm/p2m.h
@@ -57,6 +57,9 @@ void guest_physmap_remove_page(struct domain *d,
 
 unsigned long gmfn_to_mfn(struct domain *d, unsigned long gpfn);
 
+/* walk the guest page table to find out the next non-used gpfn */
+xen_pfn_t p2m_get_next_non_used_gpfn(struct domain *d, xen_pfn_t start);
+
 /*
  * Populate-on-demand
  */
diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
index 352c08d..4a53692 100644
--- a/xen/include/public/arch-arm.h
+++ b/xen/include/public/arch-arm.h
@@ -274,6 +274,12 @@ typedef uint64_t xen_callback_t;
 
 #define PSR_GUEST_INIT  (PSR_ABT_MASK|PSR_FIQ_MASK|PSR_IRQ_MASK|PSR_MODE_SVC)
 
+/*
+ * Guest virtual RAM starts here. This must be consistent with the DTB
+ * appended to the guest kernel.
+ */
+#define GUEST_RAM_BASE 0x80000000
+
 #endif /*  __XEN_PUBLIC_ARCH_ARM_H__ */
 
 /*
-- 
1.8.1.2


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.