* [PATCH 0/3] KVM: arm64: Fix userspace access to HW pending state
@ 2022-06-02 8:30 Marc Zyngier
2022-06-02 8:30 ` [PATCH 1/3] KVM: arm64: Don't read a HW interrupt pending state in user context Marc Zyngier
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Marc Zyngier @ 2022-06-02 8:30 UTC (permalink / raw)
To: kvmarm, linux-arm-kernel, kvm
Cc: Eric Auger, Ricardo Koller, James Morse, Suzuki K Poulose,
Alexandru Elisei, Oliver Upton, kernel-team
Eric reported that a Seattle system was pretty unhappy about VM
migration, and the trace pointed to a glaring bug in the way the GICv2
emulation code reported the interrupt pending state to userspace for
HW interrupts, specially if the interrupt state is per-CPU, as this is
the case for the timer...
Fixing this actually results in a minor cleanup, followed by a bit of
extra hardening so that we can catch further issues in this area
without completely taking the system down.
Unless someone screams, I plan to take these in as fixes as quickly as
possible, with the first patch being an obvious stable candidate. I'd
appreciate it if people could verify that VM migration still works
correctly for both GICv2 and GICv3.
Thanks,
M.
Marc Zyngier (3):
KVM: arm64: Don't read a HW interrupt pending state in user context
KVM: arm64: Replace vgic_v3_uaccess_read_pending with
vgic_uaccess_read_pending
KVM: arm64: Warn if accessing timer pending state outside of vcpu
context
arch/arm64/kvm/arch_timer.c | 3 +++
arch/arm64/kvm/vgic/vgic-mmio-v2.c | 4 +--
arch/arm64/kvm/vgic/vgic-mmio-v3.c | 40 ++----------------------------
arch/arm64/kvm/vgic/vgic-mmio.c | 19 +++++++++++---
arch/arm64/kvm/vgic/vgic-mmio.h | 3 +++
5 files changed, 26 insertions(+), 43 deletions(-)
--
2.34.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH 1/3] KVM: arm64: Don't read a HW interrupt pending state in user context 2022-06-02 8:30 [PATCH 0/3] KVM: arm64: Fix userspace access to HW pending state Marc Zyngier @ 2022-06-02 8:30 ` Marc Zyngier 2022-06-02 19:40 ` Eric Auger 2022-06-02 20:08 ` Eric Auger 2022-06-02 8:30 ` [PATCH 2/3] KVM: arm64: Replace vgic_v3_uaccess_read_pending with vgic_uaccess_read_pending Marc Zyngier 2022-06-02 8:30 ` [PATCH 3/3] KVM: arm64: Warn if accessing timer pending state outside of vcpu context Marc Zyngier 2 siblings, 2 replies; 9+ messages in thread From: Marc Zyngier @ 2022-06-02 8:30 UTC (permalink / raw) To: kvmarm, linux-arm-kernel, kvm Cc: Eric Auger, Ricardo Koller, James Morse, Suzuki K Poulose, Alexandru Elisei, Oliver Upton, kernel-team Since 5bfa685e62e9 ("KVM: arm64: vgic: Read HW interrupt pending state from the HW"), we're able to source the pending bit for an interrupt that is stored either on the physical distributor or on a device. However, this state is only available when the vcpu is loaded, and is not intended to be accessed from userspace. Unfortunately, the GICv2 emulation doesn't provide specific userspace accessors, and we fallback with the ones that are intended for the guest, with fatal consequences. Add a new vgic_uaccess_read_pending() accessor for userspace to use, build on top of the existing vgic_mmio_read_pending(). Reported-by: Eric Auger <eauger@redhat.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Fixes: 5bfa685e62e9 ("KVM: arm64: vgic: Read HW interrupt pending state from the HW") --- arch/arm64/kvm/vgic/vgic-mmio-v2.c | 4 ++-- arch/arm64/kvm/vgic/vgic-mmio.c | 19 ++++++++++++++++--- arch/arm64/kvm/vgic/vgic-mmio.h | 3 +++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v2.c b/arch/arm64/kvm/vgic/vgic-mmio-v2.c index 77a67e9d3d14..e070cda86e12 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v2.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v2.c @@ -429,11 +429,11 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = { VGIC_ACCESS_32bit), REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET, vgic_mmio_read_pending, vgic_mmio_write_spending, - NULL, vgic_uaccess_write_spending, 1, + vgic_uaccess_read_pending, vgic_uaccess_write_spending, 1, VGIC_ACCESS_32bit), REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR, vgic_mmio_read_pending, vgic_mmio_write_cpending, - NULL, vgic_uaccess_write_cpending, 1, + vgic_uaccess_read_pending, vgic_uaccess_write_cpending, 1, VGIC_ACCESS_32bit), REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET, vgic_mmio_read_active, vgic_mmio_write_sactive, diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c index 49837d3a3ef5..dc8c52487e47 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio.c +++ b/arch/arm64/kvm/vgic/vgic-mmio.c @@ -226,8 +226,9 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu, return 0; } -unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, - gpa_t addr, unsigned int len) +static unsigned long __read_pending(struct kvm_vcpu *vcpu, + gpa_t addr, unsigned int len, + bool is_user) { u32 intid = VGIC_ADDR_TO_INTID(addr, 1); u32 value = 0; @@ -248,7 +249,7 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, IRQCHIP_STATE_PENDING, &val); WARN_RATELIMIT(err, "IRQ %d", irq->host_irq); - } else if (vgic_irq_is_mapped_level(irq)) { + } else if (!is_user && vgic_irq_is_mapped_level(irq)) { val = vgic_get_phys_line_level(irq); } else { val = irq_is_pending(irq); @@ -263,6 +264,18 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, return value; } +unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, + gpa_t addr, unsigned int len) +{ + return __read_pending(vcpu, addr, len, false); +} + +unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu, + gpa_t addr, unsigned int len) +{ + return __read_pending(vcpu, addr, len, true); +} + static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq) { return (vgic_irq_is_sgi(irq->intid) && diff --git a/arch/arm64/kvm/vgic/vgic-mmio.h b/arch/arm64/kvm/vgic/vgic-mmio.h index 3fa696f198a3..6082d4b66d39 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio.h +++ b/arch/arm64/kvm/vgic/vgic-mmio.h @@ -149,6 +149,9 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu, unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len); +unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu, + gpa_t addr, unsigned int len); + void vgic_mmio_write_spending(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len, unsigned long val); -- 2.34.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] KVM: arm64: Don't read a HW interrupt pending state in user context 2022-06-02 8:30 ` [PATCH 1/3] KVM: arm64: Don't read a HW interrupt pending state in user context Marc Zyngier @ 2022-06-02 19:40 ` Eric Auger 2022-06-02 20:08 ` Eric Auger 1 sibling, 0 replies; 9+ messages in thread From: Eric Auger @ 2022-06-02 19:40 UTC (permalink / raw) To: Marc Zyngier, kvmarm, linux-arm-kernel, kvm Cc: Ricardo Koller, James Morse, Suzuki K Poulose, Alexandru Elisei, Oliver Upton, kernel-team On 6/2/22 10:30, Marc Zyngier wrote: > Since 5bfa685e62e9 ("KVM: arm64: vgic: Read HW interrupt pending state > from the HW"), we're able to source the pending bit for an interrupt > that is stored either on the physical distributor or on a device. > > However, this state is only available when the vcpu is loaded, > and is not intended to be accessed from userspace. Unfortunately, > the GICv2 emulation doesn't provide specific userspace accessors, > and we fallback with the ones that are intended for the guest, > with fatal consequences. > > Add a new vgic_uaccess_read_pending() accessor for userspace > to use, build on top of the existing vgic_mmio_read_pending(). > > Reported-by: Eric Auger <eauger@redhat.com> > Signed-off-by: Marc Zyngier <maz@kernel.org> > Fixes: 5bfa685e62e9 ("KVM: arm64: vgic: Read HW interrupt pending state from the HW") Reviewed-by: Eric Auger <eric.auger@redhat.com> Eric > --- > arch/arm64/kvm/vgic/vgic-mmio-v2.c | 4 ++-- > arch/arm64/kvm/vgic/vgic-mmio.c | 19 ++++++++++++++++--- > arch/arm64/kvm/vgic/vgic-mmio.h | 3 +++ > 3 files changed, 21 insertions(+), 5 deletions(-) > > diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v2.c b/arch/arm64/kvm/vgic/vgic-mmio-v2.c > index 77a67e9d3d14..e070cda86e12 100644 > --- a/arch/arm64/kvm/vgic/vgic-mmio-v2.c > +++ b/arch/arm64/kvm/vgic/vgic-mmio-v2.c > @@ -429,11 +429,11 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = { > VGIC_ACCESS_32bit), > REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET, > vgic_mmio_read_pending, vgic_mmio_write_spending, > - NULL, vgic_uaccess_write_spending, 1, > + vgic_uaccess_read_pending, vgic_uaccess_write_spending, 1, > VGIC_ACCESS_32bit), > REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR, > vgic_mmio_read_pending, vgic_mmio_write_cpending, > - NULL, vgic_uaccess_write_cpending, 1, > + vgic_uaccess_read_pending, vgic_uaccess_write_cpending, 1, > VGIC_ACCESS_32bit), > REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET, > vgic_mmio_read_active, vgic_mmio_write_sactive, > diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c > index 49837d3a3ef5..dc8c52487e47 100644 > --- a/arch/arm64/kvm/vgic/vgic-mmio.c > +++ b/arch/arm64/kvm/vgic/vgic-mmio.c > @@ -226,8 +226,9 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu, > return 0; > } > > -unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, > - gpa_t addr, unsigned int len) > +static unsigned long __read_pending(struct kvm_vcpu *vcpu, > + gpa_t addr, unsigned int len, > + bool is_user) > { > u32 intid = VGIC_ADDR_TO_INTID(addr, 1); > u32 value = 0; > @@ -248,7 +249,7 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, > IRQCHIP_STATE_PENDING, > &val); > WARN_RATELIMIT(err, "IRQ %d", irq->host_irq); > - } else if (vgic_irq_is_mapped_level(irq)) { > + } else if (!is_user && vgic_irq_is_mapped_level(irq)) { > val = vgic_get_phys_line_level(irq); > } else { > val = irq_is_pending(irq); > @@ -263,6 +264,18 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, > return value; > } > > +unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, > + gpa_t addr, unsigned int len) > +{ > + return __read_pending(vcpu, addr, len, false); > +} > + > +unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu, > + gpa_t addr, unsigned int len) > +{ > + return __read_pending(vcpu, addr, len, true); > +} > + > static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq) > { > return (vgic_irq_is_sgi(irq->intid) && > diff --git a/arch/arm64/kvm/vgic/vgic-mmio.h b/arch/arm64/kvm/vgic/vgic-mmio.h > index 3fa696f198a3..6082d4b66d39 100644 > --- a/arch/arm64/kvm/vgic/vgic-mmio.h > +++ b/arch/arm64/kvm/vgic/vgic-mmio.h > @@ -149,6 +149,9 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu, > unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, > gpa_t addr, unsigned int len); > > +unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu, > + gpa_t addr, unsigned int len); > + > void vgic_mmio_write_spending(struct kvm_vcpu *vcpu, > gpa_t addr, unsigned int len, > unsigned long val); _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 1/3] KVM: arm64: Don't read a HW interrupt pending state in user context 2022-06-02 8:30 ` [PATCH 1/3] KVM: arm64: Don't read a HW interrupt pending state in user context Marc Zyngier 2022-06-02 19:40 ` Eric Auger @ 2022-06-02 20:08 ` Eric Auger 1 sibling, 0 replies; 9+ messages in thread From: Eric Auger @ 2022-06-02 20:08 UTC (permalink / raw) To: Marc Zyngier, kvmarm, linux-arm-kernel, kvm Cc: Ricardo Koller, James Morse, Suzuki K Poulose, Alexandru Elisei, Oliver Upton, kernel-team Marc, On 6/2/22 10:30, Marc Zyngier wrote: > Since 5bfa685e62e9 ("KVM: arm64: vgic: Read HW interrupt pending state > from the HW"), we're able to source the pending bit for an interrupt > that is stored either on the physical distributor or on a device. > > However, this state is only available when the vcpu is loaded, > and is not intended to be accessed from userspace. Unfortunately, > the GICv2 emulation doesn't provide specific userspace accessors, > and we fallback with the ones that are intended for the guest, > with fatal consequences. > > Add a new vgic_uaccess_read_pending() accessor for userspace > to use, build on top of the existing vgic_mmio_read_pending(). > > Reported-by: Eric Auger <eauger@redhat.com> > Signed-off-by: Marc Zyngier <maz@kernel.org> > Fixes: 5bfa685e62e9 ("KVM: arm64: vgic: Read HW interrupt pending state from the HW") Feel free to add my Tested-by: Eric Auger <eric.auger@redhat.com> Thanks! Eric > --- > arch/arm64/kvm/vgic/vgic-mmio-v2.c | 4 ++-- > arch/arm64/kvm/vgic/vgic-mmio.c | 19 ++++++++++++++++--- > arch/arm64/kvm/vgic/vgic-mmio.h | 3 +++ > 3 files changed, 21 insertions(+), 5 deletions(-) > > diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v2.c b/arch/arm64/kvm/vgic/vgic-mmio-v2.c > index 77a67e9d3d14..e070cda86e12 100644 > --- a/arch/arm64/kvm/vgic/vgic-mmio-v2.c > +++ b/arch/arm64/kvm/vgic/vgic-mmio-v2.c > @@ -429,11 +429,11 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = { > VGIC_ACCESS_32bit), > REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET, > vgic_mmio_read_pending, vgic_mmio_write_spending, > - NULL, vgic_uaccess_write_spending, 1, > + vgic_uaccess_read_pending, vgic_uaccess_write_spending, 1, > VGIC_ACCESS_32bit), > REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR, > vgic_mmio_read_pending, vgic_mmio_write_cpending, > - NULL, vgic_uaccess_write_cpending, 1, > + vgic_uaccess_read_pending, vgic_uaccess_write_cpending, 1, > VGIC_ACCESS_32bit), > REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET, > vgic_mmio_read_active, vgic_mmio_write_sactive, > diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c > index 49837d3a3ef5..dc8c52487e47 100644 > --- a/arch/arm64/kvm/vgic/vgic-mmio.c > +++ b/arch/arm64/kvm/vgic/vgic-mmio.c > @@ -226,8 +226,9 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu, > return 0; > } > > -unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, > - gpa_t addr, unsigned int len) > +static unsigned long __read_pending(struct kvm_vcpu *vcpu, > + gpa_t addr, unsigned int len, > + bool is_user) > { > u32 intid = VGIC_ADDR_TO_INTID(addr, 1); > u32 value = 0; > @@ -248,7 +249,7 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, > IRQCHIP_STATE_PENDING, > &val); > WARN_RATELIMIT(err, "IRQ %d", irq->host_irq); > - } else if (vgic_irq_is_mapped_level(irq)) { > + } else if (!is_user && vgic_irq_is_mapped_level(irq)) { > val = vgic_get_phys_line_level(irq); > } else { > val = irq_is_pending(irq); > @@ -263,6 +264,18 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, > return value; > } > > +unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, > + gpa_t addr, unsigned int len) > +{ > + return __read_pending(vcpu, addr, len, false); > +} > + > +unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu, > + gpa_t addr, unsigned int len) > +{ > + return __read_pending(vcpu, addr, len, true); > +} > + > static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq) > { > return (vgic_irq_is_sgi(irq->intid) && > diff --git a/arch/arm64/kvm/vgic/vgic-mmio.h b/arch/arm64/kvm/vgic/vgic-mmio.h > index 3fa696f198a3..6082d4b66d39 100644 > --- a/arch/arm64/kvm/vgic/vgic-mmio.h > +++ b/arch/arm64/kvm/vgic/vgic-mmio.h > @@ -149,6 +149,9 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu, > unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, > gpa_t addr, unsigned int len); > > +unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu, > + gpa_t addr, unsigned int len); > + > void vgic_mmio_write_spending(struct kvm_vcpu *vcpu, > gpa_t addr, unsigned int len, > unsigned long val); _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/3] KVM: arm64: Replace vgic_v3_uaccess_read_pending with vgic_uaccess_read_pending 2022-06-02 8:30 [PATCH 0/3] KVM: arm64: Fix userspace access to HW pending state Marc Zyngier 2022-06-02 8:30 ` [PATCH 1/3] KVM: arm64: Don't read a HW interrupt pending state in user context Marc Zyngier @ 2022-06-02 8:30 ` Marc Zyngier 2022-06-02 20:06 ` Eric Auger 2022-06-02 8:30 ` [PATCH 3/3] KVM: arm64: Warn if accessing timer pending state outside of vcpu context Marc Zyngier 2 siblings, 1 reply; 9+ messages in thread From: Marc Zyngier @ 2022-06-02 8:30 UTC (permalink / raw) To: kvmarm, linux-arm-kernel, kvm Cc: Eric Auger, Ricardo Koller, James Morse, Suzuki K Poulose, Alexandru Elisei, Oliver Upton, kernel-team Now that GICv2 has a proper userspace accessor for the pending state, switch GICv3 over to it, dropping the local version. Signed-off-by: Marc Zyngier <maz@kernel.org> --- arch/arm64/kvm/vgic/vgic-mmio-v3.c | 40 ++---------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c index f7aa7bcd6fb8..f15e29cc63ce 100644 --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c @@ -353,42 +353,6 @@ static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu, return 0; } -static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu, - gpa_t addr, unsigned int len) -{ - u32 intid = VGIC_ADDR_TO_INTID(addr, 1); - u32 value = 0; - int i; - - /* - * pending state of interrupt is latched in pending_latch variable. - * Userspace will save and restore pending state and line_level - * separately. - * Refer to Documentation/virt/kvm/devices/arm-vgic-v3.rst - * for handling of ISPENDR and ICPENDR. - */ - for (i = 0; i < len * 8; i++) { - struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); - bool state = irq->pending_latch; - - if (irq->hw && vgic_irq_is_sgi(irq->intid)) { - int err; - - err = irq_get_irqchip_state(irq->host_irq, - IRQCHIP_STATE_PENDING, - &state); - WARN_ON(err); - } - - if (state) - value |= (1U << i); - - vgic_put_irq(vcpu->kvm, irq); - } - - return value; -} - static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len, unsigned long val) @@ -666,7 +630,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = { VGIC_ACCESS_32bit), REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR, vgic_mmio_read_pending, vgic_mmio_write_spending, - vgic_v3_uaccess_read_pending, vgic_v3_uaccess_write_pending, 1, + vgic_uaccess_read_pending, vgic_v3_uaccess_write_pending, 1, VGIC_ACCESS_32bit), REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR, vgic_mmio_read_pending, vgic_mmio_write_cpending, @@ -750,7 +714,7 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = { VGIC_ACCESS_32bit), REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISPENDR0, vgic_mmio_read_pending, vgic_mmio_write_spending, - vgic_v3_uaccess_read_pending, vgic_v3_uaccess_write_pending, 4, + vgic_uaccess_read_pending, vgic_v3_uaccess_write_pending, 4, VGIC_ACCESS_32bit), REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ICPENDR0, vgic_mmio_read_pending, vgic_mmio_write_cpending, -- 2.34.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 2/3] KVM: arm64: Replace vgic_v3_uaccess_read_pending with vgic_uaccess_read_pending 2022-06-02 8:30 ` [PATCH 2/3] KVM: arm64: Replace vgic_v3_uaccess_read_pending with vgic_uaccess_read_pending Marc Zyngier @ 2022-06-02 20:06 ` Eric Auger 2022-06-07 11:10 ` Marc Zyngier 0 siblings, 1 reply; 9+ messages in thread From: Eric Auger @ 2022-06-02 20:06 UTC (permalink / raw) To: Marc Zyngier, kvmarm, linux-arm-kernel, kvm Cc: Ricardo Koller, James Morse, Suzuki K Poulose, Alexandru Elisei, Oliver Upton, kernel-team Hi Marc, On 6/2/22 10:30, Marc Zyngier wrote: > Now that GICv2 has a proper userspace accessor for the pending state, > switch GICv3 over to it, dropping the local version. > > Signed-off-by: Marc Zyngier <maz@kernel.org> > --- > arch/arm64/kvm/vgic/vgic-mmio-v3.c | 40 ++---------------------------- > 1 file changed, 2 insertions(+), 38 deletions(-) > > diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c > index f7aa7bcd6fb8..f15e29cc63ce 100644 > --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c > +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c > @@ -353,42 +353,6 @@ static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu, > return 0; > } > > -static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu, > - gpa_t addr, unsigned int len) > -{ > - u32 intid = VGIC_ADDR_TO_INTID(addr, 1); > - u32 value = 0; > - int i; > - > - /* > - * pending state of interrupt is latched in pending_latch variable. > - * Userspace will save and restore pending state and line_level > - * separately. > - * Refer to Documentation/virt/kvm/devices/arm-vgic-v3.rst > - * for handling of ISPENDR and ICPENDR. Don't know if you want a derivative of this comment in vgic_uaccess_read_pending()? > - */ > - for (i = 0; i < len * 8; i++) { > - struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); > - bool state = irq->pending_latch; > - > - if (irq->hw && vgic_irq_is_sgi(irq->intid)) { > - int err; > - in __read_pending(), irq->irq_lock is hold which looks safer at 1st sight. If potentially fixing something this can be documented in the commit msg. > - err = irq_get_irqchip_state(irq->host_irq, > - IRQCHIP_STATE_PENDING, > - &state); > - WARN_ON(err); > - } > - in __read_pending(), irq_is_pending(irq) is used instead of irq->pending_latch. for level sensitive IRQ this is not identical. This may also deserve some comment. The nuance may be related to the above comment. Thanks Eric > - if (state) > - value |= (1U << i); > - > - vgic_put_irq(vcpu->kvm, irq); > - } > - > - return value; > -} > - > static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu, > gpa_t addr, unsigned int len, > unsigned long val) > @@ -666,7 +630,7 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = { > VGIC_ACCESS_32bit), > REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ISPENDR, > vgic_mmio_read_pending, vgic_mmio_write_spending, > - vgic_v3_uaccess_read_pending, vgic_v3_uaccess_write_pending, 1, > + vgic_uaccess_read_pending, vgic_v3_uaccess_write_pending, 1, > VGIC_ACCESS_32bit), > REGISTER_DESC_WITH_BITS_PER_IRQ_SHARED(GICD_ICPENDR, > vgic_mmio_read_pending, vgic_mmio_write_cpending, > @@ -750,7 +714,7 @@ static const struct vgic_register_region vgic_v3_rd_registers[] = { > VGIC_ACCESS_32bit), > REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISPENDR0, > vgic_mmio_read_pending, vgic_mmio_write_spending, > - vgic_v3_uaccess_read_pending, vgic_v3_uaccess_write_pending, 4, > + vgic_uaccess_read_pending, vgic_v3_uaccess_write_pending, 4, > VGIC_ACCESS_32bit), > REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ICPENDR0, > vgic_mmio_read_pending, vgic_mmio_write_cpending, _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 2/3] KVM: arm64: Replace vgic_v3_uaccess_read_pending with vgic_uaccess_read_pending 2022-06-02 20:06 ` Eric Auger @ 2022-06-07 11:10 ` Marc Zyngier 0 siblings, 0 replies; 9+ messages in thread From: Marc Zyngier @ 2022-06-07 11:10 UTC (permalink / raw) To: Eric Auger Cc: kvmarm, linux-arm-kernel, kvm, Ricardo Koller, James Morse, Suzuki K Poulose, Alexandru Elisei, Oliver Upton, kernel-team On Thu, 02 Jun 2022 21:06:42 +0100, Eric Auger <eauger@redhat.com> wrote: > > Hi Marc, > On 6/2/22 10:30, Marc Zyngier wrote: > > Now that GICv2 has a proper userspace accessor for the pending state, > > switch GICv3 over to it, dropping the local version. > > > > Signed-off-by: Marc Zyngier <maz@kernel.org> > > --- > > arch/arm64/kvm/vgic/vgic-mmio-v3.c | 40 ++---------------------------- > > 1 file changed, 2 insertions(+), 38 deletions(-) > > > > diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c > > index f7aa7bcd6fb8..f15e29cc63ce 100644 > > --- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c > > +++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c > > @@ -353,42 +353,6 @@ static unsigned long vgic_mmio_read_v3_idregs(struct kvm_vcpu *vcpu, > > return 0; > > } > > > > -static unsigned long vgic_v3_uaccess_read_pending(struct kvm_vcpu *vcpu, > > - gpa_t addr, unsigned int len) > > -{ > > - u32 intid = VGIC_ADDR_TO_INTID(addr, 1); > > - u32 value = 0; > > - int i; > > > - > > - /* > > - * pending state of interrupt is latched in pending_latch variable. > > - * Userspace will save and restore pending state and line_level > > - * separately. > > - * Refer to Documentation/virt/kvm/devices/arm-vgic-v3.rst > > - * for handling of ISPENDR and ICPENDR. > Don't know if you want a derivative of this comment in > vgic_uaccess_read_pending()? I don't find it specially helpful, but at the same time, it doesn't hurt to move it around. > > - */ > > - for (i = 0; i < len * 8; i++) { > > - struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i); > > - bool state = irq->pending_latch; > > - > > - if (irq->hw && vgic_irq_is_sgi(irq->intid)) { > > - int err; > > - > in __read_pending(), irq->irq_lock is hold which looks safer at 1st > sight. If potentially fixing something this can be documented in the > commit msg. I don't think it fixes anything. The idea is that if you are accessing the state from userspace, you already have stopped the VM, and thus there is no concurrent modifications if the state. > > - err = irq_get_irqchip_state(irq->host_irq, > > - IRQCHIP_STATE_PENDING, > > - &state); > > - WARN_ON(err); > > - } > > - > in __read_pending(), irq_is_pending(irq) is used instead of > irq->pending_latch. for level sensitive IRQ this is not identical. This > may also deserve some comment. The nuance may be related to the above > comment. That is a good point, and we should unify the userspace behaviours between GICv2 and v3. I'll respin the series shortly. Thanks, M. -- Without deviation from the norm, progress is not possible. _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/3] KVM: arm64: Warn if accessing timer pending state outside of vcpu context 2022-06-02 8:30 [PATCH 0/3] KVM: arm64: Fix userspace access to HW pending state Marc Zyngier 2022-06-02 8:30 ` [PATCH 1/3] KVM: arm64: Don't read a HW interrupt pending state in user context Marc Zyngier 2022-06-02 8:30 ` [PATCH 2/3] KVM: arm64: Replace vgic_v3_uaccess_read_pending with vgic_uaccess_read_pending Marc Zyngier @ 2022-06-02 8:30 ` Marc Zyngier 2022-06-02 19:39 ` Eric Auger 2 siblings, 1 reply; 9+ messages in thread From: Marc Zyngier @ 2022-06-02 8:30 UTC (permalink / raw) To: kvmarm, linux-arm-kernel, kvm Cc: Eric Auger, Ricardo Koller, James Morse, Suzuki K Poulose, Alexandru Elisei, Oliver Upton, kernel-team A recurrent bug in the KVM/arm64 code base consists in trying to access the timer pending state outside of the vcpu context, which makes zero sense (the pending state only exists when the vcpu is loaded). In order to avoid more embarassing crashes and catch the offenders red-handed, add a warning to kvm_arch_timer_get_input_level() and return the state as non-pending. This avoids taking the system down, and still helps tracking down silly bugs. Signed-off-by: Marc Zyngier <maz@kernel.org> --- arch/arm64/kvm/arch_timer.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c index 5290ca5db663..bb24a76b4224 100644 --- a/arch/arm64/kvm/arch_timer.c +++ b/arch/arm64/kvm/arch_timer.c @@ -1230,6 +1230,9 @@ bool kvm_arch_timer_get_input_level(int vintid) struct kvm_vcpu *vcpu = kvm_get_running_vcpu(); struct arch_timer_context *timer; + if (WARN(!vcpu, "No vcpu context!\n")) + return false; + if (vintid == vcpu_vtimer(vcpu)->irq.irq) timer = vcpu_vtimer(vcpu); else if (vintid == vcpu_ptimer(vcpu)->irq.irq) -- 2.34.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH 3/3] KVM: arm64: Warn if accessing timer pending state outside of vcpu context 2022-06-02 8:30 ` [PATCH 3/3] KVM: arm64: Warn if accessing timer pending state outside of vcpu context Marc Zyngier @ 2022-06-02 19:39 ` Eric Auger 0 siblings, 0 replies; 9+ messages in thread From: Eric Auger @ 2022-06-02 19:39 UTC (permalink / raw) To: Marc Zyngier, kvmarm, linux-arm-kernel, kvm Cc: Ricardo Koller, James Morse, Suzuki K Poulose, Alexandru Elisei, Oliver Upton, kernel-team Hi Marc, On 6/2/22 10:30, Marc Zyngier wrote: > A recurrent bug in the KVM/arm64 code base consists in trying to > access the timer pending state outside of the vcpu context, which > makes zero sense (the pending state only exists when the vcpu > is loaded). > > In order to avoid more embarassing crashes and catch the offenders > red-handed, add a warning to kvm_arch_timer_get_input_level() and > return the state as non-pending. This avoids taking the system down, > and still helps tracking down silly bugs. > > Signed-off-by: Marc Zyngier <maz@kernel.org> Reviewed-by: Eric Auger <eric.auger@redhat.com> Eric > --- > arch/arm64/kvm/arch_timer.c | 3 +++ > 1 file changed, 3 insertions(+) > > diff --git a/arch/arm64/kvm/arch_timer.c b/arch/arm64/kvm/arch_timer.c > index 5290ca5db663..bb24a76b4224 100644 > --- a/arch/arm64/kvm/arch_timer.c > +++ b/arch/arm64/kvm/arch_timer.c > @@ -1230,6 +1230,9 @@ bool kvm_arch_timer_get_input_level(int vintid) > struct kvm_vcpu *vcpu = kvm_get_running_vcpu(); > struct arch_timer_context *timer; > > + if (WARN(!vcpu, "No vcpu context!\n")) > + return false; > + > if (vintid == vcpu_vtimer(vcpu)->irq.irq) > timer = vcpu_vtimer(vcpu); > else if (vintid == vcpu_ptimer(vcpu)->irq.irq) _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2022-06-07 11:11 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-06-02 8:30 [PATCH 0/3] KVM: arm64: Fix userspace access to HW pending state Marc Zyngier 2022-06-02 8:30 ` [PATCH 1/3] KVM: arm64: Don't read a HW interrupt pending state in user context Marc Zyngier 2022-06-02 19:40 ` Eric Auger 2022-06-02 20:08 ` Eric Auger 2022-06-02 8:30 ` [PATCH 2/3] KVM: arm64: Replace vgic_v3_uaccess_read_pending with vgic_uaccess_read_pending Marc Zyngier 2022-06-02 20:06 ` Eric Auger 2022-06-07 11:10 ` Marc Zyngier 2022-06-02 8:30 ` [PATCH 3/3] KVM: arm64: Warn if accessing timer pending state outside of vcpu context Marc Zyngier 2022-06-02 19:39 ` Eric Auger
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).