diff options
Diffstat (limited to 'arch/arm64/kvm/hyp/timer-sr.c')
-rw-r--r-- | arch/arm64/kvm/hyp/timer-sr.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/arch/arm64/kvm/hyp/timer-sr.c b/arch/arm64/kvm/hyp/timer-sr.c new file mode 100644 index 000000000000..1051e5d7320f --- /dev/null +++ b/arch/arm64/kvm/hyp/timer-sr.c | |||
@@ -0,0 +1,71 @@ | |||
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_el0); | ||
35 | timer->cntv_cval = read_sysreg(cntv_cval_el0); | ||
36 | } | ||
37 | |||
38 | /* Disable the virtual timer */ | ||
39 | write_sysreg(0, cntv_ctl_el0); | ||
40 | |||
41 | /* Allow physical timer/counter access for the host */ | ||
42 | val = read_sysreg(cnthctl_el2); | ||
43 | val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN; | ||
44 | write_sysreg(val, cnthctl_el2); | ||
45 | |||
46 | /* Clear cntvoff for the host */ | ||
47 | write_sysreg(0, cntvoff_el2); | ||
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_el2); | ||
61 | val &= ~CNTHCTL_EL1PCEN; | ||
62 | val |= CNTHCTL_EL1PCTEN; | ||
63 | write_sysreg(val, cnthctl_el2); | ||
64 | |||
65 | if (kvm->arch.timer.enabled) { | ||
66 | write_sysreg(kvm->arch.timer.cntvoff, cntvoff_el2); | ||
67 | write_sysreg(timer->cntv_cval, cntv_cval_el0); | ||
68 | isb(); | ||
69 | write_sysreg(timer->cntv_ctl, cntv_ctl_el0); | ||
70 | } | ||
71 | } | ||