]> xenbits.xensource.com Git - people/royger/xen.git/commitdiff
xen/arm: Allow lpae_is_{table, mapping} helpers to work on invalid entry
authorJulien Grall <julien.grall@arm.com>
Mon, 8 Oct 2018 18:33:39 +0000 (19:33 +0100)
committerJulien Grall <julien.grall@arm.com>
Thu, 22 Nov 2018 14:17:16 +0000 (14:17 +0000)
Currently, lpae_is_{table, mapping} helpers will always return false on
entries with the valid bit unset. However, it would be useful to have them
operating on any entry. For instance to store information in advance but
still request a fault.

With that change, the p2m is now providing an overlay for *_is_{table,
mapping} that will check the valid bit of the entry.

Signed-off-by: Julien Grall <julien.grall@arm.com>
Reviewed-by: Stefano Stabellini <sstabellini@kernel.org>
xen/arch/arm/guest_walk.c
xen/arch/arm/mm.c
xen/arch/arm/p2m.c
xen/include/asm-arm/lpae.h

index e3e21bdad3ad7c16e0c66aa00dc6c04939389392..4a1b4cf2c8f5d810caf76f3036cc8394b58ea7d6 100644 (file)
@@ -566,7 +566,7 @@ static int guest_walk_ld(const struct vcpu *v,
      * PTE is invalid or holds a reserved entry (PTE<1:0> == x0)) or if the PTE
      * maps a memory block at level 3 (PTE<1:0> == 01).
      */
-    if ( !lpae_is_mapping(pte, level) )
+    if ( !lpae_is_valid(pte) || !lpae_is_mapping(pte, level) )
         return -EFAULT;
 
     /* Make sure that the lower bits of the PTE's base address are zero. */
index 0bc31b1d9b167fa7f9d65b10c4cb197cb88cffbb..987fcb916213d8fdc4989c2a57cd3d06de4bd013 100644 (file)
@@ -996,7 +996,7 @@ static int create_xen_entries(enum xenmap_operation op,
     for(; addr < addr_end; addr += PAGE_SIZE, mfn = mfn_add(mfn, 1))
     {
         entry = &xen_second[second_linear_offset(addr)];
-        if ( !lpae_is_table(*entry, 2) )
+        if ( !lpae_is_valid(*entry) || !lpae_is_table(*entry, 2) )
         {
             rc = create_xen_table(entry);
             if ( rc < 0 ) {
index f8a2f6459e4e45cf5bd7d6e85d0677aa4a376a5f..8fffb4288933f402c13b8436d48e00771fba6a93 100644 (file)
@@ -219,6 +219,20 @@ static p2m_access_t p2m_mem_access_radix_get(struct p2m_domain *p2m, gfn_t gfn)
         return radix_tree_ptr_to_int(ptr);
 }
 
+/*
+ * lpae_is_* helpers don't check whether the valid bit is set in the
+ * PTE. Provide our own overlay to check the valid bit.
+ */
+static inline bool p2m_is_mapping(lpae_t pte, unsigned int level)
+{
+    return lpae_is_valid(pte) && lpae_is_mapping(pte, level);
+}
+
+static inline bool p2m_is_superpage(lpae_t pte, unsigned int level)
+{
+    return lpae_is_valid(pte) && lpae_is_superpage(pte, level);
+}
+
 #define GUEST_TABLE_MAP_FAILED 0
 #define GUEST_TABLE_SUPER_PAGE 1
 #define GUEST_TABLE_NORMAL_PAGE 2
@@ -262,7 +276,7 @@ static int p2m_next_level(struct p2m_domain *p2m, bool read_only,
 
     /* The function p2m_next_level is never called at the 3rd level */
     ASSERT(level < 3);
-    if ( lpae_is_mapping(*entry, level) )
+    if ( p2m_is_mapping(*entry, level) )
         return GUEST_TABLE_SUPER_PAGE;
 
     mfn = lpae_get_mfn(*entry);
@@ -642,7 +656,7 @@ static void p2m_free_entry(struct p2m_domain *p2m,
         return;
 
     /* Nothing to do but updating the stats if the entry is a super-page. */
-    if ( lpae_is_superpage(entry, level) )
+    if ( p2m_is_superpage(entry, level) )
     {
         p2m->stats.mappings[level]--;
         return;
@@ -697,7 +711,7 @@ static bool p2m_split_superpage(struct p2m_domain *p2m, lpae_t *entry,
      * a superpage.
      */
     ASSERT(level < target);
-    ASSERT(lpae_is_superpage(*entry, level));
+    ASSERT(p2m_is_superpage(*entry, level));
 
     page = alloc_domheap_page(NULL, 0);
     if ( !page )
@@ -836,7 +850,7 @@ static int __p2m_set_entry(struct p2m_domain *p2m,
         /* We need to split the original page. */
         lpae_t split_pte = *entry;
 
-        ASSERT(lpae_is_superpage(*entry, level));
+        ASSERT(p2m_is_superpage(*entry, level));
 
         if ( !p2m_split_superpage(p2m, &split_pte, level, target, offsets) )
         {
index 17fdc6074f037b839da880056118d898430d7347..545b0c8f2486f87b1609d790c97d1b680c63b66b 100644 (file)
@@ -133,16 +133,19 @@ static inline bool lpae_is_valid(lpae_t pte)
     return pte.walk.valid;
 }
 
+/*
+ * lpae_is_* don't check the valid bit. This gives an opportunity for the
+ * callers to operate on the entry even if they are not valid. For
+ * instance to store information in advance.
+ */
 static inline bool lpae_is_table(lpae_t pte, unsigned int level)
 {
-    return (level < 3) && lpae_is_valid(pte) && pte.walk.table;
+    return (level < 3) && pte.walk.table;
 }
 
 static inline bool lpae_is_mapping(lpae_t pte, unsigned int level)
 {
-    if ( !lpae_is_valid(pte) )
-        return false;
-    else if ( level == 3 )
+    if ( level == 3 )
         return pte.walk.table;
     else
         return !pte.walk.table;