qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-ppc] [PATCH 1/5] target-ppc: Synchronize VPA state with KVM


From: David Gibson
Subject: Re: [Qemu-ppc] [PATCH 1/5] target-ppc: Synchronize VPA state with KVM
Date: Mon, 8 Apr 2013 15:01:45 +1000
User-agent: Mutt/1.5.21 (2010-09-15)

On Fri, Mar 15, 2013 at 01:22:08PM +0100, Alexander Graf wrote:
> 
> On 14.03.2013, at 02:53, David Gibson wrote:
> 
> > For PAPR guests, KVM tracks the various areas registered with the
> > H_REGISTER_VPA hypercall.  For full emulation, of course, these are tracked
> > within qemu.  At present these values are not synchronized.  This is a
> > problem for reset (qemu's reset of the VPA address is not pushed to KVM)
> > and will also be a problem for savevm / migration.
> > 
> > The kernel now supports accessing the VPA state via the ONE_REG interface,
> > this patch adds code to qemu to use that interface to keep the qemu and
> > KVM ideas of the VPA state synchronized.
> > 
> > Signed-off-by: David Gibson <address@hidden>
> > ---
> > target-ppc/kvm.c |  121 
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 121 insertions(+)
> > 
> > diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
> > index 67f3f42..f5710b7 100644
> > --- a/target-ppc/kvm.c
> > +++ b/target-ppc/kvm.c
> > @@ -63,6 +63,7 @@ static int cap_ppc_rma;
> > static int cap_spapr_tce;
> > static int cap_hior;
> > static int cap_one_reg;
> > +static int cap_papr;
> > 
> > /* XXX We have a race condition where we actually have a level triggered
> >  *     interrupt, but the infrastructure can't expose that yet, so the guest
> > @@ -95,6 +96,8 @@ int kvm_arch_init(KVMState *s)
> >     cap_spapr_tce = kvm_check_extension(s, KVM_CAP_SPAPR_TCE);
> >     cap_one_reg = kvm_check_extension(s, KVM_CAP_ONE_REG);
> >     cap_hior = kvm_check_extension(s, KVM_CAP_PPC_HIOR);
> > +    /* Note: we don't set cap_papr here, because this capability is
> > +     * only activated after this by kvmppc_set_papr() */
> > 
> >     if (!cap_interrupt_level) {
> >         fprintf(stderr, "KVM: Couldn't find level irq capability. Expect 
> > the "
> > @@ -652,6 +655,103 @@ static int kvm_get_fp(CPUState *cs)
> >     return 0;
> > }
> > 
> > +#if defined(TARGET_PPC64)
> > +static int kvm_get_vpa(CPUState *cs)
> > +{
> > +    PowerPCCPU *cpu = POWERPC_CPU(cs);
> > +    CPUPPCState *env = &cpu->env;
> > +    struct kvm_one_reg reg;
> > +    int ret;
> > +
> > +    reg.id = KVM_REG_PPC_VPA_ADDR;
> > +    reg.addr = (uintptr_t)&env->vpa_addr;
> > +    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
> > +    if (ret < 0) {
> > +        dprintf("Unable to get VPA address from KVM: %s\n", 
> > strerror(errno));
> > +        return ret;
> > +    }
> > +
> > +    assert((uintptr_t)&env->slb_shadow_size
> > +           == ((uintptr_t)&env->slb_shadow_addr + 8));
> > +    reg.id = KVM_REG_PPC_VPA_SLB;
> > +    reg.addr = (uintptr_t)&env->slb_shadow_addr;
> > +    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
> > +    if (ret < 0) {
> > +        dprintf("Unable to get SLB shadow state from KVM: %s\n",
> > +                strerror(errno));
> > +        return ret;
> > +    }
> > +
> > +    assert((uintptr_t)&env->dtl_size == ((uintptr_t)&env->dtl_addr + 8));
> > +    reg.id = KVM_REG_PPC_VPA_DTL;
> > +    reg.addr = (uintptr_t)&env->dtl_addr;
> > +    ret = kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &reg);
> > +    if (ret < 0) {
> > +        dprintf("Unable to get dispatch trace log state from KVM: %s\n",
> > +                strerror(errno));
> > +        return ret;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> > +static int kvm_put_vpa(CPUState *cs)
> > +{
> > +    PowerPCCPU *cpu = POWERPC_CPU(cs);
> > +    CPUPPCState *env = &cpu->env;
> > +    struct kvm_one_reg reg;
> > +    int ret;
> > +
> > +    /* SLB shadow or DTL can't be registered unless a master VPA is
> > +     * registered.  That means when restoring state, if a VPA *is*
> > +     * registered, we need to set that up first.  If not, we need to
> > +     * deregister the others before deregistering the master VPA */
> > +    assert(env->vpa_addr || !(env->slb_shadow_addr || env->dtl_addr));
> > +
> > +    if (env->vpa_addr) {
> > +        reg.id = KVM_REG_PPC_VPA_ADDR;
> > +        reg.addr = (uintptr_t)&env->vpa_addr;
> > +        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
> > +        if (ret < 0) {
> > +            dprintf("Unable to set VPA address to KVM: %s\n", 
> > strerror(errno));
> > +            return ret;
> > +        }
> > +    }
> > +
> > +    assert((uintptr_t)&env->slb_shadow_size
> > +           == ((uintptr_t)&env->slb_shadow_addr + 8));
> > +    reg.id = KVM_REG_PPC_VPA_SLB;
> > +    reg.addr = (uintptr_t)&env->slb_shadow_addr;
> > +    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
> > +    if (ret < 0) {
> > +        dprintf("Unable to set SLB shadow state to KVM: %s\n", 
> > strerror(errno));
> > +        return ret;
> > +    }
> > +
> > +    assert((uintptr_t)&env->dtl_size == ((uintptr_t)&env->dtl_addr + 8));
> > +    reg.id = KVM_REG_PPC_VPA_DTL;
> > +    reg.addr = (uintptr_t)&env->dtl_addr;
> > +    ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
> > +    if (ret < 0) {
> > +        dprintf("Unable to set dispatch trace log state to KVM: %s\n",
> > +                strerror(errno));
> > +        return ret;
> > +    }
> > +
> > +    if (!env->vpa_addr) {
> > +        reg.id = KVM_REG_PPC_VPA_ADDR;
> > +        reg.addr = (uintptr_t)&env->vpa_addr;
> > +        ret = kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &reg);
> > +        if (ret < 0) {
> > +            dprintf("Unable to set VPA address to KVM: %s\n", 
> > strerror(errno));
> > +            return ret;
> > +        }
> > +    }
> > +
> > +    return 0;
> > +}
> > +#endif /* TARGET_PPC64 */
> > +
> > int kvm_arch_put_registers(CPUState *cs, int level)
> > {
> >     PowerPCCPU *cpu = POWERPC_CPU(cs);
> > @@ -752,6 +852,14 @@ int kvm_arch_put_registers(CPUState *cs, int level)
> >                 kvm_put_one_spr(cs, id, i);
> >             }
> >         }
> > +
> > +#ifdef TARGET_PPC64
> > +        if (cap_papr) {
> > +            if (kvm_put_vpa(cs) < 0) {
> > +                dprintf("Warning: Unable to set VPA information to KVM\n");
> > +            }
> > +        }
> > +#endif /* TARGET_PPC64 */
> >     }
> > 
> >     return ret;
> > @@ -953,6 +1061,15 @@ int kvm_arch_get_registers(CPUState *cs)
> >                 kvm_get_one_spr(cs, id, i);
> >             }
> >         }
> > +
> > +#ifdef TARGET_PPC64
> > +        if (cap_papr) {
> > +            if (kvm_get_vpa(cs) < 0) {
> > +                fprintf(stderr,
> > +                        "Warning: Unable to get VPA information from 
> > KVM\n");
> 
> This will give odd warnings on old HV KVM systems and PR KVM, no?

Drat, yes.  Converted the corresponding one on the get path to dprintf
but forgot this one.  Will resend with other pending pseries patches.

-- 
David Gibson                    | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
                                | _way_ _around_!
http://www.ozlabs.org/~dgibson

Attachment: signature.asc
Description: Digital signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]