vmm: Rework snapshotting of CPU-specific per-vCPU data.

Previously some per-vCPU state was saved in vmmops_snapshot and other
state was saved in vmmops_vcmx_snapshot.  Consolidate all per-vCPU
state into the latter routine and rename the hook to the more generic
'vcpu_snapshot'.  Note that the CPU-independent per-vCPU data is still
stored in a separate blob as well as the per-vCPU local APIC data.

Reviewed by:	corvink, markj
Differential Revision:	https://reviews.freebsd.org/D37150
This commit is contained in:
John Baldwin 2022-11-18 09:58:41 -08:00
parent 19b9dd2e08
commit 39ec056e6d
4 changed files with 157 additions and 177 deletions

View File

@ -185,7 +185,7 @@ typedef void (*vmi_vmspace_free)(struct vmspace *vmspace);
typedef struct vlapic * (*vmi_vlapic_init)(void *vmi, int vcpu);
typedef void (*vmi_vlapic_cleanup)(void *vmi, struct vlapic *vlapic);
typedef int (*vmi_snapshot_t)(void *vmi, struct vm_snapshot_meta *meta);
typedef int (*vmi_snapshot_vmcx_t)(void *vmi, struct vm_snapshot_meta *meta,
typedef int (*vmi_snapshot_vcpu_t)(void *vmi, struct vm_snapshot_meta *meta,
int vcpu);
typedef int (*vmi_restore_tsc_t)(void *vmi, int vcpuid, uint64_t now);
@ -210,7 +210,7 @@ struct vmm_ops {
/* checkpoint operations */
vmi_snapshot_t snapshot;
vmi_snapshot_vmcx_t vmcx_snapshot;
vmi_snapshot_vcpu_t vcpu_snapshot;
vmi_restore_tsc_t restore_tsc;
};

View File

@ -2428,224 +2428,213 @@ svm_vlapic_cleanup(void *arg, struct vlapic *vlapic)
static int
svm_snapshot(void *arg, struct vm_snapshot_meta *meta)
{
/* struct svm_softc is AMD's representation for SVM softc */
struct svm_softc *sc;
struct svm_vcpu *vcpu;
int ret;
uint16_t i, maxcpus;
sc = arg;
KASSERT(sc != NULL, ("%s: arg was NULL", __func__));
maxcpus = vm_get_maxcpus(sc->vm);
for (i = 0; i < maxcpus; i++) {
vcpu = &sc->vcpu[i];
/* Snapshot swctx for virtual cpu i */
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_rbp, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_rbx, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_rcx, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_rdx, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_rdi, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_rsi, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r8, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r9, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r10, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r11, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r12, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r13, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r14, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r15, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_dr0, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_dr1, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_dr2, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_dr3, meta, ret, done);
/* Restore other svm_vcpu struct fields */
/* Restore NEXTRIP field */
SNAPSHOT_VAR_OR_LEAVE(vcpu->nextrip, meta, ret, done);
/* Restore lastcpu field */
SNAPSHOT_VAR_OR_LEAVE(vcpu->lastcpu, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->dirty, meta, ret, done);
/* Restore EPTGEN field - EPT is Extended Page Table */
SNAPSHOT_VAR_OR_LEAVE(vcpu->eptgen, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->asid.gen, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->asid.num, meta, ret, done);
/* Set all caches dirty */
if (meta->op == VM_SNAPSHOT_RESTORE)
svm_set_dirty(sc, i, 0xffffffff);
}
if (meta->op == VM_SNAPSHOT_RESTORE)
flush_by_asid();
done:
return (ret);
return (0);
}
static int
svm_vmcx_snapshot(void *arg, struct vm_snapshot_meta *meta, int vcpu)
svm_vcpu_snapshot(void *arg, struct vm_snapshot_meta *meta, int vcpuid)
{
struct svm_softc *sc;
struct svm_vcpu *vcpu;
int err, running, hostcpu;
sc = (struct svm_softc *)arg;
vcpu = &sc->vcpu[vcpuid];
err = 0;
KASSERT(arg != NULL, ("%s: arg was NULL", __func__));
running = vcpu_is_running(sc->vm, vcpu, &hostcpu);
if (running && hostcpu !=curcpu) {
printf("%s: %s%d is running", __func__, vm_name(sc->vm), vcpu);
running = vcpu_is_running(sc->vm, vcpuid, &hostcpu);
if (running && hostcpu != curcpu) {
printf("%s: %s%d is running", __func__, vm_name(sc->vm),
vcpuid);
return (EINVAL);
}
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_CR0, meta);
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_CR2, meta);
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_CR3, meta);
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_CR4, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_CR0, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_CR2, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_CR3, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_CR4, meta);
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_DR6, meta);
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_DR7, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_DR6, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_DR7, meta);
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_RAX, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_RAX, meta);
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_RSP, meta);
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_RIP, meta);
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_RFLAGS, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_RSP, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_RIP, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_RFLAGS, meta);
/* Guest segments */
/* ES */
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_ES, meta);
err += vmcb_snapshot_desc(sc, vcpu, VM_REG_GUEST_ES, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_ES, meta);
err += vmcb_snapshot_desc(sc, vcpuid, VM_REG_GUEST_ES, meta);
/* CS */
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_CS, meta);
err += vmcb_snapshot_desc(sc, vcpu, VM_REG_GUEST_CS, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_CS, meta);
err += vmcb_snapshot_desc(sc, vcpuid, VM_REG_GUEST_CS, meta);
/* SS */
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_SS, meta);
err += vmcb_snapshot_desc(sc, vcpu, VM_REG_GUEST_SS, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_SS, meta);
err += vmcb_snapshot_desc(sc, vcpuid, VM_REG_GUEST_SS, meta);
/* DS */
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_DS, meta);
err += vmcb_snapshot_desc(sc, vcpu, VM_REG_GUEST_DS, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_DS, meta);
err += vmcb_snapshot_desc(sc, vcpuid, VM_REG_GUEST_DS, meta);
/* FS */
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_FS, meta);
err += vmcb_snapshot_desc(sc, vcpu, VM_REG_GUEST_FS, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_FS, meta);
err += vmcb_snapshot_desc(sc, vcpuid, VM_REG_GUEST_FS, meta);
/* GS */
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_GS, meta);
err += vmcb_snapshot_desc(sc, vcpu, VM_REG_GUEST_GS, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_GS, meta);
err += vmcb_snapshot_desc(sc, vcpuid, VM_REG_GUEST_GS, meta);
/* TR */
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_TR, meta);
err += vmcb_snapshot_desc(sc, vcpu, VM_REG_GUEST_TR, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_TR, meta);
err += vmcb_snapshot_desc(sc, vcpuid, VM_REG_GUEST_TR, meta);
/* LDTR */
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_LDTR, meta);
err += vmcb_snapshot_desc(sc, vcpu, VM_REG_GUEST_LDTR, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_LDTR, meta);
err += vmcb_snapshot_desc(sc, vcpuid, VM_REG_GUEST_LDTR, meta);
/* EFER */
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_EFER, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_EFER, meta);
/* IDTR and GDTR */
err += vmcb_snapshot_desc(sc, vcpu, VM_REG_GUEST_IDTR, meta);
err += vmcb_snapshot_desc(sc, vcpu, VM_REG_GUEST_GDTR, meta);
err += vmcb_snapshot_desc(sc, vcpuid, VM_REG_GUEST_IDTR, meta);
err += vmcb_snapshot_desc(sc, vcpuid, VM_REG_GUEST_GDTR, meta);
/* Specific AMD registers */
err += svm_snapshot_reg(sc, vcpu, VM_REG_GUEST_INTR_SHADOW, meta);
err += svm_snapshot_reg(sc, vcpuid, VM_REG_GUEST_INTR_SHADOW, meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_CR_INTERCEPT, 4), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_DR_INTERCEPT, 4), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_EXC_INTERCEPT, 4), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_INST1_INTERCEPT, 4), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_INST2_INTERCEPT, 4), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_PAUSE_FILTHRESH, 2), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_PAUSE_FILCNT, 2), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_ASID, 4), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_TLB_CTRL, 4), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_VIRQ, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_EXIT_REASON, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_EXITINFO1, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_EXITINFO2, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_EXITINTINFO, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_NP_ENABLE, 1), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_AVIC_BAR, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_AVIC_PAGE, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_AVIC_LT, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_AVIC_PT, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_CPL, 1), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_STAR, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_LSTAR, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_CSTAR, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_SFMASK, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_KERNELGBASE, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_SYSENTER_CS, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_SYSENTER_ESP, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_SYSENTER_EIP, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_GUEST_PAT, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_DBGCTL, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_BR_FROM, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_BR_TO, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_INT_FROM, 8), meta);
err += vmcb_snapshot_any(sc, vcpu,
err += vmcb_snapshot_any(sc, vcpuid,
VMCB_ACCESS(VMCB_OFF_INT_TO, 8), meta);
if (err != 0)
goto done;
/* Snapshot swctx for virtual cpu */
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_rbp, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_rbx, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_rcx, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_rdx, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_rdi, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_rsi, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r8, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r9, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r10, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r11, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r12, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r13, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r14, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_r15, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_dr0, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_dr1, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_dr2, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->swctx.sctx_dr3, meta, err, done);
/* Restore other svm_vcpu struct fields */
/* Restore NEXTRIP field */
SNAPSHOT_VAR_OR_LEAVE(vcpu->nextrip, meta, err, done);
/* Restore lastcpu field */
SNAPSHOT_VAR_OR_LEAVE(vcpu->lastcpu, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->dirty, meta, err, done);
/* Restore EPTGEN field - EPT is Extended Page Table */
SNAPSHOT_VAR_OR_LEAVE(vcpu->eptgen, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->asid.gen, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vcpu->asid.num, meta, err, done);
/* Set all caches dirty */
if (meta->op == VM_SNAPSHOT_RESTORE)
svm_set_dirty(sc, vcpuid, 0xffffffff);
done:
return (err);
}
@ -2679,7 +2668,7 @@ const struct vmm_ops vmm_ops_amd = {
.vlapic_cleanup = svm_vlapic_cleanup,
#ifdef BHYVE_SNAPSHOT
.snapshot = svm_snapshot,
.vmcx_snapshot = svm_vmcx_snapshot,
.vcpu_snapshot = svm_vcpu_snapshot,
.restore_tsc = svm_restore_tsc,
#endif
};

View File

@ -4102,67 +4102,29 @@ vmx_vlapic_cleanup(void *arg, struct vlapic *vlapic)
static int
vmx_snapshot(void *arg, struct vm_snapshot_meta *meta)
{
struct vmx *vmx;
struct vmx_vcpu *vcpu;
struct vmxctx *vmxctx;
int ret;
uint16_t i, maxcpus;
vmx = arg;
KASSERT(vmx != NULL, ("%s: arg was NULL", __func__));
maxcpus = vm_get_maxcpus(vmx->vm);
for (i = 0; i < maxcpus; i++) {
vcpu = &vmx->vcpus[i];
SNAPSHOT_BUF_OR_LEAVE(vcpu->guest_msrs,
sizeof(vcpu->guest_msrs), meta, ret, done);
vmxctx = &vcpu->ctx;
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rdi, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rsi, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rdx, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rcx, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r8, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r9, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rax, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rbx, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rbp, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r10, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r11, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r12, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r13, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r14, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r15, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_cr2, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_dr0, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_dr1, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_dr2, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_dr3, meta, ret, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_dr6, meta, ret, done);
}
done:
return (ret);
return (0);
}
static int
vmx_vmcx_snapshot(void *arg, struct vm_snapshot_meta *meta, int vcpu)
vmx_vcpu_snapshot(void *arg, struct vm_snapshot_meta *meta, int vcpuid)
{
struct vmcs *vmcs;
struct vmx *vmx;
struct vmx_vcpu *vcpu;
struct vmxctx *vmxctx;
int err, run, hostcpu;
vmx = (struct vmx *)arg;
err = 0;
KASSERT(arg != NULL, ("%s: arg was NULL", __func__));
vmcs = vmx->vcpus[vcpu].vmcs;
vcpu = &vmx->vcpus[vcpuid];
vmcs = vcpu->vmcs;
run = vcpu_is_running(vmx->vm, vcpu, &hostcpu);
run = vcpu_is_running(vmx->vm, vcpuid, &hostcpu);
if (run && hostcpu != curcpu) {
printf("%s: %s%d is running", __func__, vm_name(vmx->vm), vcpu);
printf("%s: %s%d is running", __func__, vm_name(vmx->vm),
vcpuid);
return (EINVAL);
}
@ -4218,7 +4180,36 @@ vmx_vmcx_snapshot(void *arg, struct vm_snapshot_meta *meta, int vcpu)
err += vmcs_snapshot_any(vmcs, run, VMCS_GUEST_ACTIVITY, meta);
err += vmcs_snapshot_any(vmcs, run, VMCS_ENTRY_CTLS, meta);
err += vmcs_snapshot_any(vmcs, run, VMCS_EXIT_CTLS, meta);
if (err != 0)
goto done;
SNAPSHOT_BUF_OR_LEAVE(vcpu->guest_msrs,
sizeof(vcpu->guest_msrs), meta, err, done);
vmxctx = &vcpu->ctx;
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rdi, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rsi, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rdx, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rcx, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r8, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r9, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rax, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rbx, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_rbp, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r10, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r11, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r12, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r13, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r14, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_r15, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_cr2, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_dr0, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_dr1, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_dr2, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_dr3, meta, err, done);
SNAPSHOT_VAR_OR_LEAVE(vmxctx->guest_dr6, meta, err, done);
done:
return (err);
}
@ -4268,7 +4259,7 @@ const struct vmm_ops vmm_ops_intel = {
.vlapic_cleanup = vmx_vlapic_cleanup,
#ifdef BHYVE_SNAPSHOT
.snapshot = vmx_snapshot,
.vmcx_snapshot = vmx_vmcx_snapshot,
.vcpu_snapshot = vmx_vcpu_snapshot,
.restore_tsc = vmx_restore_tsc,
#endif
};

View File

@ -229,7 +229,7 @@ DEFINE_VMMOPS_IFUNC(void, vlapic_cleanup, (void *vmi, struct vlapic *vlapic))
#ifdef BHYVE_SNAPSHOT
DEFINE_VMMOPS_IFUNC(int, snapshot, (void *vmi, struct vm_snapshot_meta
*meta))
DEFINE_VMMOPS_IFUNC(int, vmcx_snapshot, (void *vmi, struct vm_snapshot_meta
DEFINE_VMMOPS_IFUNC(int, vcpu_snapshot, (void *vmi, struct vm_snapshot_meta
*meta, int vcpu))
DEFINE_VMMOPS_IFUNC(int, restore_tsc, (void *vmi, int vcpuid, uint64_t now))
#endif
@ -2860,7 +2860,7 @@ vm_snapshot_vmcx(struct vm *vm, struct vm_snapshot_meta *meta)
maxcpus = vm_get_maxcpus(vm);
for (i = 0; i < maxcpus; i++) {
error = vmmops_vmcx_snapshot(vm->cookie, meta, i);
error = vmmops_vcpu_snapshot(vm->cookie, meta, i);
if (error != 0) {
printf("%s: failed to snapshot vmcs/vmcb data for "
"vCPU: %d; error: %d\n", __func__, i, error);