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