diff options
author | David Gibson <david@gibson.dropbear.id.au> | 2016-11-10 14:37:38 +1100 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2017-01-31 10:10:14 +1100 |
commit | f6f242c7578fbedcdb53a14d4b057a7059b8dd1d (patch) | |
tree | 073ca40777358eab78a72c8fea13bcfdcd21268a /target/ppc | |
parent | 152ef803ceb1959e2380a1da7736b935b109222e (diff) |
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.c | 35 | ||||
-rw-r--r-- | target/ppc/cpu.h | 3 |
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) */ |