Date: Sat, 3 Aug 2013 13:06:28 GMT From: iori@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r255481 - in soc2013/iori/suspendresume/head: lib/libvmmapi sys/amd64/include sys/amd64/vmm sys/amd64/vmm/amd sys/amd64/vmm/intel Message-ID: <201308031306.r73D6Sx5070572@socsvn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: iori Date: Sat Aug 3 13:06:28 2013 New Revision: 255481 URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=255481 Log: Added new ioctl to prevent VM from running, kill it, and save emulated integer and contol registers and copy them to userland. If VM killed by suspend request ioctl, vmrun ioctl returns value indicate that save registers request was issued and this is why it returns. TODO: hook vmrun ioctl return in userland tool bhyve, and save registers and transfer to the process requested to suspend. develop new test tool to make sure that it saves. memory save. Modified: soc2013/iori/suspendresume/head/lib/libvmmapi/vmmapi.c soc2013/iori/suspendresume/head/lib/libvmmapi/vmmapi.h soc2013/iori/suspendresume/head/sys/amd64/include/vmm.h soc2013/iori/suspendresume/head/sys/amd64/include/vmm_dev.h soc2013/iori/suspendresume/head/sys/amd64/vmm/amd/amdv.c soc2013/iori/suspendresume/head/sys/amd64/vmm/intel/vmx.c soc2013/iori/suspendresume/head/sys/amd64/vmm/intel/vmx.h soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm.c soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm_dev.c Modified: soc2013/iori/suspendresume/head/lib/libvmmapi/vmmapi.c ============================================================================== --- soc2013/iori/suspendresume/head/lib/libvmmapi/vmmapi.c Sat Aug 3 12:45:00 2013 (r255480) +++ soc2013/iori/suspendresume/head/lib/libvmmapi/vmmapi.c Sat Aug 3 13:06:28 2013 (r255481) @@ -123,6 +123,39 @@ free(vm); } +unsigned long +vm_get_allvstate(struct vmctx *ctx, struct vmstate *vmstate) +{ + int error; + + error = ioctl(ctx->fd, VM_SAVE_VCPUSTATE, vmstate); + return error; +} + +size_t +vmm_get_mem_total(void) +{ + size_t mem_total = 0; + size_t oldlen = sizeof(mem_total); + int error; + error = sysctlbyname("hw.vmm.mem_total", &mem_total, &oldlen, NULL, 0); + if (error) + return -1; + return mem_total; +} + +size_t +vmm_get_mem_free(void) +{ + size_t mem_free = 0; + size_t oldlen = sizeof(mem_free); + int error; + error = sysctlbyname("hw.vmm.mem_free", &mem_free, &oldlen, NULL, 0); + if (error) + return -1; + return mem_free; +} + int vm_get_memory_seg(struct vmctx *ctx, vm_paddr_t gpa, size_t *ret_len) { Modified: soc2013/iori/suspendresume/head/lib/libvmmapi/vmmapi.h ============================================================================== --- soc2013/iori/suspendresume/head/lib/libvmmapi/vmmapi.h Sat Aug 3 12:45:00 2013 (r255480) +++ soc2013/iori/suspendresume/head/lib/libvmmapi/vmmapi.h Sat Aug 3 13:06:28 2013 (r255481) @@ -45,6 +45,9 @@ int vm_create(const char *name); struct vmctx *vm_open(const char *name); void vm_destroy(struct vmctx *ctx); +unsigned long vm_get_allvstate(struct vmctx *ctx, struct vmstate *vmstate); +size_t vmm_get_mem_total(void); +size_t vmm_get_mem_free(void); int vm_get_memory_seg(struct vmctx *ctx, vm_paddr_t gpa, size_t *ret_len); int vm_setup_memory(struct vmctx *ctx, size_t len, enum vm_mmap_style s); void *vm_map_gpa(struct vmctx *ctx, vm_paddr_t gaddr, size_t len); Modified: soc2013/iori/suspendresume/head/sys/amd64/include/vmm.h ============================================================================== --- soc2013/iori/suspendresume/head/sys/amd64/include/vmm.h Sat Aug 3 12:45:00 2013 (r255480) +++ soc2013/iori/suspendresume/head/sys/amd64/include/vmm.h Sat Aug 3 13:06:28 2013 (r255481) @@ -33,19 +33,29 @@ #define VM_MAX_NAMELEN 32 +#define VM_SUSPEND 1 +#define VM_USERLAND 0 + +/*- vmrun control -*/ +#define REQ_SUSPEND 0x01 +#define REQ_SNAPSHOT 0x02 +#define REQ_SLEEP 0x04 + struct vm; struct vm_memory_segment; struct seg_desc; struct vm_exit; struct vm_run; struct vlapic; +struct vm_vcpustate; +struct vm_registers; enum x2apic_state; typedef int (*vmm_init_func_t)(void); typedef int (*vmm_cleanup_func_t)(void); typedef void * (*vmi_init_func_t)(struct vm *vm); /* instance specific apis */ -typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip); +typedef int (*vmi_run_func_t)(void *vmi, int vcpu, register_t rip, int *control); typedef void (*vmi_cleanup_func_t)(void *vmi); typedef int (*vmi_mmap_set_func_t)(void *vmi, vm_paddr_t gpa, vm_paddr_t hpa, size_t length, @@ -65,11 +75,11 @@ uint32_t code, int code_valid); typedef int (*vmi_get_cap_t)(void *vmi, int vcpu, int num, int *retval); typedef int (*vmi_set_cap_t)(void *vmi, int vcpu, int num, int val); +typedef int (*vmi_reg_copy_t)(void *vmi, int ncpu, struct vm_registers **vmcpu); struct vmm_ops { vmm_init_func_t init; /* module wide initialization */ vmm_cleanup_func_t cleanup; - vmi_init_func_t vminit; /* vm-specific initialization */ vmi_run_func_t vmrun; vmi_cleanup_func_t vmcleanup; @@ -82,6 +92,7 @@ vmi_inject_event_t vminject; vmi_get_cap_t vmgetcap; vmi_set_cap_t vmsetcap; + vmi_reg_copy_t vreg_copy; }; extern struct vmm_ops vmm_ops_intel; @@ -117,6 +128,7 @@ void vm_activate_cpu(struct vm *vm, int vcpu); cpuset_t vm_active_cpus(struct vm *vm); struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid); +int vm_save_vcpustate(struct vm *vm, int i, struct vm_vcpustate *vmstate); /* * Return 1 if device indicated by bus/slot/func is supposed to be a @@ -288,4 +300,120 @@ } u; }; +/* Virtual Machine abstract representation for saving its state)*/ + +typedef struct { + uint16_t highreg; + uint64_t otherreg; +} floatreg80_t; + +typedef struct { + uint64_t hireg; + uint64_t loreg; +} floatreg128_t; + +struct vm_x87_registers { + floatreg80_t st[8]; + uint16_t control_reg; + uint16_t status_reg; + uint16_t tag_reg; + uint16_t opcode; //11bit + uint64_t fip; //instruction pointer + uint64_t dpr; //data pointer register +}; + +struct vm_mmx_registers { + uint64_t mm[8]; +}; + +struct vm_sse_registers { + floatreg128_t xmm[16]; + uint32_t mxcsr; +}; + +struct desc_table_register { + uint64_t baseaddr; + uint32_t table_limit; +}; + +struct segment_register { + uint16_t segselect; + uint64_t baseaddr; + uint32_t table_limit; + uint32_t attribute; +}; + +struct vm_registers { +/* memory_registers */ + struct segment_register *tr; + struct seg_desc *gdtr; + struct seg_desc *ldtr; + struct seg_desc *idtr; + +/* control_registers */ + uint32_t cr0; + uint32_t cr1; + uint32_t cr2; + uint32_t cr3; + uint32_t cr4; + uint64_t cr8; + uint64_t xcr0; + +/* vm_gp_registers */ + uint64_t rax; + uint64_t rbx; + uint64_t rcx; + uint64_t rdx; + uint64_t rdi; + uint64_t rsi; + uint64_t rbp; + uint64_t rsp; + uint64_t r8; + uint64_t r9; + uint64_t r10; + uint64_t r11; + uint64_t r12; + uint64_t r13; + uint64_t r14; + uint64_t r15; + +/* vm_segment_registers */ + struct segment_register *cs; + struct segment_register *ds; + struct segment_register *ss; + struct segment_register *es; + struct segment_register *fs; + struct segment_register *gs; + + uint64_t dr7; //vmcs + uint64_t rflags; + uint64_t rip; + struct savefpu *vfpu; + uint64_t efer; +}; + +struct vm_interrupt_state { +}; + +struct vm_mem_state { +}; + +struct vm_devices { +}; + +struct vm_vcpustate { + struct vm_vcpustate *nextcpu; + struct vm_registers *regs; + struct vm_interrupt_state *intrinfo; +}; + +struct vmstate{ + int bhyve_version; + int host_vendor; + int ncpu; + struct vm_vcpustate *vmcpu; + struct vm_mem_state mem; + struct vm_devices dev; +}; + #endif /* _VMM_H_ */ Modified: soc2013/iori/suspendresume/head/sys/amd64/include/vmm_dev.h ============================================================================== --- soc2013/iori/suspendresume/head/sys/amd64/include/vmm_dev.h Sat Aug 3 12:45:00 2013 (r255480) +++ soc2013/iori/suspendresume/head/sys/amd64/include/vmm_dev.h Sat Aug 3 13:06:28 2013 (r255481) @@ -157,6 +157,7 @@ IOCNUM_VM_STAT_DESC, IOCNUM_SET_X2APIC_STATE, IOCNUM_GET_X2APIC_STATE, + IOCNUM_SAVE_VCPUSTATE, }; #define VM_RUN \ @@ -201,4 +202,6 @@ _IOW('v', IOCNUM_SET_X2APIC_STATE, struct vm_x2apic) #define VM_GET_X2APIC_STATE \ _IOWR('v', IOCNUM_GET_X2APIC_STATE, struct vm_x2apic) +#define VM_SAVE_VCPUSTATE\ + _IOWR('v', IOCNUM_SAVE_VCPUSTATE, struct vmstate) #endif Modified: soc2013/iori/suspendresume/head/sys/amd64/vmm/amd/amdv.c ============================================================================== --- soc2013/iori/suspendresume/head/sys/amd64/vmm/amd/amdv.c Sat Aug 3 12:45:00 2013 (r255480) +++ soc2013/iori/suspendresume/head/sys/amd64/vmm/amd/amdv.c Sat Aug 3 13:06:28 2013 (r255481) @@ -62,7 +62,7 @@ } static int -amdv_vmrun(void *arg, int vcpu, register_t rip) +amdv_vmrun(void *arg, int vcpu, register_t rip, int *control) { printf("amdv_vmrun: not implemented\n"); Modified: soc2013/iori/suspendresume/head/sys/amd64/vmm/intel/vmx.c ============================================================================== --- soc2013/iori/suspendresume/head/sys/amd64/vmm/intel/vmx.c Sat Aug 3 12:45:00 2013 (r255480) +++ soc2013/iori/suspendresume/head/sys/amd64/vmm/intel/vmx.c Sat Aug 3 13:06:28 2013 (r255481) @@ -1436,7 +1436,7 @@ } static int -vmx_run(void *arg, int vcpu, register_t rip) +vmx_run(void *arg, int vcpu, register_t rip, int *control) { int error, vie, rc, handled, astpending; uint32_t exit_reason; @@ -1539,6 +1539,8 @@ handled = vmx_exit_process(vmx, vcpu, vmexit); vmx_exit_trace(vmx, vcpu, rip, exit_reason, handled); + if ( *control == REQ_SUSPEND ) + break; } while (handled); @@ -1566,7 +1568,13 @@ * Can we avoid doing this? */ VMCLEAR(vmcs); - return (0); + + if ( *control ){ + printf("suspend_request has been issued!(cpu=%d)\n", vcpu); + return (VM_SUSPEND); + } + else + return (VM_USERLAND); err_exit: vmexit->exitcode = VM_EXITCODE_VMX; @@ -1930,6 +1938,102 @@ return (retval); } + +static int +vmx_getseg(void *arg, int vcpu, int reg, struct segment_register *seg) +{ + struct seg_desc tmpsegment; + uint64_t tmpregs; + int error; + + printf("getreg"); + error = vmx_getreg(arg, vcpu, reg, &tmpregs); + if (error) + return error; + + printf("getdesc"); + error = vmx_getdesc(arg, vcpu, reg, &tmpsegment); + if (error) + return error; + + printf("seg"); + seg->segselect = (uint16_t) (0xffff & tmpregs); + printf("limit"); + seg->table_limit = tmpsegment.limit; + printf("base"); + seg->baseaddr = tmpsegment.base; + printf("atri"); + seg->attribute = tmpsegment.access; + + return 0; +} + +static int +vmx_cpu_regcopy(void *arg, int ncpu, struct vm_registers **vmcpu) +{ + struct vmx *vmx = arg; + uint64_t tmpreg; + int vcpu; + int buzy_count = 0; + int hostcpu; + + /*- This is a busy loop and must be fixed -*/ + for (vcpu = 0; vcpu < ncpu; vcpu++) + while (vcpu_is_running(vmx->vm, vcpu, &hostcpu)) + buzy_count++; + + printf("buzy_count waiting for vcpu stop is %d", buzy_count); + + /*- save all register and descriptor -*/ + for (vcpu = 0; vcpu < ncpu; vcpu++) { + vmx_getreg(arg, vcpu, VM_REG_GUEST_RAX, &(vmcpu[vcpu]->rax)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_RBX, &(vmcpu[vcpu]->rbx)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_RCX, &(vmcpu[vcpu]->rcx)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_RDX, &(vmcpu[vcpu]->rdx)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_RSI, &(vmcpu[vcpu]->rsi)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_RDI, &(vmcpu[vcpu]->rdi)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_RBP, &(vmcpu[vcpu]->rbp)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_RSP, &(vmcpu[vcpu]->rsp)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_R8, &(vmcpu[vcpu]->r8)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_R9, &(vmcpu[vcpu]->r9)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_R10, &(vmcpu[vcpu]->r10)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_R11, &(vmcpu[vcpu]->r11)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_R12, &(vmcpu[vcpu]->r12)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_R13, &(vmcpu[vcpu]->r13)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_R14, &(vmcpu[vcpu]->r14)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_R15, &(vmcpu[vcpu]->r15)); + + vmx_getreg(arg, vcpu, VM_REG_GUEST_CR0, &tmpreg); + vmcpu[vcpu]->cr0 = (uint32_t)tmpreg; + + vmx_getreg(arg, vcpu, VM_REG_GUEST_CR3, &tmpreg); + + vmcpu[vcpu]->cr3 = (uint32_t)tmpreg; + vmx_getreg(arg, vcpu, VM_REG_GUEST_CR4, &tmpreg); + vmcpu[vcpu]->cr4 = (uint32_t)tmpreg; + + vmx_getreg(arg, vcpu, VM_REG_GUEST_DR7, &(vmcpu[vcpu]->dr7)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_RIP, &(vmcpu[vcpu]->rip)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_RFLAGS, &(vmcpu[vcpu]->rflags)); + vmx_getreg(arg, vcpu, VM_REG_GUEST_EFER, &(vmcpu[vcpu]->efer)); + + vmx_getseg(arg, vcpu, VM_REG_GUEST_ES, (vmcpu[vcpu]->es)); + vmx_getseg(arg, vcpu, VM_REG_GUEST_CS, (vmcpu[vcpu]->cs)); + vmx_getseg(arg, vcpu, VM_REG_GUEST_SS, (vmcpu[vcpu]->ss)); + vmx_getseg(arg, vcpu, VM_REG_GUEST_DS, (vmcpu[vcpu]->ds)); + vmx_getseg(arg, vcpu, VM_REG_GUEST_FS, (vmcpu[vcpu]->fs)); + vmx_getseg(arg, vcpu, VM_REG_GUEST_GS, (vmcpu[vcpu]->gs)); + + vmx_getseg(arg, vcpu, VM_REG_GUEST_TR, (vmcpu[vcpu]->tr)); + + vmx_getdesc(arg, vcpu, VM_REG_GUEST_LDTR, (vmcpu[vcpu]->ldtr)); + vmx_getdesc(arg, vcpu, VM_REG_GUEST_IDTR, (vmcpu[vcpu]->idtr)); + vmx_getdesc(arg, vcpu, VM_REG_GUEST_GDTR, (vmcpu[vcpu]->gdtr)); + } + + return 1; +} + struct vmm_ops vmm_ops_intel = { vmx_init, vmx_cleanup, @@ -1944,5 +2048,6 @@ vmx_setdesc, vmx_inject, vmx_getcap, - vmx_setcap + vmx_setcap, + vmx_cpu_regcopy }; Modified: soc2013/iori/suspendresume/head/sys/amd64/vmm/intel/vmx.h ============================================================================== --- soc2013/iori/suspendresume/head/sys/amd64/vmm/intel/vmx.h Sat Aug 3 12:45:00 2013 (r255480) +++ soc2013/iori/suspendresume/head/sys/amd64/vmm/intel/vmx.h Sat Aug 3 13:06:28 2013 (r255481) @@ -91,6 +91,7 @@ struct vmxstate state[VM_MAXCPU]; struct vm *vm; }; + CTASSERT((offsetof(struct vmx, pml4ept) & PAGE_MASK) == 0); CTASSERT((offsetof(struct vmx, vmcs) & PAGE_MASK) == 0); CTASSERT((offsetof(struct vmx, msr_bitmap) & PAGE_MASK) == 0); Modified: soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm.c ============================================================================== --- soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm.c Sat Aug 3 12:45:00 2013 (r255480) +++ soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm.c Sat Aug 3 13:06:28 2013 (r255481) @@ -64,6 +64,8 @@ #include "io/ppt.h" #include "io/iommu.h" +#include "vm_abststate.h" + struct vlapic; struct vcpu { @@ -101,6 +103,7 @@ * explicitly (AP) by sending it a startup ipi. */ cpuset_t active_cpus; + int control; }; static int vmm_initialized; @@ -110,8 +113,8 @@ #define VMM_CLEANUP() (ops != NULL ? (*ops->cleanup)() : 0) #define VMINIT(vm) (ops != NULL ? (*ops->vminit)(vm): NULL) -#define VMRUN(vmi, vcpu, rip) \ - (ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip) : ENXIO) +#define VMRUN(vmi, vcpu, rip, control) \ + (ops != NULL ? (*ops->vmrun)(vmi, vcpu, rip, control) : ENXIO) #define VMCLEANUP(vmi) (ops != NULL ? (*ops->vmcleanup)(vmi) : NULL) #define VMMMAP_SET(vmi, gpa, hpa, len, attr, prot, spm) \ (ops != NULL ? \ @@ -134,10 +137,14 @@ #define VMSETCAP(vmi, vcpu, num, val) \ (ops != NULL ? (*ops->vmsetcap)(vmi, vcpu, num, val) : ENXIO) +#define VREG_COPY(vmi, ncpu, vregs) \ + (ops != NULL ? (*ops->vreg_copy)(vmi, ncpu, vregs) : ENXIO) + #define fpu_start_emulating() load_cr0(rcr0() | CR0_TS) #define fpu_stop_emulating() clts() static MALLOC_DEFINE(M_VM, "vm", "vm"); +static MALLOC_DEFINE(M_VMREGISTERS, "vreg", "snapshot image of virual cpu"); CTASSERT(VMM_MSR_NUM <= 64); /* msr_mask can keep track of up to 64 msrs */ /* statistics */ @@ -632,6 +639,82 @@ static VMM_STAT(VCPU_IDLE_TICKS, "number of ticks vcpu was idle"); + +static struct vm_registers** +construct_vmcpu_snapshot(const int ncpu) +{ + int i = 0; + struct vm_registers **vmcpu = + malloc(ncpu * sizeof(struct vm_registers*), + M_VMREGISTERS, M_ZERO | M_WAITOK); + + for (;i < ncpu; i++){ + vmcpu[i] = + malloc(sizeof(struct vm_registers), M_VMREGISTERS, M_ZERO | M_WAITOK); + + vmcpu[i]->cs = + malloc(sizeof(struct segment_register), M_VMREGISTERS, + M_ZERO | M_WAITOK); + + vmcpu[i]->ds = + malloc(sizeof(struct segment_register), M_VMREGISTERS, + M_ZERO | M_WAITOK); + + vmcpu[i]->ss = + malloc(sizeof(struct segment_register), M_VMREGISTERS, + M_ZERO | M_WAITOK); + + vmcpu[i]->es = + malloc(sizeof(struct segment_register), M_VMREGISTERS, + M_ZERO | M_WAITOK); + + vmcpu[i]->fs = + malloc(sizeof(struct segment_register), M_VMREGISTERS, + M_ZERO | M_WAITOK); + + vmcpu[i]->gs = + malloc(sizeof(struct segment_register), M_VMREGISTERS, + M_ZERO | M_WAITOK); + + vmcpu[i]->tr = + malloc(sizeof(struct segment_register), M_VMREGISTERS, + M_ZERO | M_WAITOK); + + vmcpu[i]->gdtr = + malloc(sizeof(struct seg_desc), M_VMREGISTERS, + M_ZERO | M_WAITOK); + + vmcpu[i]->ldtr = + malloc(sizeof(struct seg_desc), M_VMREGISTERS, + M_ZERO | M_WAITOK); + + vmcpu[i]->idtr = + malloc(sizeof(struct seg_desc), M_VMREGISTERS, + M_ZERO | M_WAITOK); + } + return vmcpu; +} + +static void +destruct_vmcpu_snapshot(struct vm_registers *vmcpu[], int ncpu) +{ + int i = 0; + for (;i < ncpu; i++) { + free(vmcpu[i]->cs, M_VMREGISTERS); + free(vmcpu[i]->ds, M_VMREGISTERS); + free(vmcpu[i]->ss, M_VMREGISTERS); + free(vmcpu[i]->es, M_VMREGISTERS); + free(vmcpu[i]->fs, M_VMREGISTERS); + free(vmcpu[i]->gs, M_VMREGISTERS); + free(vmcpu[i]->tr, M_VMREGISTERS); + free(vmcpu[i]->gdtr, M_VMREGISTERS); + free(vmcpu[i]->ldtr, M_VMREGISTERS); + free(vmcpu[i]->idtr, M_VMREGISTERS); + free(vmcpu[i], M_VMREGISTERS); + } + free(vmcpu, M_VMREGISTERS); +} + int vm_run(struct vm *vm, struct vm_run *vmrun) { @@ -661,7 +744,7 @@ restore_guest_fpustate(vcpu); vcpu->hostcpu = curcpu; - error = VMRUN(vm->cookie, vcpuid, rip); + error = VMRUN(vm->cookie, vcpuid, rip, &(vm->control)); vcpu->hostcpu = NOCPU; save_guest_fpustate(vcpu); @@ -715,6 +798,10 @@ rip = vme->rip + vme->inst_length; goto restart; } + if (error == VM_SUSPEND) { + /*- stab -*/ + printf("hook"); + } return (error); } @@ -997,3 +1084,71 @@ } vcpu_unlock(vcpu); } + +int +vm_save_vcpustate(struct vm *vm, int ncpu, struct vm_vcpustate *vmcpu) +{ + int ret; + int vcpuid; + struct segment_register *cs, *ds, *ss, *es, *fs, *gs; + struct vm_registers **vmregs; + struct vm_vcpustate kvmcpu; + struct vm_registers kvmregs; + struct vcpu *vcpu, *kvcpu; + + vm->control = REQ_SUSPEND; + + for (vcpuid = 0; vcpuid < ncpu; vcpuid++) + vm_interrupt_hostcpu(vm, vcpuid); + + vmregs = construct_vmcpu_snapshot(2); + ret = VREG_COPY(vm->cookie, ncpu, vmregs); + printf("vmcpu is %p", vmcpu); + copyin(vmcpu, &kvmcpu, sizeof(struct vm_vcpuidstate)); + printf("vreg is %p", kvmcpu.regs); + + for (vcpuid = 0; vcpuid < ncpu; vcpuid++) { + vcpu = &vm->vcpu[vcpuid]; + printf("start to copy in\n"); +/* vm_segment_registers */ + printf("1 to copy in\n"); + copyin(kvmcpu.regs, &kvmregs, + sizeof(struct vm_vcpuidstate)); + + printf("rax=%lu\n", kvmregs.rax); + + printf("start to copy out\n"); +/* vm_segment_registers */ + copyout(vmregs[vcpuid]->cs, cs = kvmregs.cs, + sizeof(struct segment_register)); + printf("1 to copy out\n"); + copyout(vmregs[vcpuid]->ds, ds = kvmregs.ds, + sizeof(struct segment_register)); + copyout(vmregs[vcpuid]->ss, ss = kvmregs.ss, + sizeof(struct segment_register)); + copyout(vmregs[vcpuid]->es, es = kvmregs.es, + sizeof(struct segment_register)); + copyout(vmregs[vcpuid]->fs, fs = kvmregs.fs, + sizeof(struct segment_register)); + copyout(vmregs[vcpuid]->gs, gs = kvmregs.gs, + sizeof(struct segment_register)); + copyout(vcpu->guestfpu, kvcpu = kvmregs.vfpu, + sizeof(struct segment_register*)); + + copyout(vmregs[vcpuid], vmcpu->regs, sizeof(struct vm_registers)); + + copyout(&cs, &(kvmregs.cs), sizeof(struct segment_register*)); + copyout(&ds, &(kvmregs.ds), sizeof(struct segment_register*)); + copyout(&ss, &(kvmregs.ss), sizeof(struct segment_register*)); + copyout(&es, &(kvmregs.es), sizeof(struct segment_register*)); + copyout(&fs, &(kvmregs.fs), sizeof(struct segment_register*)); + copyout(&gs, &(kvmregs.gs), sizeof(struct segment_register*)); + + + vmcpu = kvmcpu.nextcpu; + } + + destruct_vmcpu_snapshot(vmregs, ncpu); + return ret; +}; + Modified: soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm_dev.c ============================================================================== --- soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm_dev.c Sat Aug 3 12:45:00 2013 (r255480) +++ soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm_dev.c Sat Aug 3 13:06:28 2013 (r255481) @@ -54,6 +54,7 @@ #include "vmm_mem.h" #include "io/ppt.h" #include <machine/vmm_dev.h> +#include "vm_abststate.h" struct vmmdev_softc { struct vm *vm; /* vm instance cookie */ @@ -156,6 +157,7 @@ struct vm_stats *vmstats; struct vm_stat_desc *statdesc; struct vm_x2apic *x2apic; + struct vmstate *vmstate; sc = vmmdev_lookup2(cdev); if (sc == NULL) @@ -219,6 +221,7 @@ if (error) { while (--vcpu >= 0) vcpu_set_state(sc->vm, vcpu, VCPU_IDLE); + printf("vm busy. cmd: %lx\n", cmd); goto done; } @@ -348,6 +351,11 @@ error = vm_get_x2apic_state(sc->vm, x2apic->cpuid, &x2apic->state); break; + case VM_SAVE_VCPUSTATE: + vmstate = (struct vmstate *)data; + vmstate->bhyve_version = 0; + error = vm_save_vcpustate(sc->vm, vmstate->ncpu, vmstate->vmcpu); + break; default: error = ENOTTY; break;
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201308031306.r73D6Sx5070572>