Blame SOURCES/kvm-spapr-Enable-ISA-3.0-MMU-mode-selection-via-CAS.patch

76daa3
From f836e519f8b9d62104838b164a13a13667771c50 Mon Sep 17 00:00:00 2001
76daa3
From: David Gibson <dgibson@redhat.com>
76daa3
Date: Thu, 27 Apr 2017 02:15:57 +0200
76daa3
Subject: [PATCH 22/23] spapr: Enable ISA 3.0 MMU mode selection via CAS
76daa3
76daa3
RH-Author: David Gibson <dgibson@redhat.com>
76daa3
Message-id: <20170427021558.4884-7-dgibson@redhat.com>
76daa3
Patchwork-id: 74919
76daa3
O-Subject: [Pegas-1.0 qemu-kvm-rhev PATCH 6/7] spapr: Enable ISA 3.0 MMU mode selection via CAS
76daa3
Bugzilla: 1368786
76daa3
RH-Acked-by: Thomas Huth <thuth@redhat.com>
76daa3
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
76daa3
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
76daa3
76daa3
From: Sam Bobroff <sam.bobroff@au1.ibm.com>
76daa3
76daa3
Add the new node, /chosen/ibm,arch-vec-5-platform-support to the
76daa3
device tree. This allows the guest to determine which modes are
76daa3
supported by the hypervisor.
76daa3
76daa3
Update the option vector processing in h_client_architecture_support()
76daa3
to handle the new MMU bits. This allows guests to request hash or
76daa3
radix mode and QEMU to create the guest's HPT at this time if it is
76daa3
necessary but hasn't yet been done.  QEMU will terminate the guest if
76daa3
it requests an unavailable mode, as required by the architecture.
76daa3
76daa3
Extend the ibm,pa-features node with the new ISA 3.0 values
76daa3
and set the radix bit if KVM supports radix mode. This probably won't
76daa3
be used directly by guests to determine the availability of radix mode
76daa3
(that is indicated by the new node added above) but the architecture
76daa3
requires that it be set when the hardware supports it.
76daa3
76daa3
If QEMU is using KVM, and KVM is capable of running in radix mode,
76daa3
guests can be run in real-mode without allocating a HPT (because KVM
76daa3
will use a minimal RPT). So in this case, we avoid creating the HPT
76daa3
at reset time and later (during CAS) create it if it is necessary.
76daa3
76daa3
ISA 3.0 guests will now begin to call h_register_process_table(),
76daa3
which has been added previously.
76daa3
76daa3
Signed-off-by: Sam Bobroff <sam.bobroff@au1.ibm.com>
76daa3
[dwg: Strip some unneeded prefix from error messages]
76daa3
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
76daa3
76daa3
(cherry picked from commit 9fb4541f5803f8d2ba116b12113386e26482ba30)
76daa3
76daa3
Siged-off-by: David Gibson <dgibson@redhat.com>
76daa3
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
76daa3
---
76daa3
 hw/ppc/spapr.c              | 71 ++++++++++++++++++++++++++++++++++++---------
76daa3
 hw/ppc/spapr_hcall.c        | 30 +++++++++++++++++++
76daa3
 include/hw/ppc/spapr_ovec.h |  5 ++++
76daa3
 3 files changed, 93 insertions(+), 13 deletions(-)
76daa3
76daa3
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
76daa3
index 7376bb5..5a5196a 100644
76daa3
--- a/hw/ppc/spapr.c
76daa3
+++ b/hw/ppc/spapr.c
76daa3
@@ -237,20 +237,31 @@ static void spapr_populate_pa_features(CPUPPCState *env, void *fdt, int offset)
76daa3
         0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
76daa3
         0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
76daa3
         0x80, 0x00, 0x80, 0x00, 0x00, 0x00 };
76daa3
-    /* Currently we don't advertise any of the "new" ISAv3.00 functionality */
76daa3
-    uint8_t pa_features_300[] = { 64, 0,
76daa3
-        0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /*  0 -  5 */
76daa3
-        0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /*  6 - 11 */
76daa3
+    uint8_t pa_features_300[] = { 66, 0,
76daa3
+        /* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
76daa3
+        /* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, SSO, 5: LE|CFAR|EB|LSQ */
76daa3
+        0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /* 0 - 5 */
76daa3
+        /* 6: DS207 */
76daa3
+        0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
76daa3
+        /* 16: Vector */
76daa3
         0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
76daa3
-        0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */
76daa3
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 24 - 29 */
76daa3
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 30 - 35 */
76daa3
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 36 - 41 */
76daa3
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 42 - 47 */
76daa3
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 48 - 53 */
76daa3
-        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 54 - 59 */
76daa3
-        0x00, 0x00, 0x00, 0x00           }; /* 60 - 63 */
76daa3
-
76daa3
+        /* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */
76daa3
+        0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 18 - 23 */
76daa3
+        /* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
76daa3
+        0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
76daa3
+        /* 30: MMR, 32: LE atomic, 34: EBB + ext EBB */
76daa3
+        0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
76daa3
+        /* 36: SPR SO, 38: Copy/Paste, 40: Radix MMU */
76daa3
+        0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 36 - 41 */
76daa3
+        /* 42: PM, 44: PC RA, 46: SC vec'd */
76daa3
+        0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
76daa3
+        /* 48: SIMD, 50: QP BFP, 52: String */
76daa3
+        0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */
76daa3
+        /* 54: DecFP, 56: DecI, 58: SHA */
76daa3
+        0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */
76daa3
+        /* 60: NM atomic, 62: RNG */
76daa3
+        0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
76daa3
+    };
76daa3
     uint8_t *pa_features;
76daa3
     size_t pa_size;
76daa3
 
76daa3
@@ -856,6 +867,33 @@ static void spapr_dt_rtas(sPAPRMachineState *spapr, void *fdt)
76daa3
     spapr_dt_rtas_tokens(fdt, rtas);
76daa3
 }
76daa3
 
76daa3
+/* Prepare ibm,arch-vec-5-platform-support, which indicates the MMU features
76daa3
+ * that the guest may request and thus the valid values for bytes 24..26 of
76daa3
+ * option vector 5: */
76daa3
+static void spapr_dt_ov5_platform_support(void *fdt, int chosen)
76daa3
+{
76daa3
+    char val[2 * 3] = {
76daa3
+        24, 0x00, /* Hash/Radix, filled in below. */
76daa3
+        25, 0x00, /* Hash options: Segment Tables == no, GTSE == no. */
76daa3
+        26, 0x40, /* Radix options: GTSE == yes. */
76daa3
+    };
76daa3
+
76daa3
+    if (kvm_enabled()) {
76daa3
+        if (kvmppc_has_cap_mmu_radix() && kvmppc_has_cap_mmu_hash_v3()) {
76daa3
+            val[1] = 0x80; /* OV5_MMU_BOTH */
76daa3
+        } else if (kvmppc_has_cap_mmu_radix()) {
76daa3
+            val[1] = 0x40; /* OV5_MMU_RADIX_300 */
76daa3
+        } else {
76daa3
+            val[1] = 0x00; /* Hash */
76daa3
+        }
76daa3
+    } else {
76daa3
+        /* TODO: TCG case, hash */
76daa3
+        val[1] = 0x00;
76daa3
+    }
76daa3
+    _FDT(fdt_setprop(fdt, chosen, "ibm,arch-vec-5-platform-support",
76daa3
+                     val, sizeof(val)));
76daa3
+}
76daa3
+
76daa3
 static void spapr_dt_chosen(sPAPRMachineState *spapr, void *fdt)
76daa3
 {
76daa3
     MachineState *machine = MACHINE(spapr);
76daa3
@@ -909,6 +947,8 @@ static void spapr_dt_chosen(sPAPRMachineState *spapr, void *fdt)
76daa3
         _FDT(fdt_setprop_string(fdt, chosen, "linux,stdout-path", stdout_path));
76daa3
     }
76daa3
 
76daa3
+    spapr_dt_ov5_platform_support(fdt, chosen);
76daa3
+
76daa3
     g_free(stdout_path);
76daa3
     g_free(bootlist);
76daa3
 }
76daa3
@@ -2079,6 +2119,11 @@ static void ppc_spapr_init(MachineState *machine)
76daa3
     }
76daa3
 
76daa3
     spapr_ovec_set(spapr->ov5, OV5_FORM1_AFFINITY);
76daa3
+    if (kvmppc_has_cap_mmu_radix()) {
76daa3
+        /* KVM always allows GTSE with radix... */
76daa3
+        spapr_ovec_set(spapr->ov5, OV5_MMU_RADIX_GTSE);
76daa3
+    }
76daa3
+    /* ... but not with hash (currently). */
76daa3
 
76daa3
     /* advertise support for dedicated HP event source to guests */
76daa3
     if (spapr->use_hotplug_event_source) {
76daa3
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
76daa3
index a958fee..cbd1f29 100644
76daa3
--- a/hw/ppc/spapr_hcall.c
76daa3
+++ b/hw/ppc/spapr_hcall.c
76daa3
@@ -1063,6 +1063,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
76daa3
     uint32_t best_compat = 0;
76daa3
     int i;
76daa3
     sPAPROptionVector *ov5_guest, *ov5_cas_old, *ov5_updates;
76daa3
+    bool guest_radix;
76daa3
 
76daa3
     /*
76daa3
      * We scan the supplied table of PVRs looking for two things
76daa3
@@ -1114,6 +1115,13 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
76daa3
     ov_table = list;
76daa3
 
76daa3
     ov5_guest = spapr_ovec_parse_vector(ov_table, 5);
76daa3
+    if (spapr_ovec_test(ov5_guest, OV5_MMU_BOTH)) {
76daa3
+        error_report("guest requested hash and radix MMU, which is invalid.");
76daa3
+        exit(EXIT_FAILURE);
76daa3
+    }
76daa3
+    /* The radix/hash bit in byte 24 requires special handling: */
76daa3
+    guest_radix = spapr_ovec_test(ov5_guest, OV5_MMU_RADIX_300);
76daa3
+    spapr_ovec_clear(ov5_guest, OV5_MMU_RADIX_300);
76daa3
 
76daa3
     /* NOTE: there are actually a number of ov5 bits where input from the
76daa3
      * guest is always zero, and the platform/QEMU enables them independently
76daa3
@@ -1132,6 +1140,21 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
76daa3
     ov5_updates = spapr_ovec_new();
76daa3
     spapr->cas_reboot = spapr_ovec_diff(ov5_updates,
76daa3
                                         ov5_cas_old, spapr->ov5_cas);
76daa3
+    /* Now that processing is finished, set the radix/hash bit for the
76daa3
+     * guest if it requested a valid mode; otherwise terminate the boot. */
76daa3
+    if (guest_radix) {
76daa3
+        if (kvm_enabled() && !kvmppc_has_cap_mmu_radix()) {
76daa3
+            error_report("Guest requested unavailable MMU mode (radix).");
76daa3
+            exit(EXIT_FAILURE);
76daa3
+        }
76daa3
+        spapr_ovec_set(spapr->ov5_cas, OV5_MMU_RADIX_300);
76daa3
+    } else {
76daa3
+        if (kvm_enabled() && kvmppc_has_cap_mmu_radix()
76daa3
+            && !kvmppc_has_cap_mmu_hash_v3()) {
76daa3
+            error_report("Guest requested unavailable MMU mode (hash).");
76daa3
+            exit(EXIT_FAILURE);
76daa3
+        }
76daa3
+    }
76daa3
 
76daa3
     if (!spapr->cas_reboot) {
76daa3
         spapr->cas_reboot =
76daa3
@@ -1142,6 +1165,13 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
76daa3
 
76daa3
     if (spapr->cas_reboot) {
76daa3
         qemu_system_reset_request();
76daa3
+    } else {
76daa3
+        /* If ppc_spapr_reset() did not set up a HPT but one is necessary
76daa3
+         * (because the guest isn't going to use radix) then set it up here. */
76daa3
+        if ((spapr->patb_entry & PATBE1_GR) && !guest_radix) {
76daa3
+            /* legacy hash or new hash: */
76daa3
+            spapr_setup_hpt_and_vrma(spapr);
76daa3
+        }
76daa3
     }
76daa3
 
76daa3
     return H_SUCCESS;
76daa3
diff --git a/include/hw/ppc/spapr_ovec.h b/include/hw/ppc/spapr_ovec.h
76daa3
index 355a344..f7f2abe 100644
76daa3
--- a/include/hw/ppc/spapr_ovec.h
76daa3
+++ b/include/hw/ppc/spapr_ovec.h
76daa3
@@ -48,6 +48,11 @@ typedef struct sPAPROptionVector sPAPROptionVector;
76daa3
 #define OV5_FORM1_AFFINITY      OV_BIT(5, 0)
76daa3
 #define OV5_HP_EVT              OV_BIT(6, 5)
76daa3
 
76daa3
+/* ISA 3.00 MMU features: */
76daa3
+#define OV5_MMU_BOTH            OV_BIT(24, 0) /* Radix and hash */
76daa3
+#define OV5_MMU_RADIX_300       OV_BIT(24, 1) /* 1=Radix only, 0=Hash only */
76daa3
+#define OV5_MMU_RADIX_GTSE      OV_BIT(26, 1) /* Radix GTSE */
76daa3
+
76daa3
 /* interfaces */
76daa3
 sPAPROptionVector *spapr_ovec_new(void);
76daa3
 sPAPROptionVector *spapr_ovec_clone(sPAPROptionVector *ov_orig);
76daa3
-- 
76daa3
1.8.3.1
76daa3