summaryrefslogtreecommitdiff
path: root/target/ppc
diff options
context:
space:
mode:
authorDavid Gibson <david@gibson.dropbear.id.au>2016-11-10 14:37:38 +1100
committerDavid Gibson <david@gibson.dropbear.id.au>2017-01-31 10:10:14 +1100
commitf6f242c7578fbedcdb53a14d4b057a7059b8dd1d (patch)
tree073ca40777358eab78a72c8fea13bcfdcd21268a /target/ppc
parent152ef803ceb1959e2380a1da7736b935b109222e (diff)
downloadqemu-f6f242c7578fbedcdb53a14d4b057a7059b8dd1d.tar.gz
ppc: Add ppc_set_compat_all()
Once a compatiblity mode is negotiated with the guest, h_client_architecture_support() uses run_on_cpu() to update each CPU to the new mode. We're going to want this logic somewhere else shortly, so make a helper function to do this global update. We put it in target-ppc/compat.c - it makes as much sense at the CPU level as it does at the machine level. We also move the cpu_synchronize_state() into ppc_set_compat(), since it doesn't really make any sense to call that without synchronizing state. Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target/ppc')
-rw-r--r--target/ppc/compat.c35
-rw-r--r--target/ppc/cpu.h3
2 files changed, 38 insertions, 0 deletions
diff --git a/target/ppc/compat.c b/target/ppc/compat.c
index 10595550f9..458da262be 100644
--- a/target/ppc/compat.c
+++ b/target/ppc/compat.c
@@ -18,6 +18,7 @@
*/
#include "qemu/osdep.h"
+#include "sysemu/hw_accel.h"
#include "sysemu/kvm.h"
#include "kvm_ppc.h"
#include "sysemu/cpus.h"
@@ -124,6 +125,8 @@ void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp)
pcr = compat->pcr;
}
+ cpu_synchronize_state(CPU(cpu));
+
cpu->compat_pvr = compat_pvr;
env->spr[SPR_PCR] = pcr & pcc->pcr_mask;
@@ -136,6 +139,38 @@ void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp)
}
}
+typedef struct {
+ uint32_t compat_pvr;
+ Error *err;
+} SetCompatState;
+
+static void do_set_compat(CPUState *cs, run_on_cpu_data arg)
+{
+ PowerPCCPU *cpu = POWERPC_CPU(cs);
+ SetCompatState *s = arg.host_ptr;
+
+ ppc_set_compat(cpu, s->compat_pvr, &s->err);
+}
+
+void ppc_set_compat_all(uint32_t compat_pvr, Error **errp)
+{
+ CPUState *cs;
+
+ CPU_FOREACH(cs) {
+ SetCompatState s = {
+ .compat_pvr = compat_pvr,
+ .err = NULL,
+ };
+
+ run_on_cpu(cs, do_set_compat, RUN_ON_CPU_HOST_PTR(&s));
+
+ if (s.err) {
+ error_propagate(errp, s.err);
+ return;
+ }
+ }
+}
+
int ppc_compat_max_threads(PowerPCCPU *cpu)
{
const CompatInfo *compat = compat_by_pvr(cpu->compat_pvr);
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 22842ddd35..4d72d75e83 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -1326,6 +1326,9 @@ static inline int cpu_mmu_index (CPUPPCState *env, bool ifetch)
bool ppc_check_compat(PowerPCCPU *cpu, uint32_t compat_pvr,
uint32_t min_compat_pvr, uint32_t max_compat_pvr);
void ppc_set_compat(PowerPCCPU *cpu, uint32_t compat_pvr, Error **errp);
+#if !defined(CONFIG_USER_ONLY)
+void ppc_set_compat_all(uint32_t compat_pvr, Error **errp);
+#endif
int ppc_compat_max_threads(PowerPCCPU *cpu);
#endif /* defined(TARGET_PPC64) */