summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2014-05-31 23:37:34 +0000
committerneel <neel@FreeBSD.org>2014-05-31 23:37:34 +0000
commit9c2a9423876303af6b7757283943735603cdacf7 (patch)
tree7c418a681bb97d7aaf33db6bbb701d15bf078026 /sys/amd64
parent7f92c4861a4aba3ec77c8d72e941a081d86a2d1a (diff)
downloadFreeBSD-src-9c2a9423876303af6b7757283943735603cdacf7.zip
FreeBSD-src-9c2a9423876303af6b7757283943735603cdacf7.tar.gz
Activate vcpus from bhyve(8) using the ioctl VM_ACTIVATE_CPU instead of doing
it implicitly in vmm.ko. Add ioctl VM_GET_CPUS to get the current set of 'active' and 'suspended' cpus and display them via /usr/sbin/bhyvectl using the "--get-active-cpus" and "--get-suspended-cpus" options. This is in preparation for being able to reset virtual machine state without having to destroy and recreate it.
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/include/vmm.h3
-rw-r--r--sys/amd64/include/vmm_dev.h20
-rw-r--r--sys/amd64/vmm/io/vlapic.c4
-rw-r--r--sys/amd64/vmm/vmm.c29
-rw-r--r--sys/amd64/vmm/vmm_dev.c29
5 files changed, 70 insertions, 15 deletions
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h
index f1902d2..05df325 100644
--- a/sys/amd64/include/vmm.h
+++ b/sys/amd64/include/vmm.h
@@ -140,8 +140,9 @@ int vm_set_capability(struct vm *vm, int vcpu, int type, int val);
int vm_get_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state *state);
int vm_set_x2apic_state(struct vm *vm, int vcpu, enum x2apic_state state);
int vm_apicid2vcpuid(struct vm *vm, int apicid);
-void vm_activate_cpu(struct vm *vm, int vcpu);
+int vm_activate_cpu(struct vm *vm, int vcpu);
cpuset_t vm_active_cpus(struct vm *vm);
+cpuset_t vm_suspended_cpus(struct vm *vm);
struct vm_exit *vm_exitinfo(struct vm *vm, int vcpuid);
void vm_exit_suspended(struct vm *vm, int vcpuid, uint64_t rip);
diff --git a/sys/amd64/include/vmm_dev.h b/sys/amd64/include/vmm_dev.h
index f094d51..a6568dc 100644
--- a/sys/amd64/include/vmm_dev.h
+++ b/sys/amd64/include/vmm_dev.h
@@ -177,6 +177,18 @@ struct vm_gla2gpa {
uint64_t gpa;
};
+struct vm_activate_cpu {
+ int vcpuid;
+};
+
+struct vm_cpuset {
+ int which;
+ int cpusetsize;
+ cpuset_t *cpus;
+};
+#define VM_ACTIVE_CPUS 0
+#define VM_SUSPENDED_CPUS 1
+
enum {
/* general routines */
IOCNUM_ABIVERS = 0,
@@ -229,6 +241,10 @@ enum {
IOCNUM_ISA_DEASSERT_IRQ = 81,
IOCNUM_ISA_PULSE_IRQ = 82,
IOCNUM_ISA_SET_IRQ_TRIGGER = 83,
+
+ /* vm_cpuset */
+ IOCNUM_ACTIVATE_CPU = 90,
+ IOCNUM_GET_CPUSET = 91,
};
#define VM_RUN \
@@ -301,4 +317,8 @@ enum {
_IOWR('v', IOCNUM_GET_GPA_PMAP, struct vm_gpa_pte)
#define VM_GLA2GPA \
_IOWR('v', IOCNUM_GLA2GPA, struct vm_gla2gpa)
+#define VM_ACTIVATE_CPU \
+ _IOW('v', IOCNUM_ACTIVATE_CPU, struct vm_activate_cpu)
+#define VM_GET_CPUS \
+ _IOW('v', IOCNUM_GET_CPUSET, struct vm_cpuset)
#endif
diff --git a/sys/amd64/vmm/io/vlapic.c b/sys/amd64/vmm/io/vlapic.c
index d93641c..4034d34 100644
--- a/sys/amd64/vmm/io/vlapic.c
+++ b/sys/amd64/vmm/io/vlapic.c
@@ -1004,11 +1004,7 @@ vlapic_icrlo_write_handler(struct vlapic *vlapic, bool *retu)
if (vlapic2->boot_state != BS_SIPI)
return (0);
- /*
- * XXX this assumes that the startup IPI always succeeds
- */
vlapic2->boot_state = BS_RUNNING;
- vm_activate_cpu(vlapic2->vm, dest);
*retu = true;
vmexit = vm_exitinfo(vlapic->vm, vlapic->vcpuid);
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
index 8ebdfd7..e84359d 100644
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -342,8 +342,6 @@ vm_create(const char *name, struct vm **retvm)
struct vm *vm;
struct vmspace *vmspace;
- const int BSP = 0;
-
/*
* If vmm.ko could not be successfully initialized then don't attempt
* to create the virtual machine.
@@ -373,8 +371,6 @@ vm_create(const char *name, struct vm **retvm)
guest_msrs_init(vm, i);
}
- vm_activate_cpu(vm, BSP);
-
*retvm = vm;
return (0);
}
@@ -1294,6 +1290,12 @@ vm_run(struct vm *vm, struct vm_run *vmrun)
if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
return (EINVAL);
+ if (!CPU_ISSET(vcpuid, &vm->active_cpus))
+ return (EINVAL);
+
+ if (CPU_ISSET(vcpuid, &vm->suspended_cpus))
+ return (EINVAL);
+
rptr = &vm->rendezvous_func;
sptr = &vm->suspend;
pmap = vmspace_pmap(vm->vmspace);
@@ -1708,17 +1710,19 @@ vcpu_get_state(struct vm *vm, int vcpuid, int *hostcpu)
return (state);
}
-void
+int
vm_activate_cpu(struct vm *vm, int vcpuid)
{
- KASSERT(vcpuid >= 0 && vcpuid < VM_MAXCPU,
- ("vm_activate_cpu: invalid vcpuid %d", vcpuid));
- KASSERT(!CPU_ISSET(vcpuid, &vm->active_cpus),
- ("vm_activate_cpu: vcpuid %d is already active", vcpuid));
+ if (vcpuid < 0 || vcpuid >= VM_MAXCPU)
+ return (EINVAL);
+
+ if (CPU_ISSET(vcpuid, &vm->active_cpus))
+ return (EBUSY);
VCPU_CTR0(vm, vcpuid, "activated");
CPU_SET_ATOMIC(vcpuid, &vm->active_cpus);
+ return (0);
}
cpuset_t
@@ -1728,6 +1732,13 @@ vm_active_cpus(struct vm *vm)
return (vm->active_cpus);
}
+cpuset_t
+vm_suspended_cpus(struct vm *vm)
+{
+
+ return (vm->suspended_cpus);
+}
+
void *
vcpu_stats(struct vm *vm, int vcpuid)
{
diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c
index 0561785..824389f 100644
--- a/sys/amd64/vmm/vmm_dev.c
+++ b/sys/amd64/vmm/vmm_dev.c
@@ -146,7 +146,8 @@ static int
vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
struct thread *td)
{
- int error, vcpu, state_changed;
+ int error, vcpu, state_changed, size;
+ cpuset_t *cpuset;
struct vmmdev_softc *sc;
struct vm_memory_segment *seg;
struct vm_register *vmreg;
@@ -170,6 +171,8 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
struct vm_gpa_pte *gpapte;
struct vm_suspend *vmsuspend;
struct vm_gla2gpa *gg;
+ struct vm_activate_cpu *vac;
+ struct vm_cpuset *vm_cpuset;
sc = vmmdev_lookup2(cdev);
if (sc == NULL)
@@ -195,6 +198,7 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
case VM_PPTDEV_MSIX:
case VM_SET_X2APIC_STATE:
case VM_GLA2GPA:
+ case VM_ACTIVATE_CPU:
/*
* XXX fragile, handle with care
* Assumes that the first field of the ioctl data is the vcpu.
@@ -439,6 +443,29 @@ vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag,
}
break;
}
+ case VM_ACTIVATE_CPU:
+ vac = (struct vm_activate_cpu *)data;
+ error = vm_activate_cpu(sc->vm, vac->vcpuid);
+ break;
+ case VM_GET_CPUS:
+ error = 0;
+ vm_cpuset = (struct vm_cpuset *)data;
+ size = vm_cpuset->cpusetsize;
+ if (size < sizeof(cpuset_t) || size > CPU_MAXSIZE / NBBY) {
+ error = ERANGE;
+ break;
+ }
+ cpuset = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
+ if (vm_cpuset->which == VM_ACTIVE_CPUS)
+ *cpuset = vm_active_cpus(sc->vm);
+ else if (vm_cpuset->which == VM_SUSPENDED_CPUS)
+ *cpuset = vm_suspended_cpus(sc->vm);
+ else
+ error = EINVAL;
+ if (error == 0)
+ error = copyout(cpuset, vm_cpuset->cpus, size);
+ free(cpuset, M_TEMP);
+ break;
default:
error = ENOTTY;
break;
OpenPOWER on IntegriCloud