From 986af8e0789a41ac4844e6eefed4a33e86524918 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 29 Aug 2013 11:08:22 +0100 Subject: ARM: KVM: vgic: simplify vgic_get_target_reg vgic_get_target_reg is quite complicated, for no good reason. Actually, it is fairly easy to write it in a much more efficient way by using the target CPU array instead of the bitmap. Signed-off-by: Marc Zyngier Signed-off-by: Gleb Natapov --- virt/kvm/arm/vgic.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'virt/kvm/arm/vgic.c') diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 17c5ac7d10ed..a2d478aec046 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c @@ -432,19 +432,13 @@ static bool handle_mmio_priority_reg(struct kvm_vcpu *vcpu, static u32 vgic_get_target_reg(struct kvm *kvm, int irq) { struct vgic_dist *dist = &kvm->arch.vgic; - struct kvm_vcpu *vcpu; - int i, c; - unsigned long *bmap; + int i; u32 val = 0; irq -= VGIC_NR_PRIVATE_IRQS; - kvm_for_each_vcpu(c, vcpu, kvm) { - bmap = vgic_bitmap_get_shared_map(&dist->irq_spi_target[c]); - for (i = 0; i < GICD_IRQS_PER_ITARGETSR; i++) - if (test_bit(irq + i, bmap)) - val |= 1 << (c + i * 8); - } + for (i = 0; i < GICD_IRQS_PER_ITARGETSR; i++) + val |= 1 << (dist->irq_spi_cpu[irq + i] + i * 8); return val; } -- cgit v1.2.3 From 6545eae3d7a1b6dc2edb8ede9107998aee1207ef Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Thu, 29 Aug 2013 11:08:23 +0100 Subject: ARM: KVM: vgic: fix GICD_ICFGRn access All the code in handle_mmio_cfg_reg() assumes the offset has been shifted right to accomodate for the 2:1 bit compression, but this is only done when getting the register address. Shift the offset early so the code works mostly unchanged. Reported-by: Zhaobo (Bob, ERC) Signed-off-by: Marc Zyngier Signed-off-by: Gleb Natapov --- virt/kvm/arm/vgic.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'virt/kvm/arm/vgic.c') diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index a2d478aec046..902789ff4abb 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c @@ -541,8 +541,12 @@ static bool handle_mmio_cfg_reg(struct kvm_vcpu *vcpu, struct kvm_exit_mmio *mmio, phys_addr_t offset) { u32 val; - u32 *reg = vgic_bitmap_get_reg(&vcpu->kvm->arch.vgic.irq_cfg, - vcpu->vcpu_id, offset >> 1); + u32 *reg; + + offset >>= 1; + reg = vgic_bitmap_get_reg(&vcpu->kvm->arch.vgic.irq_cfg, + vcpu->vcpu_id, offset); + if (offset & 2) val = *reg >> 16; else -- cgit v1.2.3 From 8d98915b6bda499e47d19166101d0bbcfd409c80 Mon Sep 17 00:00:00 2001 From: Christoffer Dall Date: Thu, 29 Aug 2013 11:08:24 +0100 Subject: ARM: KVM: Bugfix: vgic_bytemap_get_reg per cpu regs For bytemaps each IRQ field is 1 byte wide, so we pack 4 irq fields in one word and since there are 32 private (per cpu) irqs, we have 8 private u32 fields on the vgic_bytemap struct. We shift the offset from the base of the register group right by 2, giving us the word index instead of the field index. But then there are 8 private words, not 4, which is also why we subtract 8 words from the offset of the shared words. Signed-off-by: Christoffer Dall Signed-off-by: Marc Zyngier Signed-off-by: Gleb Natapov --- virt/kvm/arm/vgic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'virt/kvm/arm/vgic.c') diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 902789ff4abb..685fc72fc751 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c @@ -149,7 +149,7 @@ static u32 *vgic_bytemap_get_reg(struct vgic_bytemap *x, int cpuid, u32 offset) { offset >>= 2; BUG_ON(offset > (VGIC_NR_IRQS / 4)); - if (offset < 4) + if (offset < 8) return x->percpu[cpuid] + offset; else return x->shared + offset - 8; -- cgit v1.2.3