History

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().

Marc Zyngier committed 4 years ago

Commit 2cdea191 parent e3fe65e3 files · +21 −5Browse files

Unified · Split

3 files
  1. arch/arm64/kvm/vgic/vgic-mmio-v2.c +2 −2
  2. arch/arm64/kvm/vgic/vgic-mmio.c +16 −3
  3. arch/arm64/kvm/vgic/vgic-mmio.h +3 −0
arch/arm64/kvm/vgic/vgic-mmio-v2.c+2−2
@@ -429,11 +429,11 @@ static const struct vgic_register_region vgic_v2_dist_registers[] = { · 428 unmodified lines
429 VGIC_ACCESS_32bit),429 VGIC_ACCESS_32bit),
430 REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,430 REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_SET,
431 vgic_mmio_read_pending, vgic_mmio_write_spending,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 VGIC_ACCESS_32bit),433 VGIC_ACCESS_32bit),
434 REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,434 REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_PENDING_CLEAR,
435 vgic_mmio_read_pending, vgic_mmio_write_cpending,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 VGIC_ACCESS_32bit),437 VGIC_ACCESS_32bit),
438 REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,438 REGISTER_DESC_WITH_BITS_PER_IRQ(GIC_DIST_ACTIVE_SET,
439 vgic_mmio_read_active, vgic_mmio_write_sactive,439 vgic_mmio_read_active, vgic_mmio_write_sactive,
arch/arm64/kvm/vgic/vgic-mmio.c+16−3
@@ -226,8 +226,9 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu, · 225 unmodified lines
226 return 0;226 return 0;
227}227}
228 228
229unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,229static unsigned long __read_pending(struct kvm_vcpu *vcpu,
230 gpa_t addr, unsigned int len)230 gpa_t addr, unsigned int len,
231 bool is_user)
231{232{
232 u32 intid = VGIC_ADDR_TO_INTID(addr, 1);233 u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
233 u32 value = 0;234 u32 value = 0;
@@ -248,7 +249,7 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, · 14 unmodified lines
248 IRQCHIP_STATE_PENDING,249 IRQCHIP_STATE_PENDING,
249 &val);250 &val);
250 WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);251 WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
251 } else if (vgic_irq_is_mapped_level(irq)) {252 } else if (!is_user && vgic_irq_is_mapped_level(irq)) {
252 val = vgic_get_phys_line_level(irq);253 val = vgic_get_phys_line_level(irq);
253 } else {254 } else {
254 val = irq_is_pending(irq);255 val = irq_is_pending(irq);
@@ -263,6 +264,18 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu, · 8 unmodified lines
263 return value;264 return value;
264}265}
265 266
267unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
268 gpa_t addr, unsigned int len)
269{
270 return __read_pending(vcpu, addr, len, false);
271}
272
273unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu,
274 gpa_t addr, unsigned int len)
275{
276 return __read_pending(vcpu, addr, len, true);
277}
278
266static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq)279static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
267{280{
268 return (vgic_irq_is_sgi(irq->intid) &&281 return (vgic_irq_is_sgi(irq->intid) &&
arch/arm64/kvm/vgic/vgic-mmio.h+3−0
@@ -149,6 +149,9 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu, · 148 unmodified lines
149unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,149unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
150 gpa_t addr, unsigned int len);150 gpa_t addr, unsigned int len);
151 151
152unsigned long vgic_uaccess_read_pending(struct kvm_vcpu *vcpu,
153 gpa_t addr, unsigned int len);
154
152void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,155void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
153 gpa_t addr, unsigned int len,156 gpa_t addr, unsigned int len,
154 unsigned long val);157 unsigned long val);

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t