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>
This commit is contained in:
David Gibson 2016-11-10 14:37:38 +11:00
parent 152ef803ce
commit f6f242c757
3 changed files with 43 additions and 26 deletions

View File

@ -921,20 +921,6 @@ static target_ulong h_signal_sys_reset(PowerPCCPU *cpu,
}
}
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;
cpu_synchronize_state(cs);
ppc_set_compat(cpu, s->compat_pvr, &s->err);
}
static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
target_ulong opcode,
@ -942,7 +928,6 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
{
target_ulong list = ppc64_phys_to_real(args[0]);
target_ulong ov_table;
CPUState *cs;
bool explicit_match = false; /* Matched the CPU's real PVR */
uint32_t max_compat = cpu->max_compat;
uint32_t best_compat = 0;
@ -986,18 +971,12 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
/* Update CPUs */
if (cpu->compat_pvr != best_compat) {
CPU_FOREACH(cs) {
SetCompatState s = {
.compat_pvr = best_compat,
.err = NULL,
};
Error *local_err = NULL;
run_on_cpu(cs, do_set_compat, RUN_ON_CPU_HOST_PTR(&s));
if (s.err) {
error_report_err(s.err);
return H_HARDWARE;
}
ppc_set_compat_all(best_compat, &local_err);
if (local_err) {
error_report_err(local_err);
return H_HARDWARE;
}
}

View File

@ -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);

View File

@ -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) */