From 233ec8fc888d117728fe67bd3c1736e381f72824 Mon Sep 17 00:00:00 2001 From: David Gwynne Date: Mon, 11 Sep 2017 23:32:35 +0000 Subject: add functions to provide direct access to guest memory as vmd addresses iovec_mem() populates an iovec array based on guest physical addresses. this allows the use of things like readv and writev for moving data between the guest and a disk image file without having to bounce the memory. vaddr_mem() provides a vmd usable pointer based on a guests physical address. this makes it possible to directly reference things like virtio rings without having to bounce that memory either. however, it assumes that a contiguous range of guest physical memory will sit in a single vm memory range. mlarkin@ says this is right. ok mlarkin@ --- usr.sbin/vmd/vm.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++- usr.sbin/vmd/vmd.h | 6 +++++- 2 files changed, 66 insertions(+), 2 deletions(-) (limited to 'usr.sbin') diff --git a/usr.sbin/vmd/vm.c b/usr.sbin/vmd/vm.c index 0199f77860a..25547127e1a 100644 --- a/usr.sbin/vmd/vm.c +++ b/usr.sbin/vmd/vm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vm.c,v 1.24 2017/08/20 21:15:32 pd Exp $ */ +/* $OpenBSD: vm.c,v 1.25 2017/09/11 23:32:34 dlg Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -1561,6 +1561,29 @@ find_gpa_range(struct vm_create_params *vcp, paddr_t gpa, size_t len) return (vmr); } +void * +vaddr_mem(paddr_t gpa, size_t len) +{ + struct vm_create_params *vcp = ¤t_vm->vm_params.vmc_params; + size_t i; + struct vm_mem_range *vmr; + paddr_t gpend = gpa + len; + + /* Find the first vm_mem_range that contains gpa */ + for (i = 0; i < vcp->vcp_nmemranges; i++) { + vmr = &vcp->vcp_memranges[i]; + if (gpa < vmr->vmr_gpa) + continue; + + if (gpend >= vmr->vmr_gpa + vmr->vmr_size) + continue; + + return ((char *)vmr->vmr_va + (gpa - vmr->vmr_gpa)); + } + + return (NULL); +} + /* * write_mem * @@ -1658,6 +1681,43 @@ read_mem(paddr_t src, void *buf, size_t len) return (0); } +int +iovec_mem(paddr_t src, size_t len, struct iovec *iov, int iovcnt) +{ + size_t n, off; + struct vm_mem_range *vmr; + int niov = 0; + + vmr = find_gpa_range(¤t_vm->vm_params.vmc_params, src, len); + if (vmr == NULL) { + errno = EINVAL; + return (-1); + } + + off = src - vmr->vmr_gpa; + while (len > 0) { + if (niov == iovcnt) { + errno = ENOMEM; + return (-1); + } + + n = vmr->vmr_size - off; + if (len < n) + n = len; + + iov[niov].iov_base = (char *)vmr->vmr_va + off; + iov[niov].iov_len = n; + + niov++; + + len -= n; + off = 0; + vmr++; + } + + return (niov); +} + /* * vcpu_assert_pic_irq * diff --git a/usr.sbin/vmd/vmd.h b/usr.sbin/vmd/vmd.h index 02f05c32603..4b7b5f70495 100644 --- a/usr.sbin/vmd/vmd.h +++ b/usr.sbin/vmd/vmd.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vmd.h,v 1.63 2017/09/11 23:25:05 dlg Exp $ */ +/* $OpenBSD: vmd.h,v 1.64 2017/09/11 23:32:34 dlg Exp $ */ /* * Copyright (c) 2015 Mike Larkin @@ -326,10 +326,14 @@ int vm_priv_brconfig(struct privsep *, struct vmd_switch *); uint32_t vm_priv_addr(struct address *, uint32_t, int, int); /* vmm.c */ +struct iovec; + void vmm(struct privsep *, struct privsep_proc *); void vmm_shutdown(void); +void *vaddr_mem(paddr_t, size_t); int write_mem(paddr_t, const void *buf, size_t); int read_mem(paddr_t, void *buf, size_t); +int iovec_mem(paddr_t, size_t, struct iovec *, int); int opentap(char *); int fd_hasdata(int); void mutex_lock(pthread_mutex_t *); -- cgit v1.2.3