diff options
Diffstat (limited to 'virt/kvm/arm/hyp/timer-sr.c')
-rw-r--r-- | virt/kvm/arm/hyp/timer-sr.c | 74 |
1 files changed, 32 insertions, 42 deletions
diff --git a/virt/kvm/arm/hyp/timer-sr.c b/virt/kvm/arm/hyp/timer-sr.c index 4734915ab71f..f39861639f08 100644 --- a/virt/kvm/arm/hyp/timer-sr.c +++ b/virt/kvm/arm/hyp/timer-sr.c | |||
@@ -21,58 +21,48 @@ | |||
21 | 21 | ||
22 | #include <asm/kvm_hyp.h> | 22 | #include <asm/kvm_hyp.h> |
23 | 23 | ||
24 | /* vcpu is already in the HYP VA space */ | 24 | void __hyp_text __kvm_timer_set_cntvoff(u32 cntvoff_low, u32 cntvoff_high) |
25 | void __hyp_text __timer_save_state(struct kvm_vcpu *vcpu) | 25 | { |
26 | u64 cntvoff = (u64)cntvoff_high << 32 | cntvoff_low; | ||
27 | write_sysreg(cntvoff, cntvoff_el2); | ||
28 | } | ||
29 | |||
30 | void __hyp_text enable_el1_phys_timer_access(void) | ||
26 | { | 31 | { |
27 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | ||
28 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | ||
29 | u64 val; | 32 | u64 val; |
30 | 33 | ||
31 | if (timer->enabled) { | 34 | /* Allow physical timer/counter access for the host */ |
32 | vtimer->cnt_ctl = read_sysreg_el0(cntv_ctl); | 35 | val = read_sysreg(cnthctl_el2); |
33 | vtimer->cnt_cval = read_sysreg_el0(cntv_cval); | 36 | val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN; |
34 | } | 37 | write_sysreg(val, cnthctl_el2); |
38 | } | ||
35 | 39 | ||
36 | /* Disable the virtual timer */ | 40 | void __hyp_text disable_el1_phys_timer_access(void) |
37 | write_sysreg_el0(0, cntv_ctl); | 41 | { |
42 | u64 val; | ||
38 | 43 | ||
39 | /* | 44 | /* |
45 | * Disallow physical timer access for the guest | ||
46 | * Physical counter access is allowed | ||
47 | */ | ||
48 | val = read_sysreg(cnthctl_el2); | ||
49 | val &= ~CNTHCTL_EL1PCEN; | ||
50 | val |= CNTHCTL_EL1PCTEN; | ||
51 | write_sysreg(val, cnthctl_el2); | ||
52 | } | ||
53 | |||
54 | void __hyp_text __timer_disable_traps(struct kvm_vcpu *vcpu) | ||
55 | { | ||
56 | /* | ||
40 | * We don't need to do this for VHE since the host kernel runs in EL2 | 57 | * We don't need to do this for VHE since the host kernel runs in EL2 |
41 | * with HCR_EL2.TGE ==1, which makes those bits have no impact. | 58 | * with HCR_EL2.TGE ==1, which makes those bits have no impact. |
42 | */ | 59 | */ |
43 | if (!has_vhe()) { | 60 | if (!has_vhe()) |
44 | /* Allow physical timer/counter access for the host */ | 61 | enable_el1_phys_timer_access(); |
45 | val = read_sysreg(cnthctl_el2); | ||
46 | val |= CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN; | ||
47 | write_sysreg(val, cnthctl_el2); | ||
48 | } | ||
49 | |||
50 | /* Clear cntvoff for the host */ | ||
51 | write_sysreg(0, cntvoff_el2); | ||
52 | } | 62 | } |
53 | 63 | ||
54 | void __hyp_text __timer_restore_state(struct kvm_vcpu *vcpu) | 64 | void __hyp_text __timer_enable_traps(struct kvm_vcpu *vcpu) |
55 | { | 65 | { |
56 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 66 | if (!has_vhe()) |
57 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | 67 | disable_el1_phys_timer_access(); |
58 | u64 val; | ||
59 | |||
60 | /* Those bits are already configured at boot on VHE-system */ | ||
61 | if (!has_vhe()) { | ||
62 | /* | ||
63 | * Disallow physical timer access for the guest | ||
64 | * Physical counter access is allowed | ||
65 | */ | ||
66 | val = read_sysreg(cnthctl_el2); | ||
67 | val &= ~CNTHCTL_EL1PCEN; | ||
68 | val |= CNTHCTL_EL1PCTEN; | ||
69 | write_sysreg(val, cnthctl_el2); | ||
70 | } | ||
71 | |||
72 | if (timer->enabled) { | ||
73 | write_sysreg(vtimer->cntvoff, cntvoff_el2); | ||
74 | write_sysreg_el0(vtimer->cnt_cval, cntv_cval); | ||
75 | isb(); | ||
76 | write_sysreg_el0(vtimer->cnt_ctl, cntv_ctl); | ||
77 | } | ||
78 | } | 68 | } |