diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2016-03-03 10:43:58 -0500 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2016-03-08 23:24:09 -0500 |
commit | 0d98d00b8d80bfdee95cf7e85f20f107377e2662 (patch) | |
tree | 0962d058aec3a40e6e6488856e6a3b4a5f89f2c5 | |
parent | 84e8b9c88d5fe9c9a59ed24ae44d7ac0983df92b (diff) |
arm64: KVM: vgic-v3: Reset LRs at boot time
In order to let the GICv3 code be more lazy in the way it
accesses the LRs, it is necessary to start with a clean slate.
Let's reset the LRs on each CPU when the vgic is probed (which
includes a round trip to EL2...).
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r-- | arch/arm64/include/asm/kvm_asm.h | 1 | ||||
-rw-r--r-- | arch/arm64/kvm/hyp/vgic-v3-sr.c | 9 | ||||
-rw-r--r-- | virt/kvm/arm/vgic-v3.c | 7 |
3 files changed, 17 insertions, 0 deletions
diff --git a/arch/arm64/include/asm/kvm_asm.h b/arch/arm64/include/asm/kvm_asm.h index 1037392ae134..2d02ba67478c 100644 --- a/arch/arm64/include/asm/kvm_asm.h +++ b/arch/arm64/include/asm/kvm_asm.h | |||
@@ -42,6 +42,7 @@ extern void __kvm_tlb_flush_vmid(struct kvm *kvm); | |||
42 | extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu); | 42 | extern int __kvm_vcpu_run(struct kvm_vcpu *vcpu); |
43 | 43 | ||
44 | extern u64 __vgic_v3_get_ich_vtr_el2(void); | 44 | extern u64 __vgic_v3_get_ich_vtr_el2(void); |
45 | extern void __vgic_v3_init_lrs(void); | ||
45 | 46 | ||
46 | extern u32 __kvm_get_mdcr_el2(void); | 47 | extern u32 __kvm_get_mdcr_el2(void); |
47 | 48 | ||
diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c index 0db426e6c13e..81349479e17c 100644 --- a/arch/arm64/kvm/hyp/vgic-v3-sr.c +++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c | |||
@@ -321,6 +321,15 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu) | |||
321 | } | 321 | } |
322 | } | 322 | } |
323 | 323 | ||
324 | void __hyp_text __vgic_v3_init_lrs(void) | ||
325 | { | ||
326 | int max_lr_idx = vtr_to_max_lr_idx(read_gicreg(ICH_VTR_EL2)); | ||
327 | int i; | ||
328 | |||
329 | for (i = 0; i <= max_lr_idx; i++) | ||
330 | __gic_v3_set_lr(0, i); | ||
331 | } | ||
332 | |||
324 | static u64 __hyp_text __vgic_v3_read_ich_vtr_el2(void) | 333 | static u64 __hyp_text __vgic_v3_read_ich_vtr_el2(void) |
325 | { | 334 | { |
326 | return read_gicreg(ICH_VTR_EL2); | 335 | return read_gicreg(ICH_VTR_EL2); |
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c index 11b5ff6ce81c..999bdc6d9d9f 100644 --- a/virt/kvm/arm/vgic-v3.c +++ b/virt/kvm/arm/vgic-v3.c | |||
@@ -216,6 +216,11 @@ static const struct vgic_ops vgic_v3_ops = { | |||
216 | 216 | ||
217 | static struct vgic_params vgic_v3_params; | 217 | static struct vgic_params vgic_v3_params; |
218 | 218 | ||
219 | static void vgic_cpu_init_lrs(void *params) | ||
220 | { | ||
221 | kvm_call_hyp(__vgic_v3_init_lrs); | ||
222 | } | ||
223 | |||
219 | /** | 224 | /** |
220 | * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT | 225 | * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT |
221 | * @node: pointer to the DT node | 226 | * @node: pointer to the DT node |
@@ -284,6 +289,8 @@ int vgic_v3_probe(struct device_node *vgic_node, | |||
284 | kvm_info("%s@%llx IRQ%d\n", vgic_node->name, | 289 | kvm_info("%s@%llx IRQ%d\n", vgic_node->name, |
285 | vcpu_res.start, vgic->maint_irq); | 290 | vcpu_res.start, vgic->maint_irq); |
286 | 291 | ||
292 | on_each_cpu(vgic_cpu_init_lrs, vgic, 1); | ||
293 | |||
287 | *ops = &vgic_v3_ops; | 294 | *ops = &vgic_v3_ops; |
288 | *params = vgic; | 295 | *params = vgic; |
289 | 296 | ||