1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
2 | /* |
3 | * Copyright (C) 2012 ARM Ltd. |
4 | * Author: Marc Zyngier <marc.zyngier@arm.com> |
5 | */ |
6 | |
7 | #ifndef __ASM_ARM_KVM_ARCH_TIMER_H |
8 | #define __ASM_ARM_KVM_ARCH_TIMER_H |
9 | |
10 | #include <linux/clocksource.h> |
11 | #include <linux/hrtimer.h> |
12 | |
13 | enum kvm_arch_timers { |
14 | TIMER_PTIMER, |
15 | TIMER_VTIMER, |
16 | NR_KVM_EL0_TIMERS, |
17 | TIMER_HVTIMER = NR_KVM_EL0_TIMERS, |
18 | TIMER_HPTIMER, |
19 | NR_KVM_TIMERS |
20 | }; |
21 | |
22 | enum kvm_arch_timer_regs { |
23 | TIMER_REG_CNT, |
24 | TIMER_REG_CVAL, |
25 | TIMER_REG_TVAL, |
26 | TIMER_REG_CTL, |
27 | TIMER_REG_VOFF, |
28 | }; |
29 | |
30 | struct arch_timer_offset { |
31 | /* |
32 | * If set, pointer to one of the offsets in the kvm's offset |
33 | * structure. If NULL, assume a zero offset. |
34 | */ |
35 | u64 *vm_offset; |
36 | /* |
37 | * If set, pointer to one of the offsets in the vcpu's sysreg |
38 | * array. If NULL, assume a zero offset. |
39 | */ |
40 | u64 *vcpu_offset; |
41 | }; |
42 | |
43 | struct arch_timer_vm_data { |
44 | /* Offset applied to the virtual timer/counter */ |
45 | u64 voffset; |
46 | /* Offset applied to the physical timer/counter */ |
47 | u64 poffset; |
48 | |
49 | /* The PPI for each timer, global to the VM */ |
50 | u8 ppi[NR_KVM_TIMERS]; |
51 | }; |
52 | |
53 | struct arch_timer_context { |
54 | struct kvm_vcpu *vcpu; |
55 | |
56 | /* Emulated Timer (may be unused) */ |
57 | struct hrtimer hrtimer; |
58 | u64 ns_frac; |
59 | |
60 | /* Offset for this counter/timer */ |
61 | struct arch_timer_offset offset; |
62 | /* |
63 | * We have multiple paths which can save/restore the timer state onto |
64 | * the hardware, so we need some way of keeping track of where the |
65 | * latest state is. |
66 | */ |
67 | bool loaded; |
68 | |
69 | /* Output level of the timer IRQ */ |
70 | struct { |
71 | bool level; |
72 | } irq; |
73 | |
74 | /* Duplicated state from arch_timer.c for convenience */ |
75 | u32 host_timer_irq; |
76 | }; |
77 | |
78 | struct timer_map { |
79 | struct arch_timer_context *direct_vtimer; |
80 | struct arch_timer_context *direct_ptimer; |
81 | struct arch_timer_context *emul_vtimer; |
82 | struct arch_timer_context *emul_ptimer; |
83 | }; |
84 | |
85 | void get_timer_map(struct kvm_vcpu *vcpu, struct timer_map *map); |
86 | |
87 | struct arch_timer_cpu { |
88 | struct arch_timer_context timers[NR_KVM_TIMERS]; |
89 | |
90 | /* Background timer used when the guest is not running */ |
91 | struct hrtimer bg_timer; |
92 | |
93 | /* Is the timer enabled */ |
94 | bool enabled; |
95 | }; |
96 | |
97 | int __init kvm_timer_hyp_init(bool has_gic); |
98 | int kvm_timer_enable(struct kvm_vcpu *vcpu); |
99 | void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu); |
100 | void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu); |
101 | void kvm_timer_sync_user(struct kvm_vcpu *vcpu); |
102 | bool kvm_timer_should_notify_user(struct kvm_vcpu *vcpu); |
103 | void kvm_timer_update_run(struct kvm_vcpu *vcpu); |
104 | void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu); |
105 | |
106 | void kvm_timer_init_vm(struct kvm *kvm); |
107 | |
108 | u64 kvm_arm_timer_get_reg(struct kvm_vcpu *, u64 regid); |
109 | int kvm_arm_timer_set_reg(struct kvm_vcpu *, u64 regid, u64 value); |
110 | |
111 | int kvm_arm_timer_set_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); |
112 | int kvm_arm_timer_get_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); |
113 | int kvm_arm_timer_has_attr(struct kvm_vcpu *vcpu, struct kvm_device_attr *attr); |
114 | |
115 | u64 kvm_phys_timer_read(void); |
116 | |
117 | void kvm_timer_vcpu_load(struct kvm_vcpu *vcpu); |
118 | void kvm_timer_vcpu_put(struct kvm_vcpu *vcpu); |
119 | |
120 | void kvm_timer_init_vhe(void); |
121 | |
122 | #define vcpu_timer(v) (&(v)->arch.timer_cpu) |
123 | #define vcpu_get_timer(v,t) (&vcpu_timer(v)->timers[(t)]) |
124 | #define vcpu_vtimer(v) (&(v)->arch.timer_cpu.timers[TIMER_VTIMER]) |
125 | #define vcpu_ptimer(v) (&(v)->arch.timer_cpu.timers[TIMER_PTIMER]) |
126 | #define vcpu_hvtimer(v) (&(v)->arch.timer_cpu.timers[TIMER_HVTIMER]) |
127 | #define vcpu_hptimer(v) (&(v)->arch.timer_cpu.timers[TIMER_HPTIMER]) |
128 | |
129 | #define arch_timer_ctx_index(ctx) ((ctx) - vcpu_timer((ctx)->vcpu)->timers) |
130 | |
131 | #define timer_vm_data(ctx) (&(ctx)->vcpu->kvm->arch.timer_data) |
132 | #define timer_irq(ctx) (timer_vm_data(ctx)->ppi[arch_timer_ctx_index(ctx)]) |
133 | |
134 | u64 kvm_arm_timer_read_sysreg(struct kvm_vcpu *vcpu, |
135 | enum kvm_arch_timers tmr, |
136 | enum kvm_arch_timer_regs treg); |
137 | void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu, |
138 | enum kvm_arch_timers tmr, |
139 | enum kvm_arch_timer_regs treg, |
140 | u64 val); |
141 | |
142 | /* Needed for tracing */ |
143 | u32 timer_get_ctl(struct arch_timer_context *ctxt); |
144 | u64 timer_get_cval(struct arch_timer_context *ctxt); |
145 | |
146 | /* CPU HP callbacks */ |
147 | void kvm_timer_cpu_up(void); |
148 | void kvm_timer_cpu_down(void); |
149 | |
150 | static inline bool has_cntpoff(void) |
151 | { |
152 | return (has_vhe() && cpus_have_final_cap(ARM64_HAS_ECV_CNTPOFF)); |
153 | } |
154 | |
155 | #endif |
156 | |