File xsa286-1.patch of Package xen
x86/mm: split L4 and L3 parts of the walk out of do_page_walk()
The L3 one at least is going to be re-used by a subsequent patch, and
splitting the L4 one then as well seems only natural.
This is part of XSA-286.
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: George Dunlap <george.dunlap@citrix.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
--- a/xen/arch/x86/x86_64/mm.c
+++ b/xen/arch/x86/x86_64/mm.c
@@ -44,26 +44,47 @@ unsigned int __read_mostly m2p_compat_vs
l2_pgentry_t *compat_idle_pg_table_l2;
-void *do_page_walk(struct vcpu *v, unsigned long addr)
+static l4_pgentry_t page_walk_get_l4e(pagetable_t root, unsigned long addr)
{
- unsigned long mfn = pagetable_get_pfn(v->arch.guest_table);
- l4_pgentry_t l4e, *l4t;
- l3_pgentry_t l3e, *l3t;
- l2_pgentry_t l2e, *l2t;
- l1_pgentry_t l1e, *l1t;
+ unsigned long mfn = pagetable_get_pfn(root);
+ l4_pgentry_t *l4t, l4e;
- if ( !is_pv_vcpu(v) || !is_canonical_address(addr) )
- return NULL;
+ if ( !is_canonical_address(addr) )
+ return l4e_empty();
l4t = map_domain_page(_mfn(mfn));
l4e = l4t[l4_table_offset(addr)];
unmap_domain_page(l4t);
+
+ return l4e;
+}
+
+static l3_pgentry_t page_walk_get_l3e(pagetable_t root, unsigned long addr)
+{
+ l4_pgentry_t l4e = page_walk_get_l4e(root, addr);
+ l3_pgentry_t *l3t, l3e;
+
if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
- return NULL;
+ return l3e_empty();
l3t = map_l3t_from_l4e(l4e);
l3e = l3t[l3_table_offset(addr)];
unmap_domain_page(l3t);
+
+ return l3e;
+}
+
+void *do_page_walk(struct vcpu *v, unsigned long addr)
+{
+ l3_pgentry_t l3e;
+ l2_pgentry_t l2e, *l2t;
+ l1_pgentry_t l1e, *l1t;
+ unsigned long mfn;
+
+ if ( !is_pv_vcpu(v) )
+ return NULL;
+
+ l3e = page_walk_get_l3e(v->arch.guest_table, addr);
mfn = l3e_get_pfn(l3e);
if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) || !mfn_valid(_mfn(mfn)) )
return NULL;