git: 009b4d719039 - stable/13 - vlapic: Schedule callouts on the local CPU

From: Mark Johnston <markj_at_FreeBSD.org>
Date: Wed, 03 Nov 2021 13:15:35 UTC
The branch stable/13 has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=009b4d7190397032d21a7470ddf0cc93482297e2

commit 009b4d7190397032d21a7470ddf0cc93482297e2
Author:     Mark Johnston <markj@FreeBSD.org>
AuthorDate: 2021-10-20 00:50:06 +0000
Commit:     Mark Johnston <markj@FreeBSD.org>
CommitDate: 2021-11-03 13:15:18 +0000

    vlapic: Schedule callouts on the local CPU
    
    The virtual LAPIC driver uses callouts to implement the LAPIC timer.
    Callouts are armed using callout_reset_sbt(), which currently puts
    everything on CPU 0.  On systems running many bhyve VMs this results in
    a large amount of contention for CPU 0's callout lock.
    
    Modify vlapic to schedule callouts on the local CPU instead.  This
    allows timer interrupts to be scheduled more evenly among CPUs where
    bhyve is running.
    
    Reviewed by:    grehan, jhb
    Sponsored by:   The FreeBSD Foundation
    
    (cherry picked from commit 4c812fe61b7ce2f297a381950ff7bd87fd51f698)
---
 sys/amd64/vmm/io/vlapic.c | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c
index 4e7ddbafd447..940e45cce458 100644
--- a/sys/amd64/vmm/io/vlapic.c
+++ b/sys/amd64/vmm/io/vlapic.c
@@ -83,6 +83,7 @@ __FBSDID("$FreeBSD$");
 #define VLAPIC_BUS_FREQ		(128 * 1024 * 1024)
 
 static void vlapic_set_error(struct vlapic *, uint32_t, bool);
+static void vlapic_callout_handler(void *arg);
 
 static __inline uint32_t
 vlapic_get_id(struct vlapic *vlapic)
@@ -710,6 +711,13 @@ vlapic_trigger_lvt(struct vlapic *vlapic, int vector)
 	return (0);
 }
 
+static void
+vlapic_callout_reset(struct vlapic *vlapic, sbintime_t t)
+{
+	callout_reset_sbt_curcpu(&vlapic->callout, t, 0,
+	    vlapic_callout_handler, vlapic, 0);
+}
+
 static void
 vlapic_callout_handler(void *arg)
 {
@@ -765,8 +773,7 @@ vlapic_callout_handler(void *arg)
 		}
 
 		bintime_add(&vlapic->timer_fire_bt, &vlapic->timer_period_bt);
-		callout_reset_sbt(&vlapic->callout, rem_sbt, 0,
-		    vlapic_callout_handler, vlapic, 0);
+		vlapic_callout_reset(vlapic, rem_sbt);
 	}
 done:
 	VLAPIC_TIMER_UNLOCK(vlapic);
@@ -792,8 +799,7 @@ vlapic_icrtmr_write_handler(struct vlapic *vlapic)
 		bintime_add(&vlapic->timer_fire_bt, &vlapic->timer_period_bt);
 
 		sbt = bttosbt(vlapic->timer_period_bt);
-		callout_reset_sbt(&vlapic->callout, sbt, 0,
-		    vlapic_callout_handler, vlapic, 0);
+		vlapic_callout_reset(vlapic, sbt);
 	} else
 		callout_stop(&vlapic->callout);
 
@@ -1667,8 +1673,7 @@ vlapic_reset_callout(struct vlapic *vlapic, uint32_t ccr)
 		bintime_add(&vlapic->timer_fire_bt, &bt);
 
 		sbt = bttosbt(bt);
-		callout_reset_sbt(&vlapic->callout, sbt, 0,
-		    vlapic_callout_handler, vlapic, 0);
+		vlapic_callout_reset(vlapic, sbt);
 	} else {
 		/* even if the CCR was 0, periodic timers should be reset */
 		if (vlapic_periodic_timer(vlapic)) {
@@ -1678,8 +1683,7 @@ vlapic_reset_callout(struct vlapic *vlapic, uint32_t ccr)
 			sbt = bttosbt(vlapic->timer_period_bt);
 
 			callout_stop(&vlapic->callout);
-			callout_reset_sbt(&vlapic->callout, sbt, 0,
-					  vlapic_callout_handler, vlapic, 0);
+			vlapic_callout_reset(vlapic, sbt);
 		}
 	}