Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ARM: KVM: Add timer save/restore

This patch shouldn't exist, as we should be able to reuse the
arm64 version for free. I'll get there eventually, but in the
meantime I need a timer ticking.

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

+80
+1
arch/arm/kvm/hyp/Makefile
··· 4 4 5 5 obj-$(CONFIG_KVM_ARM_HOST) += tlb.o 6 6 obj-$(CONFIG_KVM_ARM_HOST) += cp15-sr.o 7 + obj-$(CONFIG_KVM_ARM_HOST) += timer-sr.o
+8
arch/arm/kvm/hyp/hyp.h
··· 46 46 #define TTBR1 __ACCESS_CP15_64(1, c2) 47 47 #define VTTBR __ACCESS_CP15_64(6, c2) 48 48 #define PAR __ACCESS_CP15_64(0, c7) 49 + #define CNTV_CVAL __ACCESS_CP15_64(3, c14) 50 + #define CNTVOFF __ACCESS_CP15_64(4, c14) 51 + 49 52 #define CSSELR __ACCESS_CP15(c0, 2, c0, 0) 50 53 #define VMPIDR __ACCESS_CP15(c0, 4, c0, 5) 51 54 #define SCTLR __ACCESS_CP15(c1, 0, c0, 0) ··· 74 71 #define TID_URO __ACCESS_CP15(c13, 0, c0, 3) 75 72 #define TID_PRIV __ACCESS_CP15(c13, 0, c0, 4) 76 73 #define CNTKCTL __ACCESS_CP15(c14, 0, c1, 0) 74 + #define CNTV_CTL __ACCESS_CP15(c14, 0, c3, 1) 75 + #define CNTHCTL __ACCESS_CP15(c14, 4, c1, 0) 76 + 77 + void __timer_save_state(struct kvm_vcpu *vcpu); 78 + void __timer_restore_state(struct kvm_vcpu *vcpu); 77 79 78 80 void __sysreg_save_state(struct kvm_cpu_context *ctxt); 79 81 void __sysreg_restore_state(struct kvm_cpu_context *ctxt);
+71
arch/arm/kvm/hyp/timer-sr.c
··· 1 + /* 2 + * Copyright (C) 2012-2015 - ARM Ltd 3 + * Author: Marc Zyngier <marc.zyngier@arm.com> 4 + * 5 + * This program is free software; you can redistribute it and/or modify 6 + * it under the terms of the GNU General Public License version 2 as 7 + * published by the Free Software Foundation. 8 + * 9 + * This program is distributed in the hope that it will be useful, 10 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 + * GNU General Public License for more details. 13 + * 14 + * You should have received a copy of the GNU General Public License 15 + * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 + */ 17 + 18 + #include <clocksource/arm_arch_timer.h> 19 + #include <linux/compiler.h> 20 + #include <linux/kvm_host.h> 21 + 22 + #include <asm/kvm_mmu.h> 23 + 24 + #include "hyp.h" 25 + 26 + /* vcpu is already in the HYP VA space */ 27 + void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu) 28 + { 29 + struct kvm *kvm = kern_hyp_va(vcpu->kvm); 30 + struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; 31 + u64 val; 32 + 33 + if (kvm->arch.timer.enabled) { 34 + timer->cntv_ctl = read_sysreg(CNTV_CTL); 35 + timer->cntv_cval = read_sysreg(CNTV_CVAL); 36 + } 37 + 38 + /* Disable the virtual timer */ 39 + write_sysreg(0, CNTV_CTL); 40 + 41 + /* Allow physical timer/counter access for the host */ 42 + val = read_sysreg(CNTHCTL); 43 + val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN; 44 + write_sysreg(val, CNTHCTL); 45 + 46 + /* Clear cntvoff for the host */ 47 + write_sysreg(0, CNTVOFF); 48 + } 49 + 50 + void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu) 51 + { 52 + struct kvm *kvm = kern_hyp_va(vcpu->kvm); 53 + struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; 54 + u64 val; 55 + 56 + /* 57 + * Disallow physical timer access for the guest 58 + * Physical counter access is allowed 59 + */ 60 + val = read_sysreg(CNTHCTL); 61 + val &= ~CNTHCTL_EL1PCEN; 62 + val |= CNTHCTL_EL1PCTEN; 63 + write_sysreg(val, CNTHCTL); 64 + 65 + if (kvm->arch.timer.enabled) { 66 + write_sysreg(kvm->arch.timer.cntvoff, CNTVOFF); 67 + write_sysreg(timer->cntv_cval, CNTV_CVAL); 68 + isb(); 69 + write_sysreg(timer->cntv_ctl, CNTV_CTL); 70 + } 71 + }