x86: allow Meltdown band-aid to be disabled

First of all we don't need it on AMD systems. Additionally allow its use
to be controlled by command line option. For best backportability, this
intentionally doesn't use alternative instruction patching to achieve
the intended effect - while we likely want it, this will be later
follow-up.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v3: Add warning about incomplete implementation to command lne option
    doc. Use local variable in paravirt_ctxt_switch_to().
v2: New.

--- sle11sp3.orig/docs/misc/xen-command-line.markdown	2018-01-16 17:00:38.000000000 +0100
+++ sle11sp3/docs/misc/xen-command-line.markdown	2018-01-16 10:14:10.000000000 +0100
@@ -1018,6 +1018,18 @@ Permit use of x2apic setup for SMP envir
 
 Use the x2apic physical apic driver.  The alternative is the x2apic cluster driver.
 
+### xpti
+> `= <boolean>`
+
+> Default: `false` on AMD hardware
+> Default: `true` everywhere else
+
+Override default selection of whether to isolate 64-bit PV guest page
+tables.
+
+** WARNING: Not yet a complete isolation implementation, but better than
+nothing. **
+
 ### xsave
 > `= <boolean>`
 
--- sle11sp3.orig/xen/arch/x86/domain.c	2018-01-16 10:12:40.000000000 +0100
+++ sle11sp3/xen/arch/x86/domain.c	2018-01-16 10:14:10.000000000 +0100
@@ -1580,15 +1580,19 @@ static void paravirt_ctxt_switch_from(st
 
 static void paravirt_ctxt_switch_to(struct vcpu *v)
 {
+#ifdef __x86_64__
+    root_pgentry_t *root_pgt = this_cpu(root_pgt);
+#endif
     unsigned long cr4;
 
     set_int80_direct_trap(v);
     switch_kernel_stack(v);
 
 #ifdef __x86_64__
-    this_cpu(root_pgt)[root_table_offset(PERDOMAIN_VIRT_START)] =
-        root_from_paddr(__pa(v->domain->arch.mm_perdomain_l3),
-                        __PAGE_HYPERVISOR);
+    if ( root_pgt )
+        root_pgt[root_table_offset(PERDOMAIN_VIRT_START)] =
+            root_from_paddr(__pa(v->domain->arch.mm_perdomain_l3),
+                            __PAGE_HYPERVISOR);
 #endif
 
     cr4 = pv_guest_cr4_to_real_cr4(v);
--- sle11sp3.orig/xen/arch/x86/mm.c	2018-01-16 11:31:51.000000000 +0100
+++ sle11sp3/xen/arch/x86/mm.c	2018-01-16 10:14:10.000000000 +0100
@@ -4102,7 +4102,7 @@ long do_mmu_update(
                     rc = mod_l4_entry(va, l4e_from_intpte(req.val), mfn,
                                       cmd == MMU_PT_UPDATE_PRESERVE_AD, v);
                     if ( !rc )
-                        sync_guest = 1;
+                        sync_guest = !!this_cpu(root_pgt);
                 break;
 #endif
                 case PGT_writable_page:
--- sle11sp3.orig/xen/arch/x86/smpboot.c	2018-01-16 10:12:40.000000000 +0100
+++ sle11sp3/xen/arch/x86/smpboot.c	2018-01-16 10:14:10.000000000 +0100
@@ -349,7 +349,7 @@ void start_secondary(void *unused)
     spin_debug_disable();
 
     get_cpu_info()->xen_cr3 = 0;
-    get_cpu_info()->pv_cr3 = __pa(this_cpu(root_pgt));
+    get_cpu_info()->pv_cr3 = this_cpu(root_pgt) ? __pa(this_cpu(root_pgt)) : 0;
 
     percpu_traps_init();
 
@@ -753,15 +753,23 @@ static int clone_mapping(const void *ptr
 }
 #endif
 
+#ifdef __x86_64__
+static __read_mostly int8_t opt_xpti = -1;
+boolean_param("xpti", opt_xpti);
+#endif
 DEFINE_PER_CPU(root_pgentry_t *, root_pgt);
 
 static int setup_cpu_root_pgt(unsigned int cpu)
 {
     int rc = 0;
 #ifdef __x86_64__
-    root_pgentry_t *rpt = alloc_xen_pagetable();
+    root_pgentry_t *rpt;
     unsigned int off;
 
+    if ( !opt_xpti )
+        return 0;
+
+    rpt = alloc_xen_pagetable();
     if ( !rpt )
         return -ENOMEM;
 
@@ -962,10 +970,16 @@ void __init smp_prepare_cpus(unsigned in
 
     stack_base[0] = stack_start.esp;
 
+#ifdef __x86_64__
+    if ( opt_xpti < 0 )
+        opt_xpti = boot_cpu_data.x86_vendor != X86_VENDOR_AMD;
+#endif
+
     rc = setup_cpu_root_pgt(0);
     if ( rc )
         panic("Error %d setting up PV root page table\n", rc);
-    get_cpu_info()->pv_cr3 = __pa(per_cpu(root_pgt, 0));
+    if ( per_cpu(root_pgt, 0) )
+        get_cpu_info()->pv_cr3 = __pa(per_cpu(root_pgt, 0));
 
     if ( !zalloc_cpumask_var(&per_cpu(cpu_sibling_mask, 0)) ||
          !zalloc_cpumask_var(&per_cpu(cpu_core_mask, 0)) )
@@ -1028,6 +1042,7 @@ void __init smp_prepare_boot_cpu(void)
     cpumask_set_cpu(smp_processor_id(), &cpu_present_map);
 
     get_cpu_info()->xen_cr3 = 0;
+    get_cpu_info()->pv_cr3 = 0;
 }
 
 static void
--- sle11sp3.orig/xen/arch/x86/x86_64/entry.S	2018-01-16 17:39:19.000000000 +0100
+++ sle11sp3/xen/arch/x86/x86_64/entry.S	2018-01-16 12:37:15.000000000 +0100
@@ -46,6 +46,7 @@ restore_all_guest:
         movabs $DIRECTMAP_VIRT_START, %rcx
         mov   %rdi, %rax
         and   %rsi, %rdi
+        jz    .Lrag_keep_cr3
         and   %r9, %rsi
         add   %rcx, %rdi
         add   %rcx, %rsi
@@ -62,6 +63,7 @@ restore_all_guest:
         rep movsq
         mov   %r9, STACK_CPUINFO_FIELD(xen_cr3)(%rdx)
         write_cr3 rax, rdi, rsi
+.Lrag_keep_cr3:
 
         RESTORE_ALL
         testw $TRAP_syscall,4(%rsp)
