summaryrefslogtreecommitdiffstats
path: root/usr.sbin/bhyve
diff options
context:
space:
mode:
authorneel <neel@FreeBSD.org>2013-03-01 02:26:28 +0000
committerneel <neel@FreeBSD.org>2013-03-01 02:26:28 +0000
commit9c2aecf6da5fb6aafba1ce1f1488a6b13c8a3174 (patch)
tree2000067d1528e9e61ee28a8010e91859f3f23e01 /usr.sbin/bhyve
parent65c312a935cde98a1292b6337cd3c1ece740b835 (diff)
downloadFreeBSD-src-9c2aecf6da5fb6aafba1ce1f1488a6b13c8a3174.zip
FreeBSD-src-9c2aecf6da5fb6aafba1ce1f1488a6b13c8a3174.tar.gz
Specify the length of the mapping requested from 'paddr_guest2host()'.
This seems prudent to do in its own right but it also opens up the possibility of not having to mmap the entire guest address space in the 'bhyve' process context. Discussed with: grehan Obtained from: NetApp
Diffstat (limited to 'usr.sbin/bhyve')
-rw-r--r--usr.sbin/bhyve/acpi.c9
-rw-r--r--usr.sbin/bhyve/bhyverun.c18
-rw-r--r--usr.sbin/bhyve/bhyverun.h2
-rw-r--r--usr.sbin/bhyve/mptbl.c9
-rw-r--r--usr.sbin/bhyve/pci_virtio_block.c19
-rw-r--r--usr.sbin/bhyve/pci_virtio_net.c14
-rw-r--r--usr.sbin/bhyve/virtio.h15
7 files changed, 49 insertions, 37 deletions
diff --git a/usr.sbin/bhyve/acpi.c b/usr.sbin/bhyve/acpi.c
index 32effdc..cabe75e 100644
--- a/usr.sbin/bhyve/acpi.c
+++ b/usr.sbin/bhyve/acpi.c
@@ -683,13 +683,16 @@ static int
basl_load(int fd, uint64_t off)
{
struct stat sb;
+ void *gaddr;
int err;
err = 0;
-
- if (fstat(fd, &sb) < 0 ||
- read(fd, paddr_guest2host(basl_acpi_base + off), sb.st_size) < 0)
+ gaddr = paddr_guest2host(basl_acpi_base + off, sb.st_size);
+ if (gaddr != NULL) {
+ if (fstat(fd, &sb) < 0 || read(fd, gaddr, sb.st_size) < 0)
err = errno;
+ } else
+ err = EFAULT;
return (err);
}
diff --git a/usr.sbin/bhyve/bhyverun.c b/usr.sbin/bhyve/bhyverun.c
index ea4b68c..17d60d6 100644
--- a/usr.sbin/bhyve/bhyverun.c
+++ b/usr.sbin/bhyve/bhyverun.c
@@ -157,17 +157,19 @@ usage(int code)
}
void *
-paddr_guest2host(uintptr_t gaddr)
+paddr_guest2host(uintptr_t gaddr, size_t len)
{
- if (lomem_sz == 0)
- return (NULL);
- if (gaddr < lomem_sz) {
+ if (gaddr < lomem_sz && gaddr + len <= lomem_sz)
return ((void *)(lomem_addr + gaddr));
- } else if (gaddr >= 4*GB && gaddr < (4*GB + himem_sz)) {
- return ((void *)(himem_addr + gaddr - 4*GB));
- } else
- return (NULL);
+
+ if (gaddr >= 4*GB) {
+ gaddr -= 4*GB;
+ if (gaddr < himem_sz && gaddr + len <= himem_sz)
+ return ((void *)(himem_addr + gaddr));
+ }
+
+ return (NULL);
}
int
diff --git a/usr.sbin/bhyve/bhyverun.h b/usr.sbin/bhyve/bhyverun.h
index 45033b8..70455bf 100644
--- a/usr.sbin/bhyve/bhyverun.h
+++ b/usr.sbin/bhyve/bhyverun.h
@@ -43,7 +43,7 @@ extern char *vmname;
extern u_long lomem_sz, himem_sz;
-void *paddr_guest2host(uintptr_t);
+void *paddr_guest2host(uintptr_t addr, size_t len);
void fbsdrun_addcpu(struct vmctx *ctx, int cpu, uint64_t rip);
int fbsdrun_muxed(void);
diff --git a/usr.sbin/bhyve/mptbl.c b/usr.sbin/bhyve/mptbl.c
index 52790f3..9c68b3d 100644
--- a/usr.sbin/bhyve/mptbl.c
+++ b/usr.sbin/bhyve/mptbl.c
@@ -41,6 +41,9 @@ __FBSDID("$FreeBSD$");
#define MPTABLE_BASE 0xF0000
+/* floating pointer length + maximum length of configuration table */
+#define MPTABLE_MAX_LENGTH (65536 + 16)
+
#define LAPIC_PADDR 0xFEE00000
#define LAPIC_VERSION 16
@@ -346,13 +349,13 @@ mptable_build(struct vmctx *ctx, int ncpu, int ioapic)
char *curraddr;
char *startaddr;
- if (paddr_guest2host(0) == NULL) {
+ startaddr = paddr_guest2host(MPTABLE_BASE, MPTABLE_MAX_LENGTH);
+ if (startaddr == NULL) {
printf("mptable requires mapped mem\n");
return (ENOMEM);
}
- startaddr = curraddr = paddr_guest2host(MPTABLE_BASE);
-
+ curraddr = startaddr;
mpfp = (mpfps_t)curraddr;
mpt_build_mpfp(mpfp, MPTABLE_BASE);
curraddr += sizeof(*mpfp);
diff --git a/usr.sbin/bhyve/pci_virtio_block.c b/usr.sbin/bhyve/pci_virtio_block.c
index 62bf801..31ff2e6 100644
--- a/usr.sbin/bhyve/pci_virtio_block.c
+++ b/usr.sbin/bhyve/pci_virtio_block.c
@@ -222,13 +222,13 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
assert(nsegs >= 3);
assert(nsegs < VTBLK_MAXSEGS + 2);
- vid = paddr_guest2host(vd->vd_addr);
+ vid = paddr_guest2host(vd->vd_addr, vd->vd_len);
assert((vid->vd_flags & VRING_DESC_F_INDIRECT) == 0);
/*
* The first descriptor will be the read-only fixed header
*/
- vbh = paddr_guest2host(vid[0].vd_addr);
+ vbh = paddr_guest2host(vid[0].vd_addr, sizeof(struct virtio_blk_hdr));
assert(vid[0].vd_len == sizeof(struct virtio_blk_hdr));
assert(vid[0].vd_flags & VRING_DESC_F_NEXT);
assert((vid[0].vd_flags & VRING_DESC_F_WRITE) == 0);
@@ -247,7 +247,8 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
* Build up the iovec based on the guest's data descriptors
*/
for (i = 1, iolen = 0; i < nsegs - 1; i++) {
- iov[i-1].iov_base = paddr_guest2host(vid[i].vd_addr);
+ iov[i-1].iov_base = paddr_guest2host(vid[i].vd_addr,
+ vid[i].vd_len);
iov[i-1].iov_len = vid[i].vd_len;
iolen += vid[i].vd_len;
@@ -265,7 +266,7 @@ pci_vtblk_proc(struct pci_vtblk_softc *sc, struct vring_hqueue *hq)
}
/* Lastly, get the address of the status byte */
- status = paddr_guest2host(vid[nsegs - 1].vd_addr);
+ status = paddr_guest2host(vid[nsegs - 1].vd_addr, 1);
assert(vid[nsegs - 1].vd_len == 1);
assert((vid[nsegs - 1].vd_flags & VRING_DESC_F_NEXT) == 0);
assert(vid[nsegs - 1].vd_flags & VRING_DESC_F_WRITE);
@@ -341,7 +342,8 @@ pci_vtblk_ring_init(struct pci_vtblk_softc *sc, uint64_t pfn)
hq = &sc->vbsc_q;
hq->hq_size = VTBLK_RINGSZ;
- hq->hq_dtable = paddr_guest2host(pfn << VRING_PFN);
+ hq->hq_dtable = paddr_guest2host(pfn << VRING_PFN,
+ vring_size(VTBLK_RINGSZ));
hq->hq_avail_flags = (uint16_t *)(hq->hq_dtable + hq->hq_size);
hq->hq_avail_idx = hq->hq_avail_flags + 1;
hq->hq_avail_ring = hq->hq_avail_flags + 2;
@@ -372,13 +374,6 @@ pci_vtblk_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
}
/*
- * Access to guest memory is required. Fail if
- * memory not mapped
- */
- if (paddr_guest2host(0) == NULL)
- return (1);
-
- /*
* The supplied backing file has to exist
*/
fd = open(opts, O_RDWR);
diff --git a/usr.sbin/bhyve/pci_virtio_net.c b/usr.sbin/bhyve/pci_virtio_net.c
index 327ebf7..a5cf8b3 100644
--- a/usr.sbin/bhyve/pci_virtio_net.c
+++ b/usr.sbin/bhyve/pci_virtio_net.c
@@ -326,7 +326,7 @@ pci_vtnet_tap_rx(struct pci_vtnet_softc *sc)
* Get a pointer to the rx header, and use the
* data immediately following it for the packet buffer.
*/
- vrx = (struct virtio_net_rxhdr *)paddr_guest2host(vd->vd_addr);
+ vrx = paddr_guest2host(vd->vd_addr, vd->vd_len);
buf = (uint8_t *)(vrx + 1);
len = read(sc->vsc_tapfd, buf,
@@ -434,7 +434,7 @@ pci_vtnet_proctx(struct pci_vtnet_softc *sc, struct vring_hqueue *hq)
for (i = 0, plen = 0;
i < VTNET_MAXSEGS;
i++, vd = &hq->hq_dtable[vd->vd_next]) {
- iov[i].iov_base = paddr_guest2host(vd->vd_addr);
+ iov[i].iov_base = paddr_guest2host(vd->vd_addr, vd->vd_len);
iov[i].iov_len = vd->vd_len;
plen += vd->vd_len;
tlen += vd->vd_len;
@@ -517,7 +517,8 @@ pci_vtnet_ring_init(struct pci_vtnet_softc *sc, uint64_t pfn)
hq = &sc->vsc_hq[qnum];
hq->hq_size = pci_vtnet_qsize(qnum);
- hq->hq_dtable = paddr_guest2host(pfn << VRING_PFN);
+ hq->hq_dtable = paddr_guest2host(pfn << VRING_PFN,
+ vring_size(hq->hq_size));
hq->hq_avail_flags = (uint16_t *)(hq->hq_dtable + hq->hq_size);
hq->hq_avail_idx = hq->hq_avail_flags + 1;
hq->hq_avail_ring = hq->hq_avail_flags + 2;
@@ -541,13 +542,6 @@ pci_vtnet_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
struct pci_vtnet_softc *sc;
const char *env_msi;
- /*
- * Access to guest memory is required. Fail if
- * memory not mapped
- */
- if (paddr_guest2host(0) == NULL)
- return (1);
-
sc = malloc(sizeof(struct pci_vtnet_softc));
memset(sc, 0, sizeof(struct pci_vtnet_softc));
diff --git a/usr.sbin/bhyve/virtio.h b/usr.sbin/bhyve/virtio.h
index 04ef586..fe6fb1a 100644
--- a/usr.sbin/bhyve/virtio.h
+++ b/usr.sbin/bhyve/virtio.h
@@ -85,4 +85,19 @@ struct virtio_used {
#define VTCFG_R_CFG1 24 /* With MSI-X */
#define VTCFG_R_MSIX 20
+/* From section 2.3, "Virtqueue Configuration", of the virtio specification */
+static inline u_int
+vring_size(u_int qsz)
+{
+ u_int size;
+
+ size = sizeof(struct virtio_desc) * qsz + sizeof(uint16_t) * (3 + qsz);
+ size = roundup2(size, VRING_ALIGN);
+
+ size += sizeof(uint16_t) * 3 + sizeof(struct virtio_used) * qsz;
+ size = roundup2(size, VRING_ALIGN);
+
+ return (size);
+}
+
#endif /* _VIRTIO_H_ */
OpenPOWER on IntegriCloud