aboutsummaryrefslogtreecommitdiff
path: root/hw/ppc
diff options
context:
space:
mode:
authorSuraj Jitindar Singh <sjitindarsingh@gmail.com>2019-03-01 14:19:12 +1100
committerDavid Gibson <david@gibson.dropbear.id.au>2019-03-12 12:07:49 +1100
commit8ff43ee404d3e295839d1fd4e9e6571ca7a62a66 (patch)
treef3a77de59523fe38cc5479afdc3087e8c7f7b53f /hw/ppc
parent399b2896d4948a1ec0278d896ea3a561df768d64 (diff)
downloadqemu-8ff43ee404d3e295839d1fd4e9e6571ca7a62a66.zip
qemu-8ff43ee404d3e295839d1fd4e9e6571ca7a62a66.tar.gz
qemu-8ff43ee404d3e295839d1fd4e9e6571ca7a62a66.tar.bz2
target/ppc/spapr: Add SPAPR_CAP_CCF_ASSIST
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>
Diffstat (limited to 'hw/ppc')
-rw-r--r--hw/ppc/spapr.c2
-rw-r--r--hw/ppc/spapr_caps.c25
-rw-r--r--hw/ppc/spapr_hcall.c5
3 files changed, 32 insertions, 0 deletions
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 8e24d7d..37fd7a1 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -2097,6 +2097,7 @@ static const VMStateDescription vmstate_spapr = {
&vmstate_spapr_cap_nested_kvm_hv,
&vmstate_spapr_dtb,
&vmstate_spapr_cap_large_decr,
+ &vmstate_spapr_cap_ccf_assist,
NULL
}
};
@@ -4312,6 +4313,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
+ smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_OFF;
spapr_caps_add_properties(smc, &error_abort);
smc->irq = &spapr_irq_xics;
smc->dr_phb_enabled = true;
diff --git a/hw/ppc/spapr_caps.c b/hw/ppc/spapr_caps.c
index ca35b51..c5d381f 100644
--- a/hw/ppc/spapr_caps.c
+++ b/hw/ppc/spapr_caps.c
@@ -441,6 +441,21 @@ static void cap_large_decr_cpu_apply(sPAPRMachineState *spapr,
ppc_store_lpcr(cpu, lpcr);
}
+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",
@@ -530,6 +545,15 @@ sPAPRCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
.apply = cap_large_decr_apply,
.cpu_apply = cap_large_decr_cpu_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,
@@ -664,6 +688,7 @@ 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(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
+SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
void spapr_caps_init(sPAPRMachineState *spapr)
{
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 4aa8036..15bdd30 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1693,6 +1693,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:
@@ -1733,6 +1735,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);