git: 0b32ef71f9f1 - main - vmm: Correctly suspend and resume the vmm driver.
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Fri, 29 Nov 2024 21:39:24 UTC
The branch main has been updated by imp:
URL: https://cgit.FreeBSD.org/src/commit/?id=0b32ef71f9f154f4da5037bfcbb4916960d38452
commit 0b32ef71f9f154f4da5037bfcbb4916960d38452
Author: Joshua Rogers <Joshua@Joshua.Hu>
AuthorDate: 2024-09-11 17:42:25 +0000
Commit: Warner Losh <imp@FreeBSD.org>
CommitDate: 2024-11-29 21:38:35 +0000
vmm: Correctly suspend and resume the vmm driver.
Previously, VMXON would be executed on a resume, contrary to proper
initalization. The contents of MSR_IA32_FEATURE_CONTROL may be lost on
suspension, therefore must be restored. Likewise, the VMX Enable bit may be
cleared upon suspend, requiring it to be re-set.
Concretely disable VMX on suspend, and re-enable it on resume.
Note: any IOMMU context will remain lost for any enabled vmm devices.
Signed-off-by: Joshua Rogers <Joshua@Joshua.Hu>
Reviewed by: jhb,imp
Pull Request: https://github.com/freebsd/freebsd-src/pull/1419
---
sys/amd64/acpica/acpi_wakeup.c | 3 +++
sys/amd64/amd64/machdep.c | 1 +
sys/amd64/include/cpu.h | 3 ++-
sys/amd64/include/vmm.h | 2 ++
sys/amd64/vmm/amd/svm.c | 7 +++++++
sys/amd64/vmm/intel/vmx.c | 11 ++++++++++-
sys/amd64/vmm/vmm.c | 3 +++
sys/x86/x86/mp_x86.c | 5 +++++
8 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/sys/amd64/acpica/acpi_wakeup.c b/sys/amd64/acpica/acpi_wakeup.c
index 351cd16ff9ca..51d6d5e36840 100644
--- a/sys/amd64/acpica/acpi_wakeup.c
+++ b/sys/amd64/acpica/acpi_wakeup.c
@@ -202,6 +202,9 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state)
intr_suspend();
+ if (vmm_suspend_p != NULL)
+ vmm_suspend_p();
+
pcb = &susppcbs[0]->sp_pcb;
if (savectx(pcb)) {
fpususpend(susppcbs[0]->sp_fpususpend);
diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c
index e2ae3843a119..73bfdd4d07f5 100644
--- a/sys/amd64/amd64/machdep.c
+++ b/sys/amd64/amd64/machdep.c
@@ -213,6 +213,7 @@ struct mem_range_softc mem_range_softc;
struct mtx dt_lock; /* lock for GDT and LDT */
+void (*vmm_suspend_p)(void);
void (*vmm_resume_p)(void);
bool efi_boot;
diff --git a/sys/amd64/include/cpu.h b/sys/amd64/include/cpu.h
index 99b8806ba0ba..57f2a0b59bbb 100644
--- a/sys/amd64/include/cpu.h
+++ b/sys/amd64/include/cpu.h
@@ -70,7 +70,8 @@ extern char btext[];
extern char _end[];
extern char etext[];
-/* Resume hook for VMM. */
+/* Suspend and resume hook for VMM. */
+extern void (*vmm_suspend_p)(void);
extern void (*vmm_resume_p)(void);
void cpu_halt(void);
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h
index be88fc867e98..dd8e76962caf 100644
--- a/sys/amd64/include/vmm.h
+++ b/sys/amd64/include/vmm.h
@@ -170,6 +170,7 @@ struct vm_eventinfo {
typedef int (*vmm_init_func_t)(int ipinum);
typedef int (*vmm_cleanup_func_t)(void);
+typedef void (*vmm_suspend_func_t)(void);
typedef void (*vmm_resume_func_t)(void);
typedef void * (*vmi_init_func_t)(struct vm *vm, struct pmap *pmap);
typedef int (*vmi_run_func_t)(void *vcpui, register_t rip,
@@ -194,6 +195,7 @@ typedef int (*vmi_restore_tsc_t)(void *vcpui, uint64_t now);
struct vmm_ops {
vmm_init_func_t modinit; /* module wide initialization */
vmm_cleanup_func_t modcleanup;
+ vmm_resume_func_t modsuspend;
vmm_resume_func_t modresume;
vmi_init_func_t init; /* vm-specific initialization */
diff --git a/sys/amd64/vmm/amd/svm.c b/sys/amd64/vmm/amd/svm.c
index cc0b1c0c8725..2d40d3756f4a 100644
--- a/sys/amd64/vmm/amd/svm.c
+++ b/sys/amd64/vmm/amd/svm.c
@@ -277,6 +277,13 @@ svm_modinit(int ipinum)
return (0);
}
+static void
+svm_modsuspend(void)
+{
+
+ return;
+}
+
static void
svm_modresume(void)
{
diff --git a/sys/amd64/vmm/intel/vmx.c b/sys/amd64/vmm/intel/vmx.c
index 34b5fecc149c..13a53fa8eed6 100644
--- a/sys/amd64/vmm/intel/vmx.c
+++ b/sys/amd64/vmm/intel/vmx.c
@@ -648,12 +648,20 @@ vmx_enable(void *arg __unused)
vmxon_enabled[curcpu] = 1;
}
+static void
+vmx_modsuspend(void)
+{
+
+ if (vmxon_enabled[curcpu])
+ vmx_disable(NULL);
+}
+
static void
vmx_modresume(void)
{
if (vmxon_enabled[curcpu])
- vmxon(&vmxon_region[curcpu * PAGE_SIZE]);
+ vmx_enable(NULL);
}
static int
@@ -4271,6 +4279,7 @@ vmx_restore_tsc(void *vcpui, uint64_t offset)
const struct vmm_ops vmm_ops_intel = {
.modinit = vmx_modinit,
.modcleanup = vmx_modcleanup,
+ .modsuspend = vmx_modsuspend,
.modresume = vmx_modresume,
.init = vmx_init,
.run = vmx_run,
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index 9569f8ace909..d1f57a717fdf 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -232,6 +232,7 @@ vmmops_panic(void)
DEFINE_VMMOPS_IFUNC(int, modinit, (int ipinum))
DEFINE_VMMOPS_IFUNC(int, modcleanup, (void))
+DEFINE_VMMOPS_IFUNC(void, modsuspend, (void))
DEFINE_VMMOPS_IFUNC(void, modresume, (void))
DEFINE_VMMOPS_IFUNC(void *, init, (struct vm *vm, struct pmap *pmap))
DEFINE_VMMOPS_IFUNC(int, run, (void *vcpui, register_t rip, struct pmap *pmap,
@@ -452,6 +453,7 @@ vmm_init(void)
if (error)
return (error);
+ vmm_suspend_p = vmmops_modsuspend;
vmm_resume_p = vmmops_modresume;
return (vmmops_modinit(vmm_ipinum));
@@ -479,6 +481,7 @@ vmm_handler(module_t mod, int what, void *arg)
if (vmm_is_hw_supported()) {
error = vmmdev_cleanup();
if (error == 0) {
+ vmm_suspend_p = NULL;
vmm_resume_p = NULL;
iommu_cleanup();
if (vmm_ipinum != IPI_AST)
diff --git a/sys/x86/x86/mp_x86.c b/sys/x86/x86/mp_x86.c
index 0a683b3e841a..493017e303e3 100644
--- a/sys/x86/x86/mp_x86.c
+++ b/sys/x86/x86/mp_x86.c
@@ -1591,6 +1591,11 @@ cpususpend_handler(void)
mtx_assert(&smp_ipi_mtx, MA_NOTOWNED);
+#ifdef __amd64__
+ if (vmm_suspend_p)
+ vmm_suspend_p();
+#endif
+
cpu = PCPU_GET(cpuid);
#ifdef XENHVM