From: andre.przywara@linaro.org (Andre Przywara)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2] ARM/KVM: save and restore generic timer registers
Date: Fri, 05 Jul 2013 16:08:55 +0200 [thread overview]
Message-ID: <51D6D377.70708@linaro.org> (raw)
In-Reply-To: <51C2D528.90805@arm.com>
Hi Marc,
>> ...
>>
>> +int kvm_arm_num_timer_regs(void)
>> +{
>> + return 3;
>> +}
>> +
>> +int kvm_arm_copy_timer_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
>> +{
>> + if (put_user(KVM_REG_ARM_TIMER_CTL, uindices))
>> + return -EFAULT;
>> + uindices++;
>> + if (put_user(KVM_REG_ARM_TIMER_CNT, uindices))
>> + return -EFAULT;
>> + uindices++;
>> + if (put_user(KVM_REG_ARM_TIMER_CVAL, uindices))
>> + return -EFAULT;
>
> So these macros are going to break arm64. Any chance you could introduce
> them at the same time on both platforms? The rest of the work can be
> delayed, but you shouldn't break arm64 (you'd expect me to say that,
> wouldn't you? ;-).
Is that just due to KVM_REG_ARM instead of KVM_REG_ARM64?
Or do you expect the numbering to be completely different since there is
no mrc/mcr anymore (IIRC)?
Is put_user an issue here (should not, right?)
Is there already a document describing arch timer access on AARCH64?
If I am thinking in a totally wrong direction, please bear with me and
feel free to point me to the right one ;-)
/me is now looking at getting a cross compiler to see what you mean...
> Also, I'd like to keep userspace access out of the timer code itself.
> Low level code shouldn't have to know about that. Can you create proper
> accessors instead, and move whole userspace access to coproc.c?
IIRC Christoffer recommended to keep this code completely out of
coproc.c ;-) This also helps to keep coproc.c clean of ARCH_TIMER ifdefs
in coproc.c (which I completely forgot in this version, btw, but that's
already fixed).
>
>> + return 0;
>> +}
>> +
>> +int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>> +{
>> + struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
>> + void __user *uaddr = (void __user *)(long)reg->addr;
>> + u64 val;
>> + int ret;
>> +
>> + ret = copy_from_user(&val, uaddr, KVM_REG_SIZE(reg->id));
>> + if (ret != 0)
>> + return ret;
>> +
>> + switch (reg->id) {
>> + case KVM_REG_ARM_TIMER_CTL:
>> + timer->cntv_ctl = val;
>> + break;
>> + case KVM_REG_ARM_TIMER_CNT:
>> + vcpu->kvm->arch.timer.cntvoff = kvm_phys_timer_read() - val;
>
> I just realized what bothers me here: You're computing cntvoff on a per
> vcpu basis, while this is a VM property. Which means that as you're
> restoring vcpus, you'll be changing cntvoff - sounds like a bad idea to me.
>
> The counter is really global. Do we have a way to handle VM-wide
> registers? I think Christoffer was trying to some a similar thing with
> the GIC...
So the consensus of this discussion was just to block writing when the
VCPU is running, right? Or is there something else?
Regards,
Andre.
>
>> + break;
>> + case KVM_REG_ARM_TIMER_CVAL:
>> + timer->cntv_cval = val;
>> + break;
>> + }
>> +
>> + return 0;
>> +}
>> +
>> +int kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>> +{
>> + struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
>> + void __user *uaddr = (void __user *)(long)reg->addr;
>> + u64 val;
>> +
>> + switch (reg->id) {
>> + case KVM_REG_ARM_TIMER_CTL:
>> + val = timer->cntv_ctl;
>> + break;
>> + case KVM_REG_ARM_TIMER_CNT:
>> + val = kvm_phys_timer_read() - vcpu->kvm->arch.timer.cntvoff;
>> + break;
>> + case KVM_REG_ARM_TIMER_CVAL:
>> + val = timer->cntv_cval;
>> + break;
>> + }
>> + return copy_to_user(uaddr, &val, KVM_REG_SIZE(reg->id));
>> +}
>>
>> static int kvm_timer_cpu_notify(struct notifier_block *self,
>> unsigned long action, void *cpu)
>> diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
>> index 152d036..a50ffb6 100644
>> --- a/arch/arm/kvm/guest.c
>> +++ b/arch/arm/kvm/guest.c
>> @@ -121,7 +121,8 @@ static unsigned long num_core_regs(void)
>> */
>> unsigned long kvm_arm_num_regs(struct kvm_vcpu *vcpu)
>> {
>> - return num_core_regs() + kvm_arm_num_coproc_regs(vcpu);
>> + return num_core_regs() + kvm_arm_num_coproc_regs(vcpu)
>> + + kvm_arm_num_timer_regs();
>> }
>>
>> /**
>> @@ -133,6 +134,7 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
>> {
>> unsigned int i;
>> const u64 core_reg = KVM_REG_ARM | KVM_REG_SIZE_U32 | KVM_REG_ARM_CORE;
>> + int ret;
>>
>> for (i = 0; i < sizeof(struct kvm_regs)/sizeof(u32); i++) {
>> if (put_user(core_reg | i, uindices))
>> @@ -140,9 +142,25 @@ int kvm_arm_copy_reg_indices(struct kvm_vcpu *vcpu, u64 __user *uindices)
>> uindices++;
>> }
>>
>> + ret = kvm_arm_copy_timer_indices(vcpu, uindices);
>> + if (ret)
>> + return ret;
>> + uindices += kvm_arm_num_timer_regs();
>> +
>> return kvm_arm_copy_coproc_indices(vcpu, uindices);
>> }
>>
>> +static bool is_timer_reg(u64 index)
>> +{
>> + switch (index) {
>> + case KVM_REG_ARM_TIMER_CTL:
>> + case KVM_REG_ARM_TIMER_CNT:
>> + case KVM_REG_ARM_TIMER_CVAL:
>> + return true;
>> + }
>> + return false;
>> +}
>> +
>> int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>> {
>> /* We currently use nothing arch-specific in upper 32 bits */
>> @@ -153,6 +171,9 @@ int kvm_arm_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>> if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
>> return get_core_reg(vcpu, reg);
>>
>> + if (is_timer_reg(reg->id))
>> + return kvm_arm_timer_get_reg(vcpu, reg);
>> +
>> return kvm_arm_coproc_get_reg(vcpu, reg);
>> }
>>
>> @@ -166,6 +187,9 @@ int kvm_arm_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *reg)
>> if ((reg->id & KVM_REG_ARM_COPROC_MASK) == KVM_REG_ARM_CORE)
>> return set_core_reg(vcpu, reg);
>>
>> + if (is_timer_reg(reg->id))
>> + return kvm_arm_timer_set_reg(vcpu, reg);
>> +
>> return kvm_arm_coproc_set_reg(vcpu, reg);
>> }
>
> This is otherwise moving in the right direction.
>
> Thanks,
>
> M.
>
next prev parent reply other threads:[~2013-07-05 14:08 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-06-11 15:16 [PATCH v2] ARM/KVM: save and restore generic timer registers Andre Przywara
2013-06-19 21:16 ` Christoffer Dall
2013-06-20 10:10 ` Marc Zyngier
2013-06-20 17:09 ` Christoffer Dall
2013-06-20 17:19 ` Marc Zyngier
2013-06-20 18:32 ` Christoffer Dall
2013-06-20 18:39 ` Marc Zyngier
2013-06-20 19:29 ` Peter Maydell
2013-06-20 20:37 ` Christoffer Dall
2013-06-20 21:55 ` Alexander Graf
2013-06-20 21:59 ` Peter Maydell
2013-06-20 22:02 ` Alexander Graf
2013-06-20 22:48 ` Christoffer Dall
2013-07-05 14:08 ` Andre Przywara [this message]
2013-07-05 14:44 ` Marc Zyngier
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=51D6D377.70708@linaro.org \
--to=andre.przywara@linaro.org \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.