git: ee9205f068c7 - main - vmm: Add a bulk TMR reset hook for Intel APICv
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 02 Nov 2026 16:27:15 UTC
The branch main has been updated by markj:
URL: https://cgit.FreeBSD.org/src/commit/?id=ee9205f068c7675cf4d23e51cc98238d95ba1950
commit ee9205f068c7675cf4d23e51cc98238d95ba1950
Author: Hayzam Sherif <hayzam@gmail.com>
AuthorDate: 2026-11-02 16:21:18 +0000
Commit: Mark Johnston <markj@FreeBSD.org>
CommitDate: 2026-11-02 16:26:52 +0000
vmm: Add a bulk TMR reset hook for Intel APICv
vioapic_update_tmr() resets all 256 vectors before rebuilding the
level-triggered vector set. With Intel virtual interrupt delivery,
each per-vector reset loads the VMCS, reads and writes an EOI-exit
bitmap, and clears the VMCS.
Add an optional bulk-reset hook so VMX can clear the four EOI-exit
bitmaps with one VMCS load/clear pair. Clear the software TMR banks
directly when using the hook, and retain the per-vector fallback
for backends without it.
Reviewed by: markj
MFC after: 2 weeks
Differential Revision: https://reviews.freebsd.org/D60692
---
sys/amd64/vmm/intel/vmx.c | 21 +++++++++++++++++++++
sys/amd64/vmm/io/vlapic.c | 12 +++++++++++-
sys/amd64/vmm/io/vlapic_priv.h | 1 +
3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index ff0e1cb2b882..0b9a4eea3ebb 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -3921,6 +3921,26 @@ vmx_set_tmr(struct vlapic *vlapic, int vector, bool level)
VMCLEAR(vmcs);
}
+static void
+vmx_reset_tmr(struct vlapic *vlapic)
+{
+ struct vlapic_vtx *vlapic_vtx;
+ struct vmcs *vmcs;
+
+ KASSERT(!vcpu_is_running(vlapic->vcpu, NULL),
+ ("vmx_reset_tmr: vcpu cannot be running"));
+
+ vlapic_vtx = (struct vlapic_vtx *)vlapic;
+ vmcs = vlapic_vtx->vcpu->vmcs;
+
+ VMPTRLD(vmcs);
+ vmcs_write(VMCS_EOI_EXIT0, 0);
+ vmcs_write(VMCS_EOI_EXIT1, 0);
+ vmcs_write(VMCS_EOI_EXIT2, 0);
+ vmcs_write(VMCS_EOI_EXIT3, 0);
+ VMCLEAR(vmcs);
+}
+
static void
vmx_enable_x2apic_mode_ts(struct vlapic *vlapic)
{
@@ -4121,6 +4141,7 @@ vmx_vlapic_init(void *vcpui)
vlapic->ops.pending_intr = vmx_pending_intr;
vlapic->ops.intr_accepted = vmx_intr_accepted;
vlapic->ops.set_tmr = vmx_set_tmr;
+ vlapic->ops.reset_tmr = vmx_reset_tmr;
vlapic->ops.enable_x2apic_mode = vmx_enable_x2apic_mode_vid;
}
diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c
index e0a1359dffb6..a5009804d72b 100644
--- a/sys/amd64/vmm/io/vlapic.c
+++ b/sys/amd64/vmm/io/vlapic.c
@@ -1776,10 +1776,20 @@ vlapic_set_tmr(struct vlapic *vlapic, int vector, bool level)
void
vlapic_reset_tmr(struct vlapic *vlapic)
{
- int vector;
+ uint32_t *tmrptr;
+ int i, vector;
VLAPIC_CTR0(vlapic, "vlapic resetting all vectors to edge-triggered");
+ if (vlapic->ops.reset_tmr != NULL) {
+ tmrptr = &vlapic->apic_page->tmr0;
+ /* APIC register slots are 16 bytes apart. */
+ for (i = 0; i < 8; i++)
+ tmrptr[i * 4] = 0;
+ (*vlapic->ops.reset_tmr)(vlapic);
+ return;
+ }
+
for (vector = 0; vector <= 255; vector++)
vlapic_set_tmr(vlapic, vector, false);
}
diff --git a/sys/amd64/vmm/io/vlapic_priv.h b/sys/amd64/vmm/io/vlapic_priv.h
index 1dce593b9444..f8d23530d277 100644
--- a/sys/amd64/vmm/io/vlapic_priv.h
+++ b/sys/amd64/vmm/io/vlapic_priv.h
@@ -139,6 +139,7 @@ struct vlapic_ops {
void (*intr_accepted)(struct vlapic *vlapic, int vector);
void (*post_intr)(struct vlapic *vlapic, int hostcpu);
void (*set_tmr)(struct vlapic *vlapic, int vector, bool level);
+ void (*reset_tmr)(struct vlapic *vlapic);
void (*enable_x2apic_mode)(struct vlapic *vlapic);
};