Changeset View
Changeset View
Standalone View
Standalone View
sys/arm64/vmm/vmm_dev.c
Show First 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | if (jailed(ucred) && | ||||
return (EPERM); | return (EPERM); | ||||
return (0); | return (0); | ||||
} | } | ||||
static int | static int | ||||
vcpu_lock_one(struct vcpu *vcpu) | vcpu_lock_one(struct vcpu *vcpu) | ||||
{ | { | ||||
int error; | return (vcpu_set_state(vcpu, VCPU_FROZEN, true)); | ||||
error = vcpu_set_state(vcpu, VCPU_FROZEN, true); | |||||
return (error); | |||||
} | } | ||||
static void | static void | ||||
vcpu_unlock_one(struct vcpu *vcpu) | vcpu_unlock_one(struct vcpu *vcpu) | ||||
{ | { | ||||
enum vcpu_state state; | enum vcpu_state state; | ||||
state = vcpu_get_state(vcpu, NULL); | state = vcpu_get_state(vcpu, NULL); | ||||
▲ Show 20 Lines • Show All 130 Lines • ▼ Show 20 Lines | if (hpa == NULL) { | ||||
error = uiomove(hpa, c, uio); | error = uiomove(hpa, c, uio); | ||||
vm_gpa_release(cookie); | vm_gpa_release(cookie); | ||||
} | } | ||||
} | } | ||||
vm_unlock_memsegs(sc->vm); | vm_unlock_memsegs(sc->vm); | ||||
return (error); | return (error); | ||||
} | } | ||||
CTASSERT(sizeof(((struct vm_memseg *)0)->name) >= VM_MAX_SUFFIXLEN + 1); | |||||
static int | static int | ||||
get_memseg(struct vmmdev_softc *sc, struct vm_memseg *mseg) | get_memseg(struct vmmdev_softc *sc, struct vm_memseg *mseg, size_t len) | ||||
{ | { | ||||
struct devmem_softc *dsc; | struct devmem_softc *dsc; | ||||
int error; | int error; | ||||
bool sysmem; | bool sysmem; | ||||
error = vm_get_memseg(sc->vm, mseg->segid, &mseg->len, &sysmem, NULL); | error = vm_get_memseg(sc->vm, mseg->segid, &mseg->len, &sysmem, NULL); | ||||
if (error || mseg->len == 0) | if (error || mseg->len == 0) | ||||
return (error); | return (error); | ||||
if (!sysmem) { | if (!sysmem) { | ||||
SLIST_FOREACH(dsc, &sc->devmem, link) { | SLIST_FOREACH(dsc, &sc->devmem, link) { | ||||
if (dsc->segid == mseg->segid) | if (dsc->segid == mseg->segid) | ||||
break; | break; | ||||
} | } | ||||
KASSERT(dsc != NULL, ("%s: devmem segment %d not found", | KASSERT(dsc != NULL, ("%s: devmem segment %d not found", | ||||
__func__, mseg->segid)); | __func__, mseg->segid)); | ||||
error = copystr(dsc->name, mseg->name, sizeof(mseg->name), | error = copystr(dsc->name, mseg->name, len, NULL); | ||||
NULL); | |||||
} else { | } else { | ||||
bzero(mseg->name, sizeof(mseg->name)); | bzero(mseg->name, len); | ||||
corvink: Shouldn't we check that `len <= mseg->name`? | |||||
Done Inline ActionsIn general it's up to the caller to pass the correct len, as mseg might be a struct vm_memseg or a struct vm_memseg_fbsd12. Are you asking me to add KASSERT(len <= sizeof(mseg->name)) or so? That's fine, but I'd probably put that in a separate commit; this patch is just about minimizing differences between amd64 and arm64. markj: In general it's up to the caller to pass the correct `len`, as `mseg` might be a `struct… | |||||
Not Done Inline ActionsYes, a kassert might be a good idea. corvink: Yes, a kassert might be a good idea. | |||||
Done Inline ActionsActually, that assertion would be wrong in the COMPAT12 case, struct vm_memseg_fbsd12's name field is larger than the one in struct vm_memseg. (That is a bit surprising really.) So, I think I prefer to leave the code as it is. markj: Actually, that assertion would be wrong in the COMPAT12 case, struct vm_memseg_fbsd12's `name`… | |||||
} | } | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | static int | ||||
alloc_memseg(struct vmmdev_softc *sc, struct vm_memseg *mseg) | alloc_memseg(struct vmmdev_softc *sc, struct vm_memseg *mseg, size_t len) | ||||
{ | { | ||||
char *name; | char *name; | ||||
int error; | int error; | ||||
bool sysmem; | bool sysmem; | ||||
error = 0; | error = 0; | ||||
name = NULL; | name = NULL; | ||||
sysmem = true; | sysmem = true; | ||||
/* | /* | ||||
* The allocation is lengthened by 1 to hold a terminating NUL. It'll | * The allocation is lengthened by 1 to hold a terminating NUL. It'll | ||||
* by stripped off when devfs processes the full string. | * by stripped off when devfs processes the full string. | ||||
*/ | */ | ||||
if (VM_MEMSEG_NAME(mseg)) { | if (VM_MEMSEG_NAME(mseg)) { | ||||
sysmem = false; | sysmem = false; | ||||
name = malloc(sizeof(mseg->name), M_VMMDEV, M_WAITOK); | name = malloc(len, M_VMMDEV, M_WAITOK); | ||||
error = copystr(mseg->name, name, sizeof(mseg->name), NULL); | error = copystr(mseg->name, name, len, NULL); | ||||
if (error) | if (error) | ||||
goto done; | goto done; | ||||
} | } | ||||
error = vm_alloc_memseg(sc->vm, mseg->segid, mseg->len, sysmem); | error = vm_alloc_memseg(sc->vm, mseg->segid, mseg->len, sysmem); | ||||
if (error) | if (error) | ||||
goto done; | goto done; | ||||
▲ Show 20 Lines • Show All 231 Lines • ▼ Show 20 Lines | case VM_MMAP_MEMSEG: | ||||
error = vm_mmap_memseg(sc->vm, mm->gpa, mm->segid, mm->segoff, | error = vm_mmap_memseg(sc->vm, mm->gpa, mm->segid, mm->segoff, | ||||
mm->len, mm->prot, mm->flags); | mm->len, mm->prot, mm->flags); | ||||
break; | break; | ||||
case VM_MUNMAP_MEMSEG: | case VM_MUNMAP_MEMSEG: | ||||
mu = (struct vm_munmap *)data; | mu = (struct vm_munmap *)data; | ||||
error = vm_munmap_memseg(sc->vm, mu->gpa, mu->len); | error = vm_munmap_memseg(sc->vm, mu->gpa, mu->len); | ||||
break; | break; | ||||
case VM_ALLOC_MEMSEG: | case VM_ALLOC_MEMSEG: | ||||
error = alloc_memseg(sc, (struct vm_memseg *)data); | error = alloc_memseg(sc, (struct vm_memseg *)data, | ||||
sizeof(((struct vm_memseg *)0)->name)); | |||||
break; | break; | ||||
case VM_GET_MEMSEG: | case VM_GET_MEMSEG: | ||||
error = get_memseg(sc, (struct vm_memseg *)data); | error = get_memseg(sc, (struct vm_memseg *)data, | ||||
sizeof(((struct vm_memseg *)0)->name)); | |||||
break; | break; | ||||
case VM_GET_REGISTER: | case VM_GET_REGISTER: | ||||
vmreg = (struct vm_register *)data; | vmreg = (struct vm_register *)data; | ||||
error = vm_get_register(vcpu, vmreg->regnum, &vmreg->regval); | error = vm_get_register(vcpu, vmreg->regnum, &vmreg->regval); | ||||
break; | break; | ||||
case VM_SET_REGISTER: | case VM_SET_REGISTER: | ||||
vmreg = (struct vm_register *)data; | vmreg = (struct vm_register *)data; | ||||
error = vm_set_register(vcpu, vmreg->regnum, vmreg->regval); | error = vm_set_register(vcpu, vmreg->regnum, vmreg->regval); | ||||
▲ Show 20 Lines • Show All 429 Lines • ▼ Show 20 Lines | devmem_mmap_single(struct cdev *cdev, vm_ooffset_t *offset, vm_size_t len, | ||||
error = vm_get_memseg(dsc->sc->vm, dsc->segid, &seglen, &sysmem, objp); | error = vm_get_memseg(dsc->sc->vm, dsc->segid, &seglen, &sysmem, objp); | ||||
KASSERT(error == 0 && !sysmem && *objp != NULL, | KASSERT(error == 0 && !sysmem && *objp != NULL, | ||||
("%s: invalid devmem segment %d", __func__, dsc->segid)); | ("%s: invalid devmem segment %d", __func__, dsc->segid)); | ||||
if (seglen >= last) | if (seglen >= last) | ||||
vm_object_reference(*objp); | vm_object_reference(*objp); | ||||
else | else | ||||
error = 0; | error = EINVAL; | ||||
vm_unlock_memsegs(dsc->sc->vm); | vm_unlock_memsegs(dsc->sc->vm); | ||||
return (error); | return (error); | ||||
} | } | ||||
static struct cdevsw devmemsw = { | static struct cdevsw devmemsw = { | ||||
.d_name = "devmem", | .d_name = "devmem", | ||||
.d_version = D_VERSION, | .d_version = D_VERSION, | ||||
.d_mmap_single = devmem_mmap_single, | .d_mmap_single = devmem_mmap_single, | ||||
▲ Show 20 Lines • Show All 49 Lines • Show Last 20 Lines |
Shouldn't we check that len <= mseg->name?