diff options
-rw-r--r-- | arch/arm/kvm/reset.c | 12 | ||||
-rw-r--r-- | include/kvm/arm_arch_timer.h | 4 | ||||
-rw-r--r-- | virt/kvm/arm/arch_timer.c | 29 |
3 files changed, 36 insertions, 9 deletions
diff --git a/arch/arm/kvm/reset.c b/arch/arm/kvm/reset.c index b80256b554cd..b7840e7aa452 100644 --- a/arch/arm/kvm/reset.c +++ b/arch/arm/kvm/reset.c | |||
@@ -27,6 +27,8 @@ | |||
27 | #include <asm/kvm_arm.h> | 27 | #include <asm/kvm_arm.h> |
28 | #include <asm/kvm_coproc.h> | 28 | #include <asm/kvm_coproc.h> |
29 | 29 | ||
30 | #include <kvm/arm_arch_timer.h> | ||
31 | |||
30 | /****************************************************************************** | 32 | /****************************************************************************** |
31 | * Cortex-A15 Reset Values | 33 | * Cortex-A15 Reset Values |
32 | */ | 34 | */ |
@@ -37,6 +39,11 @@ static struct kvm_regs a15_regs_reset = { | |||
37 | .usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT, | 39 | .usr_regs.ARM_cpsr = SVC_MODE | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT, |
38 | }; | 40 | }; |
39 | 41 | ||
42 | static const struct kvm_irq_level a15_vtimer_irq = { | ||
43 | .irq = 27, | ||
44 | .level = 1, | ||
45 | }; | ||
46 | |||
40 | 47 | ||
41 | /******************************************************************************* | 48 | /******************************************************************************* |
42 | * Exported reset function | 49 | * Exported reset function |
@@ -52,6 +59,7 @@ static struct kvm_regs a15_regs_reset = { | |||
52 | int kvm_reset_vcpu(struct kvm_vcpu *vcpu) | 59 | int kvm_reset_vcpu(struct kvm_vcpu *vcpu) |
53 | { | 60 | { |
54 | struct kvm_regs *cpu_reset; | 61 | struct kvm_regs *cpu_reset; |
62 | const struct kvm_irq_level *cpu_vtimer_irq; | ||
55 | 63 | ||
56 | switch (vcpu->arch.target) { | 64 | switch (vcpu->arch.target) { |
57 | case KVM_ARM_TARGET_CORTEX_A15: | 65 | case KVM_ARM_TARGET_CORTEX_A15: |
@@ -59,6 +67,7 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) | |||
59 | return -EINVAL; | 67 | return -EINVAL; |
60 | cpu_reset = &a15_regs_reset; | 68 | cpu_reset = &a15_regs_reset; |
61 | vcpu->arch.midr = read_cpuid_id(); | 69 | vcpu->arch.midr = read_cpuid_id(); |
70 | cpu_vtimer_irq = &a15_vtimer_irq; | ||
62 | break; | 71 | break; |
63 | default: | 72 | default: |
64 | return -ENODEV; | 73 | return -ENODEV; |
@@ -70,5 +79,8 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) | |||
70 | /* Reset CP15 registers */ | 79 | /* Reset CP15 registers */ |
71 | kvm_reset_coprocs(vcpu); | 80 | kvm_reset_coprocs(vcpu); |
72 | 81 | ||
82 | /* Reset arch_timer context */ | ||
83 | kvm_timer_vcpu_reset(vcpu, cpu_vtimer_irq); | ||
84 | |||
73 | return 0; | 85 | return 0; |
74 | } | 86 | } |
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h index 68cb9e1dfb81..6d9aeddc09bf 100644 --- a/include/kvm/arm_arch_timer.h +++ b/include/kvm/arm_arch_timer.h | |||
@@ -61,6 +61,8 @@ struct arch_timer_cpu { | |||
61 | #ifdef CONFIG_KVM_ARM_TIMER | 61 | #ifdef CONFIG_KVM_ARM_TIMER |
62 | int kvm_timer_hyp_init(void); | 62 | int kvm_timer_hyp_init(void); |
63 | int kvm_timer_init(struct kvm *kvm); | 63 | int kvm_timer_init(struct kvm *kvm); |
64 | void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, | ||
65 | const struct kvm_irq_level *irq); | ||
64 | void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu); | 66 | void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu); |
65 | void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu); | 67 | void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu); |
66 | void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu); | 68 | void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu); |
@@ -76,6 +78,8 @@ static inline int kvm_timer_init(struct kvm *kvm) | |||
76 | return 0; | 78 | return 0; |
77 | } | 79 | } |
78 | 80 | ||
81 | static inline void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, | ||
82 | const struct kvm_irq_level *irq) {} | ||
79 | static inline void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) {} | 83 | static inline void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) {} |
80 | static inline void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) {} | 84 | static inline void kvm_timer_flush_hwstate(struct kvm_vcpu *vcpu) {} |
81 | static inline void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) {} | 85 | static inline void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) {} |
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 2d00b2925780..af4583e2c185 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c | |||
@@ -30,9 +30,7 @@ | |||
30 | 30 | ||
31 | static struct timecounter *timecounter; | 31 | static struct timecounter *timecounter; |
32 | static struct workqueue_struct *wqueue; | 32 | static struct workqueue_struct *wqueue; |
33 | static struct kvm_irq_level timer_irq = { | 33 | static unsigned int host_vtimer_irq; |
34 | .level = 1, | ||
35 | }; | ||
36 | 34 | ||
37 | static cycle_t kvm_phys_timer_read(void) | 35 | static cycle_t kvm_phys_timer_read(void) |
38 | { | 36 | { |
@@ -67,8 +65,8 @@ static void kvm_timer_inject_irq(struct kvm_vcpu *vcpu) | |||
67 | 65 | ||
68 | timer->cntv_ctl |= ARCH_TIMER_CTRL_IT_MASK; | 66 | timer->cntv_ctl |= ARCH_TIMER_CTRL_IT_MASK; |
69 | kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, | 67 | kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id, |
70 | vcpu->arch.timer_cpu.irq->irq, | 68 | timer->irq->irq, |
71 | vcpu->arch.timer_cpu.irq->level); | 69 | timer->irq->level); |
72 | } | 70 | } |
73 | 71 | ||
74 | static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id) | 72 | static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id) |
@@ -156,6 +154,20 @@ void kvm_timer_sync_hwstate(struct kvm_vcpu *vcpu) | |||
156 | timer_arm(timer, ns); | 154 | timer_arm(timer, ns); |
157 | } | 155 | } |
158 | 156 | ||
157 | void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu, | ||
158 | const struct kvm_irq_level *irq) | ||
159 | { | ||
160 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | ||
161 | |||
162 | /* | ||
163 | * The vcpu timer irq number cannot be determined in | ||
164 | * kvm_timer_vcpu_init() because it is called much before | ||
165 | * kvm_vcpu_set_target(). To handle this, we determine | ||
166 | * vcpu timer irq number when the vcpu is reset. | ||
167 | */ | ||
168 | timer->irq = irq; | ||
169 | } | ||
170 | |||
159 | void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) | 171 | void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) |
160 | { | 172 | { |
161 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 173 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; |
@@ -163,12 +175,11 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) | |||
163 | INIT_WORK(&timer->expired, kvm_timer_inject_irq_work); | 175 | INIT_WORK(&timer->expired, kvm_timer_inject_irq_work); |
164 | hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); | 176 | hrtimer_init(&timer->timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); |
165 | timer->timer.function = kvm_timer_expire; | 177 | timer->timer.function = kvm_timer_expire; |
166 | timer->irq = &timer_irq; | ||
167 | } | 178 | } |
168 | 179 | ||
169 | static void kvm_timer_init_interrupt(void *info) | 180 | static void kvm_timer_init_interrupt(void *info) |
170 | { | 181 | { |
171 | enable_percpu_irq(timer_irq.irq, 0); | 182 | enable_percpu_irq(host_vtimer_irq, 0); |
172 | } | 183 | } |
173 | 184 | ||
174 | 185 | ||
@@ -182,7 +193,7 @@ static int kvm_timer_cpu_notify(struct notifier_block *self, | |||
182 | break; | 193 | break; |
183 | case CPU_DYING: | 194 | case CPU_DYING: |
184 | case CPU_DYING_FROZEN: | 195 | case CPU_DYING_FROZEN: |
185 | disable_percpu_irq(timer_irq.irq); | 196 | disable_percpu_irq(host_vtimer_irq); |
186 | break; | 197 | break; |
187 | } | 198 | } |
188 | 199 | ||
@@ -229,7 +240,7 @@ int kvm_timer_hyp_init(void) | |||
229 | goto out; | 240 | goto out; |
230 | } | 241 | } |
231 | 242 | ||
232 | timer_irq.irq = ppi; | 243 | host_vtimer_irq = ppi; |
233 | 244 | ||
234 | err = register_cpu_notifier(&kvm_timer_cpu_nb); | 245 | err = register_cpu_notifier(&kvm_timer_cpu_nb); |
235 | if (err) { | 246 | if (err) { |