[Android-virt] [PATCH 09/10] ARM: KVM: arch_timers: Add timer world switch

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

 



On Mon, May 14, 2012 at 9:07 AM, Marc Zyngier <marc.zyngier at arm.com> wrote:
> Do the necessary save/restore dance for the timers in the world
> switch code. In the process, allow the guest to read the physical
> counter, which is useful for its own clock_event_device.
>
> Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
> ---
> ?arch/arm/kernel/asm-offsets.c | ? ?8 +++++++
> ?arch/arm/kvm/arm.c ? ? ? ? ? ?| ? ?2 +
> ?arch/arm/kvm/interrupts.S ? ? | ? 43 +++++++++++++++++++++++++++++++++++++++++
> ?3 files changed, 53 insertions(+), 0 deletions(-)
>
> diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
> index d5f4ddf..039ef64 100644
> --- a/arch/arm/kernel/asm-offsets.c
> +++ b/arch/arm/kernel/asm-offsets.c
> @@ -184,6 +184,14 @@ int main(void)
> ? DEFINE(VCPU_VGIC_APR, ? ? ? ? ? ? ? ?offsetof(struct kvm_vcpu, arch.vgic_cpu.vgic_apr));
> ? DEFINE(VCPU_VGIC_LR, ? ? ? ? offsetof(struct kvm_vcpu, arch.vgic_cpu.vgic_lr));
> ? DEFINE(VCPU_VGIC_NR_LR, ? ? ?offsetof(struct kvm_vcpu, arch.vgic_cpu.nr_lr));
> +#ifdef CONFIG_KVM_ARM_TIMER
> + ?DEFINE(VCPU_TIMER_CNTV_CTL, ?offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_ctl));
> + ?DEFINE(VCPU_TIMER_CNTV_CVALH, ? ? ? ?offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_cval_high));
> + ?DEFINE(VCPU_TIMER_CNTV_CVALL, ? ? ? ?offsetof(struct kvm_vcpu, arch.timer_cpu.cntv_cval_low));
> + ?DEFINE(KVM_TIMER_CNTVOFF_H, ?offsetof(struct kvm, arch.timer.cntvoff32.cntvoff_high));
> + ?DEFINE(KVM_TIMER_CNTVOFF_L, ?offsetof(struct kvm, arch.timer.cntvoff32.cntvoff_low));
> + ?DEFINE(KVM_TIMER_ENABLED, ? ?offsetof(struct kvm, arch.timer.enabled));
> +#endif
> ? DEFINE(KVM_VGIC_VCTRL, ? ? ? offsetof(struct kvm, arch.vgic.vctrl_base));
> ?#endif
> ? DEFINE(KVM_VTTBR, ? ? ? ? ? ?offsetof(struct kvm, arch.vttbr));
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index 86eca66..ccb2c08 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -511,9 +511,11 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run)
> ? ? ? ? ? ? ? ?kvm_guest_enter();
> ? ? ? ? ? ? ? ?vcpu->mode = IN_GUEST_MODE;
> ? ? ? ? ? ? ? ?kvm_vgic_sync_to_cpu(vcpu);
> + ? ? ? ? ? ? ? kvm_timer_sync_to_cpu(vcpu);
>
> ? ? ? ? ? ? ? ?ret = __kvm_vcpu_run(vcpu);
>
> + ? ? ? ? ? ? ? kvm_timer_sync_from_cpu(vcpu);
> ? ? ? ? ? ? ? ?kvm_vgic_sync_from_cpu(vcpu);
> ? ? ? ? ? ? ? ?vcpu->mode = OUTSIDE_GUEST_MODE;
> ? ? ? ? ? ? ? ?vcpu->stat.exits++;
> diff --git a/arch/arm/kvm/interrupts.S b/arch/arm/kvm/interrupts.S
> index 56a65c4..1481d44 100644
> --- a/arch/arm/kvm/interrupts.S
> +++ b/arch/arm/kvm/interrupts.S
> @@ -312,10 +312,33 @@ ENTRY(__kvm_flush_vm_context)
> ?#endif
> ?.endm
>
> +#ifdef CONFIG_KVM_ARM_TIMER
> +#define PL1P_ENABLE ? ?3
> +#define PL1P_DISABLE ? 2
> +#else
> ?#define PL1P_ENABLE ? ?3
> ?#define PL1P_DISABLE ? 3
> +#endif
>
> ?.macro save_timer_state ? ? ? ?vcpup
> +#ifdef CONFIG_KVM_ARM_TIMER
> + ? ? ? ldr ? ? r4, [\vcpup, #VCPU_KVM]
> + ? ? ? ldr ? ? r2, [r4, #KVM_TIMER_ENABLED]
> + ? ? ? cmp ? ? r2, #0
> + ? ? ? beq ? ? 1f
> +
> + ? ? ? mrc ? ? p15, 0, r2, c14, c3, 1 ?@ CNTV_CTL
> + ? ? ? and ? ? r2, #3
> + ? ? ? str ? ? r2, [\vcpup, #VCPU_TIMER_CNTV_CTL]
> + ? ? ? bic ? ? r2, #1 ? ? ? ? ? ? ? ? ?@ Clear ENABLE
> + ? ? ? mcr ? ? p15, 0, r2, c14, c3, 1 ?@ CNTV_CTL
> +
> + ? ? ? mrrc ? ?p15, 3, r2, r3, c14 ? ? @ CNTV_CVAL
> + ? ? ? str ? ? r3, [\vcpup, #VCPU_TIMER_CNTV_CVALH]
> + ? ? ? str ? ? r2, [\vcpup, #VCPU_TIMER_CNTV_CVALL]
> +
> +1:
> +#endif
> ? ? ? ?@ Allow physical timer access for the host
> ? ? ? ?mrc ? ? p15, 4, r2, c14, c1, 0 ?@ CNTHCTL
> ? ? ? ?orr ? ? r2, r2, #PL1P_ENABLE
> @@ -328,6 +351,26 @@ ENTRY(__kvm_flush_vm_context)
> ? ? ? ?bic ? ? r2, r2, #PL1P_DISABLE
> ? ? ? ?mcr ? ? p15, 4, r2, c14, c1, 0 ?@ CNTHCTL
>
> +#ifdef CONFIG_KVM_ARM_TIMER
> + ? ? ? ldr ? ? r4, [\vcpup, #VCPU_KVM]
> + ? ? ? ldr ? ? r2, [r4, #KVM_TIMER_ENABLED]
> + ? ? ? cmp ? ? r2, #0
> + ? ? ? beq ? ? 1f
> +
> + ? ? ? ldr ? ? r3, [\vcpup, #VCPU_TIMER_CNTV_CVALH]
> + ? ? ? ldr ? ? r2, [\vcpup, #VCPU_TIMER_CNTV_CVALL]
> + ? ? ? mcrr ? ?p15, 3, r2, r3, c14 ? ? @ CNTV_CVAL
> +
> + ? ? ? ldr ? ? r3, [r4, #KVM_TIMER_CNTVOFF_H]
> + ? ? ? ldr ? ? r2, [r4, #KVM_TIMER_CNTVOFF_L]
> + ? ? ? mcrr ? ?p15, 4, r2, r3, c14 ? ? @ CNTVOFF

still not quite understanding where we adjust this or why we don't. If
this is effectively zero do we have to bother with it on every
world-switch and could this be documented somewhere?

> + ? ? ? isb
> +
> + ? ? ? ldr ? ? r2, [\vcpup, #VCPU_TIMER_CNTV_CTL]
> + ? ? ? and ? ? r2, #3

Are we clearing the enable and mask bits here, because in any case we
offloaded a remaining timer from last time around to a host timer?

> + ? ? ? mcr ? ? p15, 0, r2, c14, c3, 1 ?@ CNTV_CTL
> +1:
> +#endif
> ? ? ? ?isb
> ?.endm
>
> --
> 1.7.7.1
>
Thanks,
-Christoffer



[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux