b38b0f
From d63d52e74a9af9d7d45f5734c4a6e127c3ecc0b4 Mon Sep 17 00:00:00 2001
b38b0f
From: Sam Bobroff <sbobroff@redhat.com>
b38b0f
Date: Thu, 29 Aug 2019 05:53:36 +0100
b38b0f
Subject: [PATCH 03/10] target/ppc/spapr: Add SPAPR_CAP_CCF_ASSIST
b38b0f
b38b0f
RH-Author: Sam Bobroff <sbobroff@redhat.com>
b38b0f
Message-id: <80714b6e8fc19054881e9c1eaf1b8a332f8e104f.1567057498.git.sbobroff@redhat.com>
b38b0f
Patchwork-id: 90189
b38b0f
O-Subject: [RHEL8.1 qemu-kvm BZ1744415 PATCH 2/2] target/ppc/spapr: Add SPAPR_CAP_CCF_ASSIST
b38b0f
Bugzilla: 1744415
b38b0f
RH-Acked-by: David Gibson <dgibson@redhat.com>
b38b0f
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
b38b0f
RH-Acked-by: Thomas Huth <thuth@redhat.com>
b38b0f
b38b0f
From: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
b38b0f
b38b0f
Introduce a new spapr_cap SPAPR_CAP_CCF_ASSIST to be used to indicate
b38b0f
the requirement for a hw-assisted version of the count cache flush
b38b0f
workaround.
b38b0f
b38b0f
The count cache flush workaround is a software workaround which can be
b38b0f
used to flush the count cache on context switch. Some revisions of
b38b0f
hardware may have a hardware accelerated flush, in which case the
b38b0f
software flush can be shortened. This cap is used to set the
b38b0f
availability of such hardware acceleration for the count cache flush
b38b0f
routine.
b38b0f
b38b0f
The availability of such hardware acceleration is indicated by the
b38b0f
H_CPU_CHAR_BCCTR_FLUSH_ASSIST flag being set in the characteristics
b38b0f
returned from the KVM_PPC_GET_CPU_CHAR ioctl.
b38b0f
b38b0f
Signed-off-by: Suraj Jitindar Singh <sjitindarsingh@gmail.com>
b38b0f
Message-Id: <20190301031912.28809-2-sjitindarsingh@gmail.com>
b38b0f
[dwg: Small style fixes]
b38b0f
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
b38b0f
(cherry picked from commit 8ff43ee404d3e295839d1fd4e9e6571ca7a62a66)
b38b0f
[SB: Minor fixup for context change.]
b38b0f
b38b0f
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=1744415
b38b0f
Brew: https://brewweb.engineering.redhat.com/brew/taskinfo?taskID=23229146
b38b0f
Signed-off-by: Sam Bobroff <sbobroff@redhat.com>
b38b0f
Testing: QEMU -M cap-ibs=workaround,cap-ccf-assist=on, check guest dmesg
b38b0f
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
b38b0f
---
b38b0f
 hw/ppc/spapr.c         |  2 ++
b38b0f
 hw/ppc/spapr_caps.c    | 25 +++++++++++++++++++++++++
b38b0f
 hw/ppc/spapr_hcall.c   |  5 +++++
b38b0f
 include/hw/ppc/spapr.h |  5 ++++-
b38b0f
 target/ppc/kvm.c       | 16 ++++++++++++++++
b38b0f
 target/ppc/kvm_ppc.h   |  6 ++++++
b38b0f
 6 files changed, 58 insertions(+), 1 deletion(-)
b38b0f
b38b0f
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
b38b0f
index c72aad1..1a2f0d9 100644
b38b0f
--- a/hw/ppc/spapr.c
b38b0f
+++ b/hw/ppc/spapr.c
b38b0f
@@ -1828,6 +1828,7 @@ static const VMStateDescription vmstate_spapr = {
b38b0f
         &vmstate_spapr_cap_sbbc,
b38b0f
         &vmstate_spapr_cap_ibs,
b38b0f
         &vmstate_spapr_cap_nested_kvm_hv,
b38b0f
+        &vmstate_spapr_cap_ccf_assist,
b38b0f
         NULL
b38b0f
     }
b38b0f
 };
b38b0f
@@ -3939,6 +3940,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
b38b0f
     smc->default_caps.caps[SPAPR_CAP_SBBC] = SPAPR_CAP_BROKEN;
b38b0f
     smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_BROKEN;
b38b0f
     smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
b38b0f
+    smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
b38b0f
     spapr_caps_add_properties(smc, &error_abort);
b38b0f
     smc->has_power9_support = true;
b38b0f
 }
b38b0f
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
b38b0f
index dfc8cce..5353255 100644
b38b0f
--- a/hw/ppc/spapr_caps.c
b38b0f
+++ b/hw/ppc/spapr_caps.c
b38b0f
@@ -285,6 +285,21 @@ static void cap_nested_kvm_hv_apply(sPAPRMachineState *spapr,
b38b0f
     }
b38b0f
 }
b38b0f
 
b38b0f
+static void cap_ccf_assist_apply(sPAPRMachineState *spapr, uint8_t val,
b38b0f
+                                 Error **errp)
b38b0f
+{
b38b0f
+    uint8_t kvm_val = kvmppc_get_cap_count_cache_flush_assist();
b38b0f
+
b38b0f
+    if (tcg_enabled() && val) {
b38b0f
+        /* TODO - for now only allow broken for TCG */
b38b0f
+        error_setg(errp,
b38b0f
+"Requested count cache flush assist capability level not supported by tcg, try cap-ccf-assist=off");
b38b0f
+    } else if (kvm_enabled() && (val > kvm_val)) {
b38b0f
+        error_setg(errp,
b38b0f
+"Requested count cache flush assist capability level not supported by kvm, try cap-ccf-assist=off");
b38b0f
+    }
b38b0f
+}
b38b0f
+
b38b0f
 sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
b38b0f
     [SPAPR_CAP_HTM] = {
b38b0f
         .name = "htm",
b38b0f
@@ -354,6 +369,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
b38b0f
         .type = "bool",
b38b0f
         .apply = cap_nested_kvm_hv_apply,
b38b0f
     },
b38b0f
+    [SPAPR_CAP_CCF_ASSIST] = {
b38b0f
+        .name = "ccf-assist",
b38b0f
+        .description = "Count Cache Flush Assist via HW Instruction",
b38b0f
+        .index = SPAPR_CAP_CCF_ASSIST,
b38b0f
+        .get = spapr_cap_get_bool,
b38b0f
+        .set = spapr_cap_set_bool,
b38b0f
+        .type = "bool",
b38b0f
+        .apply = cap_ccf_assist_apply,
b38b0f
+    },
b38b0f
 };
b38b0f
 
b38b0f
 static sPAPRCapabilities default_caps_with_cpu(sPAPRMachineState *spapr,
b38b0f
@@ -470,6 +494,7 @@ SPAPR_CAP_MIG_STATE(cfpc, SPAPR_CAP_CFPC);
b38b0f
 SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
b38b0f
 SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
b38b0f
 SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
b38b0f
+SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
b38b0f
 
b38b0f
 void spapr_caps_reset(sPAPRMachineState *spapr)
b38b0f
 {
b38b0f
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
b38b0f
index 01c4215..141d1f4 100644
b38b0f
--- a/hw/ppc/spapr_hcall.c
b38b0f
+++ b/hw/ppc/spapr_hcall.c
b38b0f
@@ -1675,6 +1675,8 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu,
b38b0f
     uint8_t safe_cache = spapr_get_cap(spapr, SPAPR_CAP_CFPC);
b38b0f
     uint8_t safe_bounds_check = spapr_get_cap(spapr, SPAPR_CAP_SBBC);
b38b0f
     uint8_t safe_indirect_branch = spapr_get_cap(spapr, SPAPR_CAP_IBS);
b38b0f
+    uint8_t count_cache_flush_assist = spapr_get_cap(spapr,
b38b0f
+                                                     SPAPR_CAP_CCF_ASSIST);
b38b0f
 
b38b0f
     switch (safe_cache) {
b38b0f
     case SPAPR_CAP_WORKAROUND:
b38b0f
@@ -1715,6 +1717,9 @@ static target_ulong h_get_cpu_characteristics(PowerPCCPU *cpu,
b38b0f
         break;
b38b0f
     case SPAPR_CAP_WORKAROUND:
b38b0f
         behaviour |= H_CPU_BEHAV_FLUSH_COUNT_CACHE;
b38b0f
+        if (count_cache_flush_assist) {
b38b0f
+            characteristics |= H_CPU_CHAR_BCCTR_FLUSH_ASSIST;
b38b0f
+        }
b38b0f
         break;
b38b0f
     default: /* broken */
b38b0f
         assert(safe_indirect_branch == SPAPR_CAP_BROKEN);
b38b0f
diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h
b38b0f
index 8bb95bb..4aff3b6 100644
b38b0f
--- a/include/hw/ppc/spapr.h
b38b0f
+++ b/include/hw/ppc/spapr.h
b38b0f
@@ -68,8 +68,10 @@ typedef enum {
b38b0f
 #define SPAPR_CAP_IBS                   0x05
b38b0f
 /* Nested KVM-HV */
b38b0f
 #define SPAPR_CAP_NESTED_KVM_HV         0x06
b38b0f
+/* Count Cache Flush Assist HW Instruction */
b38b0f
+#define SPAPR_CAP_CCF_ASSIST            0x07
b38b0f
 /* Num Caps */
b38b0f
-#define SPAPR_CAP_NUM                   (SPAPR_CAP_NESTED_KVM_HV + 1)
b38b0f
+#define SPAPR_CAP_NUM                   (SPAPR_CAP_CCF_ASSIST + 1)
b38b0f
 
b38b0f
 /*
b38b0f
  * Capability Values
b38b0f
@@ -807,6 +809,7 @@ extern const VMStateDescription vmstate_spapr_cap_cfpc;
b38b0f
 extern const VMStateDescription vmstate_spapr_cap_sbbc;
b38b0f
 extern const VMStateDescription vmstate_spapr_cap_ibs;
b38b0f
 extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
b38b0f
+extern const VMStateDescription vmstate_spapr_cap_ccf_assist;
b38b0f
 
b38b0f
 static inline uint8_t spapr_get_cap(sPAPRMachineState *spapr, int cap)
b38b0f
 {
b38b0f
diff --git a/target/ppc/kvm.c b/target/ppc/kvm.c
b38b0f
index 0e94cfc..8f90ee5 100644
b38b0f
--- a/target/ppc/kvm.c
b38b0f
+++ b/target/ppc/kvm.c
b38b0f
@@ -92,6 +92,7 @@ static int cap_ppc_pvr_compat;
b38b0f
 static int cap_ppc_safe_cache;
b38b0f
 static int cap_ppc_safe_bounds_check;
b38b0f
 static int cap_ppc_safe_indirect_branch;
b38b0f
+static int cap_ppc_count_cache_flush_assist;
b38b0f
 static int cap_ppc_nested_kvm_hv;
b38b0f
 
b38b0f
 static uint32_t debug_inst_opcode;
b38b0f
@@ -2526,6 +2527,14 @@ static int parse_cap_ppc_safe_indirect_branch(struct kvm_ppc_cpu_char c)
b38b0f
     return 0;
b38b0f
 }
b38b0f
 
b38b0f
+static int parse_cap_ppc_count_cache_flush_assist(struct kvm_ppc_cpu_char c)
b38b0f
+{
b38b0f
+    if (c.character & c.character_mask & H_CPU_CHAR_BCCTR_FLUSH_ASSIST) {
b38b0f
+        return 1;
b38b0f
+    }
b38b0f
+    return 0;
b38b0f
+}
b38b0f
+
b38b0f
 static void kvmppc_get_cpu_characteristics(KVMState *s)
b38b0f
 {
b38b0f
     struct kvm_ppc_cpu_char c;
b38b0f
@@ -2548,6 +2557,8 @@ static void kvmppc_get_cpu_characteristics(KVMState *s)
b38b0f
     cap_ppc_safe_cache = parse_cap_ppc_safe_cache(c);
b38b0f
     cap_ppc_safe_bounds_check = parse_cap_ppc_safe_bounds_check(c);
b38b0f
     cap_ppc_safe_indirect_branch = parse_cap_ppc_safe_indirect_branch(c);
b38b0f
+    cap_ppc_count_cache_flush_assist =
b38b0f
+        parse_cap_ppc_count_cache_flush_assist(c);
b38b0f
 }
b38b0f
 
b38b0f
 int kvmppc_get_cap_safe_cache(void)
b38b0f
@@ -2565,6 +2576,11 @@ int kvmppc_get_cap_safe_indirect_branch(void)
b38b0f
     return cap_ppc_safe_indirect_branch;
b38b0f
 }
b38b0f
 
b38b0f
+int kvmppc_get_cap_count_cache_flush_assist(void)
b38b0f
+{
b38b0f
+    return cap_ppc_count_cache_flush_assist;
b38b0f
+}
b38b0f
+
b38b0f
 bool kvmppc_has_cap_nested_kvm_hv(void)
b38b0f
 {
b38b0f
     return !!cap_ppc_nested_kvm_hv;
b38b0f
diff --git a/target/ppc/kvm_ppc.h b/target/ppc/kvm_ppc.h
b38b0f
index dc86eff..e440c75 100644
b38b0f
--- a/target/ppc/kvm_ppc.h
b38b0f
+++ b/target/ppc/kvm_ppc.h
b38b0f
@@ -63,6 +63,7 @@ bool kvmppc_has_cap_mmu_hash_v3(void);
b38b0f
 int kvmppc_get_cap_safe_cache(void);
b38b0f
 int kvmppc_get_cap_safe_bounds_check(void);
b38b0f
 int kvmppc_get_cap_safe_indirect_branch(void);
b38b0f
+int kvmppc_get_cap_count_cache_flush_assist(void);
b38b0f
 bool kvmppc_has_cap_nested_kvm_hv(void);
b38b0f
 int kvmppc_set_cap_nested_kvm_hv(int enable);
b38b0f
 int kvmppc_enable_hwrng(void);
b38b0f
@@ -316,6 +317,11 @@ static inline int kvmppc_get_cap_safe_indirect_branch(void)
b38b0f
     return 0;
b38b0f
 }
b38b0f
 
b38b0f
+static inline int kvmppc_get_cap_count_cache_flush_assist(void)
b38b0f
+{
b38b0f
+    return 0;
b38b0f
+}
b38b0f
+
b38b0f
 static inline bool kvmppc_has_cap_nested_kvm_hv(void)
b38b0f
 {
b38b0f
     return false;
b38b0f
-- 
b38b0f
1.8.3.1
b38b0f