]> git.proxmox.com Git - mirror_qemu.git/commitdiff
target/ppc/spapr: Add workaround option to SPAPR_CAP_IBS
authorSuraj Jitindar Singh <sjitindarsingh@gmail.com>
Fri, 1 Mar 2019 03:19:11 +0000 (14:19 +1100)
committerDavid Gibson <david@gibson.dropbear.id.au>
Tue, 12 Mar 2019 01:07:49 +0000 (12:07 +1100)
The spapr_cap SPAPR_CAP_IBS is used to indicate the level of capability
for mitigations for indirect branch speculation. Currently the available
values are broken (default), fixed-ibs (fixed by serialising indirect
branches) and fixed-ccd (fixed by diabling the count cache).

Introduce a new value for this capability denoted workaround, meaning that
software can work around the issue by flushing the count cache on
context switch. This option is available if the hypervisor sets the
H_CPU_BEHAV_FLUSH_COUNT_CACHE flag in the cpu behaviours returned from
the KVM_PPC_GET_CPU_CHAR ioctl.

Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
Message-Id: <20190301031912.28809-1-sjitindarsingh@gmail.com>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
hw/ppc/spapr_caps.c
hw/ppc/spapr_hcall.c
include/hw/ppc/spapr.h
target/ppc/kvm.c

index faab472d06f6deaf59ddad5fa61054b6a563372c..ca35b5153db33a1aca67dfa0fbc9853aacd1248e 100644 (file)
@@ -276,11 +276,13 @@ static void cap_safe_bounds_check_apply(sPAPRMachineState *spapr, uint8_t val,
 }
 
 sPAPRCapPossible cap_ibs_possible = {
-    .num = 4,
+    .num = 5,
     /* Note workaround only maintained for compatibility */
-    .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd"},
-    .help = "broken - no protection, fixed-ibs - indirect branch serialisation,"
-            " fixed-ccd - cache count disabled",
+    .vals = {"broken", "workaround", "fixed-ibs", "fixed-ccd", "fixed-na"},
+    .help = "broken - no protection, workaround - count cache flush"
+            ", fixed-ibs - indirect branch serialisation,"
+            " fixed-ccd - cache count disabled,"
+            " fixed-na - fixed in hardware (no longer applicable)",
 };
 
 static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
@@ -288,15 +290,11 @@ static void cap_safe_indirect_branch_apply(sPAPRMachineState *spapr,
 {
     uint8_t kvm_val = kvmppc_get_cap_safe_indirect_branch();
 
-    if (val == SPAPR_CAP_WORKAROUND) { /* Can only be Broken or Fixed */
-        error_setg(errp,
-"Requested safe indirect branch capability level \"workaround\" not valid, try cap-ibs=%s",
-                   cap_ibs_possible.vals[kvm_val]);
-    } else if (tcg_enabled() && val) {
+    if (tcg_enabled() && val) {
         /* TODO - for now only allow broken for TCG */
         error_setg(errp,
 "Requested safe indirect branch capability level not supported by tcg, try a different value for cap-ibs");
-    } else if (kvm_enabled() && val && (val != kvm_val)) {
+    } else if (kvm_enabled() && (val > kvm_val)) {
         error_setg(errp,
 "Requested safe indirect branch capability level not supported by kvm, try cap-ibs=%s",
                    cap_ibs_possible.vals[kvm_val]);
@@ -494,7 +492,8 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
     [SPAPR_CAP_IBS] = {
         .name = "ibs",
         .description =
-            "Indirect Branch Speculation (broken, fixed-ibs, fixed-ccd)",
+            "Indirect Branch Speculation (broken, workaround, fixed-ibs,"
+            "fixed-ccd, fixed-na)",
         .index = SPAPR_CAP_IBS,
         .get = spapr_cap_get_string,
         .set = spapr_cap_set_string,
index 476bad627141a79a42837dc2241e7554d781937e..4aa8036fc059854401a2e9e2a5a5bdc5ae9ad0e4 100644 (file)
@@ -1723,12 +1723,17 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu,
     }
 
     switch (safe_indirect_branch) {
+    case SPAPR_CAP_FIXED_NA:
+        break;
     case SPAPR_CAP_FIXED_CCD:
         characteristics |= H_CPU_CHAR_CACHE_COUNT_DIS;
         break;
     case SPAPR_CAP_FIXED_IBS:
         characteristics |= H_CPU_CHAR_BCCTRL_SERIALISED;
         break;
+    case SPAPR_CAP_WORKAROUND:
+        behaviour |= H_CPU_BEHAV_FLUSH_COUNT_CACHE;
+        break;
     default: /* broken */
         assert(safe_indirect_branch == SPAPR_CAP_BROKEN);
         break;
index 8efc5e0779db75ee60f4f02ebe248d1ff2ecebfd..a7f3b1bfdd7e203e0bf83a7d22c6708b84bb9a1a 100644 (file)
@@ -85,12 +85,17 @@ typedef enum {
 /* Bool Caps */
 #define SPAPR_CAP_OFF                   0x00
 #define SPAPR_CAP_ON                    0x01
+
 /* Custom Caps */
+
+/* Generic */
 #define SPAPR_CAP_BROKEN                0x00
 #define SPAPR_CAP_WORKAROUND            0x01
 #define SPAPR_CAP_FIXED                 0x02
+/* SPAPR_CAP_IBS (cap-ibs) */
 #define SPAPR_CAP_FIXED_IBS             0x02
 #define SPAPR_CAP_FIXED_CCD             0x03
+#define SPAPR_CAP_FIXED_NA              0x10 /* Lets leave a bit of a gap... */
 
 typedef struct sPAPRCapabilities sPAPRCapabilities;
 struct sPAPRCapabilities {
@@ -339,9 +344,11 @@ struct sPAPRMachineState {
 #define H_CPU_CHAR_HON_BRANCH_HINTS             PPC_BIT(5)
 #define H_CPU_CHAR_THR_RECONF_TRIG              PPC_BIT(6)
 #define H_CPU_CHAR_CACHE_COUNT_DIS              PPC_BIT(7)
+#define H_CPU_CHAR_BCCTR_FLUSH_ASSIST           PPC_BIT(9)
 #define H_CPU_BEHAV_FAVOUR_SECURITY             PPC_BIT(0)
 #define H_CPU_BEHAV_L1D_FLUSH_PR                PPC_BIT(1)
 #define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR           PPC_BIT(2)
+#define H_CPU_BEHAV_FLUSH_COUNT_CACHE           PPC_BIT(5)
 
 /* Each control block has to be on a 4K boundary */
 #define H_CB_ALIGNMENT     4096
index f0f5bf9391953e89833fce82aee5b5526fdc8953..4d46314276a3fda0ff0a76040e6adb72be932f20 100644 (file)
@@ -2392,7 +2392,13 @@ static int parse_cap_ppc_safe_bounds_check(struct kvm_ppc_cpu_char c)
 
 static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c)
 {
-    if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) {
+    if ((~c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) &&
+        (~c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) &&
+        (~c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED)) {
+        return SPAPR_CAP_FIXED_NA;
+    } else if (c.behaviour & c.behaviour_mask & H_CPU_BEHAV_FLUSH_COUNT_CACHE) {
+        return SPAPR_CAP_WORKAROUND;
+    } else if (c.character & c.character_mask & H_CPU_CHAR_CACHE_COUNT_DIS) {
         return  SPAPR_CAP_FIXED_CCD;
     } else if (c.character & c.character_mask & H_CPU_CHAR_BCCTRL_SERIALISED) {
         return SPAPR_CAP_FIXED_IBS;