A VMCB's clean bits must all be clear when its vCPU next runs after a
deschedule, as other VMCBs run on the pCPU in the meantime.
svm_ctxt_switch_to() clears them as the vCPU is scheduled in; clear them
in svm_ctxt_switch_from() instead, as it is scheduled out.
This is equivalent. While the vCPU is descheduled, accessors reaching
its VMCB only ever clear clean bits: svm_vmexit_handler(), which sets
them all, runs only in the vCPU's own context. So do the nested-SVM
paths that change the active VMCB, nsvm_vcpu_hostrestore() and
nsvm_vcpu_vmentry(), and they clear the incoming VMCB's clean bits
themselves.
This prepares for moving VMCBs off always-mapped memory:
svm_ctxt_switch_to() runs before write_ptbase(), where the incoming
vCPU's VMCB will not be mapped.
Assisted-by: Claude Code:claude-fable-5, Claude Code:claude-opus-5-5
Signed-off-by: George Dunlap <gwd@xxxxxxxxxxxxxx>
---
Changes in v4:
- New in this version.
---
xen/arch/x86/hvm/svm/svm.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 241843d8c0..4e19df9865 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -919,6 +919,8 @@ static void cf_check svm_ctxt_switch_from(struct vcpu *v)
svm_save_dr(v);
svm_tsc_ratio_save(v);
+ v->arch.hvm.svm.vmcb->cleanbits.raw = 0;
+
svm_sync_vmcb(v, vmcb_needs_vmload);
svm_vmload_pa(per_cpu(host_vmcb, cpu));
@@ -938,7 +940,6 @@ static void cf_check svm_ctxt_switch_from(struct vcpu *v)
static void cf_check svm_ctxt_switch_to(struct vcpu *v)
{
- struct vmcb_struct *vmcb = v->arch.hvm.svm.vmcb;
int cpu = smp_processor_id();
/*
@@ -956,7 +957,6 @@ static void cf_check svm_ctxt_switch_to(struct vcpu *v)
svm_restore_dr(v);
- vmcb->cleanbits.raw = 0;
svm_tsc_ratio_load(v);
if ( cpu_has_msr_tsc_aux )