aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Johnston <markj@FreeBSD.org>2021-10-20 00:50:06 +0000
committerMark Johnston <markj@FreeBSD.org>2021-10-20 01:22:57 +0000
commit4c812fe61b7ce2f297a381950ff7bd87fd51f698 (patch)
treece5f721cb55c06d12ac2e7157105e24952419921
parentbd49c454ca62170506a98959c1acab7ad50c3276 (diff)
downloadsrc-4c812fe61b7ce2f297a381950ff7bd87fd51f698.tar.gz
src-4c812fe61b7ce2f297a381950ff7bd87fd51f698.zip
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 MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D32559
-rw-r--r--sys/amd64/vmm/io/vlapic.c20
1 files 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)
@@ -711,6 +712,13 @@ vlapic_trigger_lvt(struct vlapic *vlapic, int vector)
}
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)
{
struct vlapic *vlapic;
@@ -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);
}
}