This patch implements a very simple virtio transport for 9p in QEMU. The kernel side of this is going to change dramatically in the very near future so this is just a demonstration for the moment. It requires an external 9p file server and communicates with it over a TCP port. In future versions of this patch, we'll link directly against a 9p file server library and expose the ability to expose filesystems directly from the QEMU command line.
Signed-off-by: Anthony Liguori <[EMAIL PROTECTED]> diff --git a/qemu/Makefile.target b/qemu/Makefile.target index 49c0fc7..fedf1e0 100644 --- a/qemu/Makefile.target +++ b/qemu/Makefile.target @@ -449,7 +449,7 @@ VL_OBJS += rtl8139.o VL_OBJS+= hypercall.o # virtio devices -VL_OBJS += virtio.o virtio-blk.o +VL_OBJS += virtio.o virtio-blk.o virtio-9p.o ifeq ($(TARGET_BASE_ARCH), i386) # Hardware support diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c index c7483e8..fa0346b 100644 --- a/qemu/hw/pc.c +++ b/qemu/hw/pc.c @@ -951,6 +951,9 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, int boot_device, virtio_blk_init(pci_bus, 0x5002, 0x2258, bs); } + if (1) + virtio_9p_init(pci_bus, 0x5002, 0x2258); + if (pci_enabled) { pci_piix3_ide_init(pci_bus, bs_table, piix3_devfn + 1, i8259); } else { diff --git a/qemu/hw/virtio-9p.c b/qemu/hw/virtio-9p.c new file mode 100644 index 0000000..c77b594 --- /dev/null +++ b/qemu/hw/virtio-9p.c @@ -0,0 +1,121 @@ +/* + * Virtio 9p backend + * + * Copyright IBM, Corp. 2007 + * + * Authors: + * Anthony Liguori <[EMAIL PROTECTED]> + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include "vl.h" +#include "qemu_socket.h" +#include "virtio.h" +#include <sys/uio.h> +#include <arpa/inet.h> + +/* from Linux's linux/virtio_9p.h */ + +/* The ID for virtio console */ +#define VIRTIO_ID_9P 9 +/* Maximum number of virtio channels per partition (1 for now) */ +#define MAX_9P_CHAN 1 + +typedef struct V9fsState +{ + VirtIODevice vdev; + + int fd; + int listening; + VirtQueue *in_vq; +} V9fsState; + +static V9fsState *to_v9fs_state(VirtIODevice *vdev) +{ + return (V9fsState *)vdev; +} + +static void virtio_9p_handle_output(VirtIODevice *vdev, VirtQueue *vq) +{ + V9fsState *s = to_v9fs_state(vdev); + VirtQueueElement elem; + ssize_t len; + + while ((len = virtqueue_pop(vq, &elem)) != 0) { + len = writev(s->fd, elem.out_sg, elem.out_num); + if (len == -1 && (errno == EINTR || errno == EAGAIN)) + continue; + + virtqueue_push(vq, &elem, len); + virtio_notify(vdev, vq); + } +} + +static void virtio_9p_kick_input(VirtIODevice *vdev, VirtQueue *vq) +{ + V9fsState *s = to_v9fs_state(vdev); + s->listening = 1; +} + +static int virtio_9p_can_read(void *opaque) +{ + V9fsState *s = opaque; + return s->listening; +} + +static void virtio_9p_handle_input(void *opaque) +{ + V9fsState *s = opaque; + VirtQueueElement elem; + ssize_t len; + + len = virtqueue_pop(s->in_vq, &elem); + if (!len) { + /* stop listening until more queue space frees up */ + s->listening = 0; + return; + } + +again: + len = readv(s->fd, elem.in_sg, elem.in_num); + if (len == -1 && (errno == EINTR || errno == EAGAIN)) + goto again; + + virtqueue_push(s->in_vq, &elem, len); + virtio_notify(&s->vdev, s->in_vq); +} + +VirtIODevice *virtio_9p_init(PCIBus *bus, uint16_t vendor, uint16_t device) +{ + V9fsState *s; + struct sockaddr_in addr; + struct in_addr in; + + s = (V9fsState *)virtio_init_pci(bus, "virtio-9p", vendor, device, + vendor, VIRTIO_ID_9P, + 0, sizeof(V9fsState)); + + s->fd = socket(PF_INET, SOCK_STREAM, 0); + if (s->fd == -1) + exit(1); + addr.sin_family = AF_INET; + addr.sin_port = htons(1025); + inet_aton("127.0.0.1", &in); + memcpy(&addr.sin_addr, &in, sizeof(in)); + + if (connect(s->fd, (struct sockaddr *)&addr, sizeof(addr)) == -1) + exit(2); + + s->listening = 0; /* don't start listening until the queue is inited */ + + s->in_vq = virtio_add_queue(&s->vdev, virtio_9p_kick_input); + virtio_add_queue(&s->vdev, virtio_9p_handle_output); + + qemu_set_fd_handler2(s->fd, virtio_9p_can_read, virtio_9p_handle_input, + NULL, s); + + return &s->vdev; +} diff --git a/qemu/vl.h b/qemu/vl.h index 249ede2..7b5cc8d 100644 --- a/qemu/vl.h +++ b/qemu/vl.h @@ -1399,6 +1399,8 @@ typedef struct VirtIODevice VirtIODevice; VirtIODevice *virtio_blk_init(PCIBus *bus, uint16_t vendor, uint16_t device, BlockDriverState *bs); +VirtIODevice *virtio_9p_init(PCIBus *bus, uint16_t vendor, uint16_t device); + /* buf = NULL means polling */ typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out, const uint8_t *buf, int len); ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel