|  | /* SPDX-License-Identifier: GPL-2.0-only */ | 
|  | /* | 
|  | * Copyright (C) 2012 ARM Ltd. | 
|  | * Author: Marc Zyngier <[email protected]> | 
|  | */ | 
|  |  | 
|  | #ifndef __ASM_ARM_KVM_ARCH_TIMER_H | 
|  | #define __ASM_ARM_KVM_ARCH_TIMER_H | 
|  |  | 
|  | #include <linux/clocksource.h> | 
|  | #include <linux/hrtimer.h> | 
|  |  | 
|  | enum kvm_arch_timers { | 
|  | TIMER_PTIMER, | 
|  | TIMER_VTIMER, | 
|  | NR_KVM_TIMERS | 
|  | }; | 
|  |  | 
|  | enum kvm_arch_timer_regs { | 
|  | TIMER_REG_CNT, | 
|  | TIMER_REG_CVAL, | 
|  | TIMER_REG_TVAL, | 
|  | TIMER_REG_CTL, | 
|  | }; | 
|  |  | 
|  | struct arch_timer_context { | 
|  | struct kvm_vcpu			*vcpu; | 
|  |  | 
|  | /* Timer IRQ */ | 
|  | struct kvm_irq_level		irq; | 
|  |  | 
|  | /* Emulated Timer (may be unused) */ | 
|  | struct hrtimer			hrtimer; | 
|  |  | 
|  | /* | 
|  | * We have multiple paths which can save/restore the timer state onto | 
|  | * the hardware, so we need some way of keeping track of where the | 
|  | * latest state is. | 
|  | */ | 
|  | bool				loaded; | 
|  |  | 
|  | /* Duplicated state from arch_timer.c for convenience */ | 
|  | u32				host_timer_irq; | 
|  | u32				host_timer_irq_flags; | 
|  | }; | 
|  |  | 
|  | struct timer_map { | 
|  | struct arch_timer_context *direct_vtimer; | 
|  | struct arch_timer_context *direct_ptimer; | 
|  | struct arch_timer_context *emul_ptimer; | 
|  | }; | 
|  |  | 
|  | struct arch_timer_cpu { | 
|  | struct arch_timer_context timers[NR_KVM_TIMERS]; | 
|  |  | 
|  | /* Background timer used when the guest is not running */ | 
|  | struct hrtimer			bg_timer; | 
|  |  | 
|  | /* Is the timer enabled */ | 
|  | bool			enabled; | 
|  | }; | 
|  |  | 
|  | int kvm_timer_hyp_init(bool); | 
|  | int kvm_timer_enable(struct kvm_vcpu *vcpu); | 
|  | int kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu); | 
|  | void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu); | 
|  | void kvm_timer_sync_user(struct kvm_vcpu *vcpu); | 
|  | bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu); | 
|  | void kvm_timer_update_run(struct kvm_vcpu *vcpu); | 
|  | void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu); | 
|  |  | 
|  | u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid); | 
|  | int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value); | 
|  |  | 
|  | int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); | 
|  | int kvm_arm_timer_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); | 
|  | int kvm_arm_timer_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); | 
|  |  | 
|  | bool kvm_timer_is_pending(struct kvm_vcpu *vcpu); | 
|  |  | 
|  | u64 kvm_phys_timer_read(void); | 
|  |  | 
|  | void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu); | 
|  | void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); | 
|  |  | 
|  | void kvm_timer_init_vhe(void); | 
|  |  | 
|  | bool kvm_arch_timer_get_input_level(int vintid); | 
|  |  | 
|  | #define vcpu_timer(v)	(&(v)->arch.timer_cpu) | 
|  | #define vcpu_get_timer(v,t)	(&vcpu_timer(v)->timers[(t)]) | 
|  | #define vcpu_vtimer(v)	(&(v)->arch.timer_cpu.timers[TIMER_VTIMER]) | 
|  | #define vcpu_ptimer(v)	(&(v)->arch.timer_cpu.timers[TIMER_PTIMER]) | 
|  |  | 
|  | #define arch_timer_ctx_index(ctx)	((ctx) - vcpu_timer((ctx)->vcpu)->timers) | 
|  |  | 
|  | u64 kvm_arm_timer_read_sysreg(struct kvm_vcpu *vcpu, | 
|  | enum kvm_arch_timers tmr, | 
|  | enum kvm_arch_timer_regs treg); | 
|  | void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu, | 
|  | enum kvm_arch_timers tmr, | 
|  | enum kvm_arch_timer_regs treg, | 
|  | u64 val); | 
|  |  | 
|  | /* Needed for tracing */ | 
|  | u32 timer_get_ctl(struct arch_timer_context *ctxt); | 
|  | u64 timer_get_cval(struct arch_timer_context *ctxt); | 
|  |  | 
|  | #endif |