Changeset View
Changeset View
Standalone View
Standalone View
sys/amd64/vmm/vmm_dev.c
Show All 25 Lines | |||||
* SUCH DAMAGE. | * SUCH DAMAGE. | ||||
* | * | ||||
* $FreeBSD$ | * $FreeBSD$ | ||||
*/ | */ | ||||
#include <sys/cdefs.h> | #include <sys/cdefs.h> | ||||
__FBSDID("$FreeBSD$"); | __FBSDID("$FreeBSD$"); | ||||
#include "opt_bhyve_snapshot.h" | |||||
#include <sys/param.h> | #include <sys/param.h> | ||||
#include <sys/kernel.h> | #include <sys/kernel.h> | ||||
#include <sys/jail.h> | #include <sys/jail.h> | ||||
#include <sys/queue.h> | #include <sys/queue.h> | ||||
#include <sys/lock.h> | #include <sys/lock.h> | ||||
#include <sys/mutex.h> | #include <sys/mutex.h> | ||||
#include <sys/malloc.h> | #include <sys/malloc.h> | ||||
#include <sys/conf.h> | #include <sys/conf.h> | ||||
#include <sys/sysctl.h> | #include <sys/sysctl.h> | ||||
#include <sys/libkern.h> | #include <sys/libkern.h> | ||||
#include <sys/ioccom.h> | #include <sys/ioccom.h> | ||||
#include <sys/mman.h> | #include <sys/mman.h> | ||||
#include <sys/uio.h> | #include <sys/uio.h> | ||||
#include <sys/proc.h> | #include <sys/proc.h> | ||||
#include <vm/vm.h> | #include <vm/vm.h> | ||||
#include <vm/pmap.h> | #include <vm/pmap.h> | ||||
#include <vm/vm_map.h> | #include <vm/vm_map.h> | ||||
#include <vm/vm_object.h> | #include <vm/vm_object.h> | ||||
#include <machine/vmparam.h> | #include <machine/vmparam.h> | ||||
#include <machine/vmm.h> | #include <machine/vmm.h> | ||||
#include <machine/vmm_instruction_emul.h> | |||||
#include <machine/vmm_dev.h> | #include <machine/vmm_dev.h> | ||||
#include <machine/vmm_instruction_emul.h> | |||||
#include <machine/vmm_snapshot.h> | |||||
#include "vmm_lapic.h" | #include "vmm_lapic.h" | ||||
#include "vmm_stat.h" | #include "vmm_stat.h" | ||||
#include "vmm_mem.h" | #include "vmm_mem.h" | ||||
#include "io/ppt.h" | #include "io/ppt.h" | ||||
#include "io/vatpic.h" | #include "io/vatpic.h" | ||||
#include "io/vioapic.h" | #include "io/vioapic.h" | ||||
#include "io/vhpet.h" | #include "io/vhpet.h" | ||||
▲ Show 20 Lines • Show All 310 Lines • ▼ Show 20 Lines | vmmdev_ioctl(struct cdev *cdev, u_long cmd, caddr_t data, int fflag, | ||||
struct vm_cpuset *vm_cpuset; | struct vm_cpuset *vm_cpuset; | ||||
struct vm_intinfo *vmii; | struct vm_intinfo *vmii; | ||||
struct vm_rtc_time *rtctime; | struct vm_rtc_time *rtctime; | ||||
struct vm_rtc_data *rtcdata; | struct vm_rtc_data *rtcdata; | ||||
struct vm_memmap *mm; | struct vm_memmap *mm; | ||||
struct vm_cpu_topology *topology; | struct vm_cpu_topology *topology; | ||||
uint64_t *regvals; | uint64_t *regvals; | ||||
int *regnums; | int *regnums; | ||||
#ifdef BHYVE_SNAPSHOT | |||||
struct vm_snapshot_meta *snapshot_meta; | |||||
#endif | |||||
error = vmm_priv_check(curthread->td_ucred); | error = vmm_priv_check(curthread->td_ucred); | ||||
if (error) | if (error) | ||||
return (error); | return (error); | ||||
sc = vmmdev_lookup2(cdev); | sc = vmmdev_lookup2(cdev); | ||||
if (sc == NULL) | if (sc == NULL) | ||||
return (ENXIO); | return (ENXIO); | ||||
▲ Show 20 Lines • Show All 75 Lines • ▼ Show 20 Lines | case VM_RUN: | ||||
break; | break; | ||||
case VM_SUSPEND: | case VM_SUSPEND: | ||||
vmsuspend = (struct vm_suspend *)data; | vmsuspend = (struct vm_suspend *)data; | ||||
error = vm_suspend(sc->vm, vmsuspend->how); | error = vm_suspend(sc->vm, vmsuspend->how); | ||||
break; | break; | ||||
case VM_REINIT: | case VM_REINIT: | ||||
error = vm_reinit(sc->vm); | error = vm_reinit(sc->vm); | ||||
break; | break; | ||||
case VM_STAT_DESC: { | case VM_STAT_DESC: { | ||||
statdesc = (struct vm_stat_desc *)data; | statdesc = (struct vm_stat_desc *)data; | ||||
error = vmm_stat_desc_copy(statdesc->index, | error = vmm_stat_desc_copy(statdesc->index, | ||||
statdesc->desc, sizeof(statdesc->desc)); | statdesc->desc, sizeof(statdesc->desc)); | ||||
break; | break; | ||||
} | } | ||||
case VM_STATS: { | case VM_STATS: { | ||||
pmooney_pfmooney.com: I'm uncomfortable about providing ioctl interfaces to these locking operations. All of the… | |||||
Done Inline ActionsReworked the VM pause to block the threads in userspace. darius.mihaim_gmail.com: Reworked the VM pause to block the threads in userspace. | |||||
CTASSERT(MAX_VM_STATS >= MAX_VMM_STAT_ELEMS); | CTASSERT(MAX_VM_STATS >= MAX_VMM_STAT_ELEMS); | ||||
vmstats = (struct vm_stats *)data; | vmstats = (struct vm_stats *)data; | ||||
getmicrotime(&vmstats->tv); | getmicrotime(&vmstats->tv); | ||||
error = vmm_stat_copy(sc->vm, vmstats->cpuid, | error = vmm_stat_copy(sc->vm, vmstats->cpuid, | ||||
&vmstats->num_entries, vmstats->statbuf); | &vmstats->num_entries, vmstats->statbuf); | ||||
break; | break; | ||||
} | } | ||||
case VM_PPTDEV_MSI: | case VM_PPTDEV_MSI: | ||||
▲ Show 20 Lines • Show All 287 Lines • ▼ Show 20 Lines | case VM_SET_TOPOLOGY: | ||||
topology = (struct vm_cpu_topology *)data; | topology = (struct vm_cpu_topology *)data; | ||||
error = vm_set_topology(sc->vm, topology->sockets, | error = vm_set_topology(sc->vm, topology->sockets, | ||||
topology->cores, topology->threads, topology->maxcpus); | topology->cores, topology->threads, topology->maxcpus); | ||||
break; | break; | ||||
case VM_GET_TOPOLOGY: | case VM_GET_TOPOLOGY: | ||||
topology = (struct vm_cpu_topology *)data; | topology = (struct vm_cpu_topology *)data; | ||||
vm_get_topology(sc->vm, &topology->sockets, &topology->cores, | vm_get_topology(sc->vm, &topology->sockets, &topology->cores, | ||||
&topology->threads, &topology->maxcpus); | &topology->threads, &topology->maxcpus); | ||||
error = 0; | error = 0; | ||||
Done Inline ActionsMissing a 'break' here now. jhb: Missing a 'break' here now. | |||||
break; | break; | ||||
#ifdef BHYVE_SNAPSHOT | |||||
case VM_SNAPSHOT_REQ: | |||||
snapshot_meta = (struct vm_snapshot_meta *)data; | |||||
error = vm_snapshot_req(sc->vm, snapshot_meta); | |||||
break; | |||||
case VM_RESTORE_TIME: | |||||
error = vm_restore_time(sc->vm); | |||||
break; | |||||
#endif | |||||
default: | default: | ||||
error = ENOTTY; | error = ENOTTY; | ||||
break; | break; | ||||
} | } | ||||
if (state_changed == 1) | if (state_changed == 1) | ||||
vcpu_unlock_one(sc, vcpu); | vcpu_unlock_one(sc, vcpu); | ||||
else if (state_changed == 2) | else if (state_changed == 2) | ||||
▲ Show 20 Lines • Show All 231 Lines • ▼ Show 20 Lines | sysctl_vmm_create(SYSCTL_HANDLER_ARGS) | ||||
if (sc2 != NULL) { | if (sc2 != NULL) { | ||||
vmmdev_destroy(sc); | vmmdev_destroy(sc); | ||||
error = EEXIST; | error = EEXIST; | ||||
goto out; | goto out; | ||||
} | } | ||||
error = make_dev_p(MAKEDEV_CHECKNAME, &cdev, &vmmdevsw, NULL, | error = make_dev_p(MAKEDEV_CHECKNAME, &cdev, &vmmdevsw, NULL, | ||||
UID_ROOT, GID_WHEEL, 0600, "vmm/%s", buf); | UID_ROOT, GID_WHEEL, 0600, "vmm/%s", buf); | ||||
if (error != 0) { | if (error != 0) { | ||||
Not Done Inline ActionsYou can't call make_dev* while holding locks. There is a race with setting si_drv1 that can be fixed by using make_dev_s instead of make_dev_p, but that would be a separate change from save/restore I think, jhb: You can't call make_dev* while holding locks. There is a race with setting si_drv1 that can be… | |||||
Done Inline ActionsRemoved the comment, since it was not related to save/restore. darius.mihaim_gmail.com: Removed the comment, since it was not related to save/restore. | |||||
vmmdev_destroy(sc); | vmmdev_destroy(sc); | ||||
goto out; | goto out; | ||||
} | } | ||||
mtx_lock(&vmmdev_mtx); | mtx_lock(&vmmdev_mtx); | ||||
sc->cdev = cdev; | sc->cdev = cdev; | ||||
sc->cdev->si_drv1 = sc; | sc->cdev->si_drv1 = sc; | ||||
mtx_unlock(&vmmdev_mtx); | mtx_unlock(&vmmdev_mtx); | ||||
▲ Show 20 Lines • Show All 125 Lines • Show Last 20 Lines |
I'm uncomfortable about providing ioctl interfaces to these locking operations. All of the other vCPU lock consumers will take the needed lock(s), perform their action in kernel space, and the release the lock(s) prior to returning to userspace. These ioctls break that model. Furthermore, since the save/restore operation is driven from userspace, where the vCPU run threads are operating, there's no reason why the quiescence cannot start there.