Pablo Greco e6a3ae
From c1bd7825b1cbe0ff34be196effc7a18992cce269 Mon Sep 17 00:00:00 2001
Pablo Greco e6a3ae
From: Sam Bobroff <sbobroff@redhat.com>
Pablo Greco e6a3ae
Date: Thu, 29 Aug 2019 05:53:35 +0100
Pablo Greco e6a3ae
Subject: [PATCH 02/10] target/ppc/spapr: Add workaround option to
Pablo Greco e6a3ae
 SPAPR_CAP_IBS
Pablo Greco e6a3ae
Pablo Greco e6a3ae
RH-Author: Sam Bobroff <sbobroff@redhat.com>
Pablo Greco e6a3ae
Message-id: <67946d77e95afc19f2afc5f8dfa4e89335dbb58d.1567057498.git.sbobroff@redhat.com>
Pablo Greco e6a3ae
Patchwork-id: 90188
Pablo Greco e6a3ae
O-Subject: [RHEL8.1 qemu-kvm BZ1744415 PATCH 1/2] target/ppc/spapr: Add workaround option to SPAPR_CAP_IBS
Pablo Greco e6a3ae
Bugzilla: 1744415
Pablo Greco e6a3ae
RH-Acked-by: David Gibson <dgibson@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
Pablo Greco e6a3ae
RH-Acked-by: Thomas Huth <thuth@redhat.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
From: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
Pablo Greco e6a3ae
Pablo Greco e6a3ae
The spapr_cap SPAPR_CAP_IBS is used to indicate the level of capability
Pablo Greco e6a3ae
for mitigations for indirect branch speculation. Currently the available
Pablo Greco e6a3ae
values are broken (default), fixed-ibs (fixed by serialising indirect
Pablo Greco e6a3ae
branches) and fixed-ccd (fixed by diabling the count cache).
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Introduce a new value for this capability denoted workaround, meaning that
Pablo Greco e6a3ae
software can work around the issue by flushing the count cache on
Pablo Greco e6a3ae
context switch. This option is available if the hypervisor sets the
Pablo Greco e6a3ae
H_CPU_BEHAV_FLUSH_COUNT_CACHE flag in the cpu behaviours returned from
Pablo Greco e6a3ae
the KVM_PPC_GET_CPU_CHAR ioctl.
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
Pablo Greco e6a3ae
Message-Id: <20190301031912.28809-1-sjitindarsingh@gmail.com>
Pablo Greco e6a3ae
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Pablo Greco e6a3ae
(cherry picked from commit 399b2896d4948a1ec0278d896ea3a561df768d64)
Pablo Greco e6a3ae
Pablo Greco e6a3ae
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1744415
Pablo Greco e6a3ae
Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23229146
Pablo Greco e6a3ae
Signed-off-by: Sam Bobroff <sbobroff@redhat.com>
Pablo Greco e6a3ae
Testing: Start QEMU with -M cap-ibs=workaround, check guest dmesg
Pablo Greco e6a3ae
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
Pablo Greco e6a3ae
---
Pablo Greco e6a3ae
 hw/ppc/spapr_caps.c    | 21 ++++++++++-----------
Pablo Greco e6a3ae
 hw/ppc/spapr_hcall.c   |  5 +++++
Pablo Greco e6a3ae
 include/hw/ppc/spapr.h |  7 +++++++
Pablo Greco e6a3ae
 target/ppc/kvm.c       |  8 +++++++-
Pablo Greco e6a3ae
 4 files changed, 29 insertions(+), 12 deletions(-)
Pablo Greco e6a3ae
Pablo Greco e6a3ae
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
Pablo Greco e6a3ae
index 86a7947..dfc8cce 100644
Pablo Greco e6a3ae
--- a/hw/ppc/spapr_caps.c
Pablo Greco e6a3ae
+++ b/hw/ppc/spapr_caps.c
Pablo Greco e6a3ae
@@ -236,11 +236,13 @@ static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val,
Pablo Greco e6a3ae
 }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 sPAPRCapPossible cap_ibs_possible = {
Pablo Greco e6a3ae
-    .num = 4,
Pablo Greco e6a3ae
+    .num = 5,
Pablo Greco e6a3ae
     /* Note workaround only maintained for compatibility */
Pablo Greco e6a3ae
-    .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd"},
Pablo Greco e6a3ae
-    .help = "broken - no protection, fixed-ibs - indirect branch serialisation,"
Pablo Greco e6a3ae
-            " fixed-ccd - cache count disabled",
Pablo Greco e6a3ae
+    .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd", "fixed-na"},
Pablo Greco e6a3ae
+    .help = "broken - no protection, workaround - count cache flush"
Pablo Greco e6a3ae
+            ", fixed-ibs - indirect branch serialisation,"
Pablo Greco e6a3ae
+            " fixed-ccd - cache count disabled,"
Pablo Greco e6a3ae
+            " fixed-na - fixed in hardware (no longer applicable)",
Pablo Greco e6a3ae
 };
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
Pablo Greco e6a3ae
@@ -248,15 +250,11 @@ static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
     uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch();
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
-    if (val == SPAPR_CAP_WORKAROUND) { /* Can only be Broken or Fixed */
Pablo Greco e6a3ae
-        error_setg(errp,
Pablo Greco e6a3ae
-"Requested safe indirect branch capability level \"workaround\" not valid, try cap-ibs=%s",
Pablo Greco e6a3ae
-                   cap_ibs_possible.vals[kvm_val]);
Pablo Greco e6a3ae
-    } else if (tcg_enabled() && val) {
Pablo Greco e6a3ae
+    if (tcg_enabled() && val) {
Pablo Greco e6a3ae
         /* TODO - for now only allow broken for TCG */
Pablo Greco e6a3ae
         error_setg(errp,
Pablo Greco e6a3ae
 "Requested safe indirect branch capability level not supported by tcg, try a different value for cap-ibs");
Pablo Greco e6a3ae
-    } else if (kvm_enabled() && val && (val != kvm_val)) {
Pablo Greco e6a3ae
+    } else if (kvm_enabled() && (val > kvm_val)) {
Pablo Greco e6a3ae
         error_setg(errp,
Pablo Greco e6a3ae
 "Requested safe indirect branch capability level not supported by kvm, try cap-ibs=%s",
Pablo Greco e6a3ae
                    cap_ibs_possible.vals[kvm_val]);
Pablo Greco e6a3ae
@@ -338,7 +336,8 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
Pablo Greco e6a3ae
     [SPAPR_CAP_IBS] = {
Pablo Greco e6a3ae
         .name = "ibs",
Pablo Greco e6a3ae
         .description =
Pablo Greco e6a3ae
-            "Indirect Branch Speculation (broken, fixed-ibs, fixed-ccd)",
Pablo Greco e6a3ae
+            "Indirect Branch Speculation (broken, workaround, fixed-ibs,"
Pablo Greco e6a3ae
+            "fixed-ccd, fixed-na)",
Pablo Greco e6a3ae
         .index = SPAPR_CAP_IBS,
Pablo Greco e6a3ae
         .get = spapr_cap_get_string,
Pablo Greco e6a3ae
         .set = spapr_cap_set_string,
Pablo Greco e6a3ae
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
Pablo Greco e6a3ae
index 16bccdd..01c4215 100644
Pablo Greco e6a3ae
--- a/hw/ppc/spapr_hcall.c
Pablo Greco e6a3ae
+++ b/hw/ppc/spapr_hcall.c
Pablo Greco e6a3ae
@@ -1705,12 +1705,17 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu,
Pablo Greco e6a3ae
     }
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
     switch (safe_indirect_branch) {
Pablo Greco e6a3ae
+    case SPAPR_CAP_FIXED_NA:
Pablo Greco e6a3ae
+        break;
Pablo Greco e6a3ae
     case SPAPR_CAP_FIXED_CCD:
Pablo Greco e6a3ae
         characteristics |= H_CPU_CHAR_CACHE_COUNT_DIS;
Pablo Greco e6a3ae
         break;
Pablo Greco e6a3ae
     case SPAPR_CAP_FIXED_IBS:
Pablo Greco e6a3ae
         characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED;
Pablo Greco e6a3ae
         break;
Pablo Greco e6a3ae
+    case SPAPR_CAP_WORKAROUND:
Pablo Greco e6a3ae
+        behaviour |= H_CPU_BEHAV_FLUSH_COUNT_CACHE;
Pablo Greco e6a3ae
+        break;
Pablo Greco e6a3ae
     default: /* broken */
Pablo Greco e6a3ae
         assert(safe_indirect_branch == SPAPR_CAP_BROKEN);
Pablo Greco e6a3ae
         break;
Pablo Greco e6a3ae
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
Pablo Greco e6a3ae
index 72cfa49..8bb95bb 100644
Pablo Greco e6a3ae
--- a/include/hw/ppc/spapr.h
Pablo Greco e6a3ae
+++ b/include/hw/ppc/spapr.h
Pablo Greco e6a3ae
@@ -77,12 +77,17 @@ typedef enum {
Pablo Greco e6a3ae
 /* Bool Caps */
Pablo Greco e6a3ae
 #define SPAPR_CAP_OFF                   0x00
Pablo Greco e6a3ae
 #define SPAPR_CAP_ON                    0x01
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
 /* Custom Caps */
Pablo Greco e6a3ae
+
Pablo Greco e6a3ae
+/* Generic */
Pablo Greco e6a3ae
 #define SPAPR_CAP_BROKEN                0x00
Pablo Greco e6a3ae
 #define SPAPR_CAP_WORKAROUND            0x01
Pablo Greco e6a3ae
 #define SPAPR_CAP_FIXED                 0x02
Pablo Greco e6a3ae
+/* SPAPR_CAP_IBS (cap-ibs) */
Pablo Greco e6a3ae
 #define SPAPR_CAP_FIXED_IBS             0x02
Pablo Greco e6a3ae
 #define SPAPR_CAP_FIXED_CCD             0x03
Pablo Greco e6a3ae
+#define SPAPR_CAP_FIXED_NA              0x10 /* Lets leave a bit of a gap... */
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 typedef struct sPAPRCapabilities sPAPRCapabilities;
Pablo Greco e6a3ae
 struct sPAPRCapabilities {
Pablo Greco e6a3ae
@@ -322,9 +327,11 @@ struct sPAPRMachineState {
Pablo Greco e6a3ae
 #define H_CPU_CHAR_HON_BRANCH_HINTS             PPC_BIT(5)
Pablo Greco e6a3ae
 #define H_CPU_CHAR_THR_RECONF_TRIG              PPC_BIT(6)
Pablo Greco e6a3ae
 #define H_CPU_CHAR_CACHE_COUNT_DIS              PPC_BIT(7)
Pablo Greco e6a3ae
+#define H_CPU_CHAR_BCCTR_FLUSH_ASSIST           PPC_BIT(9)
Pablo Greco e6a3ae
 #define H_CPU_BEHAV_FAVOUR_SECURITY             PPC_BIT(0)
Pablo Greco e6a3ae
 #define H_CPU_BEHAV_L1D_FLUSH_PR                PPC_BIT(1)
Pablo Greco e6a3ae
 #define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR           PPC_BIT(2)
Pablo Greco e6a3ae
+#define H_CPU_BEHAV_FLUSH_COUNT_CACHE           PPC_BIT(5)
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 /* Each control block has to be on a 4K boundary */
Pablo Greco e6a3ae
 #define H_CB_ALIGNMENT     4096
Pablo Greco e6a3ae
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
Pablo Greco e6a3ae
index b9858fa..0e94cfc 100644
Pablo Greco e6a3ae
--- a/target/ppc/kvm.c
Pablo Greco e6a3ae
+++ b/target/ppc/kvm.c
Pablo Greco e6a3ae
@@ -2511,7 +2511,13 @@ static int parse_cap_ppc_safe_bounds_check(struct kvm_ppc_cpu_char c)
Pablo Greco e6a3ae
 
Pablo Greco e6a3ae
 static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c)
Pablo Greco e6a3ae
 {
Pablo Greco e6a3ae
-    if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) {
Pablo Greco e6a3ae
+    if ((~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) &&
Pablo Greco e6a3ae
+        (~c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) &&
Pablo Greco e6a3ae
+        (~c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED)) {
Pablo Greco e6a3ae
+        return SPAPR_CAP_FIXED_NA;
Pablo Greco e6a3ae
+    } else if (c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) {
Pablo Greco e6a3ae
+        return SPAPR_CAP_WORKAROUND;
Pablo Greco e6a3ae
+    } else if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) {
Pablo Greco e6a3ae
         return  SPAPR_CAP_FIXED_CCD;
Pablo Greco e6a3ae
     } else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) {
Pablo Greco e6a3ae
         return SPAPR_CAP_FIXED_IBS;
Pablo Greco e6a3ae
-- 
Pablo Greco e6a3ae
1.8.3.1
Pablo Greco e6a3ae