Commit 9da48b55 authored by Christoffer Dall's avatar Christoffer Dall

arm/arm64: KVM: vgic: Fix SGI writes to GICD_I{CS}PENDR0

Writes to GICD_ISPENDR0 and GICD_ICPENDR0 ignore all settings of the
pending state for SGIs.  Make sure the implementation handles this
correctly.
Signed-off-by: default avatarChristoffer Dall <christoffer.dall@linaro.org>
parent faa1b46c
...@@ -454,7 +454,7 @@ static bool handle_mmio_set_pending_reg(struct kvm_vcpu *vcpu, ...@@ -454,7 +454,7 @@ static bool handle_mmio_set_pending_reg(struct kvm_vcpu *vcpu,
struct kvm_exit_mmio *mmio, struct kvm_exit_mmio *mmio,
phys_addr_t offset) phys_addr_t offset)
{ {
u32 *reg; u32 *reg, orig;
u32 level_mask; u32 level_mask;
struct vgic_dist *dist = &vcpu->kvm->arch.vgic; struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
...@@ -463,6 +463,7 @@ static bool handle_mmio_set_pending_reg(struct kvm_vcpu *vcpu, ...@@ -463,6 +463,7 @@ static bool handle_mmio_set_pending_reg(struct kvm_vcpu *vcpu,
/* Mark both level and edge triggered irqs as pending */ /* Mark both level and edge triggered irqs as pending */
reg = vgic_bitmap_get_reg(&dist->irq_pending, vcpu->vcpu_id, offset); reg = vgic_bitmap_get_reg(&dist->irq_pending, vcpu->vcpu_id, offset);
orig = *reg;
vgic_reg_access(mmio, reg, offset, vgic_reg_access(mmio, reg, offset,
ACCESS_READ_VALUE | ACCESS_WRITE_SETBIT); ACCESS_READ_VALUE | ACCESS_WRITE_SETBIT);
...@@ -474,6 +475,12 @@ static bool handle_mmio_set_pending_reg(struct kvm_vcpu *vcpu, ...@@ -474,6 +475,12 @@ static bool handle_mmio_set_pending_reg(struct kvm_vcpu *vcpu,
ACCESS_READ_VALUE | ACCESS_WRITE_SETBIT); ACCESS_READ_VALUE | ACCESS_WRITE_SETBIT);
*reg &= level_mask; *reg &= level_mask;
/* Ignore writes to SGIs */
if (offset < 2) {
*reg &= ~0xffff;
*reg |= orig & 0xffff;
}
vgic_update_state(vcpu->kvm); vgic_update_state(vcpu->kvm);
return true; return true;
} }
...@@ -486,10 +493,11 @@ static bool handle_mmio_clear_pending_reg(struct kvm_vcpu *vcpu, ...@@ -486,10 +493,11 @@ static bool handle_mmio_clear_pending_reg(struct kvm_vcpu *vcpu,
phys_addr_t offset) phys_addr_t offset)
{ {
u32 *level_active; u32 *level_active;
u32 *reg; u32 *reg, orig;
struct vgic_dist *dist = &vcpu->kvm->arch.vgic; struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
reg = vgic_bitmap_get_reg(&dist->irq_pending, vcpu->vcpu_id, offset); reg = vgic_bitmap_get_reg(&dist->irq_pending, vcpu->vcpu_id, offset);
orig = *reg;
vgic_reg_access(mmio, reg, offset, vgic_reg_access(mmio, reg, offset,
ACCESS_READ_VALUE | ACCESS_WRITE_CLEARBIT); ACCESS_READ_VALUE | ACCESS_WRITE_CLEARBIT);
if (mmio->is_write) { if (mmio->is_write) {
...@@ -500,6 +508,12 @@ static bool handle_mmio_clear_pending_reg(struct kvm_vcpu *vcpu, ...@@ -500,6 +508,12 @@ static bool handle_mmio_clear_pending_reg(struct kvm_vcpu *vcpu,
vcpu->vcpu_id, offset); vcpu->vcpu_id, offset);
*reg |= *level_active; *reg |= *level_active;
/* Ignore writes to SGIs */
if (offset < 2) {
*reg &= ~0xffff;
*reg |= orig & 0xffff;
}
/* Clear soft-pending flags */ /* Clear soft-pending flags */
reg = vgic_bitmap_get_reg(&dist->irq_soft_pend, reg = vgic_bitmap_get_reg(&dist->irq_soft_pend,
vcpu->vcpu_id, offset); vcpu->vcpu_id, offset);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment