Skip to content

Commit f3351c6

Browse files
committed
Merge tag 'kvmarm-fixes-for-4.17-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm
KVM/arm fixes for 4.17, take #2 - Fix proxying of GICv2 CPU interface accesses - Fix crash when switching to BE - Track source vcpu git GICv2 SGIs - Fix an outdated bit of documentation
2 parents 6da6c0d + b220244 commit f3351c6

File tree

9 files changed

+102
-68
lines changed

9 files changed

+102
-68
lines changed

arch/arm64/include/asm/kvm_emulate.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,7 @@ static inline void kvm_vcpu_set_be(struct kvm_vcpu *vcpu)
333333
} else {
334334
u64 sctlr = vcpu_read_sys_reg(vcpu, SCTLR_EL1);
335335
sctlr |= (1 << 25);
336-
vcpu_write_sys_reg(vcpu, SCTLR_EL1, sctlr);
336+
vcpu_write_sys_reg(vcpu, sctlr, SCTLR_EL1);
337337
}
338338
}
339339

arch/arm64/kvm/hyp/vgic-v2-cpuif-proxy.c

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,20 @@
1818
#include <linux/compiler.h>
1919
#include <linux/irqchip/arm-gic.h>
2020
#include <linux/kvm_host.h>
21+
#include <linux/swab.h>
2122

2223
#include <asm/kvm_emulate.h>
2324
#include <asm/kvm_hyp.h>
2425
#include <asm/kvm_mmu.h>
2526

27+
static bool __hyp_text __is_be(struct kvm_vcpu *vcpu)
28+
{
29+
if (vcpu_mode_is_32bit(vcpu))
30+
return !!(read_sysreg_el2(spsr) & COMPAT_PSR_E_BIT);
31+
32+
return !!(read_sysreg(SCTLR_EL1) & SCTLR_ELx_EE);
33+
}
34+
2635
/*
2736
* __vgic_v2_perform_cpuif_access -- perform a GICV access on behalf of the
2837
* guest.
@@ -64,14 +73,19 @@ int __hyp_text __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu)
6473
addr += fault_ipa - vgic->vgic_cpu_base;
6574

6675
if (kvm_vcpu_dabt_iswrite(vcpu)) {
67-
u32 data = vcpu_data_guest_to_host(vcpu,
68-
vcpu_get_reg(vcpu, rd),
69-
sizeof(u32));
76+
u32 data = vcpu_get_reg(vcpu, rd);
77+
if (__is_be(vcpu)) {
78+
/* guest pre-swabbed data, undo this for writel() */
79+
data = swab32(data);
80+
}
7081
writel_relaxed(data, addr);
7182
} else {
7283
u32 data = readl_relaxed(addr);
73-
vcpu_set_reg(vcpu, rd, vcpu_data_host_to_guest(vcpu, data,
74-
sizeof(u32)));
84+
if (__is_be(vcpu)) {
85+
/* guest expects swabbed data */
86+
data = swab32(data);
87+
}
88+
vcpu_set_reg(vcpu, rd, data);
7589
}
7690

7791
return 1;

include/kvm/arm_vgic.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ struct vgic_irq {
131131
u32 mpidr; /* GICv3 target VCPU */
132132
};
133133
u8 source; /* GICv2 SGIs only */
134+
u8 active_source; /* GICv2 SGIs only */
134135
u8 priority;
135136
enum vgic_irq_config config; /* Level or edge */
136137

virt/kvm/arm/vgic/vgic-init.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -423,7 +423,7 @@ static irqreturn_t vgic_maintenance_handler(int irq, void *data)
423423
* We cannot rely on the vgic maintenance interrupt to be
424424
* delivered synchronously. This means we can only use it to
425425
* exit the VM, and we perform the handling of EOIed
426-
* interrupts on the exit path (see vgic_process_maintenance).
426+
* interrupts on the exit path (see vgic_fold_lr_state).
427427
*/
428428
return IRQ_HANDLED;
429429
}

virt/kvm/arm/vgic/vgic-mmio.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,10 +289,16 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
289289
irq->vcpu->cpu != -1) /* VCPU thread is running */
290290
cond_resched_lock(&irq->irq_lock);
291291

292-
if (irq->hw)
292+
if (irq->hw) {
293293
vgic_hw_irq_change_active(vcpu, irq, active, !requester_vcpu);
294-
else
294+
} else {
295+
u32 model = vcpu->kvm->arch.vgic.vgic_model;
296+
295297
irq->active = active;
298+
if (model == KVM_DEV_TYPE_ARM_VGIC_V2 &&
299+
active && vgic_irq_is_sgi(irq->intid))
300+
irq->active_source = requester_vcpu->vcpu_id;
301+
}
296302

297303
if (irq->active)
298304
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);

virt/kvm/arm/vgic/vgic-v2.c

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,6 @@ void vgic_v2_init_lrs(void)
3737
vgic_v2_write_lr(i, 0);
3838
}
3939

40-
void vgic_v2_set_npie(struct kvm_vcpu *vcpu)
41-
{
42-
struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
43-
44-
cpuif->vgic_hcr |= GICH_HCR_NPIE;
45-
}
46-
4740
void vgic_v2_set_underflow(struct kvm_vcpu *vcpu)
4841
{
4942
struct vgic_v2_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v2;
@@ -71,13 +64,18 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
7164
int lr;
7265
unsigned long flags;
7366

74-
cpuif->vgic_hcr &= ~(GICH_HCR_UIE | GICH_HCR_NPIE);
67+
cpuif->vgic_hcr &= ~GICH_HCR_UIE;
7568

7669
for (lr = 0; lr < vgic_cpu->used_lrs; lr++) {
7770
u32 val = cpuif->vgic_lr[lr];
78-
u32 intid = val & GICH_LR_VIRTUALID;
71+
u32 cpuid, intid = val & GICH_LR_VIRTUALID;
7972
struct vgic_irq *irq;
8073

74+
/* Extract the source vCPU id from the LR */
75+
cpuid = val & GICH_LR_PHYSID_CPUID;
76+
cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
77+
cpuid &= 7;
78+
8179
/* Notify fds when the guest EOI'ed a level-triggered SPI */
8280
if (lr_signals_eoi_mi(val) && vgic_valid_spi(vcpu->kvm, intid))
8381
kvm_notify_acked_irq(vcpu->kvm, 0,
@@ -90,17 +88,16 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
9088
/* Always preserve the active bit */
9189
irq->active = !!(val & GICH_LR_ACTIVE_BIT);
9290

91+
if (irq->active && vgic_irq_is_sgi(intid))
92+
irq->active_source = cpuid;
93+
9394
/* Edge is the only case where we preserve the pending bit */
9495
if (irq->config == VGIC_CONFIG_EDGE &&
9596
(val & GICH_LR_PENDING_BIT)) {
9697
irq->pending_latch = true;
9798

98-
if (vgic_irq_is_sgi(intid)) {
99-
u32 cpuid = val & GICH_LR_PHYSID_CPUID;
100-
101-
cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
99+
if (vgic_irq_is_sgi(intid))
102100
irq->source |= (1 << cpuid);
103-
}
104101
}
105102

106103
/*
@@ -152,8 +149,15 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
152149
u32 val = irq->intid;
153150
bool allow_pending = true;
154151

155-
if (irq->active)
152+
if (irq->active) {
156153
val |= GICH_LR_ACTIVE_BIT;
154+
if (vgic_irq_is_sgi(irq->intid))
155+
val |= irq->active_source << GICH_LR_PHYSID_CPUID_SHIFT;
156+
if (vgic_irq_is_multi_sgi(irq)) {
157+
allow_pending = false;
158+
val |= GICH_LR_EOI;
159+
}
160+
}
157161

158162
if (irq->hw) {
159163
val |= GICH_LR_HW;
@@ -190,8 +194,10 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
190194
BUG_ON(!src);
191195
val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
192196
irq->source &= ~(1 << (src - 1));
193-
if (irq->source)
197+
if (irq->source) {
194198
irq->pending_latch = true;
199+
val |= GICH_LR_EOI;
200+
}
195201
}
196202
}
197203

virt/kvm/arm/vgic/vgic-v3.c

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,6 @@ static bool group1_trap;
2727
static bool common_trap;
2828
static bool gicv4_enable;
2929

30-
void vgic_v3_set_npie(struct kvm_vcpu *vcpu)
31-
{
32-
struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
33-
34-
cpuif->vgic_hcr |= ICH_HCR_NPIE;
35-
}
36-
3730
void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
3831
{
3932
struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
@@ -55,17 +48,23 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
5548
int lr;
5649
unsigned long flags;
5750

58-
cpuif->vgic_hcr &= ~(ICH_HCR_UIE | ICH_HCR_NPIE);
51+
cpuif->vgic_hcr &= ~ICH_HCR_UIE;
5952

6053
for (lr = 0; lr < vgic_cpu->used_lrs; lr++) {
6154
u64 val = cpuif->vgic_lr[lr];
62-
u32 intid;
55+
u32 intid, cpuid;
6356
struct vgic_irq *irq;
57+
bool is_v2_sgi = false;
6458

65-
if (model == KVM_DEV_TYPE_ARM_VGIC_V3)
59+
cpuid = val & GICH_LR_PHYSID_CPUID;
60+
cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
61+
62+
if (model == KVM_DEV_TYPE_ARM_VGIC_V3) {
6663
intid = val & ICH_LR_VIRTUAL_ID_MASK;
67-
else
64+
} else {
6865
intid = val & GICH_LR_VIRTUALID;
66+
is_v2_sgi = vgic_irq_is_sgi(intid);
67+
}
6968

7069
/* Notify fds when the guest EOI'ed a level-triggered IRQ */
7170
if (lr_signals_eoi_mi(val) && vgic_valid_spi(vcpu->kvm, intid))
@@ -81,18 +80,16 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
8180
/* Always preserve the active bit */
8281
irq->active = !!(val & ICH_LR_ACTIVE_BIT);
8382

83+
if (irq->active && is_v2_sgi)
84+
irq->active_source = cpuid;
85+
8486
/* Edge is the only case where we preserve the pending bit */
8587
if (irq->config == VGIC_CONFIG_EDGE &&
8688
(val & ICH_LR_PENDING_BIT)) {
8789
irq->pending_latch = true;
8890

89-
if (vgic_irq_is_sgi(intid) &&
90-
model == KVM_DEV_TYPE_ARM_VGIC_V2) {
91-
u32 cpuid = val & GICH_LR_PHYSID_CPUID;
92-
93-
cpuid >>= GICH_LR_PHYSID_CPUID_SHIFT;
91+
if (is_v2_sgi)
9492
irq->source |= (1 << cpuid);
95-
}
9693
}
9794

9895
/*
@@ -133,10 +130,20 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
133130
{
134131
u32 model = vcpu->kvm->arch.vgic.vgic_model;
135132
u64 val = irq->intid;
136-
bool allow_pending = true;
133+
bool allow_pending = true, is_v2_sgi;
137134

138-
if (irq->active)
135+
is_v2_sgi = (vgic_irq_is_sgi(irq->intid) &&
136+
model == KVM_DEV_TYPE_ARM_VGIC_V2);
137+
138+
if (irq->active) {
139139
val |= ICH_LR_ACTIVE_BIT;
140+
if (is_v2_sgi)
141+
val |= irq->active_source << GICH_LR_PHYSID_CPUID_SHIFT;
142+
if (vgic_irq_is_multi_sgi(irq)) {
143+
allow_pending = false;
144+
val |= ICH_LR_EOI;
145+
}
146+
}
140147

141148
if (irq->hw) {
142149
val |= ICH_LR_HW;
@@ -174,8 +181,10 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
174181
BUG_ON(!src);
175182
val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
176183
irq->source &= ~(1 << (src - 1));
177-
if (irq->source)
184+
if (irq->source) {
178185
irq->pending_latch = true;
186+
val |= ICH_LR_EOI;
187+
}
179188
}
180189
}
181190

virt/kvm/arm/vgic/vgic.c

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -725,14 +725,6 @@ static inline void vgic_set_underflow(struct kvm_vcpu *vcpu)
725725
vgic_v3_set_underflow(vcpu);
726726
}
727727

728-
static inline void vgic_set_npie(struct kvm_vcpu *vcpu)
729-
{
730-
if (kvm_vgic_global_state.type == VGIC_V2)
731-
vgic_v2_set_npie(vcpu);
732-
else
733-
vgic_v3_set_npie(vcpu);
734-
}
735-
736728
/* Requires the ap_list_lock to be held. */
737729
static int compute_ap_list_depth(struct kvm_vcpu *vcpu,
738730
bool *multi_sgi)
@@ -746,17 +738,15 @@ static int compute_ap_list_depth(struct kvm_vcpu *vcpu,
746738
DEBUG_SPINLOCK_BUG_ON(!spin_is_locked(&vgic_cpu->ap_list_lock));
747739

748740
list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
741+
int w;
742+
749743
spin_lock(&irq->irq_lock);
750744
/* GICv2 SGIs can count for more than one... */
751-
if (vgic_irq_is_sgi(irq->intid) && irq->source) {
752-
int w = hweight8(irq->source);
753-
754-
count += w;
755-
*multi_sgi |= (w > 1);
756-
} else {
757-
count++;
758-
}
745+
w = vgic_irq_get_lr_count(irq);
759746
spin_unlock(&irq->irq_lock);
747+
748+
count += w;
749+
*multi_sgi |= (w > 1);
760750
}
761751
return count;
762752
}
@@ -767,7 +757,6 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
767757
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
768758
struct vgic_irq *irq;
769759
int count;
770-
bool npie = false;
771760
bool multi_sgi;
772761
u8 prio = 0xff;
773762

@@ -797,10 +786,8 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
797786
if (likely(vgic_target_oracle(irq) == vcpu)) {
798787
vgic_populate_lr(vcpu, irq, count++);
799788

800-
if (irq->source) {
801-
npie = true;
789+
if (irq->source)
802790
prio = irq->priority;
803-
}
804791
}
805792

806793
spin_unlock(&irq->irq_lock);
@@ -813,9 +800,6 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
813800
}
814801
}
815802

816-
if (npie)
817-
vgic_set_npie(vcpu);
818-
819803
vcpu->arch.vgic_cpu.used_lrs = count;
820804

821805
/* Nuke remaining LRs */

virt/kvm/arm/vgic/vgic.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,20 @@ static inline bool vgic_irq_is_mapped_level(struct vgic_irq *irq)
110110
return irq->config == VGIC_CONFIG_LEVEL && irq->hw;
111111
}
112112

113+
static inline int vgic_irq_get_lr_count(struct vgic_irq *irq)
114+
{
115+
/* Account for the active state as an interrupt */
116+
if (vgic_irq_is_sgi(irq->intid) && irq->source)
117+
return hweight8(irq->source) + irq->active;
118+
119+
return irq_is_pending(irq) || irq->active;
120+
}
121+
122+
static inline bool vgic_irq_is_multi_sgi(struct vgic_irq *irq)
123+
{
124+
return vgic_irq_get_lr_count(irq) > 1;
125+
}
126+
113127
/*
114128
* This struct provides an intermediate representation of the fields contained
115129
* in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC

0 commit comments

Comments
 (0)