* [PATCH 0/3] KVM: arm64: Fix + cleanup for GICv3 ISPENDR
@ 2023-12-19 6:58 Oliver Upton
2023-12-19 6:58 ` [PATCH 1/3] KVM: arm64: vgic: Use common accessor for writes to ISPENDR Oliver Upton
` (3 more replies)
0 siblings, 4 replies; 5+ messages in thread
From: Oliver Upton @ 2023-12-19 6:58 UTC (permalink / raw)
To: kvmarm
Cc: kvm, Marc Zyngier, James Morse, Suzuki K Poulose, Zenghui Yu,
Kunkun Jiang, Oliver Upton
Here's the alternative approach I had suggested in response to Kunkun's
bug report, building the GICv3 ISPENDR accessor on top of the existing
ISPENDR / ICPENDR accessors. With these changes userspace should
consistently read / configure the hardware pending state for GICv4.1
vSGIs.
Oliver Upton (3):
KVM: arm64: vgic: Use common accessor for writes to ISPENDR
KVM: arm64: vgic: Use common accessor for writes to ICPENDR
KVM: arm64: vgic-v3: Reinterpret user ISPENDR writes as I{C,S}PENDR
arch/arm64/kvm/vgic/vgic-mmio-v3.c | 29 ++-------
arch/arm64/kvm/vgic/vgic-mmio.c | 101 ++++++++++++-----------------
2 files changed, 49 insertions(+), 81 deletions(-)
base-commit: 2cc14f52aeb78ce3f29677c2de1f06c0e91471ab
--
2.43.0.472.g3155946c3a-goog
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/3] KVM: arm64: vgic: Use common accessor for writes to ISPENDR
2023-12-19 6:58 [PATCH 0/3] KVM: arm64: Fix + cleanup for GICv3 ISPENDR Oliver Upton
@ 2023-12-19 6:58 ` Oliver Upton
2023-12-19 6:58 ` [PATCH 2/3] KVM: arm64: vgic: Use common accessor for writes to ICPENDR Oliver Upton
` (2 subsequent siblings)
3 siblings, 0 replies; 5+ messages in thread
From: Oliver Upton @ 2023-12-19 6:58 UTC (permalink / raw)
To: kvmarm
Cc: kvm, Marc Zyngier, James Morse, Suzuki K Poulose, Zenghui Yu,
Kunkun Jiang, Oliver Upton
Perhaps unsurprisingly, there is a considerable amount of duplicate
code between the MMIO and user accessors for ISPENDR. At the same
time there are some important differences between user and guest
MMIO, like how SGIs can only be made pending from userspace.
Fold user and MMIO accessors into a common helper, maintaining the
distinction between the two. User accesses can now mark SGIs as
pending in hardware for GICv4.1 vSGIs.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kvm/vgic/vgic-mmio.c | 50 ++++++++++++++-------------------
1 file changed, 21 insertions(+), 29 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c
index ff558c05e990..273912083056 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio.c
@@ -301,9 +301,8 @@ static bool is_vgic_v2_sgi(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
vcpu->kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2);
}
-void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
- gpa_t addr, unsigned int len,
- unsigned long val)
+static void __set_pending(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
+ unsigned long val, bool is_user)
{
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
int i;
@@ -312,14 +311,22 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
for_each_set_bit(i, &val, len * 8) {
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
- /* GICD_ISPENDR0 SGI bits are WI */
- if (is_vgic_v2_sgi(vcpu, irq)) {
+ /* GICD_ISPENDR0 SGI bits are WI when written from the guest. */
+ if (is_vgic_v2_sgi(vcpu, irq) && !is_user) {
vgic_put_irq(vcpu->kvm, irq);
continue;
}
raw_spin_lock_irqsave(&irq->irq_lock, flags);
+ /*
+ * GICv2 SGIs are terribly broken. We can't restore
+ * the source of the interrupt, so just pick the vcpu
+ * itself as the source...
+ */
+ if (is_vgic_v2_sgi(vcpu, irq))
+ irq->source |= BIT(vcpu->vcpu_id);
+
if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
/* HW SGI? Ask the GIC to inject it */
int err;
@@ -335,7 +342,7 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
}
irq->pending_latch = true;
- if (irq->hw)
+ if (irq->hw && !is_user)
vgic_irq_set_phys_active(irq, true);
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
@@ -343,33 +350,18 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
}
}
+void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
+ gpa_t addr, unsigned int len,
+ unsigned long val)
+{
+ __set_pending(vcpu, addr, len, val, false);
+}
+
int vgic_uaccess_write_spending(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len,
unsigned long val)
{
- u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
- int i;
- unsigned long flags;
-
- for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-
- raw_spin_lock_irqsave(&irq->irq_lock, flags);
- irq->pending_latch = true;
-
- /*
- * GICv2 SGIs are terribly broken. We can't restore
- * the source of the interrupt, so just pick the vcpu
- * itself as the source...
- */
- if (is_vgic_v2_sgi(vcpu, irq))
- irq->source |= BIT(vcpu->vcpu_id);
-
- vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
-
- vgic_put_irq(vcpu->kvm, irq);
- }
-
+ __set_pending(vcpu, addr, len, val, true);
return 0;
}
--
2.43.0.472.g3155946c3a-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/3] KVM: arm64: vgic: Use common accessor for writes to ICPENDR
2023-12-19 6:58 [PATCH 0/3] KVM: arm64: Fix + cleanup for GICv3 ISPENDR Oliver Upton
2023-12-19 6:58 ` [PATCH 1/3] KVM: arm64: vgic: Use common accessor for writes to ISPENDR Oliver Upton
@ 2023-12-19 6:58 ` Oliver Upton
2023-12-19 6:58 ` [PATCH 3/3] KVM: arm64: vgic-v3: Reinterpret user ISPENDR writes as I{C,S}PENDR Oliver Upton
2023-12-22 13:03 ` [PATCH 0/3] KVM: arm64: Fix + cleanup for GICv3 ISPENDR Marc Zyngier
3 siblings, 0 replies; 5+ messages in thread
From: Oliver Upton @ 2023-12-19 6:58 UTC (permalink / raw)
To: kvmarm
Cc: kvm, Marc Zyngier, James Morse, Suzuki K Poulose, Zenghui Yu,
Kunkun Jiang, Oliver Upton
Fold MMIO and user accessors into a common helper while maintaining the
distinction between the two. It is now possible for userspace to clear
the pending state for SGIs from the ITS, as is the case with GICv4.1
vSGIs.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kvm/vgic/vgic-mmio.c | 51 ++++++++++++++-------------------
1 file changed, 22 insertions(+), 29 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c
index 273912083056..cf76523a2194 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio.c
@@ -386,9 +386,9 @@ static void vgic_hw_irq_cpending(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
vgic_irq_set_phys_active(irq, false);
}
-void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
- gpa_t addr, unsigned int len,
- unsigned long val)
+static void __clear_pending(struct kvm_vcpu *vcpu,
+ gpa_t addr, unsigned int len,
+ unsigned long val, bool is_user)
{
u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
int i;
@@ -397,14 +397,22 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
for_each_set_bit(i, &val, len * 8) {
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
- /* GICD_ICPENDR0 SGI bits are WI */
- if (is_vgic_v2_sgi(vcpu, irq)) {
+ /* GICD_ICPENDR0 SGI bits are WI when written from the guest. */
+ if (is_vgic_v2_sgi(vcpu, irq) && !is_user) {
vgic_put_irq(vcpu->kvm, irq);
continue;
}
raw_spin_lock_irqsave(&irq->irq_lock, flags);
+ /*
+ * More fun with GICv2 SGIs! If we're clearing one of them
+ * from userspace, which source vcpu to clear? Let's not
+ * even think of it, and blow the whole set.
+ */
+ if (is_vgic_v2_sgi(vcpu, irq))
+ irq->source = 0;
+
if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
/* HW SGI? Ask the GIC to clear its pending bit */
int err;
@@ -419,7 +427,7 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
continue;
}
- if (irq->hw)
+ if (irq->hw && !is_user)
vgic_hw_irq_cpending(vcpu, irq);
else
irq->pending_latch = false;
@@ -429,33 +437,18 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
}
}
+void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
+ gpa_t addr, unsigned int len,
+ unsigned long val)
+{
+ __clear_pending(vcpu, addr, len, val, false);
+}
+
int vgic_uaccess_write_cpending(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len,
unsigned long val)
{
- u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
- int i;
- unsigned long flags;
-
- for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-
- raw_spin_lock_irqsave(&irq->irq_lock, flags);
- /*
- * More fun with GICv2 SGIs! If we're clearing one of them
- * from userspace, which source vcpu to clear? Let's not
- * even think of it, and blow the whole set.
- */
- if (is_vgic_v2_sgi(vcpu, irq))
- irq->source = 0;
-
- irq->pending_latch = false;
-
- raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
-
- vgic_put_irq(vcpu->kvm, irq);
- }
-
+ __clear_pending(vcpu, addr, len, val, true);
return 0;
}
--
2.43.0.472.g3155946c3a-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 3/3] KVM: arm64: vgic-v3: Reinterpret user ISPENDR writes as I{C,S}PENDR
2023-12-19 6:58 [PATCH 0/3] KVM: arm64: Fix + cleanup for GICv3 ISPENDR Oliver Upton
2023-12-19 6:58 ` [PATCH 1/3] KVM: arm64: vgic: Use common accessor for writes to ISPENDR Oliver Upton
2023-12-19 6:58 ` [PATCH 2/3] KVM: arm64: vgic: Use common accessor for writes to ICPENDR Oliver Upton
@ 2023-12-19 6:58 ` Oliver Upton
2023-12-22 13:03 ` [PATCH 0/3] KVM: arm64: Fix + cleanup for GICv3 ISPENDR Marc Zyngier
3 siblings, 0 replies; 5+ messages in thread
From: Oliver Upton @ 2023-12-19 6:58 UTC (permalink / raw)
To: kvmarm
Cc: kvm, Marc Zyngier, James Morse, Suzuki K Poulose, Zenghui Yu,
Kunkun Jiang, Oliver Upton
User writes to ISPENDR for GICv3 are treated specially, as zeroes
actually clear the pending state for interrupts (unlike HW). Reimplement
it using the ISPENDR and ICPENDR user accessors. This eliminates some
code and ensures that userspace can modify the state of SGIs in hardware
for GICv4.1 vSGIs.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
arch/arm64/kvm/vgic/vgic-mmio-v3.c | 28 +++++-----------------------
1 file changed, 5 insertions(+), 23 deletions(-)
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
index 89117ba2528a..2962ccd8013a 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
@@ -357,31 +357,13 @@ static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len,
unsigned long val)
{
- u32 intid = VGIC_ADDR_TO_INTID(addr, 1);
- int i;
- unsigned long flags;
-
- for (i = 0; i < len * 8; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-
- raw_spin_lock_irqsave(&irq->irq_lock, flags);
- if (test_bit(i, &val)) {
- /*
- * pending_latch is set irrespective of irq type
- * (level or edge) to avoid dependency that VM should
- * restore irq config before pending info.
- */
- irq->pending_latch = true;
- vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
- } else {
- irq->pending_latch = false;
- raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
- }
+ int ret;
- vgic_put_irq(vcpu->kvm, irq);
- }
+ ret = vgic_uaccess_write_spending(vcpu, addr, len, val);
+ if (ret)
+ return ret;
- return 0;
+ return vgic_uaccess_write_cpending(vcpu, addr, len, ~val);
}
/* We want to avoid outer shareable. */
--
2.43.0.472.g3155946c3a-goog
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 0/3] KVM: arm64: Fix + cleanup for GICv3 ISPENDR
2023-12-19 6:58 [PATCH 0/3] KVM: arm64: Fix + cleanup for GICv3 ISPENDR Oliver Upton
` (2 preceding siblings ...)
2023-12-19 6:58 ` [PATCH 3/3] KVM: arm64: vgic-v3: Reinterpret user ISPENDR writes as I{C,S}PENDR Oliver Upton
@ 2023-12-22 13:03 ` Marc Zyngier
3 siblings, 0 replies; 5+ messages in thread
From: Marc Zyngier @ 2023-12-22 13:03 UTC (permalink / raw)
To: kvmarm, Oliver Upton
Cc: Zenghui Yu, Suzuki K Poulose, kvm, James Morse, Kunkun Jiang
On Tue, 19 Dec 2023 06:58:52 +0000, Oliver Upton wrote:
> Here's the alternative approach I had suggested in response to Kunkun's
> bug report, building the GICv3 ISPENDR accessor on top of the existing
> ISPENDR / ICPENDR accessors. With these changes userspace should
> consistently read / configure the hardware pending state for GICv4.1
> vSGIs.
>
> Oliver Upton (3):
> KVM: arm64: vgic: Use common accessor for writes to ISPENDR
> KVM: arm64: vgic: Use common accessor for writes to ICPENDR
> KVM: arm64: vgic-v3: Reinterpret user ISPENDR writes as I{C,S}PENDR
>
> [...]
I have queued this for 6.8, together with my GICv4.1 fix.
[1/3] KVM: arm64: vgic: Use common accessor for writes to ISPENDR
commit: 13886f34444596e6eca124677cd8362a941b585b
[2/3] KVM: arm64: vgic: Use common accessor for writes to ICPENDR
commit: 561851424d93e91083df4071781b68dc4ba1fc5a
[3/3] KVM: arm64: vgic-v3: Reinterpret user ISPENDR writes as I{C,S}PENDR
commit: 39084ba8d0fceb477a264e2bb8dfd3553876b84c
Cheers,
M.
--
Without deviation from the norm, progress is not possible.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2023-12-22 13:03 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-12-19 6:58 [PATCH 0/3] KVM: arm64: Fix + cleanup for GICv3 ISPENDR Oliver Upton
2023-12-19 6:58 ` [PATCH 1/3] KVM: arm64: vgic: Use common accessor for writes to ISPENDR Oliver Upton
2023-12-19 6:58 ` [PATCH 2/3] KVM: arm64: vgic: Use common accessor for writes to ICPENDR Oliver Upton
2023-12-19 6:58 ` [PATCH 3/3] KVM: arm64: vgic-v3: Reinterpret user ISPENDR writes as I{C,S}PENDR Oliver Upton
2023-12-22 13:03 ` [PATCH 0/3] KVM: arm64: Fix + cleanup for GICv3 ISPENDR Marc Zyngier
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox