From 9c2a9423876303af6b7757283943735603cdacf7 Mon Sep 17 00:00:00 2001 From: neel Date: Sat, 31 May 2014 23:37:34 +0000 Subject: 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. --- sys/amd64/include/vmm.h | 3 ++- sys/amd64/include/vmm_dev.h | 20 ++++++++++++++++++++ sys/amd64/vmm/io/vlapic.c | 4 ---- sys/amd64/vmm/vmm.c | 29 ++++++++++++++++++++--------- sys/amd64/vmm/vmm_dev.c | 29 ++++++++++++++++++++++++++++- 5 files changed, 70 insertions(+), 15 deletions(-) (limited to 'sys/amd64') 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; -- cgit v1.1