diff mbox series

[v4,05/10] evtchn: closing of vIRQ-s doesn't require looping over all vCPU-s

Message ID ec877ae4-508e-6734-eae6-f3590021b712@suse.com (mailing list archive)
State Superseded
Headers show
Series evtchn: (not so) recent XSAs follow-on | expand

Commit Message

Jan Beulich Jan. 5, 2021, 1:10 p.m. UTC
Global vIRQ-s have their event channel association tracked on vCPU 0.
Per-vCPU vIRQ-s can't have their notify_vcpu_id changed. Hence it is
well-known which vCPU's virq_to_evtchn[] needs updating.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
---
v4: New.

Comments

Julien Grall Jan. 9, 2021, 4:17 p.m. UTC | #1
Hi Jan,

On 05/01/2021 13:10, Jan Beulich wrote:
> Global vIRQ-s have their event channel association tracked on vCPU 0.
> Per-vCPU vIRQ-s can't have their notify_vcpu_id changed. Hence it is
> well-known which vCPU's virq_to_evtchn[] needs updating.

I went through the history and couldn't find a reason for looping the vCPUs.

I have also looked at the code and agree with the analysis provided in 
the commit message.

Reviewed-by: Julien Grall <jgrall@amazon.com>

Cheers,
diff mbox series

Patch

--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -600,7 +600,6 @@  static long evtchn_bind_pirq(evtchn_bind
 int evtchn_close(struct domain *d1, int port1, bool guest)
 {
     struct domain *d2 = NULL;
-    struct vcpu   *v;
     struct evtchn *chn1, *chn2;
     int            port2;
     long           rc = 0;
@@ -651,17 +650,19 @@  int evtchn_close(struct domain *d1, int
         break;
     }
 
-    case ECS_VIRQ:
-        for_each_vcpu ( d1, v )
-        {
-            unsigned long flags;
+    case ECS_VIRQ: {
+        struct vcpu *v;
+        unsigned long flags;
+
+        v = d1->vcpu[virq_is_global(chn1->u.virq) ? 0 : chn1->notify_vcpu_id];
+
+        write_lock_irqsave(&v->virq_lock, flags);
+        ASSERT(read_atomic(&v->virq_to_evtchn[chn1->u.virq]) == port1);
+        write_atomic(&v->virq_to_evtchn[chn1->u.virq], 0);
+        write_unlock_irqrestore(&v->virq_lock, flags);
 
-            write_lock_irqsave(&v->virq_lock, flags);
-            if ( read_atomic(&v->virq_to_evtchn[chn1->u.virq]) == port1 )
-                write_atomic(&v->virq_to_evtchn[chn1->u.virq], 0);
-            write_unlock_irqrestore(&v->virq_lock, flags);
-        }
         break;
+    }
 
     case ECS_IPI:
         break;