# Commit fb1658221a31ec1db33253a80001191391e73b17
# Date 2024-08-28 19:59:07 +0100
# Author Roger Pau Monne <roger.pau@citrix.com>
# Committer Andrew Cooper <andrew.cooper3@citrix.com>
x86/dom0: disable SMAP for PV domain building only

Move the logic that disables SMAP so it's only performed when building a PV
dom0, PVH dom0 builder doesn't require disabling SMAP.

The fixes tag is to account for the wrong usage of cpu_has_smap in
create_dom0(), it should instead have used
boot_cpu_has(X86_FEATURE_XEN_SMAP).  Fix while moving the logic to apply to PV
only.

Fixes: 493ab190e5b1 ('xen/sm{e, a}p: allow disabling sm{e, a}p for Xen itself')
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>

--- a/xen/include/asm-x86/setup.h
+++ b/xen/include/asm-x86/setup.h
@@ -68,6 +68,8 @@ extern bool opt_dom0_shadow;
 extern bool dom0_pvh;
 extern bool dom0_verbose;
 
+extern unsigned long cr4_pv32_mask;
+
 #define max_init_domid (0)
 
 #endif
--- a/xen/arch/x86/pv/dom0_build.c
+++ b/xen/arch/x86/pv/dom0_build.c
@@ -279,11 +279,11 @@ static struct page_info * __init alloc_c
     return page;
 }
 
-int __init dom0_construct_pv(struct domain *d,
-                             const module_t *image,
-                             unsigned long image_headroom,
-                             module_t *initrd,
-                             char *cmdline)
+static int __init dom0_construct(struct domain *d,
+                                 const module_t *image,
+                                 unsigned long image_headroom,
+                                 module_t *initrd,
+                                 char *cmdline)
 {
     int i, cpu, rc, compatible, order, machine;
     struct cpu_user_regs *regs;
@@ -922,6 +922,36 @@ out:
 
     return rc;
 }
+
+int __init dom0_construct_pv(struct domain *d,
+                             const module_t *image,
+                             unsigned long image_headroom,
+                             module_t *initrd,
+                             char *cmdline)
+{
+    int rc;
+
+    /*
+     * Clear SMAP in CR4 to allow user-accesses in construct_dom0().  This
+     * prevents us needing to rewrite construct_dom0() in terms of
+     * copy_{to,from}_user().
+     */
+    if ( boot_cpu_has(X86_FEATURE_XEN_SMAP) )
+    {
+        cr4_pv32_mask &= ~X86_CR4_SMAP;
+        write_cr4(read_cr4() & ~X86_CR4_SMAP);
+    }
+
+    rc = dom0_construct(d, image, image_headroom, initrd, cmdline);
+
+    if ( boot_cpu_has(X86_FEATURE_XEN_SMAP) )
+    {
+        write_cr4(read_cr4() | X86_CR4_SMAP);
+        cr4_pv32_mask |= X86_CR4_SMAP;
+    }
+
+    return rc;
+}
 
 /*
  * Local variables:
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -1791,17 +1791,6 @@ void __init noreturn __start_xen(unsigne
                "Multiple initrd candidates, picking module #%u\n",
                initrdidx);
 
-    /*
-     * Temporarily clear SMAP in CR4 to allow user-accesses in construct_dom0().
-     * This saves a large number of corner cases interactions with
-     * copy_from_user().
-     */
-    if ( cpu_has_smap )
-    {
-        cr4_pv32_mask &= ~X86_CR4_SMAP;
-        write_cr4(read_cr4() & ~X86_CR4_SMAP);
-    }
-
     printk("%sNX (Execute Disable) protection %sactive\n",
            cpu_has_nx ? XENLOG_INFO : XENLOG_WARNING "Warning: ",
            cpu_has_nx ? "" : "not ");
@@ -1815,12 +1804,6 @@ void __init noreturn __start_xen(unsigne
                         ? mod + initrdidx : NULL, cmdline) != 0)
         panic("Could not set up DOM0 guest OS\n");
 
-    if ( cpu_has_smap )
-    {
-        write_cr4(read_cr4() | X86_CR4_SMAP);
-        cr4_pv32_mask |= X86_CR4_SMAP;
-    }
-
     heap_init_late();
 
     init_trace_bufs();
