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:
parent
19b9dd2e08
commit
39ec056e6d
@ -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;
|
||||
};
|
||||
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user