Merge tag 'for-linus-6.1-rc1-tag' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-starfive.git] / arch / x86 / xen / enlighten_pv.c
index 9b1a58d..f82857e 100644 (file)
@@ -108,11 +108,21 @@ struct tls_descs {
  */
 static DEFINE_PER_CPU(struct tls_descs, shadow_tls_desc);
 
+static __read_mostly bool xen_msr_safe = IS_ENABLED(CONFIG_XEN_PV_MSR_SAFE);
+
+static int __init parse_xen_msr_safe(char *str)
+{
+       if (str)
+               return strtobool(str, &xen_msr_safe);
+       return -EINVAL;
+}
+early_param("xen_msr_safe", parse_xen_msr_safe);
+
 static void __init xen_pv_init_platform(void)
 {
        /* PV guests can't operate virtio devices without grants. */
        if (IS_ENABLED(CONFIG_XEN_VIRTIO))
-               virtio_set_mem_acc_cb(virtio_require_restricted_mem_acc);
+               virtio_set_mem_acc_cb(xen_virtio_restricted_mem_acc);
 
        populate_extra_pte(fix_to_virt(FIX_PARAVIRT_BOOTMAP));
 
@@ -917,14 +927,18 @@ static void xen_write_cr4(unsigned long cr4)
        native_write_cr4(cr4);
 }
 
-static u64 xen_read_msr_safe(unsigned int msr, int *err)
+static u64 xen_do_read_msr(unsigned int msr, int *err)
 {
-       u64 val;
+       u64 val = 0;    /* Avoid uninitialized value for safe variant. */
 
        if (pmu_msr_read(msr, &val, err))
                return val;
 
-       val = native_read_msr_safe(msr, err);
+       if (err)
+               val = native_read_msr_safe(msr, err);
+       else
+               val = native_read_msr(msr);
+
        switch (msr) {
        case MSR_IA32_APICBASE:
                val &= ~X2APIC_ENABLE;
@@ -933,23 +947,39 @@ static u64 xen_read_msr_safe(unsigned int msr, int *err)
        return val;
 }
 
-static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
+static void set_seg(unsigned int which, unsigned int low, unsigned int high,
+                   int *err)
 {
-       int ret;
-       unsigned int which;
-       u64 base;
+       u64 base = ((u64)high << 32) | low;
 
-       ret = 0;
+       if (HYPERVISOR_set_segment_base(which, base) == 0)
+               return;
 
+       if (err)
+               *err = -EIO;
+       else
+               WARN(1, "Xen set_segment_base(%u, %llx) failed\n", which, base);
+}
+
+/*
+ * Support write_msr_safe() and write_msr() semantics.
+ * With err == NULL write_msr() semantics are selected.
+ * Supplying an err pointer requires err to be pre-initialized with 0.
+ */
+static void xen_do_write_msr(unsigned int msr, unsigned int low,
+                            unsigned int high, int *err)
+{
        switch (msr) {
-       case MSR_FS_BASE:               which = SEGBASE_FS; goto set;
-       case MSR_KERNEL_GS_BASE:        which = SEGBASE_GS_USER; goto set;
-       case MSR_GS_BASE:               which = SEGBASE_GS_KERNEL; goto set;
-
-       set:
-               base = ((u64)high << 32) | low;
-               if (HYPERVISOR_set_segment_base(which, base) != 0)
-                       ret = -EIO;
+       case MSR_FS_BASE:
+               set_seg(SEGBASE_FS, low, high, err);
+               break;
+
+       case MSR_KERNEL_GS_BASE:
+               set_seg(SEGBASE_GS_USER, low, high, err);
+               break;
+
+       case MSR_GS_BASE:
+               set_seg(SEGBASE_GS_KERNEL, low, high, err);
                break;
 
        case MSR_STAR:
@@ -965,31 +995,42 @@ static int xen_write_msr_safe(unsigned int msr, unsigned low, unsigned high)
                break;
 
        default:
-               if (!pmu_msr_write(msr, low, high, &ret))
-                       ret = native_write_msr_safe(msr, low, high);
+               if (!pmu_msr_write(msr, low, high, err)) {
+                       if (err)
+                               *err = native_write_msr_safe(msr, low, high);
+                       else
+                               native_write_msr(msr, low, high);
+               }
        }
+}
 
-       return ret;
+static u64 xen_read_msr_safe(unsigned int msr, int *err)
+{
+       return xen_do_read_msr(msr, err);
+}
+
+static int xen_write_msr_safe(unsigned int msr, unsigned int low,
+                             unsigned int high)
+{
+       int err = 0;
+
+       xen_do_write_msr(msr, low, high, &err);
+
+       return err;
 }
 
 static u64 xen_read_msr(unsigned int msr)
 {
-       /*
-        * This will silently swallow a #GP from RDMSR.  It may be worth
-        * changing that.
-        */
        int err;
 
-       return xen_read_msr_safe(msr, &err);
+       return xen_do_read_msr(msr, xen_msr_safe ? &err : NULL);
 }
 
 static void xen_write_msr(unsigned int msr, unsigned low, unsigned high)
 {
-       /*
-        * This will silently swallow a #GP from WRMSR.  It may be worth
-        * changing that.
-        */
-       xen_write_msr_safe(msr, low, high);
+       int err;
+
+       xen_do_write_msr(msr, low, high, xen_msr_safe ? &err : NULL);
 }
 
 /* This is called once we have the cpu_possible_mask */