socsvn commit: r257754 - in soc2013/iori/suspendresume/head: lib/libvmmapi sys/amd64/include sys/amd64/vmm sys/amd64/vmm/intel usr.sbin/bhyveload

iori at FreeBSD.org iori at FreeBSD.org
Fri Sep 27 10:06:14 UTC 2013


Author: iori
Date: Fri Sep 27 10:06:14 2013
New Revision: 257754
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=257754

Log:
  last commit in SoC.
  
  
  PR: Add register test api (not working).
  If it works well, I can confirm the register reloading is working correctly
  or not.
  What I have to check about register save/load are below:
  - The registers to be saved is enough or not
  - The registers to be loaded is enough or not
  - What is the best way to save the registers into a file
  
  And I make memory dump with dd command, but it's throttled, so I have to
  know the good practice to save it.
  
  (device state is included on vmm memory device).
  

Modified:
  soc2013/iori/suspendresume/head/lib/libvmmapi/vmmapi.c
  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/intel/vmx.c
  soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm.c
  soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm_dev.c
  soc2013/iori/suspendresume/head/usr.sbin/bhyveload/Makefile
  soc2013/iori/suspendresume/head/usr.sbin/bhyveload/bhyveload.8
  soc2013/iori/suspendresume/head/usr.sbin/bhyveload/bhyveload.c

Modified: soc2013/iori/suspendresume/head/lib/libvmmapi/vmmapi.c
==============================================================================
--- soc2013/iori/suspendresume/head/lib/libvmmapi/vmmapi.c	Fri Sep 27 09:55:06 2013	(r257753)
+++ soc2013/iori/suspendresume/head/lib/libvmmapi/vmmapi.c	Fri Sep 27 10:06:14 2013	(r257754)
@@ -124,6 +124,15 @@
 }
 
 unsigned long
+vm_set_allvstate(struct vmctx *ctx, struct vmstate *vmstate)
+{
+	int error;
+
+	error = ioctl(ctx->fd, VM_RESTORE_VCPUSTATE, vmstate);
+	return error;
+}
+
+unsigned long
 vm_get_allvstate(struct vmctx *ctx, struct vmstate *vmstate)
 {
 	int error;
@@ -132,6 +141,14 @@
 	return error;
 }
 
+int
+vm_polute_register(struct vmctx *ctx)
+{
+	int error;
+	error = ioctl(ctx->fd, VM_POLUTE_VCPUSTATE, NULL);
+	return error;
+}
+
 size_t
 vmm_get_mem_total(void)
 {
@@ -316,6 +333,21 @@
 }
 
 int
+vm_set_register(struct vmctx *ctx, int vcpu, int reg, uint64_t val)
+{
+	int error;
+	struct vm_register vmreg;
+
+	bzero(&vmreg, sizeof(vmreg));
+	vmreg.cpuid = vcpu;
+	vmreg.regnum = reg;
+	vmreg.regval = val;
+
+	error = ioctl(ctx->fd, VM_SET_REGISTER, &vmreg);
+	return (error);
+}
+
+int
 vm_get_register(struct vmctx *ctx, int vcpu, int reg, uint64_t *ret_val)
 {
 	int error;

Modified: soc2013/iori/suspendresume/head/sys/amd64/include/vmm.h
==============================================================================
--- soc2013/iori/suspendresume/head/sys/amd64/include/vmm.h	Fri Sep 27 09:55:06 2013	(r257753)
+++ soc2013/iori/suspendresume/head/sys/amd64/include/vmm.h	Fri Sep 27 10:06:14 2013	(r257754)
@@ -76,6 +76,7 @@
 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);
+typedef int (*vmi_reg_restore_t)(void *vmi, int ncpu, struct vm_registers **vmcpu);
 
 struct vmm_ops {
 	vmm_init_func_t		init;		/* module wide initialization */
@@ -93,6 +94,7 @@
 	vmi_get_cap_t		vmgetcap;
 	vmi_set_cap_t		vmsetcap;
 	vmi_reg_copy_t vreg_copy;
+	vmi_reg_restore_t vreg_restore;
 };
 
 extern struct vmm_ops vmm_ops_intel;
@@ -129,6 +131,7 @@
 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);
+int vm_restore_vcpustate(struct vm *vm, int i, struct vm_vcpustate *vmstate);
 
 /*
  * Return 1 if device indicated by bus/slot/func is supposed to be a

Modified: soc2013/iori/suspendresume/head/sys/amd64/include/vmm_dev.h
==============================================================================
--- soc2013/iori/suspendresume/head/sys/amd64/include/vmm_dev.h	Fri Sep 27 09:55:06 2013	(r257753)
+++ soc2013/iori/suspendresume/head/sys/amd64/include/vmm_dev.h	Fri Sep 27 10:06:14 2013	(r257754)
@@ -158,6 +158,7 @@
 	IOCNUM_SET_X2APIC_STATE,
 	IOCNUM_GET_X2APIC_STATE,
 	IOCNUM_SAVE_VCPUSTATE,
+	IOCNUM_RESTORE_VCPUSTATE,
 };
 
 #define	VM_RUN		\
@@ -204,4 +205,6 @@
 	_IOWR('v', IOCNUM_GET_X2APIC_STATE, struct vm_x2apic)
 #define	VM_SAVE_VCPUSTATE\
 	_IOWR('v', IOCNUM_SAVE_VCPUSTATE, struct vmstate)
+#define	VM_RESTORE_VCPUSTATE\
+	_IOWR('v', IOCNUM_RESTORE_VCPUSTATE, struct vmstate)
 #endif

Modified: soc2013/iori/suspendresume/head/sys/amd64/vmm/intel/vmx.c
==============================================================================
--- soc2013/iori/suspendresume/head/sys/amd64/vmm/intel/vmx.c	Fri Sep 27 09:55:06 2013	(r257753)
+++ soc2013/iori/suspendresume/head/sys/amd64/vmm/intel/vmx.c	Fri Sep 27 10:06:14 2013	(r257754)
@@ -2007,8 +2007,8 @@
 		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;
 
@@ -2034,6 +2034,68 @@
 	return 1;
 }
 
+static int
+vmx_cpu_regdisp(void *arg, int ncpu, struct vm_registers **vmcpu)
+{
+	struct vmx *vmx = arg;
+	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_setreg(arg, vcpu, VM_REG_GUEST_RAX, vmcpu[vcpu]->rax);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_RBX, vmcpu[vcpu]->rbx);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_RCX, vmcpu[vcpu]->rcx);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_RDX, vmcpu[vcpu]->rdx);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_RSI, vmcpu[vcpu]->rsi);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_RDI, vmcpu[vcpu]->rdi);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_RBP, vmcpu[vcpu]->rbp);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_RSP, vmcpu[vcpu]->rsp);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_R8, vmcpu[vcpu]->r8);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_R9, vmcpu[vcpu]->r9);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_R10, vmcpu[vcpu]->r10);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_R11, vmcpu[vcpu]->r11);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_R12, vmcpu[vcpu]->r12);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_R13, vmcpu[vcpu]->r13);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_R14, vmcpu[vcpu]->r14);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_R15, vmcpu[vcpu]->r15);
+
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_CR0, (uint64_t)vmcpu[vcpu]->cr0);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_CR3, (uint64_t)vmcpu[vcpu]->cr3);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_CR4, (uint64_t)vmcpu[vcpu]->cr4);
+
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_DR7, vmcpu[vcpu]->dr7);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_RIP, vmcpu[vcpu]->rip);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_RFLAGS, vmcpu[vcpu]->rflags);
+		vmx_setreg(arg, vcpu, VM_REG_GUEST_EFER, vmcpu[vcpu]->efer);
+
+		/*
+		vmx_setseg(arg, vcpu, VM_REG_GUEST_ES, *(vmcpu[vcpu]->es));
+		vmx_setseg(arg, vcpu, VM_REG_GUEST_CS, *(vmcpu[vcpu]->cs));
+		vmx_setseg(arg, vcpu, VM_REG_GUEST_SS, *(vmcpu[vcpu]->ss));
+		vmx_setseg(arg, vcpu, VM_REG_GUEST_DS, *(vmcpu[vcpu]->ds));
+		vmx_setseg(arg, vcpu, VM_REG_GUEST_FS, *(vmcpu[vcpu]->fs));
+		vmx_setseg(arg, vcpu, VM_REG_GUEST_GS, *(vmcpu[vcpu]->gs));
+
+		vmx_setseg(arg, vcpu, VM_REG_GUEST_TR, *(vmcpu[vcpu]->tr));
+		*/
+	
+		vmx_setdesc(arg, vcpu, VM_REG_GUEST_LDTR, vmcpu[vcpu]->ldtr);
+		vmx_setdesc(arg, vcpu, VM_REG_GUEST_IDTR, vmcpu[vcpu]->idtr);
+		vmx_setdesc(arg, vcpu, VM_REG_GUEST_GDTR, vmcpu[vcpu]->gdtr);
+	}
+
+	return 1;
+}
+
 struct vmm_ops vmm_ops_intel = {
 	vmx_init,
 	vmx_cleanup,
@@ -2049,5 +2111,7 @@
 	vmx_inject,
 	vmx_getcap,
 	vmx_setcap,
-	vmx_cpu_regcopy
+	vmx_cpu_regcopy,
+	vmx_cpu_regdisp,
 };
+

Modified: soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm.c
==============================================================================
--- soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm.c	Fri Sep 27 09:55:06 2013	(r257753)
+++ soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm.c	Fri Sep 27 10:06:14 2013	(r257754)
@@ -139,6 +139,8 @@
 
 #define	VREG_COPY(vmi, ncpu, vregs)		\
 	(ops != NULL ? (*ops->vreg_copy)(vmi, ncpu, vregs) : ENXIO)
+#define	VREG_RESTORE(vmi, ncpu, vregs)		\
+	(ops != NULL ? (*ops->vreg_restore)(vmi, ncpu, vregs) : ENXIO)
 
 #define	fpu_start_emulating()	load_cr0(rcr0() | CR0_TS)
 #define	fpu_stop_emulating()	clts()
@@ -1094,34 +1096,35 @@
 	struct vm_registers **vmregs;
 	struct vm_vcpustate kvmcpu;
 	struct vm_registers kvmregs;
-	struct vcpu *vcpu, *kvcpu;
+	struct vcpu *vcpu;
+	struct savefpu* kfpu;
 
 	vm->control = REQ_SUSPEND;
 	
 	for (vcpuid = 0; vcpuid < ncpu; vcpuid++)
 		vm_interrupt_hostcpu(vm, vcpuid);
 
-	vmregs = construct_vmcpu_snapshot(2);
+	vmregs = construct_vmcpu_snapshot(ncpu);
+
 	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);
+	/* we have to know the addresses of non-integer registers or structured
+	 * register. The addresses are used to save these registers and after
+	 * save operation, this addresses are written back into virtual registers
+	 * struct.
+	 */
+	copyin(vmcpu, &kvmcpu, sizeof(struct vm_vcpustate));
 
 	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);
+				sizeof(struct vm_vcpustate));
 
 		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,
@@ -1132,9 +1135,10 @@
 				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*));
 
+/* vm registers */
+		copyout(vcpu->guestfpu, kfpu = kvmregs.vfpu,
+				sizeof(struct segment_register*));
 		copyout(vmregs[vcpuid], vmcpu->regs, sizeof(struct vm_registers));
 
 		copyout(&cs, &(kvmregs.cs), sizeof(struct segment_register*));
@@ -1143,6 +1147,7 @@
 		copyout(&es, &(kvmregs.es), sizeof(struct segment_register*));
 		copyout(&fs, &(kvmregs.fs), sizeof(struct segment_register*));
 		copyout(&gs, &(kvmregs.gs), sizeof(struct segment_register*));
+		copyout(&kfpu, &(kvmregs.vfpu), sizeof(struct savefpu*));
 
 
 		vmcpu = kvmcpu.nextcpu;
@@ -1152,3 +1157,51 @@
 	return ret;
 };
 
+int
+vm_restore_vcpustate(struct vm *vm, int ncpu, struct vm_vcpustate *vmcpu)
+{
+	int ret;
+	int vcpuid;
+	struct vm_registers **vmregs;
+	struct vm_vcpustate kvmcpu;
+	struct vm_registers kvmregs;
+	struct vcpu *vcpu;
+
+	printf("restoring vm is not implemented yet.\n");
+	vmregs = construct_vmcpu_snapshot(ncpu);
+
+	copyin(vmcpu, &kvmcpu, sizeof(struct vm_vcpustate));
+
+	for (vcpuid = 0; vcpuid != ncpu; vcpuid++) {
+		vcpu = &vm->vcpu[vcpuid];
+		copyin(kvmcpu.regs, &kvmregs,
+				sizeof(struct vm_vcpustate));
+
+/*  vm_segment_registers  */
+		copyin(kvmregs.cs, vmregs[vcpuid]->cs,
+				sizeof(struct segment_register));
+
+		copyin(kvmregs.ds, vmregs[vcpuid]->ds,
+				sizeof(struct segment_register));
+
+		copyin(kvmregs.ss, vmregs[vcpuid]->ss,
+				sizeof(struct segment_register));
+
+		copyin(kvmregs.es, vmregs[vcpuid]->es,
+				sizeof(struct segment_register));
+
+		copyin(kvmregs.ds, vmregs[vcpuid]->fs,
+				sizeof(struct segment_register));
+
+		copyin(kvmregs.ds, vmregs[vcpuid]->gs,
+				sizeof(struct segment_register));
+
+		VREG_RESTORE(vm->cookie, ncpu, vmregs);
+
+		copyin(kvmregs.vfpu, vcpu->guestfpu,
+				sizeof(struct segment_register*));
+	}
+	ret = 1;
+	return ret;
+}
+

Modified: soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm_dev.c
==============================================================================
--- soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm_dev.c	Fri Sep 27 09:55:06 2013	(r257753)
+++ soc2013/iori/suspendresume/head/sys/amd64/vmm/vmm_dev.c	Fri Sep 27 10:06:14 2013	(r257754)
@@ -351,6 +351,15 @@
 		error = vm_get_x2apic_state(sc->vm,
 					    x2apic->cpuid, &x2apic->state);
 		break;
+	case VM_RESTORE_VCPUSTATE:
+		vmstate = (struct vmstate *)data;
+		if (vmstate->bhyve_version == 0)
+			error = vm_restore_vcpustate(sc->vm, vmstate->ncpu, vmstate->vmcpu);
+		else {
+			printf("unknown bhyve save file version!\n");
+			error = -1;
+		}
+		break;
 	case VM_SAVE_VCPUSTATE:
 		vmstate = (struct vmstate *)data;
 		vmstate->bhyve_version = 0;

Modified: soc2013/iori/suspendresume/head/usr.sbin/bhyveload/Makefile
==============================================================================
--- soc2013/iori/suspendresume/head/usr.sbin/bhyveload/Makefile	Fri Sep 27 09:55:06 2013	(r257753)
+++ soc2013/iori/suspendresume/head/usr.sbin/bhyveload/Makefile	Fri Sep 27 10:06:14 2013	(r257754)
@@ -1,7 +1,7 @@
 # $FreeBSD$
 
 PROG=	bhyveload
-SRCS=	bhyveload.c
+SRCS=	bhyveload.c standalone.c
 MAN=	bhyveload.8
 
 DPADD+=	${LIBVMMAPI}

Modified: soc2013/iori/suspendresume/head/usr.sbin/bhyveload/bhyveload.8
==============================================================================
--- soc2013/iori/suspendresume/head/usr.sbin/bhyveload/bhyveload.8	Fri Sep 27 09:55:06 2013	(r257753)
+++ soc2013/iori/suspendresume/head/usr.sbin/bhyveload/bhyveload.8	Fri Sep 27 10:06:14 2013	(r257754)
@@ -38,6 +38,7 @@
 .Op Fl m Ar mem-size
 .Op Fl d Ar disk-path
 .Op Fl h Ar host-path
+.Op Fl S Ar stand-binary:stand-addr
 .Ar vmname
 .Sh DESCRIPTION
 .Nm
@@ -75,6 +76,13 @@
 The
 .Ar host-path
 is the directory at the top of the guest's boot filesystem.
+.It Fl S Ar stand-binary:stand-addr
+The
+.Ar stand-binary
+is the pathname of the standalone guest program.
+The
+.Ar stand-addr
+is the entrypoint address of the standalone guest program.
 .El
 .Sh EXAMPLES
 To create a virtual machine named

Modified: soc2013/iori/suspendresume/head/usr.sbin/bhyveload/bhyveload.c
==============================================================================
--- soc2013/iori/suspendresume/head/usr.sbin/bhyveload/bhyveload.c	Fri Sep 27 09:55:06 2013	(r257753)
+++ soc2013/iori/suspendresume/head/usr.sbin/bhyveload/bhyveload.c	Fri Sep 27 10:06:14 2013	(r257754)
@@ -95,6 +95,9 @@
 
 static void cb_exit(void *arg, int v);
 
+extern int stand_load(struct loader_callbacks *cb, char *image, 
+    uint64_t addr);
+
 /*
  * Console i/o callbacks
  */
@@ -552,6 +555,7 @@
 
 	fprintf(stderr,
 		"usage: %s [-m mem-size][-d <disk-path>] [-h <host-path>] "
+		"[-S stand-binary:stand-addr] "
 		"<vmname>\n", progname);
 	exit(1);
 }
@@ -563,6 +567,8 @@
 	void (*func)(struct loader_callbacks *, void *, int, int);
 	uint64_t mem_size;
 	int opt, error;
+	uint64_t stand_addr;
+	char *stand_image;
 	char *disk_image;
 
 	progname = argv[0];
@@ -570,7 +576,7 @@
 	mem_size = 256 * MB;
 	disk_image = NULL;
 
-	while ((opt = getopt(argc, argv, "d:h:m:")) != -1) {
+	while ((opt = getopt(argc, argv, "d:h:m:S:")) != -1) {
 		switch (opt) {
 		case 'd':
 			disk_image = optarg;
@@ -583,7 +589,26 @@
 		case 'm':
 			mem_size = strtoul(optarg, NULL, 0) * MB;
 			break;
-		
+
+		case 'S': {
+			char *addr_str;
+
+			stand_image = strtok(optarg, ":");
+			if (stand_image == NULL) {
+				usage();
+				break;
+			}
+
+			addr_str = strtok(NULL, ":");
+			if (addr_str == NULL) {
+				usage();
+				break;
+			}
+			stand_addr = strtoll(addr_str, NULL, 0);
+			
+			break;
+		}
+
 		case '?':
 			usage();
 		}
@@ -621,6 +646,11 @@
 	term.c_lflag &= ~(ICANON|ECHO);
 	term.c_iflag &= ~ICRNL;
 	tcsetattr(0, TCSAFLUSH, &term);
+	if (stand_image) {
+		if (stand_load(&cb, stand_image, stand_addr))
+			exit(1);
+		exit(0);
+	}
 	h = dlopen("/boot/userboot.so", RTLD_LOCAL);
 	if (!h) {
 		printf("%s\n", dlerror());


More information about the svn-soc-all mailing list