Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: arm64: Don't read a HW interrupt pending state in user context

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 <eric.auger@redhat.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Tested-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Fixes: 5bfa685e62e9 ("KVM: arm64: vgic: Read HW interrupt pending state from the HW")
Link: https://lore.kernel.org/r/20220607131427.1164881-2-maz@kernel.org
Cc: stable@vger.kernel.org

+21 -5
+2 -2
arch/arm64/kvm/vgic/vgic-mmio-v2.c
··· 429 429 VGIC_ACCESS_32bit), 430 430 REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET, 431 431 vgic_mmio_read_pending, vgic_mmio_write_spending, 432 - NULL, vgic_uaccess_write_spending, 1, 432 + vgic_uaccess_read_pending, vgic_uaccess_write_spending, 1, 433 433 VGIC_ACCESS_32bit), 434 434 REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR, 435 435 vgic_mmio_read_pending, vgic_mmio_write_cpending, 436 - NULL, vgic_uaccess_write_cpending, 1, 436 + vgic_uaccess_read_pending, vgic_uaccess_write_cpending, 1, 437 437 VGIC_ACCESS_32bit), 438 438 REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET, 439 439 vgic_mmio_read_active, vgic_mmio_write_sactive,
+16 -3
arch/arm64/kvm/vgic/vgic-mmio.c
··· 226 226 return 0; 227 227 } 228 228 229 - unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, 230 - gpa_t addr, unsigned int len) 229 + static unsigned long __read_pending(struct kvm_vcpu *vcpu, 230 + gpa_t addr, unsigned int len, 231 + bool is_user) 231 232 { 232 233 u32 intid = VGIC_ADDR_TO_INTID(addr, 1); 233 234 u32 value = 0; ··· 249 248 IRQCHIP_STATE_PENDING, 250 249 &val); 251 250 WARN_RATELIMIT(err, "IRQ %d", irq->host_irq); 252 - } else if (vgic_irq_is_mapped_level(irq)) { 251 + } else if (!is_user && vgic_irq_is_mapped_level(irq)) { 253 252 val = vgic_get_phys_line_level(irq); 254 253 } else { 255 254 val = irq_is_pending(irq); ··· 262 261 } 263 262 264 263 return value; 264 + } 265 + 266 + unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, 267 + gpa_t addr, unsigned int len) 268 + { 269 + return __read_pending(vcpu, addr, len, false); 270 + } 271 + 272 + unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu, 273 + gpa_t addr, unsigned int len) 274 + { 275 + return __read_pending(vcpu, addr, len, true); 265 276 } 266 277 267 278 static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
+3
arch/arm64/kvm/vgic/vgic-mmio.h
··· 149 149 unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, 150 150 gpa_t addr, unsigned int len); 151 151 152 + unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu, 153 + gpa_t addr, unsigned int len); 154 + 152 155 void vgic_mmio_write_spending(struct kvm_vcpu *vcpu, 153 156 gpa_t addr, unsigned int len, 154 157 unsigned long val);