PPC: KVM: set has-idle in guest device tree
On e500mc, the platform doesn't provide a way for the CPU to go idle. To still not uselessly burn CPU time, expose an idle hypercall to the guest if kvm supports it. Signed-off-by: Stuart Yoder <stuart.yoder@freescale.com> [agraf: adjust for current code base, add patch description, fix non-kvm case] Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
d4834ff9b7
commit
1a61a9ae61
@ -225,6 +225,10 @@ static int ppce500_load_device_tree(CPUPPCState *env,
|
||||
kvmppc_get_hypercall(env, hypercall, sizeof(hypercall));
|
||||
qemu_devtree_setprop(fdt, "/hypervisor", "hcall-instructions",
|
||||
hypercall, sizeof(hypercall));
|
||||
/* if KVM supports the idle hcall, set property indicating this */
|
||||
if (kvmppc_get_hasidle(env)) {
|
||||
qemu_devtree_setprop(fdt, "/hypervisor", "has-idle", NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create CPU nodes */
|
||||
|
@ -989,18 +989,38 @@ uint32_t kvmppc_get_dfp(void)
|
||||
return kvmppc_read_int_cpu_dt("ibm,dfp");
|
||||
}
|
||||
|
||||
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
CPUState *cs = CPU(cpu);
|
||||
uint32_t *hc = (uint32_t*)buf;
|
||||
|
||||
struct kvm_ppc_pvinfo pvinfo;
|
||||
static int kvmppc_get_pvinfo(CPUPPCState *env, struct kvm_ppc_pvinfo *pvinfo)
|
||||
{
|
||||
PowerPCCPU *cpu = ppc_env_get_cpu(env);
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
if (kvm_check_extension(cs->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&
|
||||
!kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, &pvinfo)) {
|
||||
memcpy(buf, pvinfo.hcall, buf_len);
|
||||
!kvm_vm_ioctl(cs->kvm_state, KVM_PPC_GET_PVINFO, pvinfo)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int kvmppc_get_hasidle(CPUPPCState *env)
|
||||
{
|
||||
struct kvm_ppc_pvinfo pvinfo;
|
||||
|
||||
if (!kvmppc_get_pvinfo(env, &pvinfo) &&
|
||||
(pvinfo.flags & KVM_PPC_PVINFO_FLAGS_EV_IDLE)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
|
||||
{
|
||||
uint32_t *hc = (uint32_t*)buf;
|
||||
struct kvm_ppc_pvinfo pvinfo;
|
||||
|
||||
if (!kvmppc_get_pvinfo(env, &pvinfo)) {
|
||||
memcpy(buf, pvinfo.hcall, buf_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,7 @@ uint32_t kvmppc_get_tbfreq(void);
|
||||
uint64_t kvmppc_get_clockfreq(void);
|
||||
uint32_t kvmppc_get_vmx(void);
|
||||
uint32_t kvmppc_get_dfp(void);
|
||||
int kvmppc_get_hasidle(CPUPPCState *env);
|
||||
int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len);
|
||||
int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level);
|
||||
void kvmppc_set_papr(PowerPCCPU *cpu);
|
||||
@ -55,6 +56,11 @@ static inline uint32_t kvmppc_get_dfp(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kvmppc_get_hasidle(CPUPPCState *env)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_len)
|
||||
{
|
||||
return -1;
|
||||
|
Loading…
Reference in New Issue
Block a user