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