xref: /linux/arch/arm64/kvm/hyp/nvhe/timer-sr.c (revision cdd5b5a9761fd66d17586e4f4ba6588c70e640ea)
19aebdea4SDavid Brazdil // SPDX-License-Identifier: GPL-2.0-only
29aebdea4SDavid Brazdil /*
39aebdea4SDavid Brazdil  * Copyright (C) 2012-2015 - ARM Ltd
49aebdea4SDavid Brazdil  * Author: Marc Zyngier <marc.zyngier@arm.com>
59aebdea4SDavid Brazdil  */
69aebdea4SDavid Brazdil 
79aebdea4SDavid Brazdil #include <clocksource/arm_arch_timer.h>
89aebdea4SDavid Brazdil #include <linux/compiler.h>
99aebdea4SDavid Brazdil #include <linux/kvm_host.h>
109aebdea4SDavid Brazdil 
119aebdea4SDavid Brazdil #include <asm/kvm_hyp.h>
12c605ee24SMarc Zyngier #include <asm/kvm_mmu.h>
139aebdea4SDavid Brazdil 
__kvm_timer_set_cntvoff(u64 cntvoff)149aebdea4SDavid Brazdil void __kvm_timer_set_cntvoff(u64 cntvoff)
159aebdea4SDavid Brazdil {
169aebdea4SDavid Brazdil 	write_sysreg(cntvoff, cntvoff_el2);
179aebdea4SDavid Brazdil }
189aebdea4SDavid Brazdil 
199aebdea4SDavid Brazdil /*
20*aca18585SMarc Zyngier  * Should only be called on non-VHE or hVHE setups.
219aebdea4SDavid Brazdil  * VHE systems use EL2 timers and configure EL1 timers in kvm_timer_init_vhe().
229aebdea4SDavid Brazdil  */
__timer_disable_traps(struct kvm_vcpu * vcpu)23c50cb043SDavid Brazdil void __timer_disable_traps(struct kvm_vcpu *vcpu)
249aebdea4SDavid Brazdil {
25*aca18585SMarc Zyngier 	u64 val, shift = 0;
26*aca18585SMarc Zyngier 
27*aca18585SMarc Zyngier 	if (has_hvhe())
28*aca18585SMarc Zyngier 		shift = 10;
299aebdea4SDavid Brazdil 
309aebdea4SDavid Brazdil 	/* Allow physical timer/counter access for the host */
319aebdea4SDavid Brazdil 	val = read_sysreg(cnthctl_el2);
32*aca18585SMarc Zyngier 	val |= (CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN) << shift;
339aebdea4SDavid Brazdil 	write_sysreg(val, cnthctl_el2);
349aebdea4SDavid Brazdil }
359aebdea4SDavid Brazdil 
369aebdea4SDavid Brazdil /*
37*aca18585SMarc Zyngier  * Should only be called on non-VHE or hVHE setups.
389aebdea4SDavid Brazdil  * VHE systems use EL2 timers and configure EL1 timers in kvm_timer_init_vhe().
399aebdea4SDavid Brazdil  */
__timer_enable_traps(struct kvm_vcpu * vcpu)40c50cb043SDavid Brazdil void __timer_enable_traps(struct kvm_vcpu *vcpu)
419aebdea4SDavid Brazdil {
42c605ee24SMarc Zyngier 	u64 clr = 0, set = 0;
439aebdea4SDavid Brazdil 
449aebdea4SDavid Brazdil 	/*
459aebdea4SDavid Brazdil 	 * Disallow physical timer access for the guest
46c605ee24SMarc Zyngier 	 * Physical counter access is allowed if no offset is enforced
47c605ee24SMarc Zyngier 	 * or running protected (we don't offset anything in this case).
489aebdea4SDavid Brazdil 	 */
49c605ee24SMarc Zyngier 	clr = CNTHCTL_EL1PCEN;
50c605ee24SMarc Zyngier 	if (is_protected_kvm_enabled() ||
51c605ee24SMarc Zyngier 	    !kern_hyp_va(vcpu->kvm)->arch.timer_data.poffset)
52c605ee24SMarc Zyngier 		set |= CNTHCTL_EL1PCTEN;
53c605ee24SMarc Zyngier 	else
54c605ee24SMarc Zyngier 		clr |= CNTHCTL_EL1PCTEN;
55c605ee24SMarc Zyngier 
56*aca18585SMarc Zyngier 	if (has_hvhe()) {
57*aca18585SMarc Zyngier 		clr <<= 10;
58*aca18585SMarc Zyngier 		set <<= 10;
59*aca18585SMarc Zyngier 	}
60*aca18585SMarc Zyngier 
61c605ee24SMarc Zyngier 	sysreg_clear_set(cnthctl_el2, clr, set);
629aebdea4SDavid Brazdil }
63