Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F110743329
D37172.id112281.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D37172.id112281.diff
View Options
diff --git a/sys/amd64/include/vmm.h b/sys/amd64/include/vmm.h
--- a/sys/amd64/include/vmm.h
+++ b/sys/amd64/include/vmm.h
@@ -231,6 +231,9 @@
/*
* APIs that modify the guest memory map require all vcpus to be frozen.
*/
+void vm_slock_memsegs(struct vm *vm);
+void vm_xlock_memsegs(struct vm *vm);
+void vm_unlock_memsegs(struct vm *vm);
int vm_mmap_memseg(struct vm *vm, vm_paddr_t gpa, int segid, vm_ooffset_t off,
size_t len, int prot, int flags);
int vm_munmap_memseg(struct vm *vm, vm_paddr_t gpa, size_t len);
diff --git a/sys/amd64/vmm/vmm.c b/sys/amd64/vmm/vmm.c
--- a/sys/amd64/vmm/vmm.c
+++ b/sys/amd64/vmm/vmm.c
@@ -46,6 +46,7 @@
#include <sys/rwlock.h>
#include <sys/sched.h>
#include <sys/smp.h>
+#include <sys/sx.h>
#include <sys/vnode.h>
#include <vm/vm.h>
@@ -185,6 +186,7 @@
uint16_t cores; /* (o) num of cores/socket */
uint16_t threads; /* (o) num of threads/core */
uint16_t maxcpus; /* (o) max pluggable cpus */
+ struct sx mem_segs_lock; /* (o) */
};
#define VMM_CTR0(vcpu, format) \
@@ -518,6 +520,7 @@
strcpy(vm->name, name);
vm->vmspace = vmspace;
mtx_init(&vm->rendezvous_mtx, "vm rendezvous lock", 0, MTX_DEF);
+ sx_init(&vm->mem_segs_lock, "vm mem_segs");
vm->sockets = 1;
vm->cores = cores_per_package; /* XXX backwards compatibility */
@@ -609,6 +612,7 @@
vmmops_vmspace_free(vm->vmspace);
vm->vmspace = NULL;
+ sx_destroy(&vm->mem_segs_lock);
mtx_destroy(&vm->rendezvous_mtx);
}
}
@@ -645,6 +649,24 @@
return (vm->name);
}
+void
+vm_slock_memsegs(struct vm *vm)
+{
+ sx_slock(&vm->mem_segs_lock);
+}
+
+void
+vm_xlock_memsegs(struct vm *vm)
+{
+ sx_xlock(&vm->mem_segs_lock);
+}
+
+void
+vm_unlock_memsegs(struct vm *vm)
+{
+ sx_unlock(&vm->mem_segs_lock);
+}
+
int
vm_map_mmio(struct vm *vm, vm_paddr_t gpa, size_t len, vm_paddr_t hpa)
{
@@ -1075,19 +1097,7 @@
vm_gpa_hold_global(struct vm *vm, vm_paddr_t gpa, size_t len, int reqprot,
void **cookie)
{
-#ifdef INVARIANTS
- /*
- * All vcpus are frozen by ioctls that modify the memory map
- * (e.g. VM_MMAP_MEMSEG). Therefore 'vm->memmap[]' stability is
- * guaranteed if at least one vcpu is in the VCPU_FROZEN state.
- */
- int state;
- for (int i = 0; i < vm->maxcpus; i++) {
- state = vcpu_get_state(vm_vcpu(vm, i), NULL);
- KASSERT(state == VCPU_FROZEN, ("%s: invalid vcpu state %d",
- __func__, state));
- }
-#endif
+ sx_assert(&vm->mem_segs_lock, SX_LOCKED);
return (_vm_gpa_hold(vm, gpa, len, reqprot, cookie));
}
diff --git a/sys/amd64/vmm/vmm_dev.c b/sys/amd64/vmm/vmm_dev.c
--- a/sys/amd64/vmm/vmm_dev.c
+++ b/sys/amd64/vmm/vmm_dev.c
@@ -221,8 +221,6 @@
vm_paddr_t gpa, maxaddr;
void *hpa, *cookie;
struct vmmdev_softc *sc;
- struct vcpu *vcpu;
- uint16_t lastcpu;
error = vmm_priv_check(curthread->td_ucred);
if (error)
@@ -233,13 +231,9 @@
return (ENXIO);
/*
- * Get a read lock on the guest memory map by freezing any vcpu.
+ * Get a read lock on the guest memory map.
*/
- lastcpu = vm_get_maxcpus(sc->vm) - 1;
- error = vcpu_lock_one(sc, lastcpu);
- if (error)
- return (error);
- vcpu = vm_vcpu(sc->vm, lastcpu);
+ vm_slock_memsegs(sc->vm);
prot = (uio->uio_rw == UIO_WRITE ? VM_PROT_WRITE : VM_PROT_READ);
maxaddr = vmm_sysmem_maxaddr(sc->vm);
@@ -256,7 +250,7 @@
* Since this device does not support lseek(2), dd(1) will
* read(2) blocks of data to simulate the lseek(2).
*/
- hpa = vm_gpa_hold(vcpu, gpa, c, prot, &cookie);
+ hpa = vm_gpa_hold_global(sc->vm, gpa, c, prot, &cookie);
if (hpa == NULL) {
if (uio->uio_rw == UIO_READ && gpa < maxaddr)
error = uiomove(__DECONST(void *, zero_region),
@@ -268,7 +262,7 @@
vm_gpa_release(cookie);
}
}
- vcpu_unlock_one(sc, lastcpu);
+ vm_unlock_memsegs(sc->vm);
return (error);
}
@@ -420,6 +414,7 @@
struct vm_readwrite_kernemu_device *kernemu;
uint64_t *regvals;
int *regnums;
+ bool memsegs_locked;
#ifdef BHYVE_SNAPSHOT
struct vm_snapshot_meta *snapshot_meta;
#endif
@@ -435,6 +430,7 @@
vcpuid = -1;
vcpu = NULL;
state_changed = 0;
+ memsegs_locked = false;
/*
* For VMM ioctls that operate on a single vCPU, lookup the
@@ -476,10 +472,6 @@
vcpu = vm_vcpu(sc->vm, vcpuid);
break;
- case VM_MAP_PPTDEV_MMIO:
- case VM_UNMAP_PPTDEV_MMIO:
- case VM_BIND_PPTDEV:
- case VM_UNBIND_PPTDEV:
#ifdef COMPAT_FREEBSD12
case VM_ALLOC_MEMSEG_FBSD12:
#endif
@@ -487,6 +479,21 @@
case VM_MMAP_MEMSEG:
case VM_MUNMAP_MEMSEG:
case VM_REINIT:
+ /*
+ * ioctls that modify the memory map must lock memory
+ * segments exclusively.
+ */
+ vm_xlock_memsegs(sc->vm);
+ memsegs_locked = true;
+ /* FALLTHROUGH */
+ case VM_MAP_PPTDEV_MMIO:
+ case VM_UNMAP_PPTDEV_MMIO:
+ case VM_BIND_PPTDEV:
+ case VM_UNBIND_PPTDEV:
+#ifdef BHYVE_SNAPSHOT
+ case VM_SNAPSHOT_REQ:
+ case VM_RESTORE_TIME:
+#endif
/*
* ioctls that operate on the entire virtual machine must
* prevent all vcpus from running.
@@ -503,14 +510,10 @@
case VM_GET_MEMSEG:
case VM_MMAP_GETNEXT:
/*
- * Lock a vcpu to make sure that the memory map cannot be
- * modified while it is being inspected.
+ * Lock the memory map while it is being inspected.
*/
- vcpuid = vm_get_maxcpus(sc->vm) - 1;
- error = vcpu_lock_one(sc, vcpuid);
- if (error)
- goto done;
- state_changed = 1;
+ vm_slock_memsegs(sc->vm);
+ memsegs_locked = true;
break;
#ifdef COMPAT_FREEBSD13
@@ -958,6 +961,8 @@
vcpu_unlock_one(sc, vcpuid);
else if (state_changed == 2)
vcpu_unlock_all(sc);
+ if (memsegs_locked)
+ vm_unlock_memsegs(sc->vm);
done:
/*
@@ -978,7 +983,6 @@
size_t len;
vm_ooffset_t segoff, first, last;
int error, found, segid;
- uint16_t lastcpu;
bool sysmem;
error = vmm_priv_check(curthread->td_ucred);
@@ -997,12 +1001,9 @@
}
/*
- * Get a read lock on the guest memory map by freezing any vcpu.
+ * Get a read lock on the guest memory map.
*/
- lastcpu = vm_get_maxcpus(sc->vm) - 1;
- error = vcpu_lock_one(sc, lastcpu);
- if (error)
- return (error);
+ vm_slock_memsegs(sc->vm);
gpa = 0;
found = 0;
@@ -1029,7 +1030,7 @@
error = EINVAL;
}
}
- vcpu_unlock_one(sc, lastcpu);
+ vm_unlock_memsegs(sc->vm);
return (error);
}
@@ -1242,7 +1243,6 @@
vm_ooffset_t first, last;
size_t seglen;
int error;
- uint16_t lastcpu;
bool sysmem;
dsc = cdev->si_drv1;
@@ -1256,16 +1256,14 @@
if ((nprot & PROT_EXEC) || first < 0 || first >= last)
return (EINVAL);
- lastcpu = vm_get_maxcpus(dsc->sc->vm) - 1;
- error = vcpu_lock_one(dsc->sc, lastcpu);
- if (error)
- return (error);
+ vm_slock_memsegs(dsc->sc->vm);
error = vm_get_memseg(dsc->sc->vm, dsc->segid, &seglen, &sysmem, objp);
KASSERT(error == 0 && !sysmem && *objp != NULL,
("%s: invalid devmem segment %d", __func__, dsc->segid));
- vcpu_unlock_one(dsc->sc, lastcpu);
+
+ vm_unlock_memsegs(dsc->sc->vm);
if (seglen >= last) {
vm_object_reference(*objp);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Feb 23, 1:49 PM (16 h, 16 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16798908
Default Alt Text
D37172.id112281.diff (6 KB)
Attached To
Mode
D37172: vmm: Use an sx lock to protect the memory map.
Attached
Detach File
Event Timeline
Log In to Comment