This is prep work for adding qcow2 image support.
From Ori Bernstein. Many thanks!
Tested by many.
OK ccardenas@
-# $OpenBSD: Makefile,v 1.18 2018/06/28 02:21:15 gsoares Exp $
+# $OpenBSD: Makefile,v 1.19 2018/08/25 04:16:09 ccardenas Exp $
.if ${MACHINE} == "amd64" || ${MACHINE} == "i386"
SRCS= vmd.c control.c log.c priv.c proc.c config.c vmm.c
SRCS+= vm.c loadfile_elf.c pci.c virtio.c i8259.c mc146818.c
SRCS+= ns8250.c i8253.c vmboot.c ufs.c disklabel.c dhcp.c packet.c
-SRCS+= parse.y atomicio.c vioscsi.c
+SRCS+= parse.y atomicio.c vioscsi.c vioraw.c
CFLAGS+= -Wall -I${.CURDIR}
CFLAGS+= -Wstrict-prototypes -Wmissing-prototypes
--- /dev/null
+/* $OpenBSD: vioraw.c,v 1.1 2018/08/25 04:16:09 ccardenas Exp $ */
+/*
+ * Copyright (c) 2018 Ori Bernstein <ori@eigenstate.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/types.h>
+
+#include <machine/vmmvar.h>
+#include <dev/pci/pcireg.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "vmd.h"
+#include "vmm.h"
+#include "virtio.h"
+
+static ssize_t
+raw_pread(void *file, char *buf, size_t len, off_t off)
+{
+ return pread(*(int *)file, buf, len, off);
+}
+
+static ssize_t
+raw_pwrite(void *file, char *buf, size_t len, off_t off)
+{
+ return pwrite(*(int *)file, buf, len, off);
+}
+
+static void
+raw_close(void *file)
+{
+ close(*(int *)file);
+ free(file);
+}
+
+/*
+ * Initializes a raw disk image backing file from an fd.
+ * Stores the number of 512 byte sectors in *szp,
+ * returning -1 for error, 0 for success.
+ */
+int
+virtio_init_raw(struct virtio_backing *file, off_t *szp, int fd)
+{
+ off_t sz;
+ int *fdp;
+
+ sz = lseek(fd, 0, SEEK_END);
+ if (sz == -1)
+ return -1;
+
+ fdp = malloc(sizeof(int));
+ *fdp = fd;
+ file->p = fdp;
+ file->pread = raw_pread;
+ file->pwrite = raw_pwrite;
+ file->close = raw_close;
+ *szp = sz;
+ return 0;
+}
+
-/* $OpenBSD: vioscsi.c,v 1.10 2018/07/15 20:25:52 ccardenas Exp $ */
+/* $OpenBSD: vioscsi.c,v 1.11 2018/08/25 04:16:09 ccardenas Exp $ */
/*
* Copyright (c) 2017 Carlos Cardenas <ccardenas@openbsd.org>
goto nomem;
info->len = n_blocks * VIOSCSI_BLOCK_SIZE_CDROM;
info->offset = block * VIOSCSI_BLOCK_SIZE_CDROM;
- info->fd = dev->fd;
+ info->file = &dev->file;
return info;
static const uint8_t *
vioscsi_finish_read(struct ioinfo *info)
{
- if (pread(info->fd, info->buf, info->len, info->offset) != info->len) {
+ struct virtio_backing *f;
+
+ f = info->file;
+ if (f->pread(f->p, info->buf, info->len, info->offset) != info->len) {
info->error = errno;
log_warn("vioscsi read error");
return NULL;
-/* $OpenBSD: virtio.c,v 1.63 2018/07/09 16:11:37 mlarkin Exp $ */
+/* $OpenBSD: virtio.c,v 1.64 2018/08/25 04:16:09 ccardenas Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
goto nomem;
info->len = sz;
info->offset = sector * VIRTIO_BLK_SECTOR_SIZE;
- info->fd = dev->fd;
+ info->file = &dev->file;
return info;
static const uint8_t *
vioblk_finish_read(struct ioinfo *info)
{
- if (pread(info->fd, info->buf, info->len, info->offset) != info->len) {
+ struct virtio_backing *file;
+
+ file = info->file;
+ if (file->pread(file->p, info->buf, info->len, info->offset) != info->len) {
info->error = errno;
log_warn("vioblk read error");
return NULL;
goto nomem;
info->len = len;
info->offset = sector * VIRTIO_BLK_SECTOR_SIZE;
- info->fd = dev->fd;
+ info->file = &dev->file;
if (read_mem(addr, info->buf, len)) {
vioblk_free_info(info);
static int
vioblk_finish_write(struct ioinfo *info)
{
- if (pwrite(info->fd, info->buf, info->len, info->offset) != info->len) {
+ struct virtio_backing *file;
+
+ file = info->file;
+ if (file->pwrite(file->p, info->buf, info->len, info->offset) != info->len) {
log_warn("vioblk write error");
return EIO;
}
return (0);
}
+static int
+virtio_init_disk(struct virtio_backing *file, off_t *sz, int fd)
+{
+ /*
+ * This is where we slot in disk type selection.
+ * Right now, there's only raw.
+ */
+ return virtio_init_raw(file, sz, fd);
+}
+
void
virtio_init(struct vmd_vm *vm, int child_cdrom, int *child_disks,
int *child_taps)
uint8_t id;
uint8_t i;
int ret;
- off_t sz;
/* Virtio entropy device */
if (pci_add_device(&id, PCI_VENDOR_QUMRANET,
/* One virtio block device for each disk defined in vcp */
for (i = 0; i < vcp->vcp_ndisks; i++) {
- if ((sz = lseek(child_disks[i], 0, SEEK_END)) == -1)
- continue;
-
if (pci_add_device(&id, PCI_VENDOR_QUMRANET,
PCI_PRODUCT_QUMRANET_VIO_BLOCK,
PCI_CLASS_MASS_STORAGE,
sizeof(struct vring_desc) * VIOBLK_QUEUE_SIZE
+ sizeof(uint16_t) * (2 + VIOBLK_QUEUE_SIZE));
vioblk[i].vq[0].last_avail = 0;
- vioblk[i].fd = child_disks[i];
- vioblk[i].sz = sz / 512;
vioblk[i].cfg.device_feature = VIRTIO_BLK_F_SIZE_MAX;
vioblk[i].max_xfer = 1048576;
vioblk[i].pci_id = id;
vioblk[i].vm_id = vcp->vcp_id;
vioblk[i].irq = pci_get_dev_irq(id);
+ if (virtio_init_disk(&vioblk[i].file, &vioblk[i].sz,
+ child_disks[i]) == -1)
+ continue;
+ vioblk[i].sz /= 512;
}
}
+ sizeof(uint16_t) * (2 + VIOSCSI_QUEUE_SIZE));
vioscsi->vq[i].last_avail = 0;
}
- sz = lseek(child_cdrom, 0, SEEK_END);
- vioscsi->fd = child_cdrom;
+ if (virtio_init_disk(&vioscsi->file, &vioscsi->sz,
+ child_cdrom) == -1)
+ return;
vioscsi->locked = 0;
vioscsi->lba = 0;
- vioscsi->sz = sz;
- vioscsi->n_blocks = sz >> 11; /* num of 2048 blocks in file */
+ vioscsi->n_blocks = vioscsi->sz >> 11; /* num of 2048 blocks in file */
vioscsi->max_xfer = VIOSCSI_BLOCK_SIZE_CDROM;
vioscsi->pci_id = id;
vioscsi->vm_id = vcp->vcp_id;
vioblk_restore(int fd, struct vm_create_params *vcp, int *child_disks)
{
uint8_t i;
- off_t sz;
nr_vioblk = vcp->vcp_ndisks;
vioblk = calloc(vcp->vcp_ndisks, sizeof(struct vioblk_dev));
return (-1);
}
for (i = 0; i < vcp->vcp_ndisks; i++) {
- if ((sz = lseek(child_disks[i], 0, SEEK_END)) == -1)
- continue;
-
if (pci_set_bar_fn(vioblk[i].pci_id, 0, virtio_blk_io,
&vioblk[i])) {
log_warnx("%s: can't set bar fn for virtio block "
"device", __progname);
return (-1);
}
- vioblk[i].fd = child_disks[i];
+ if (virtio_init_disk(&vioblk[i].file, &vioblk[i].sz,
+ child_disks[i]) == -1)
+ continue;
}
return (0);
}
int
vioscsi_restore(int fd, struct vm_create_params *vcp, int child_cdrom)
{
- off_t sz;
-
if (!strlen(vcp->vcp_cdrom))
return (0);
return (-1);
}
- sz = lseek(child_cdrom, 0, SEEK_END);
-
if (pci_set_bar_fn(vioscsi->pci_id, 0, vioscsi_io, vioscsi)) {
log_warnx("%s: can't set bar fn for vmm control device",
__progname);
return (-1);
}
- vioscsi->fd = child_cdrom;
+ virtio_init_disk(&vioscsi->file, &vioscsi->sz, child_cdrom);
return (0);
}
-/* $OpenBSD: virtio.h,v 1.26 2018/07/09 08:43:09 mlarkin Exp $ */
+/* $OpenBSD: virtio.h,v 1.27 2018/08/25 04:16:09 ccardenas Exp $ */
/*
* Copyright (c) 2015 Mike Larkin <mlarkin@openbsd.org>
uint8_t isr_status;
};
+struct virtio_backing {
+ void *p;
+ ssize_t (*pread)(void *p, char *buf, size_t len, off_t off);
+ ssize_t (*pwrite)(void *p, char *buf, size_t len, off_t off);
+ void (*close)(void *p);
+};
+
/*
* A virtio device can have several virtqs. For example, vionet has one virtq
* each for transmitting and receiving packets. This struct describes the state
struct virtio_io_cfg cfg;
struct virtio_vq_info vq[VIRTIO_MAX_QUEUES];
+ struct virtio_backing file;
- int fd;
uint64_t sz;
uint32_t max_xfer;
struct virtio_vq_info vq[VIRTIO_MAX_QUEUES];
+ struct virtio_backing file;
+
/* is the device locked */
int locked;
- int fd;
/* size of iso file in bytes */
uint64_t sz;
/* last block address read */
};
struct ioinfo {
+ struct virtio_backing *file;
uint8_t *buf;
ssize_t len;
off_t offset;
- int fd;
int error;
};
void viornd_update_qa(void);
int viornd_notifyq(void);
+int virtio_init_raw(struct virtio_backing *dev, off_t *sz, int fd);
+
int virtio_blk_io(int, uint16_t, uint32_t *, uint8_t *, void *, uint8_t);
int vioblk_dump(int);
int vioblk_restore(int, struct vm_create_params *, int *);