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