From a0555e36fc44ea98edf7c50924de8b973cd4267d Mon Sep 17 00:00:00 2001 From: Zenghui Yu Date: Wed, 30 Jul 2025 00:16:49 +0800 Subject: hw/intc/arm_gicv3_kvm: Remove writes to ICPENDR registers As per the arm-vgic-v3 kernel doc [1]: Accesses to GICD_ICPENDR register region and GICR_ICPENDR0 registers have RAZ/WI semantics, meaning that reads always return 0 and writes are always ignored. The state behind these registers (both 0 and 1 bits) is written by writing to the GICD_ISPENDR and GICR_ISPENDR0 registers, unlike some of the other set/clear register pairs. Remove the useless writes to ICPENDR registers in kvm_arm_gicv3_put(). [1] https://docs.kernel.org/virt/kvm/devices/arm-vgic-v3.html Signed-off-by: Zenghui Yu Message-id: 20250729161650.43758-2-zenghui.yu@linux.dev Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/intc/arm_gicv3_kvm.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'hw/intc') diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c index 8ed88e7..f798a6e 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c @@ -387,8 +387,6 @@ static void kvm_arm_gicv3_put(GICv3State *s) reg = c->level; kvm_gic_line_level_access(s, 0, ncpu, ®, true); - reg = ~0; - kvm_gicr_access(s, GICR_ICPENDR0, ncpu, ®, true); reg = c->gicr_ipendr0; kvm_gicr_access(s, GICR_ISPENDR0, ncpu, ®, true); @@ -445,7 +443,7 @@ static void kvm_arm_gicv3_put(GICv3State *s) kvm_gic_put_line_level_bmp(s, s->level); /* s->pending bitmap -> GICD_ISPENDRn */ - kvm_dist_putbmp(s, GICD_ISPENDR, GICD_ICPENDR, s->pending); + kvm_dist_putbmp(s, GICD_ISPENDR, 0, s->pending); /* s->active bitmap -> GICD_ISACTIVERn */ kvm_dist_putbmp(s, GICD_ISACTIVER, GICD_ICACTIVER, s->active); -- cgit v1.1 From b10bd4bd17ac8628ede8735a08ad82dc3b721c64 Mon Sep 17 00:00:00 2001 From: Zenghui Yu Date: Wed, 30 Jul 2025 00:16:50 +0800 Subject: hw/intc/arm_gicv3_kvm: Write all 1's to clear enable/active KVM's userspace access interface to the GICD enable and active bits is via set/clear register pairs which implement the hardware's "write 1s to the clear register to clear the 0 bits, and write 1s to the set register to set the 1 bits" semantics. We didn't get this right, because we were writing 0 to the clear register. Writing 0 to GICD_IC{ENABLE,ACTIVE}R architecturally has no effect on interrupt status (all writes are simply ignored by KVM) and doesn't comply with the intention of "first write to the clear-reg to clear all bits". Write all 1's to actually clear the enable/active status. This didn't have any adverse effects on migration because there we start with a clean VM state; it would be guest-visible when doing a system reset, but since Linux always cleans up the register state of the GIC during bootup before it enables it most users won't have run into a problem here. Cc: qemu-stable@nongnu.org Fixes: 367b9f527bec ("hw/intc/arm_gicv3_kvm: Implement get/put functions") Signed-off-by: Zenghui Yu Message-id: 20250729161650.43758-3-zenghui.yu@linux.dev Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell --- hw/intc/arm_gicv3_kvm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'hw/intc') diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c index f798a6e..6166283 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c @@ -295,7 +295,7 @@ static void kvm_dist_putbmp(GICv3State *s, uint32_t offset, * the 1 bits. */ if (clroffset != 0) { - reg = 0; + reg = ~0; kvm_gicd_access(s, clroffset, ®, true); clroffset += 4; } -- cgit v1.1