162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (C) 2012-2015 - ARM Ltd 462306a36Sopenharmony_ci * Author: Marc Zyngier <marc.zyngier@arm.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <clocksource/arm_arch_timer.h> 862306a36Sopenharmony_ci#include <linux/compiler.h> 962306a36Sopenharmony_ci#include <linux/kvm_host.h> 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <asm/kvm_hyp.h> 1262306a36Sopenharmony_ci#include <asm/kvm_mmu.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_civoid __kvm_timer_set_cntvoff(u64 cntvoff) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci write_sysreg(cntvoff, cntvoff_el2); 1762306a36Sopenharmony_ci} 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* 2062306a36Sopenharmony_ci * Should only be called on non-VHE or hVHE setups. 2162306a36Sopenharmony_ci * VHE systems use EL2 timers and configure EL1 timers in kvm_timer_init_vhe(). 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_civoid __timer_disable_traps(struct kvm_vcpu *vcpu) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci u64 val, shift = 0; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci if (has_hvhe()) 2862306a36Sopenharmony_ci shift = 10; 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci /* Allow physical timer/counter access for the host */ 3162306a36Sopenharmony_ci val = read_sysreg(cnthctl_el2); 3262306a36Sopenharmony_ci val |= (CNTHCTL_EL1PCTEN | CNTHCTL_EL1PCEN) << shift; 3362306a36Sopenharmony_ci write_sysreg(val, cnthctl_el2); 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* 3762306a36Sopenharmony_ci * Should only be called on non-VHE or hVHE setups. 3862306a36Sopenharmony_ci * VHE systems use EL2 timers and configure EL1 timers in kvm_timer_init_vhe(). 3962306a36Sopenharmony_ci */ 4062306a36Sopenharmony_civoid __timer_enable_traps(struct kvm_vcpu *vcpu) 4162306a36Sopenharmony_ci{ 4262306a36Sopenharmony_ci u64 clr = 0, set = 0; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci /* 4562306a36Sopenharmony_ci * Disallow physical timer access for the guest 4662306a36Sopenharmony_ci * Physical counter access is allowed if no offset is enforced 4762306a36Sopenharmony_ci * or running protected (we don't offset anything in this case). 4862306a36Sopenharmony_ci */ 4962306a36Sopenharmony_ci clr = CNTHCTL_EL1PCEN; 5062306a36Sopenharmony_ci if (is_protected_kvm_enabled() || 5162306a36Sopenharmony_ci !kern_hyp_va(vcpu->kvm)->arch.timer_data.poffset) 5262306a36Sopenharmony_ci set |= CNTHCTL_EL1PCTEN; 5362306a36Sopenharmony_ci else 5462306a36Sopenharmony_ci clr |= CNTHCTL_EL1PCTEN; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci if (has_hvhe()) { 5762306a36Sopenharmony_ci clr <<= 10; 5862306a36Sopenharmony_ci set <<= 10; 5962306a36Sopenharmony_ci } 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci sysreg_clear_set(cnthctl_el2, clr, set); 6262306a36Sopenharmony_ci} 63