summaryrefslogtreecommitdiff
path: root/xsa286-1.patch
diff options
context:
space:
mode:
Diffstat (limited to 'xsa286-1.patch')
-rw-r--r--xsa286-1.patch70
1 files changed, 70 insertions, 0 deletions
diff --git a/xsa286-1.patch b/xsa286-1.patch
new file mode 100644
index 0000000..f0f51d5
--- /dev/null
+++ b/xsa286-1.patch
@@ -0,0 +1,70 @@
+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;