* [PATCH 1/7] Fix whitespace in virtio
@ 2008-12-03 17:26 Anthony Liguori
2008-12-03 17:26 ` [PATCH 2/7] Create virtio-blk.h header Anthony Liguori
2008-12-05 17:38 ` [PATCH 1/7] Fix whitespace in virtio Avi Kivity
0 siblings, 2 replies; 11+ messages in thread
From: Anthony Liguori @ 2008-12-03 17:26 UTC (permalink / raw)
To: kvm; +Cc: Avi Kivity, Anthony Liguori
Whoever originally wrote the virtio code quite rudely didn't configure their
editor to use spaces instead of tabs. This patch corrects this for all virtio
related files.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/qemu/hw/virtio-balloon.c b/qemu/hw/virtio-balloon.c
index 111f27d..9b34e87 100644
--- a/qemu/hw/virtio-balloon.c
+++ b/qemu/hw/virtio-balloon.c
@@ -79,26 +79,26 @@ static void virtio_balloon_handle_output(VirtIODevice *vdev, VirtQueue *vq)
VirtQueueElement elem;
while (virtqueue_pop(vq, &elem)) {
- size_t offset = 0;
- uint32_t pfn;
+ size_t offset = 0;
+ uint32_t pfn;
- while (memcpy_from_iovector(&pfn, offset, 4,
+ while (memcpy_from_iovector(&pfn, offset, 4,
elem.out_sg, elem.out_num) == 4) {
- ram_addr_t pa;
- ram_addr_t addr;
+ ram_addr_t pa;
+ ram_addr_t addr;
- pa = (ram_addr_t)ldl_p(&pfn) << VIRTIO_BALLOON_PFN_SHIFT;
- offset += 4;
+ pa = (ram_addr_t)ldl_p(&pfn) << VIRTIO_BALLOON_PFN_SHIFT;
+ offset += 4;
- addr = cpu_get_physical_page_desc(pa);
- if ((addr & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
- continue;
+ addr = cpu_get_physical_page_desc(pa);
+ if ((addr & ~TARGET_PAGE_MASK) != IO_MEM_RAM)
+ continue;
- balloon_page(phys_ram_base + addr, !!(vq == s->dvq));
- }
+ balloon_page(phys_ram_base + addr, !!(vq == s->dvq));
+ }
- virtqueue_push(vq, &elem, offset);
- virtio_notify(vdev, vq);
+ virtqueue_push(vq, &elem, offset);
+ virtio_notify(vdev, vq);
}
}
@@ -114,7 +114,7 @@ static void virtio_balloon_get_config(VirtIODevice *vdev, uint8_t *config_data)
}
static void virtio_balloon_set_config(VirtIODevice *vdev,
- const uint8_t *config_data)
+ const uint8_t *config_data)
{
VirtIOBalloon *dev = to_virtio_balloon(vdev);
struct virtio_balloon_config config;
@@ -132,11 +132,11 @@ static ram_addr_t virtio_balloon_to_target(void *opaque, ram_addr_t target)
VirtIOBalloon *dev = opaque;
if (target > ram_size)
- target = ram_size;
+ target = ram_size;
if (target) {
- dev->num_pages = (ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT;
- virtio_notify_config(&dev->vdev);
+ dev->num_pages = (ram_size - target) >> VIRTIO_BALLOON_PFN_SHIFT;
+ virtio_notify_config(&dev->vdev);
}
return ram_size - (dev->actual << VIRTIO_BALLOON_PFN_SHIFT);
@@ -172,10 +172,10 @@ void *virtio_balloon_init(PCIBus *bus)
VirtIOBalloon *s;
s = (VirtIOBalloon *)virtio_init_pci(bus, "virtio-balloon",
- 6900, 0x1002,
- 0, VIRTIO_ID_BALLOON,
- 0x05, 0x00, 0x00,
- 8, sizeof(VirtIOBalloon));
+ 6900, 0x1002,
+ 0, VIRTIO_ID_BALLOON,
+ 0x05, 0x00, 0x00,
+ 8, sizeof(VirtIOBalloon));
if (s == NULL)
return NULL;
diff --git a/qemu/hw/virtio-balloon.h b/qemu/hw/virtio-balloon.h
index 0466a48..45e4b03 100644
--- a/qemu/hw/virtio-balloon.h
+++ b/qemu/hw/virtio-balloon.h
@@ -18,10 +18,10 @@
/* from Linux's linux/virtio_balloon.h */
/* The ID for virtio_balloon */
-#define VIRTIO_ID_BALLOON 5
+#define VIRTIO_ID_BALLOON 5
/* The feature bitmap for virtio balloon */
-#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */
+#define VIRTIO_BALLOON_F_MUST_TELL_HOST 0 /* Tell before reclaiming pages */
/* Size of a PFN in the balloon interface. */
#define VIRTIO_BALLOON_PFN_SHIFT 12
diff --git a/qemu/hw/virtio-blk.c b/qemu/hw/virtio-blk.c
index 727119b..c9a91ba 100644
--- a/qemu/hw/virtio-blk.c
+++ b/qemu/hw/virtio-blk.c
@@ -19,13 +19,13 @@
/* from Linux's linux/virtio_blk.h */
/* The ID for virtio_block */
-#define VIRTIO_ID_BLOCK 2
+#define VIRTIO_ID_BLOCK 2
/* Feature bits */
-#define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */
-#define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */
-#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */
-#define VIRTIO_BLK_F_GEOMETRY 4 /* Indicates support of legacy geometry */
+#define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */
+#define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */
+#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */
+#define VIRTIO_BLK_F_GEOMETRY 4 /* Indicates support of legacy geometry */
struct virtio_blk_config
{
@@ -38,14 +38,14 @@ struct virtio_blk_config
} __attribute__((packed));
/* These two define direction. */
-#define VIRTIO_BLK_T_IN 0
-#define VIRTIO_BLK_T_OUT 1
+#define VIRTIO_BLK_T_IN 0
+#define VIRTIO_BLK_T_OUT 1
/* This bit says it's a scsi command, not an actual read or write. */
-#define VIRTIO_BLK_T_SCSI_CMD 2
+#define VIRTIO_BLK_T_SCSI_CMD 2
/* Barrier before this op. */
-#define VIRTIO_BLK_T_BARRIER 0x80000000
+#define VIRTIO_BLK_T_BARRIER 0x80000000
/* This is the first element of the read scatter-gather list. */
struct virtio_blk_outhdr
@@ -58,9 +58,9 @@ struct virtio_blk_outhdr
uint64_t sector;
};
-#define VIRTIO_BLK_S_OK 0
-#define VIRTIO_BLK_S_IOERR 1
-#define VIRTIO_BLK_S_UNSUPP 2
+#define VIRTIO_BLK_S_OK 0
+#define VIRTIO_BLK_S_IOERR 1
+#define VIRTIO_BLK_S_UNSUPP 2
/* This is the first element of the write scatter-gather list */
struct virtio_blk_inhdr
@@ -97,21 +97,21 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
/* Copy read data to the guest */
if (!ret && !(req->out->type & VIRTIO_BLK_T_OUT)) {
- size_t offset = 0;
- int i;
+ size_t offset = 0;
+ int i;
- for (i = 0; i < req->elem.in_num - 1; i++) {
- size_t len;
+ for (i = 0; i < req->elem.in_num - 1; i++) {
+ size_t len;
- /* Be pretty defensive wrt malicious guests */
- len = MIN(req->elem.in_sg[i].iov_len,
- req->size - offset);
+ /* Be pretty defensive wrt malicious guests */
+ len = MIN(req->elem.in_sg[i].iov_len,
+ req->size - offset);
- memcpy(req->elem.in_sg[i].iov_base,
- req->buffer + offset,
- len);
- offset += len;
- }
+ memcpy(req->elem.in_sg[i].iov_base,
+ req->buffer + offset,
+ len);
+ offset += len;
+ }
}
req->in->status = ret ? VIRTIO_BLK_S_IOERR : VIRTIO_BLK_S_OK;
@@ -128,12 +128,12 @@ static VirtIOBlockReq *virtio_blk_get_request(VirtIOBlock *s)
req = qemu_mallocz(sizeof(*req));
if (req == NULL)
- return NULL;
+ return NULL;
req->dev = s;
if (!virtqueue_pop(s->vq, &req->elem)) {
- qemu_free(req);
- return NULL;
+ qemu_free(req);
+ return NULL;
}
return req;
@@ -145,76 +145,76 @@ static void virtio_blk_handle_output(VirtIODevice *vdev, VirtQueue *vq)
VirtIOBlockReq *req;
while ((req = virtio_blk_get_request(s))) {
- int i;
-
- if (req->elem.out_num < 1 || req->elem.in_num < 1) {
- fprintf(stderr, "virtio-blk missing headers\n");
- exit(1);
- }
-
- if (req->elem.out_sg[0].iov_len < sizeof(*req->out) ||
- req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) {
- fprintf(stderr, "virtio-blk header not in correct element\n");
- exit(1);
- }
-
- req->out = (void *)req->elem.out_sg[0].iov_base;
- req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
-
- if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
- unsigned int len = sizeof(*req->in);
-
- req->in->status = VIRTIO_BLK_S_UNSUPP;
- virtqueue_push(vq, &req->elem, len);
- virtio_notify(vdev, vq);
- qemu_free(req);
- } else if (req->out->type & VIRTIO_BLK_T_OUT) {
- size_t offset;
-
- for (i = 1; i < req->elem.out_num; i++)
- req->size += req->elem.out_sg[i].iov_len;
-
- req->buffer = qemu_memalign(512, req->size);
- if (req->buffer == NULL) {
- qemu_free(req);
- break;
- }
-
- /* We copy the data from the SG list to avoid splitting up the request. This helps
- performance a lot until we can pass full sg lists as AIO operations */
- offset = 0;
- for (i = 1; i < req->elem.out_num; i++) {
- size_t len;
-
- len = MIN(req->elem.out_sg[i].iov_len,
- req->size - offset);
- memcpy(req->buffer + offset,
- req->elem.out_sg[i].iov_base,
- len);
- offset += len;
- }
-
- bdrv_aio_write(s->bs, req->out->sector,
- req->buffer,
- req->size / 512,
- virtio_blk_rw_complete,
- req);
- } else {
- for (i = 0; i < req->elem.in_num - 1; i++)
- req->size += req->elem.in_sg[i].iov_len;
-
- req->buffer = qemu_memalign(512, req->size);
- if (req->buffer == NULL) {
- qemu_free(req);
- break;
- }
-
- bdrv_aio_read(s->bs, req->out->sector,
- req->buffer,
- req->size / 512,
- virtio_blk_rw_complete,
- req);
- }
+ int i;
+
+ if (req->elem.out_num < 1 || req->elem.in_num < 1) {
+ fprintf(stderr, "virtio-blk missing headers\n");
+ exit(1);
+ }
+
+ if (req->elem.out_sg[0].iov_len < sizeof(*req->out) ||
+ req->elem.in_sg[req->elem.in_num - 1].iov_len < sizeof(*req->in)) {
+ fprintf(stderr, "virtio-blk header not in correct element\n");
+ exit(1);
+ }
+
+ req->out = (void *)req->elem.out_sg[0].iov_base;
+ req->in = (void *)req->elem.in_sg[req->elem.in_num - 1].iov_base;
+
+ if (req->out->type & VIRTIO_BLK_T_SCSI_CMD) {
+ unsigned int len = sizeof(*req->in);
+
+ req->in->status = VIRTIO_BLK_S_UNSUPP;
+ virtqueue_push(vq, &req->elem, len);
+ virtio_notify(vdev, vq);
+ qemu_free(req);
+ } else if (req->out->type & VIRTIO_BLK_T_OUT) {
+ size_t offset;
+
+ for (i = 1; i < req->elem.out_num; i++)
+ req->size += req->elem.out_sg[i].iov_len;
+
+ req->buffer = qemu_memalign(512, req->size);
+ if (req->buffer == NULL) {
+ qemu_free(req);
+ break;
+ }
+
+ /* We copy the data from the SG list to avoid splitting up the request. This helps
+ performance a lot until we can pass full sg lists as AIO operations */
+ offset = 0;
+ for (i = 1; i < req->elem.out_num; i++) {
+ size_t len;
+
+ len = MIN(req->elem.out_sg[i].iov_len,
+ req->size - offset);
+ memcpy(req->buffer + offset,
+ req->elem.out_sg[i].iov_base,
+ len);
+ offset += len;
+ }
+
+ bdrv_aio_write(s->bs, req->out->sector,
+ req->buffer,
+ req->size / 512,
+ virtio_blk_rw_complete,
+ req);
+ } else {
+ for (i = 0; i < req->elem.in_num - 1; i++)
+ req->size += req->elem.in_sg[i].iov_len;
+
+ req->buffer = qemu_memalign(512, req->size);
+ if (req->buffer == NULL) {
+ qemu_free(req);
+ break;
+ }
+
+ bdrv_aio_read(s->bs, req->out->sector,
+ req->buffer,
+ req->size / 512,
+ virtio_blk_rw_complete,
+ req);
+ }
}
/*
* FIXME: Want to check for completions before returning to guest mode,
@@ -265,7 +265,7 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
VirtIOBlock *s = opaque;
if (version_id != 1)
- return -EINVAL;
+ return -EINVAL;
virtio_load(&s->vdev, f);
@@ -273,18 +273,18 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
}
void *virtio_blk_init(PCIBus *bus, uint16_t vendor, uint16_t device,
- BlockDriverState *bs)
+ BlockDriverState *bs)
{
VirtIOBlock *s;
int cylinders, heads, secs;
static int virtio_blk_id;
s = (VirtIOBlock *)virtio_init_pci(bus, "virtio-blk", vendor, device,
- 0, VIRTIO_ID_BLOCK,
- 0x01, 0x80, 0x00,
- sizeof(struct virtio_blk_config), sizeof(VirtIOBlock));
+ 0, VIRTIO_ID_BLOCK,
+ 0x01, 0x80, 0x00,
+ sizeof(struct virtio_blk_config), sizeof(VirtIOBlock));
if (!s)
- return NULL;
+ return NULL;
s->vdev.get_config = virtio_blk_update_config;
s->vdev.get_features = virtio_blk_get_features;
@@ -297,7 +297,7 @@ void *virtio_blk_init(PCIBus *bus, uint16_t vendor, uint16_t device,
s->vq = virtio_add_queue(&s->vdev, 128, virtio_blk_handle_output);
register_savevm("virtio-blk", virtio_blk_id++, 1,
- virtio_blk_save, virtio_blk_load, s);
+ virtio_blk_save, virtio_blk_load, s);
return s;
}
diff --git a/qemu/hw/virtio-net.c b/qemu/hw/virtio-net.c
index b5d5f9e..b179fcc 100644
--- a/qemu/hw/virtio-net.c
+++ b/qemu/hw/virtio-net.c
@@ -19,27 +19,27 @@
/* from Linux's virtio_net.h */
/* The ID for virtio_net */
-#define VIRTIO_ID_NET 1
+#define VIRTIO_ID_NET 1
/* The feature bitmap for virtio net */
-#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
-#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
-#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
-#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
-#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
-#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */
-#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */
-#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */
-#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */
-#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */
-#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */
-#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */
-#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */
+#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
+#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
+#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
+#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
+#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
+#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */
+#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */
+#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */
+#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */
+#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */
+#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */
#define TX_TIMER_INTERVAL 150000 /* 150 us */
/* Maximum packet size we can receive from tap device: header + 64k */
-#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
+#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
/* The config defining mac address (6 bytes) */
struct virtio_net_config
@@ -51,13 +51,13 @@ struct virtio_net_config
* specify GSO or CSUM features, you can simply ignore the header. */
struct virtio_net_hdr
{
-#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset
+#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset
uint8_t flags;
-#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame
-#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO)
-#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO)
-#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP
-#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set
+#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame
+#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO)
+#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO)
+#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP
+#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set
uint8_t gso_type;
uint16_t hdr_len;
uint16_t gso_size;
@@ -110,17 +110,17 @@ static uint32_t virtio_net_get_features(VirtIODevice *vdev)
uint32_t features = (1 << VIRTIO_NET_F_MAC);
if (tap_has_vnet_hdr(host)) {
- tap_using_vnet_hdr(host, 1);
- features |= (1 << VIRTIO_NET_F_CSUM);
- features |= (1 << VIRTIO_NET_F_GUEST_CSUM);
- features |= (1 << VIRTIO_NET_F_GUEST_TSO4);
- features |= (1 << VIRTIO_NET_F_GUEST_TSO6);
- features |= (1 << VIRTIO_NET_F_GUEST_ECN);
- features |= (1 << VIRTIO_NET_F_HOST_TSO4);
- features |= (1 << VIRTIO_NET_F_HOST_TSO6);
- features |= (1 << VIRTIO_NET_F_HOST_ECN);
- features |= (1 << VIRTIO_NET_F_MRG_RXBUF);
- /* Kernel can't actually handle UFO in software currently. */
+ tap_using_vnet_hdr(host, 1);
+ features |= (1 << VIRTIO_NET_F_CSUM);
+ features |= (1 << VIRTIO_NET_F_GUEST_CSUM);
+ features |= (1 << VIRTIO_NET_F_GUEST_TSO4);
+ features |= (1 << VIRTIO_NET_F_GUEST_TSO6);
+ features |= (1 << VIRTIO_NET_F_GUEST_ECN);
+ features |= (1 << VIRTIO_NET_F_HOST_TSO4);
+ features |= (1 << VIRTIO_NET_F_HOST_TSO6);
+ features |= (1 << VIRTIO_NET_F_HOST_ECN);
+ features |= (1 << VIRTIO_NET_F_MRG_RXBUF);
+ /* Kernel can't actually handle UFO in software currently. */
}
return features;
@@ -134,13 +134,13 @@ static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
n->mergeable_rx_bufs = !!(features & (1 << VIRTIO_NET_F_MRG_RXBUF));
if (!tap_has_vnet_hdr(host) || !host->set_offload)
- return;
+ return;
host->set_offload(host,
- (features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
- (features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
- (features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
- (features >> VIRTIO_NET_F_GUEST_ECN) & 1);
+ (features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
+ (features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
+ (features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
+ (features >> VIRTIO_NET_F_GUEST_ECN) & 1);
}
/* RX */
@@ -150,7 +150,7 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
/* We now have RX buffers, signal to the IO thread to break out of the
select to re-poll the tap file descriptor */
if (kvm_enabled())
- qemu_kvm_notify_work();
+ qemu_kvm_notify_work();
}
static int virtio_net_can_receive(void *opaque)
@@ -158,14 +158,14 @@ static int virtio_net_can_receive(void *opaque)
VirtIONet *n = opaque;
if (n->rx_vq->vring.avail == NULL ||
- !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
- return 0;
+ !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
+ return 0;
if (n->rx_vq->vring.avail->idx == n->rx_vq->last_avail_idx ||
- (n->mergeable_rx_bufs &&
- !virtqueue_avail_bytes(n->rx_vq, VIRTIO_NET_MAX_BUFSIZE, 0))) {
- n->rx_vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
- return 0;
+ (n->mergeable_rx_bufs &&
+ !virtqueue_avail_bytes(n->rx_vq, VIRTIO_NET_MAX_BUFSIZE, 0))) {
+ n->rx_vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+ return 0;
}
n->rx_vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
@@ -206,17 +206,17 @@ static int iov_fill(struct iovec *iov, int iovcnt, const void *buf, int count)
offset = i = 0;
while (offset < count && i < iovcnt) {
- int len = MIN(iov[i].iov_len, count - offset);
- memcpy(iov[i].iov_base, buf + offset, len);
- offset += len;
- i++;
+ int len = MIN(iov[i].iov_len, count - offset);
+ memcpy(iov[i].iov_base, buf + offset, len);
+ offset += len;
+ i++;
}
return offset;
}
static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt,
- const void *buf, int size, int hdr_len)
+ const void *buf, int size, int hdr_len)
{
struct virtio_net_hdr *hdr = iov[0].iov_base;
int offset;
@@ -225,9 +225,9 @@ static int receive_header(VirtIONet *n, struct iovec *iov, int iovcnt,
hdr->gso_type = VIRTIO_NET_HDR_GSO_NONE;
if (tap_has_vnet_hdr(n->vc->vlan->first_client)) {
- memcpy(hdr, buf, sizeof(*hdr));
- offset = sizeof(*hdr);
- work_around_broken_dhclient(hdr, buf + offset, size - offset);
+ memcpy(hdr, buf, sizeof(*hdr));
+ offset = sizeof(*hdr);
+ work_around_broken_dhclient(hdr, buf + offset, size - offset);
}
/* We only ever receive a struct virtio_net_hdr from the tapfd,
@@ -247,56 +247,56 @@ static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
/* hdr_len refers to the header we supply to the guest */
hdr_len = n->mergeable_rx_bufs ?
- sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
+ sizeof(struct virtio_net_hdr_mrg_rxbuf) : sizeof(struct virtio_net_hdr);
offset = i = 0;
while (offset < size) {
- VirtQueueElement elem;
- int len, total;
-
- len = total = 0;
-
- if ((i != 0 && !n->mergeable_rx_bufs) ||
- virtqueue_pop(n->rx_vq, &elem) == 0) {
- if (i == 0)
- return;
- fprintf(stderr, "virtio-net truncating packet\n");
- exit(1);
- }
-
- if (elem.in_num < 1) {
- fprintf(stderr, "virtio-net receive queue contains no in buffers\n");
- exit(1);
- }
-
- if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != hdr_len) {
- fprintf(stderr, "virtio-net header not in first element\n");
- exit(1);
- }
-
- if (i == 0) {
- if (n->mergeable_rx_bufs)
- mhdr = (struct virtio_net_hdr_mrg_rxbuf *)elem.in_sg[0].iov_base;
-
- offset += receive_header(n, &elem.in_sg[0], elem.in_num,
- buf + offset, size - offset, hdr_len);
- total += hdr_len;
- }
-
- /* copy in packet. ugh */
- len = iov_fill(&elem.in_sg[0], elem.in_num,
- buf + offset, size - offset);
- total += len;
-
- /* signal other side */
- virtqueue_fill(n->rx_vq, &elem, total, i++);
-
- offset += len;
+ VirtQueueElement elem;
+ int len, total;
+
+ len = total = 0;
+
+ if ((i != 0 && !n->mergeable_rx_bufs) ||
+ virtqueue_pop(n->rx_vq, &elem) == 0) {
+ if (i == 0)
+ return;
+ fprintf(stderr, "virtio-net truncating packet\n");
+ exit(1);
+ }
+
+ if (elem.in_num < 1) {
+ fprintf(stderr, "virtio-net receive queue contains no in buffers\n");
+ exit(1);
+ }
+
+ if (!n->mergeable_rx_bufs && elem.in_sg[0].iov_len != hdr_len) {
+ fprintf(stderr, "virtio-net header not in first element\n");
+ exit(1);
+ }
+
+ if (i == 0) {
+ if (n->mergeable_rx_bufs)
+ mhdr = (struct virtio_net_hdr_mrg_rxbuf *)elem.in_sg[0].iov_base;
+
+ offset += receive_header(n, &elem.in_sg[0], elem.in_num,
+ buf + offset, size - offset, hdr_len);
+ total += hdr_len;
+ }
+
+ /* copy in packet. ugh */
+ len = iov_fill(&elem.in_sg[0], elem.in_num,
+ buf + offset, size - offset);
+ total += len;
+
+ /* signal other side */
+ virtqueue_fill(n->rx_vq, &elem, total, i++);
+
+ offset += len;
}
if (mhdr)
- mhdr->num_buffers = i;
+ mhdr->num_buffers = i;
virtqueue_flush(n->rx_vq, i);
virtio_notify(&n->vdev, n->rx_vq);
@@ -312,37 +312,37 @@ static void virtio_net_flush_tx(VirtIONet *n, VirtQueue *vq)
return;
while (virtqueue_pop(vq, &elem)) {
- ssize_t len = 0;
- unsigned int out_num = elem.out_num;
- struct iovec *out_sg = &elem.out_sg[0];
- unsigned hdr_len;
+ ssize_t len = 0;
+ unsigned int out_num = elem.out_num;
+ struct iovec *out_sg = &elem.out_sg[0];
+ unsigned hdr_len;
/* hdr_len refers to the header received from the guest */
- hdr_len = n->mergeable_rx_bufs ?
- sizeof(struct virtio_net_hdr_mrg_rxbuf) :
- sizeof(struct virtio_net_hdr);
-
- if (out_num < 1 || out_sg->iov_len != hdr_len) {
- fprintf(stderr, "virtio-net header not in first element\n");
- exit(1);
- }
-
- /* ignore the header if GSO is not supported */
- if (!has_vnet_hdr) {
- out_num--;
- out_sg++;
- len += hdr_len;
- } else if (n->mergeable_rx_bufs) {
- /* tapfd expects a struct virtio_net_hdr */
- hdr_len -= sizeof(struct virtio_net_hdr);
- out_sg->iov_len -= hdr_len;
- len += hdr_len;
- }
-
- len += qemu_sendv_packet(n->vc, out_sg, out_num);
-
- virtqueue_push(vq, &elem, len);
- virtio_notify(&n->vdev, vq);
+ hdr_len = n->mergeable_rx_bufs ?
+ sizeof(struct virtio_net_hdr_mrg_rxbuf) :
+ sizeof(struct virtio_net_hdr);
+
+ if (out_num < 1 || out_sg->iov_len != hdr_len) {
+ fprintf(stderr, "virtio-net header not in first element\n");
+ exit(1);
+ }
+
+ /* ignore the header if GSO is not supported */
+ if (!has_vnet_hdr) {
+ out_num--;
+ out_sg++;
+ len += hdr_len;
+ } else if (n->mergeable_rx_bufs) {
+ /* tapfd expects a struct virtio_net_hdr */
+ hdr_len -= sizeof(struct virtio_net_hdr);
+ out_sg->iov_len -= hdr_len;
+ len += hdr_len;
+ }
+
+ len += qemu_sendv_packet(n->vc, out_sg, out_num);
+
+ virtqueue_push(vq, &elem, len);
+ virtio_notify(&n->vdev, vq);
}
}
@@ -351,15 +351,15 @@ static void virtio_net_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
VirtIONet *n = to_virtio_net(vdev);
if (n->tx_timer_active) {
- vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
- qemu_del_timer(n->tx_timer);
- n->tx_timer_active = 0;
- virtio_net_flush_tx(n, vq);
+ vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+ qemu_del_timer(n->tx_timer);
+ n->tx_timer_active = 0;
+ virtio_net_flush_tx(n, vq);
} else {
- qemu_mod_timer(n->tx_timer,
- qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
- n->tx_timer_active = 1;
- vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+ qemu_mod_timer(n->tx_timer,
+ qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
+ n->tx_timer_active = 1;
+ vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
}
}
@@ -392,7 +392,7 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
VirtIONet *n = opaque;
if (version_id != 1)
- return -EINVAL;
+ return -EINVAL;
virtio_load(&n->vdev, f);
@@ -400,8 +400,8 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
n->tx_timer_active = qemu_get_be32(f);
if (n->tx_timer_active) {
- qemu_mod_timer(n->tx_timer,
- qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
+ qemu_mod_timer(n->tx_timer,
+ qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
}
return 0;
@@ -413,11 +413,11 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
static int virtio_net_id;
n = (VirtIONet *)virtio_init_pci(bus, "virtio-net", 6900, 0x1000,
- 0, VIRTIO_ID_NET,
- 0x02, 0x00, 0x00,
- 6, sizeof(VirtIONet));
+ 0, VIRTIO_ID_NET,
+ 0x02, 0x00, 0x00,
+ 6, sizeof(VirtIONet));
if (!n)
- return NULL;
+ return NULL;
n->vdev.get_config = virtio_net_update_config;
n->vdev.get_features = virtio_net_get_features;
@@ -433,7 +433,7 @@ PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn)
n->mergeable_rx_bufs = 0;
register_savevm("virtio-net", virtio_net_id++, 1,
- virtio_net_save, virtio_net_load, n);
+ virtio_net_save, virtio_net_load, n);
return (PCIDevice *)n;
}
diff --git a/qemu/hw/virtio.c b/qemu/hw/virtio.c
index 303f5e7..6d7425c 100644
--- a/qemu/hw/virtio.c
+++ b/qemu/hw/virtio.c
@@ -20,35 +20,35 @@
/* from Linux's linux/virtio_pci.h */
/* A 32-bit r/o bitmask of the features supported by the host */
-#define VIRTIO_PCI_HOST_FEATURES 0
+#define VIRTIO_PCI_HOST_FEATURES 0
/* A 32-bit r/w bitmask of features activated by the guest */
-#define VIRTIO_PCI_GUEST_FEATURES 4
+#define VIRTIO_PCI_GUEST_FEATURES 4
/* A 32-bit r/w PFN for the currently selected queue */
-#define VIRTIO_PCI_QUEUE_PFN 8
+#define VIRTIO_PCI_QUEUE_PFN 8
/* A 16-bit r/o queue size for the currently selected queue */
-#define VIRTIO_PCI_QUEUE_NUM 12
+#define VIRTIO_PCI_QUEUE_NUM 12
/* A 16-bit r/w queue selector */
-#define VIRTIO_PCI_QUEUE_SEL 14
+#define VIRTIO_PCI_QUEUE_SEL 14
/* A 16-bit r/w queue notifier */
-#define VIRTIO_PCI_QUEUE_NOTIFY 16
+#define VIRTIO_PCI_QUEUE_NOTIFY 16
/* An 8-bit device status register. */
-#define VIRTIO_PCI_STATUS 18
+#define VIRTIO_PCI_STATUS 18
/* An 8-bit r/o interrupt status register. Reading the value will return the
* current contents of the ISR and will also clear it. This is effectively
* a read-and-acknowledge. */
-#define VIRTIO_PCI_ISR 19
+#define VIRTIO_PCI_ISR 19
-#define VIRTIO_PCI_CONFIG 20
+#define VIRTIO_PCI_CONFIG 20
/* Virtio ABI version, if we increment this, we break the guest driver. */
-#define VIRTIO_PCI_ABI_VERSION 0
+#define VIRTIO_PCI_ABI_VERSION 0
/* QEMU doesn't strictly need write barriers since everything runs in
* lock-step. We'll leave the calls to wmb() in though to make it obvious for
@@ -65,29 +65,29 @@ static void *virtio_map_gpa(target_phys_addr_t addr, size_t size)
off = cpu_get_physical_page_desc(addr);
if ((off & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
- fprintf(stderr, "virtio DMA to IO ram\n");
- exit(1);
+ fprintf(stderr, "virtio DMA to IO ram\n");
+ exit(1);
}
off = (off & TARGET_PAGE_MASK) | (addr & ~TARGET_PAGE_MASK);
for (addr1 = addr + TARGET_PAGE_SIZE;
- addr1 < TARGET_PAGE_ALIGN(addr + size);
- addr1 += TARGET_PAGE_SIZE) {
- ram_addr_t off1;
-
- off1 = cpu_get_physical_page_desc(addr1);
- if ((off1 & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
- fprintf(stderr, "virtio DMA to IO ram\n");
- exit(1);
- }
-
- off1 = (off1 & TARGET_PAGE_MASK) | (addr1 & ~TARGET_PAGE_MASK);
-
- if (off1 != (off + (addr1 - addr))) {
- fprintf(stderr, "discontigous virtio memory\n");
- exit(1);
- }
+ addr1 < TARGET_PAGE_ALIGN(addr + size);
+ addr1 += TARGET_PAGE_SIZE) {
+ ram_addr_t off1;
+
+ off1 = cpu_get_physical_page_desc(addr1);
+ if ((off1 & ~TARGET_PAGE_MASK) != IO_MEM_RAM) {
+ fprintf(stderr, "virtio DMA to IO ram\n");
+ exit(1);
+ }
+
+ off1 = (off1 & TARGET_PAGE_MASK) | (addr1 & ~TARGET_PAGE_MASK);
+
+ if (off1 != (off + (addr1 - addr))) {
+ fprintf(stderr, "discontigous virtio memory\n");
+ exit(1);
+ }
}
return phys_ram_base + off;
@@ -96,8 +96,8 @@ static void *virtio_map_gpa(target_phys_addr_t addr, size_t size)
static size_t virtqueue_size(int num)
{
return TARGET_PAGE_ALIGN((sizeof(VRingDesc) * num) +
- (sizeof(VRingAvail) + sizeof(uint16_t) * num)) +
- (sizeof(VRingUsed) + sizeof(VRingUsedElem) * num);
+ (sizeof(VRingAvail) + sizeof(uint16_t) * num)) +
+ (sizeof(VRingUsed) + sizeof(VRingUsedElem) * num);
}
static void virtqueue_init(VirtQueue *vq, void *p)
@@ -108,7 +108,7 @@ static void virtqueue_init(VirtQueue *vq, void *p)
}
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
- unsigned int len, unsigned int idx)
+ unsigned int len, unsigned int idx)
{
VRingUsedElem *used;
@@ -129,7 +129,7 @@ void virtqueue_flush(VirtQueue *vq, unsigned int count)
}
void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
- unsigned int len)
+ unsigned int len)
{
virtqueue_fill(vq, elem, len, 0);
virtqueue_flush(vq, 1);
@@ -141,8 +141,8 @@ static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
/* Check it isn't doing very strange things with descriptor numbers. */
if (num_heads > vq->vring.num)
- errx(1, "Guest moved used index from %u to %u",
- idx, vq->vring.avail->idx);
+ errx(1, "Guest moved used index from %u to %u",
+ idx, vq->vring.avail->idx);
return num_heads;
}
@@ -157,7 +157,7 @@ static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx)
/* If their number is silly, that's a fatal mistake. */
if (head >= vq->vring.num)
- errx(1, "Guest says index %u is available", head);
+ errx(1, "Guest says index %u is available", head);
return head;
}
@@ -168,7 +168,7 @@ static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i)
/* If this descriptor says it doesn't chain, we're done. */
if (!(vq->vring.desc[i].flags & VRING_DESC_F_NEXT))
- return vq->vring.num;
+ return vq->vring.num;
/* Check they're not leading us off end of descriptors. */
next = vq->vring.desc[i].next;
@@ -176,7 +176,7 @@ static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i)
wmb();
if (next >= vq->vring.num)
- errx(1, "Desc next is %u", next);
+ errx(1, "Desc next is %u", next);
return next;
}
@@ -190,24 +190,24 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
num_bufs = in_total = out_total = 0;
while (virtqueue_num_heads(vq, idx)) {
- int i;
-
- i = virtqueue_get_head(vq, idx++);
- do {
- /* If we've got too many, that implies a descriptor loop. */
- if (++num_bufs > vq->vring.num)
- errx(1, "Looped descriptor");
-
- if (vq->vring.desc[i].flags & VRING_DESC_F_WRITE) {
- if (in_bytes > 0 &&
- (in_total += vq->vring.desc[i].len) >= in_bytes)
- return 1;
- } else {
- if (out_bytes > 0 &&
- (out_total += vq->vring.desc[i].len) >= out_bytes)
- return 1;
- }
- } while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num);
+ int i;
+
+ i = virtqueue_get_head(vq, idx++);
+ do {
+ /* If we've got too many, that implies a descriptor loop. */
+ if (++num_bufs > vq->vring.num)
+ errx(1, "Looped descriptor");
+
+ if (vq->vring.desc[i].flags & VRING_DESC_F_WRITE) {
+ if (in_bytes > 0 &&
+ (in_total += vq->vring.desc[i].len) >= in_bytes)
+ return 1;
+ } else {
+ if (out_bytes > 0 &&
+ (out_total += vq->vring.desc[i].len) >= out_bytes)
+ return 1;
+ }
+ } while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num);
}
return 0;
@@ -218,29 +218,29 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
unsigned int i, head;
if (!virtqueue_num_heads(vq, vq->last_avail_idx))
- return 0;
+ return 0;
/* When we start there are none of either input nor output. */
elem->out_num = elem->in_num = 0;
i = head = virtqueue_get_head(vq, vq->last_avail_idx++);
do {
- struct iovec *sg;
-
- if (vq->vring.desc[i].flags & VRING_DESC_F_WRITE)
- sg = &elem->in_sg[elem->in_num++];
- else
- sg = &elem->out_sg[elem->out_num++];
-
- /* Grab the first descriptor, and check it's OK. */
- sg->iov_len = vq->vring.desc[i].len;
- sg->iov_base = virtio_map_gpa(vq->vring.desc[i].addr, sg->iov_len);
- if (sg->iov_base == NULL)
- errx(1, "Invalid mapping\n");
-
- /* If we've got too many, that implies a descriptor loop. */
- if ((elem->in_num + elem->out_num) > vq->vring.num)
- errx(1, "Looped descriptor");
+ struct iovec *sg;
+
+ if (vq->vring.desc[i].flags & VRING_DESC_F_WRITE)
+ sg = &elem->in_sg[elem->in_num++];
+ else
+ sg = &elem->out_sg[elem->out_num++];
+
+ /* Grab the first descriptor, and check it's OK. */
+ sg->iov_len = vq->vring.desc[i].len;
+ sg->iov_base = virtio_map_gpa(vq->vring.desc[i].addr, sg->iov_len);
+ if (sg->iov_base == NULL)
+ errx(1, "Invalid mapping\n");
+
+ /* If we've got too many, that implies a descriptor loop. */
+ if ((elem->in_num + elem->out_num) > vq->vring.num)
+ errx(1, "Looped descriptor");
} while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num);
elem->index = head;
@@ -294,34 +294,34 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
switch (addr) {
case VIRTIO_PCI_GUEST_FEATURES:
- if (vdev->set_features)
- vdev->set_features(vdev, val);
- vdev->features = val;
- break;
+ if (vdev->set_features)
+ vdev->set_features(vdev, val);
+ vdev->features = val;
+ break;
case VIRTIO_PCI_QUEUE_PFN:
- pa = (ram_addr_t)val << TARGET_PAGE_BITS;
- vdev->vq[vdev->queue_sel].pfn = val;
- if (pa == 0) {
+ pa = (ram_addr_t)val << TARGET_PAGE_BITS;
+ vdev->vq[vdev->queue_sel].pfn = val;
+ if (pa == 0) {
virtio_reset(vdev);
- } else {
- size_t size = virtqueue_size(vdev->vq[vdev->queue_sel].vring.num);
- virtqueue_init(&vdev->vq[vdev->queue_sel],
- virtio_map_gpa(pa, size));
- }
- break;
+ } else {
+ size_t size = virtqueue_size(vdev->vq[vdev->queue_sel].vring.num);
+ virtqueue_init(&vdev->vq[vdev->queue_sel],
+ virtio_map_gpa(pa, size));
+ }
+ break;
case VIRTIO_PCI_QUEUE_SEL:
- if (val < VIRTIO_PCI_QUEUE_MAX)
- vdev->queue_sel = val;
- break;
+ if (val < VIRTIO_PCI_QUEUE_MAX)
+ vdev->queue_sel = val;
+ break;
case VIRTIO_PCI_QUEUE_NOTIFY:
- if (val < VIRTIO_PCI_QUEUE_MAX && vdev->vq[val].vring.desc)
- vdev->vq[val].handle_output(vdev, &vdev->vq[val]);
- break;
+ if (val < VIRTIO_PCI_QUEUE_MAX && vdev->vq[val].vring.desc)
+ vdev->vq[val].handle_output(vdev, &vdev->vq[val]);
+ break;
case VIRTIO_PCI_STATUS:
- vdev->status = val & 0xFF;
- if (vdev->status == 0)
- virtio_reset(vdev);
- break;
+ vdev->status = val & 0xFF;
+ if (vdev->status == 0)
+ virtio_reset(vdev);
+ break;
}
}
@@ -334,32 +334,32 @@ static uint32_t virtio_ioport_read(void *opaque, uint32_t addr)
switch (addr) {
case VIRTIO_PCI_HOST_FEATURES:
- ret = vdev->get_features(vdev);
- ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
- break;
+ ret = vdev->get_features(vdev);
+ ret |= (1 << VIRTIO_F_NOTIFY_ON_EMPTY);
+ break;
case VIRTIO_PCI_GUEST_FEATURES:
- ret = vdev->features;
- break;
+ ret = vdev->features;
+ break;
case VIRTIO_PCI_QUEUE_PFN:
- ret = vdev->vq[vdev->queue_sel].pfn;
- break;
+ ret = vdev->vq[vdev->queue_sel].pfn;
+ break;
case VIRTIO_PCI_QUEUE_NUM:
- ret = vdev->vq[vdev->queue_sel].vring.num;
- break;
+ ret = vdev->vq[vdev->queue_sel].vring.num;
+ break;
case VIRTIO_PCI_QUEUE_SEL:
- ret = vdev->queue_sel;
- break;
+ ret = vdev->queue_sel;
+ break;
case VIRTIO_PCI_STATUS:
- ret = vdev->status;
- break;
+ ret = vdev->status;
+ break;
case VIRTIO_PCI_ISR:
- /* reading from the ISR also clears it. */
- ret = vdev->isr;
- vdev->isr = 0;
- virtio_update_irq(vdev);
- break;
+ /* reading from the ISR also clears it. */
+ ret = vdev->isr;
+ vdev->isr = 0;
+ virtio_update_irq(vdev);
+ break;
default:
- break;
+ break;
}
return ret;
@@ -374,7 +374,7 @@ static uint32_t virtio_config_readb(void *opaque, uint32_t addr)
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
- return (uint32_t)-1;
+ return (uint32_t)-1;
memcpy(&val, vdev->config + addr, sizeof(val));
return val;
@@ -389,7 +389,7 @@ static uint32_t virtio_config_readw(void *opaque, uint32_t addr)
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
- return (uint32_t)-1;
+ return (uint32_t)-1;
memcpy(&val, vdev->config + addr, sizeof(val));
return val;
@@ -404,7 +404,7 @@ static uint32_t virtio_config_readl(void *opaque, uint32_t addr)
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
- return (uint32_t)-1;
+ return (uint32_t)-1;
memcpy(&val, vdev->config + addr, sizeof(val));
return val;
@@ -417,7 +417,7 @@ static void virtio_config_writeb(void *opaque, uint32_t addr, uint32_t data)
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
- return;
+ return;
memcpy(vdev->config + addr, &val, sizeof(val));
@@ -432,7 +432,7 @@ static void virtio_config_writew(void *opaque, uint32_t addr, uint32_t data)
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
- return;
+ return;
memcpy(vdev->config + addr, &val, sizeof(val));
@@ -447,7 +447,7 @@ static void virtio_config_writel(void *opaque, uint32_t addr, uint32_t data)
addr -= vdev->addr + VIRTIO_PCI_CONFIG;
if (addr > (vdev->config_len - sizeof(val)))
- return;
+ return;
memcpy(vdev->config + addr, &val, sizeof(val));
@@ -456,47 +456,47 @@ static void virtio_config_writel(void *opaque, uint32_t addr, uint32_t data)
}
static void virtio_map(PCIDevice *pci_dev, int region_num,
- uint32_t addr, uint32_t size, int type)
+ uint32_t addr, uint32_t size, int type)
{
VirtIODevice *vdev = to_virtio_device(pci_dev);
int i;
vdev->addr = addr;
for (i = 0; i < 3; i++) {
- register_ioport_write(addr, 20, 1 << i, virtio_ioport_write, vdev);
- register_ioport_read(addr, 20, 1 << i, virtio_ioport_read, vdev);
+ register_ioport_write(addr, 20, 1 << i, virtio_ioport_write, vdev);
+ register_ioport_read(addr, 20, 1 << i, virtio_ioport_read, vdev);
}
if (vdev->config_len) {
- register_ioport_write(addr + 20, vdev->config_len, 1,
- virtio_config_writeb, vdev);
- register_ioport_write(addr + 20, vdev->config_len, 2,
- virtio_config_writew, vdev);
- register_ioport_write(addr + 20, vdev->config_len, 4,
- virtio_config_writel, vdev);
- register_ioport_read(addr + 20, vdev->config_len, 1,
- virtio_config_readb, vdev);
- register_ioport_read(addr + 20, vdev->config_len, 2,
- virtio_config_readw, vdev);
- register_ioport_read(addr + 20, vdev->config_len, 4,
- virtio_config_readl, vdev);
-
- vdev->get_config(vdev, vdev->config);
+ register_ioport_write(addr + 20, vdev->config_len, 1,
+ virtio_config_writeb, vdev);
+ register_ioport_write(addr + 20, vdev->config_len, 2,
+ virtio_config_writew, vdev);
+ register_ioport_write(addr + 20, vdev->config_len, 4,
+ virtio_config_writel, vdev);
+ register_ioport_read(addr + 20, vdev->config_len, 1,
+ virtio_config_readb, vdev);
+ register_ioport_read(addr + 20, vdev->config_len, 2,
+ virtio_config_readw, vdev);
+ register_ioport_read(addr + 20, vdev->config_len, 4,
+ virtio_config_readl, vdev);
+
+ vdev->get_config(vdev, vdev->config);
}
}
VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
- void (*handle_output)(VirtIODevice *, VirtQueue *))
+ void (*handle_output)(VirtIODevice *, VirtQueue *))
{
int i;
for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
- if (vdev->vq[i].vring.num == 0)
- break;
+ if (vdev->vq[i].vring.num == 0)
+ break;
}
if (i == VIRTIO_PCI_QUEUE_MAX || queue_size > VIRTQUEUE_MAX_SIZE)
- abort();
+ abort();
vdev->vq[i].vring.num = queue_size;
vdev->vq[i].handle_output = handle_output;
@@ -508,8 +508,8 @@ void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
{
/* Always notify when queue is empty */
if ((vq->inuse || vq->vring.avail->idx != vq->last_avail_idx) &&
- (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
- return;
+ (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
+ return;
vdev->isr |= 0x01;
virtio_update_irq(vdev);
@@ -536,19 +536,19 @@ void virtio_save(VirtIODevice *vdev, QEMUFile *f)
qemu_put_buffer(f, vdev->config, vdev->config_len);
for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
- if (vdev->vq[i].vring.num == 0)
- break;
+ if (vdev->vq[i].vring.num == 0)
+ break;
}
qemu_put_be32(f, i);
for (i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
- if (vdev->vq[i].vring.num == 0)
- break;
+ if (vdev->vq[i].vring.num == 0)
+ break;
- qemu_put_be32(f, vdev->vq[i].vring.num);
- qemu_put_be32s(f, &vdev->vq[i].pfn);
- qemu_put_be16s(f, &vdev->vq[i].last_avail_idx);
+ qemu_put_be32(f, vdev->vq[i].vring.num);
+ qemu_put_be32s(f, &vdev->vq[i].pfn);
+ qemu_put_be16s(f, &vdev->vq[i].last_avail_idx);
}
}
@@ -569,29 +569,29 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f)
num = qemu_get_be32(f);
for (i = 0; i < num; i++) {
- vdev->vq[i].vring.num = qemu_get_be32(f);
- qemu_get_be32s(f, &vdev->vq[i].pfn);
- qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
-
- if (vdev->vq[i].pfn) {
- size_t size;
- target_phys_addr_t pa;
-
- pa = (ram_addr_t)vdev->vq[i].pfn << TARGET_PAGE_BITS;
- size = virtqueue_size(vdev->vq[i].vring.num);
- virtqueue_init(&vdev->vq[i], virtio_map_gpa(pa, size));
- }
+ vdev->vq[i].vring.num = qemu_get_be32(f);
+ qemu_get_be32s(f, &vdev->vq[i].pfn);
+ qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
+
+ if (vdev->vq[i].pfn) {
+ size_t size;
+ target_phys_addr_t pa;
+
+ pa = (ram_addr_t)vdev->vq[i].pfn << TARGET_PAGE_BITS;
+ size = virtqueue_size(vdev->vq[i].vring.num);
+ virtqueue_init(&vdev->vq[i], virtio_map_gpa(pa, size));
+ }
}
virtio_update_irq(vdev);
}
VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name,
- uint16_t vendor, uint16_t device,
- uint16_t subvendor, uint16_t subdevice,
- uint8_t class_code, uint8_t subclass_code,
- uint8_t pif, size_t config_size,
- size_t struct_size)
+ uint16_t vendor, uint16_t device,
+ uint16_t subvendor, uint16_t subdevice,
+ uint8_t class_code, uint8_t subclass_code,
+ uint8_t pif, size_t config_size,
+ size_t struct_size)
{
VirtIODevice *vdev;
PCIDevice *pci_dev;
@@ -599,9 +599,9 @@ VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name,
uint32_t size;
pci_dev = pci_register_device(bus, name, struct_size,
- -1, NULL, NULL);
+ -1, NULL, NULL);
if (!pci_dev)
- return NULL;
+ return NULL;
vdev = to_virtio_device(pci_dev);
@@ -633,16 +633,16 @@ VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name,
vdev->name = name;
vdev->config_len = config_size;
if (vdev->config_len)
- vdev->config = qemu_mallocz(config_size);
+ vdev->config = qemu_mallocz(config_size);
else
- vdev->config = NULL;
+ vdev->config = NULL;
size = 20 + config_size;
if (size & (size-1))
size = 1 << fls(size);
pci_register_io_region(pci_dev, 0, size, PCI_ADDRESS_SPACE_IO,
- virtio_map);
+ virtio_map);
qemu_register_reset(virtio_reset, vdev);
return vdev;
diff --git a/qemu/hw/virtio.h b/qemu/hw/virtio.h
index 15f020b..40c9e14 100644
--- a/qemu/hw/virtio.h
+++ b/qemu/hw/virtio.h
@@ -22,13 +22,13 @@
/* Status byte for guest to report progress, and synchronize features. */
/* We have seen device and processed generic fields (VIRTIO_CONFIG_F_VIRTIO) */
-#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
+#define VIRTIO_CONFIG_S_ACKNOWLEDGE 1
/* We have found a driver for the device. */
-#define VIRTIO_CONFIG_S_DRIVER 2
+#define VIRTIO_CONFIG_S_DRIVER 2
/* Driver has used its parts of the config, and is happy */
-#define VIRTIO_CONFIG_S_DRIVER_OK 4
+#define VIRTIO_CONFIG_S_DRIVER_OK 4
/* We've given up on this device. */
-#define VIRTIO_CONFIG_S_FAILED 0x80
+#define VIRTIO_CONFIG_S_FAILED 0x80
/* We notify when the ring is completely used, even if the guest is supressing
* callbacks */
@@ -37,14 +37,14 @@
/* from Linux's linux/virtio_ring.h */
/* This marks a buffer as continuing via the next field. */
-#define VRING_DESC_F_NEXT 1
+#define VRING_DESC_F_NEXT 1
/* This marks a buffer as write-only (otherwise read-only). */
-#define VRING_DESC_F_WRITE 2
+#define VRING_DESC_F_WRITE 2
/* This means don't notify other side when buffer added. */
-#define VRING_USED_F_NO_NOTIFY 1
+#define VRING_USED_F_NO_NOTIFY 1
/* This means don't interrupt guest when buffer consumed. */
-#define VRING_AVAIL_F_NO_INTERRUPT 1
+#define VRING_AVAIL_F_NO_INTERRUPT 1
typedef struct VirtQueue VirtQueue;
typedef struct VirtIODevice VirtIODevice;
@@ -105,7 +105,7 @@ typedef struct VirtQueueElement
struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
} VirtQueueElement;
-#define VIRTIO_PCI_QUEUE_MAX 16
+#define VIRTIO_PCI_QUEUE_MAX 16
struct VirtIODevice
{
@@ -127,21 +127,21 @@ struct VirtIODevice
};
VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name,
- uint16_t vendor, uint16_t device,
- uint16_t subvendor, uint16_t subdevice,
- uint8_t class_code, uint8_t subclass_code,
- uint8_t pif, size_t config_size,
- size_t struct_size);
+ uint16_t vendor, uint16_t device,
+ uint16_t subvendor, uint16_t subdevice,
+ uint8_t class_code, uint8_t subclass_code,
+ uint8_t pif, size_t config_size,
+ size_t struct_size);
VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
- void (*handle_output)(VirtIODevice *,
- VirtQueue *));
+ void (*handle_output)(VirtIODevice *,
+ VirtQueue *));
void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
- unsigned int len);
+ unsigned int len);
void virtqueue_flush(VirtQueue *vq, unsigned int count);
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
- unsigned int len, unsigned int idx);
+ unsigned int len, unsigned int idx);
int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem);
int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes);
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 2/7] Create virtio-blk.h header
2008-12-03 17:26 [PATCH 1/7] Fix whitespace in virtio Anthony Liguori
@ 2008-12-03 17:26 ` Anthony Liguori
2008-12-03 17:26 ` [PATCH 3/7] Create virtio-net.h header Anthony Liguori
2008-12-05 17:38 ` [PATCH 1/7] Fix whitespace in virtio Avi Kivity
1 sibling, 1 reply; 11+ messages in thread
From: Anthony Liguori @ 2008-12-03 17:26 UTC (permalink / raw)
To: kvm; +Cc: Avi Kivity, Anthony Liguori
Besides cleanliness, targets other than pc want to use virtio-blk so we need to
have to define it somewhere other than pc.h
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c
index 6de460c..ee38326 100644
--- a/qemu/hw/pc.c
+++ b/qemu/hw/pc.c
@@ -34,6 +34,7 @@
#include "console.h"
#include "fw_cfg.h"
#include "device-assignment.h"
+#include "virtio-blk.h"
#include "qemu-kvm.h"
diff --git a/qemu/hw/pc.h b/qemu/hw/pc.h
index 5349a41..a874fbd 100644
--- a/qemu/hw/pc.h
+++ b/qemu/hw/pc.h
@@ -168,10 +168,6 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd);
PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
-/* virtio-blk.h */
-void *virtio_blk_init(PCIBus *bus, uint16_t vendor, uint16_t device,
- BlockDriverState *bs);
-
/* extboot.c */
void extboot_init(BlockDriverState *bs, int cmd);
diff --git a/qemu/hw/virtio-blk.c b/qemu/hw/virtio-blk.c
index c9a91ba..bd965f9 100644
--- a/qemu/hw/virtio-blk.c
+++ b/qemu/hw/virtio-blk.c
@@ -11,62 +11,8 @@
*
*/
-#include "virtio.h"
-#include "block.h"
+#include "virtio-blk.h"
#include "block_int.h"
-#include "pc.h"
-
-/* from Linux's linux/virtio_blk.h */
-
-/* The ID for virtio_block */
-#define VIRTIO_ID_BLOCK 2
-
-/* Feature bits */
-#define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */
-#define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */
-#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */
-#define VIRTIO_BLK_F_GEOMETRY 4 /* Indicates support of legacy geometry */
-
-struct virtio_blk_config
-{
- uint64_t capacity;
- uint32_t size_max;
- uint32_t seg_max;
- uint16_t cylinders;
- uint8_t heads;
- uint8_t sectors;
-} __attribute__((packed));
-
-/* These two define direction. */
-#define VIRTIO_BLK_T_IN 0
-#define VIRTIO_BLK_T_OUT 1
-
-/* This bit says it's a scsi command, not an actual read or write. */
-#define VIRTIO_BLK_T_SCSI_CMD 2
-
-/* Barrier before this op. */
-#define VIRTIO_BLK_T_BARRIER 0x80000000
-
-/* This is the first element of the read scatter-gather list. */
-struct virtio_blk_outhdr
-{
- /* VIRTIO_BLK_T* */
- uint32_t type;
- /* io priority. */
- uint32_t ioprio;
- /* Sector (ie. 512 byte offset) */
- uint64_t sector;
-};
-
-#define VIRTIO_BLK_S_OK 0
-#define VIRTIO_BLK_S_IOERR 1
-#define VIRTIO_BLK_S_UNSUPP 2
-
-/* This is the first element of the write scatter-gather list */
-struct virtio_blk_inhdr
-{
- unsigned char status;
-};
typedef struct VirtIOBlock
{
diff --git a/qemu/hw/virtio-blk.h b/qemu/hw/virtio-blk.h
new file mode 100644
index 0000000..c6661c0
--- /dev/null
+++ b/qemu/hw/virtio-blk.h
@@ -0,0 +1,76 @@
+/*
+ * Virtio Block Device
+ *
+ * Copyright IBM, Corp. 2007
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef _QEMU_VIRTIO_BLK_H
+#define _QEMU_VIRTIO_BLK_H
+
+#include "virtio.h"
+#include "block.h"
+#include "pci.h"
+
+/* from Linux's linux/virtio_blk.h */
+
+/* The ID for virtio_block */
+#define VIRTIO_ID_BLOCK 2
+
+/* Feature bits */
+#define VIRTIO_BLK_F_BARRIER 0 /* Does host support barriers? */
+#define VIRTIO_BLK_F_SIZE_MAX 1 /* Indicates maximum segment size */
+#define VIRTIO_BLK_F_SEG_MAX 2 /* Indicates maximum # of segments */
+#define VIRTIO_BLK_F_GEOMETRY 4 /* Indicates support of legacy geometry */
+
+struct virtio_blk_config
+{
+ uint64_t capacity;
+ uint32_t size_max;
+ uint32_t seg_max;
+ uint16_t cylinders;
+ uint8_t heads;
+ uint8_t sectors;
+} __attribute__((packed));
+
+/* These two define direction. */
+#define VIRTIO_BLK_T_IN 0
+#define VIRTIO_BLK_T_OUT 1
+
+/* This bit says it's a scsi command, not an actual read or write. */
+#define VIRTIO_BLK_T_SCSI_CMD 2
+
+/* Barrier before this op. */
+#define VIRTIO_BLK_T_BARRIER 0x80000000
+
+/* This is the first element of the read scatter-gather list. */
+struct virtio_blk_outhdr
+{
+ /* VIRTIO_BLK_T* */
+ uint32_t type;
+ /* io priority. */
+ uint32_t ioprio;
+ /* Sector (ie. 512 byte offset) */
+ uint64_t sector;
+};
+
+#define VIRTIO_BLK_S_OK 0
+#define VIRTIO_BLK_S_IOERR 1
+#define VIRTIO_BLK_S_UNSUPP 2
+
+/* This is the first element of the write scatter-gather list */
+struct virtio_blk_inhdr
+{
+ unsigned char status;
+};
+
+void *virtio_blk_init(PCIBus *bus, uint16_t vendor, uint16_t device,
+ BlockDriverState *bs);
+
+#endif
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 3/7] Create virtio-net.h header
2008-12-03 17:26 ` [PATCH 2/7] Create virtio-blk.h header Anthony Liguori
@ 2008-12-03 17:26 ` Anthony Liguori
2008-12-03 17:26 ` [PATCH 4/7] Move virtio_balloon_init to virtio-balloon.h Anthony Liguori
0 siblings, 1 reply; 11+ messages in thread
From: Anthony Liguori @ 2008-12-03 17:26 UTC (permalink / raw)
To: kvm; +Cc: Avi Kivity, Anthony Liguori
Besides cleanliness, targets other than pc want to use virtio-net so we need to
have to define it somewhere other than pc.h
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/qemu/hw/pc.h b/qemu/hw/pc.h
index a874fbd..5b90198 100644
--- a/qemu/hw/pc.h
+++ b/qemu/hw/pc.h
@@ -164,10 +164,6 @@ void pci_piix4_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn,
void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd);
-/* virtio-net.c */
-
-PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
-
/* extboot.c */
void extboot_init(BlockDriverState *bs, int cmd);
diff --git a/qemu/hw/pci.c b/qemu/hw/pci.c
index 75bc9a9..c93758d 100644
--- a/qemu/hw/pci.c
+++ b/qemu/hw/pci.c
@@ -27,6 +27,7 @@
#include "net.h"
#include "pc.h"
#include "qemu-kvm.h"
+#include "virtio-net.h"
//#define DEBUG_PCI
diff --git a/qemu/hw/virtio-net.c b/qemu/hw/virtio-net.c
index b179fcc..f621ff3 100644
--- a/qemu/hw/virtio-net.c
+++ b/qemu/hw/virtio-net.c
@@ -14,65 +14,9 @@
#include "virtio.h"
#include "net.h"
#include "qemu-timer.h"
+#include "virtio-net.h"
#include "qemu-kvm.h"
-/* from Linux's virtio_net.h */
-
-/* The ID for virtio_net */
-#define VIRTIO_ID_NET 1
-
-/* The feature bitmap for virtio net */
-#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
-#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
-#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
-#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
-#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
-#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */
-#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */
-#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */
-#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */
-#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */
-#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */
-#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */
-#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */
-
-#define TX_TIMER_INTERVAL 150000 /* 150 us */
-
-/* Maximum packet size we can receive from tap device: header + 64k */
-#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
-
-/* The config defining mac address (6 bytes) */
-struct virtio_net_config
-{
- uint8_t mac[6];
-} __attribute__((packed));
-
-/* This is the first element of the scatter-gather list. If you don't
- * specify GSO or CSUM features, you can simply ignore the header. */
-struct virtio_net_hdr
-{
-#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset
- uint8_t flags;
-#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame
-#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO)
-#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO)
-#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP
-#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set
- uint8_t gso_type;
- uint16_t hdr_len;
- uint16_t gso_size;
- uint16_t csum_start;
- uint16_t csum_offset;
-};
-
-/* This is the version of the header to use when the MRG_RXBUF
- * feature has been negotiated. */
-struct virtio_net_hdr_mrg_rxbuf
-{
- struct virtio_net_hdr hdr;
- uint16_t num_buffers; /* Number of merged rx buffers */
-};
-
typedef struct VirtIONet
{
VirtIODevice vdev;
diff --git a/qemu/hw/virtio-net.h b/qemu/hw/virtio-net.h
new file mode 100644
index 0000000..0d9f71b
--- /dev/null
+++ b/qemu/hw/virtio-net.h
@@ -0,0 +1,80 @@
+/*
+ * Virtio Network Device
+ *
+ * Copyright IBM, Corp. 2007
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef _QEMU_VIRTIO_NET_H
+#define _QEMU_VIRTIO_NET_H
+
+#include "virtio.h"
+#include "net.h"
+#include "pci.h"
+
+/* from Linux's virtio_net.h */
+
+/* The ID for virtio_net */
+#define VIRTIO_ID_NET 1
+
+/* The feature bitmap for virtio net */
+#define VIRTIO_NET_F_CSUM 0 /* Host handles pkts w/ partial csum */
+#define VIRTIO_NET_F_GUEST_CSUM 1 /* Guest handles pkts w/ partial csum */
+#define VIRTIO_NET_F_MAC 5 /* Host has given MAC address. */
+#define VIRTIO_NET_F_GSO 6 /* Host handles pkts w/ any GSO type */
+#define VIRTIO_NET_F_GUEST_TSO4 7 /* Guest can handle TSOv4 in. */
+#define VIRTIO_NET_F_GUEST_TSO6 8 /* Guest can handle TSOv6 in. */
+#define VIRTIO_NET_F_GUEST_ECN 9 /* Guest can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_GUEST_UFO 10 /* Guest can handle UFO in. */
+#define VIRTIO_NET_F_HOST_TSO4 11 /* Host can handle TSOv4 in. */
+#define VIRTIO_NET_F_HOST_TSO6 12 /* Host can handle TSOv6 in. */
+#define VIRTIO_NET_F_HOST_ECN 13 /* Host can handle TSO[6] w/ ECN in. */
+#define VIRTIO_NET_F_HOST_UFO 14 /* Host can handle UFO in. */
+#define VIRTIO_NET_F_MRG_RXBUF 15 /* Host can merge receive buffers. */
+
+#define TX_TIMER_INTERVAL 150000 /* 150 us */
+
+/* Maximum packet size we can receive from tap device: header + 64k */
+#define VIRTIO_NET_MAX_BUFSIZE (sizeof(struct virtio_net_hdr) + (64 << 10))
+
+/* The config defining mac address (6 bytes) */
+struct virtio_net_config
+{
+ uint8_t mac[6];
+} __attribute__((packed));
+
+/* This is the first element of the scatter-gather list. If you don't
+ * specify GSO or CSUM features, you can simply ignore the header. */
+struct virtio_net_hdr
+{
+#define VIRTIO_NET_HDR_F_NEEDS_CSUM 1 // Use csum_start, csum_offset
+ uint8_t flags;
+#define VIRTIO_NET_HDR_GSO_NONE 0 // Not a GSO frame
+#define VIRTIO_NET_HDR_GSO_TCPV4 1 // GSO frame, IPv4 TCP (TSO)
+#define VIRTIO_NET_HDR_GSO_UDP 3 // GSO frame, IPv4 UDP (UFO)
+#define VIRTIO_NET_HDR_GSO_TCPV6 4 // GSO frame, IPv6 TCP
+#define VIRTIO_NET_HDR_GSO_ECN 0x80 // TCP has ECN set
+ uint8_t gso_type;
+ uint16_t hdr_len;
+ uint16_t gso_size;
+ uint16_t csum_start;
+ uint16_t csum_offset;
+};
+
+/* This is the version of the header to use when the MRG_RXBUF
+ * feature has been negotiated. */
+struct virtio_net_hdr_mrg_rxbuf
+{
+ struct virtio_net_hdr hdr;
+ uint16_t num_buffers; /* Number of merged rx buffers */
+};
+
+PCIDevice *virtio_net_init(PCIBus *bus, NICInfo *nd, int devfn);
+
+#endif
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 4/7] Move virtio_balloon_init to virtio-balloon.h
2008-12-03 17:26 ` [PATCH 3/7] Create virtio-net.h header Anthony Liguori
@ 2008-12-03 17:26 ` Anthony Liguori
2008-12-03 17:26 ` [PATCH 5/7] Do not access virtio-rings directly Anthony Liguori
0 siblings, 1 reply; 11+ messages in thread
From: Anthony Liguori @ 2008-12-03 17:26 UTC (permalink / raw)
To: kvm; +Cc: Avi Kivity, Anthony Liguori
Besides cleanliness, targets other than pc want to use virtio-balloon so we
need to have to define it somewhere other than pc.h
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c
index ee38326..92a8615 100644
--- a/qemu/hw/pc.c
+++ b/qemu/hw/pc.c
@@ -35,6 +35,7 @@
#include "fw_cfg.h"
#include "device-assignment.h"
#include "virtio-blk.h"
+#include "virtio-balloon.h"
#include "qemu-kvm.h"
diff --git a/qemu/hw/pc.h b/qemu/hw/pc.h
index 5b90198..8cfa1ca 100644
--- a/qemu/hw/pc.h
+++ b/qemu/hw/pc.h
@@ -168,7 +168,4 @@ void isa_ne2000_init(int base, qemu_irq irq, NICInfo *nd);
void extboot_init(BlockDriverState *bs, int cmd);
-/* virtio-balloon.h */
-void *virtio_balloon_init(PCIBus *bus);
-
#endif
diff --git a/qemu/hw/virtio-balloon.h b/qemu/hw/virtio-balloon.h
index 45e4b03..c71f970 100644
--- a/qemu/hw/virtio-balloon.h
+++ b/qemu/hw/virtio-balloon.h
@@ -15,6 +15,9 @@
#ifndef _QEMU_VIRTIO_BALLOON_H
#define _QEMU_VIRTIO_BALLOON_H
+#include "virtio.h"
+#include "pci.h"
+
/* from Linux's linux/virtio_balloon.h */
/* The ID for virtio_balloon */
@@ -34,4 +37,6 @@ struct virtio_balloon_config
uint32_t actual;
};
+void *virtio_balloon_init(PCIBus *bus);
+
#endif
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 5/7] Do not access virtio-rings directly
2008-12-03 17:26 ` [PATCH 4/7] Move virtio_balloon_init to virtio-balloon.h Anthony Liguori
@ 2008-12-03 17:26 ` Anthony Liguori
2008-12-03 17:27 ` [PATCH 6/7] Do not modify VirtQueueElement Anthony Liguori
0 siblings, 1 reply; 11+ messages in thread
From: Anthony Liguori @ 2008-12-03 17:26 UTC (permalink / raw)
To: kvm; +Cc: Avi Kivity, Anthony Liguori
This introduces accessors for all virtio ring members and then uses the
appropriate physical memory accessors. We shouldn't access guest physical
memory directly and this fixes that. As a consequence, this helps us get closer
to working live migration.
I've done light performance testing and it seems to not have an impact. If
further testing demonstrates an impact, we can optimize the physical memory
accessor functions.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/qemu/hw/virtio-net.c b/qemu/hw/virtio-net.c
index f621ff3..b64fb00 100644
--- a/qemu/hw/virtio-net.c
+++ b/qemu/hw/virtio-net.c
@@ -101,18 +101,18 @@ static int virtio_net_can_receive(void *opaque)
{
VirtIONet *n = opaque;
- if (n->rx_vq->vring.avail == NULL ||
+ if (!virtio_queue_ready(n->rx_vq) ||
!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
return 0;
- if (n->rx_vq->vring.avail->idx == n->rx_vq->last_avail_idx ||
+ if (virtio_queue_empty(n->rx_vq) ||
(n->mergeable_rx_bufs &&
!virtqueue_avail_bytes(n->rx_vq, VIRTIO_NET_MAX_BUFSIZE, 0))) {
- n->rx_vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+ virtio_queue_set_notification(n->rx_vq, 1);
return 0;
}
- n->rx_vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+ virtio_queue_set_notification(n->rx_vq, 0);
return 1;
}
@@ -295,7 +295,7 @@ static void virtio_net_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
VirtIONet *n = to_virtio_net(vdev);
if (n->tx_timer_active) {
- vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+ virtio_queue_set_notification(vq, 1);
qemu_del_timer(n->tx_timer);
n->tx_timer_active = 0;
virtio_net_flush_tx(n, vq);
@@ -303,7 +303,7 @@ static void virtio_net_handle_tx(VirtIODevice *vdev, VirtQueue *vq)
qemu_mod_timer(n->tx_timer,
qemu_get_clock(vm_clock) + TX_TIMER_INTERVAL);
n->tx_timer_active = 1;
- vq->vring.used->flags |= VRING_USED_F_NO_NOTIFY;
+ virtio_queue_set_notification(vq, 0);
}
}
@@ -317,7 +317,7 @@ static void virtio_net_tx_timer(void *opaque)
if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
return;
- n->tx_vq->vring.used->flags &= ~VRING_USED_F_NO_NOTIFY;
+ virtio_queue_set_notification(n->tx_vq, 1);
virtio_net_flush_tx(n, n->tx_vq);
}
diff --git a/qemu/hw/virtio.c b/qemu/hw/virtio.c
index 6d7425c..1a58940 100644
--- a/qemu/hw/virtio.c
+++ b/qemu/hw/virtio.c
@@ -56,8 +56,54 @@
*/
#define wmb() do { } while (0)
-/* virt queue functions */
+typedef struct VRingDesc
+{
+ uint64_t addr;
+ uint32_t len;
+ uint16_t flags;
+ uint16_t next;
+} VRingDesc;
+
+typedef struct VRingAvail
+{
+ uint16_t flags;
+ uint16_t idx;
+ uint16_t ring[0];
+} VRingAvail;
+
+typedef struct VRingUsedElem
+{
+ uint32_t id;
+ uint32_t len;
+} VRingUsedElem;
+
+typedef struct VRingUsed
+{
+ uint16_t flags;
+ uint16_t idx;
+ VRingUsedElem ring[0];
+} VRingUsed;
+typedef struct VRing
+{
+ unsigned int num;
+ target_phys_addr_t desc;
+ target_phys_addr_t avail;
+ target_phys_addr_t used;
+} VRing;
+
+struct VirtQueue
+{
+ VRing vring;
+ uint32_t pfn;
+ uint16_t last_avail_idx;
+ int inuse;
+ void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
+};
+
+#define VIRTIO_PCI_QUEUE_MAX 16
+
+/* virt queue functions */
static void *virtio_map_gpa(target_phys_addr_t addr, size_t size)
{
ram_addr_t off;
@@ -93,38 +139,137 @@ static void *virtio_map_gpa(target_phys_addr_t addr, size_t size)
return phys_ram_base + off;
}
-static size_t virtqueue_size(int num)
+static void virtqueue_init(VirtQueue *vq, target_phys_addr_t pa)
{
- return TARGET_PAGE_ALIGN((sizeof(VRingDesc) * num) +
- (sizeof(VRingAvail) + sizeof(uint16_t) * num)) +
- (sizeof(VRingUsed) + sizeof(VRingUsedElem) * num);
+ vq->vring.desc = pa;
+ vq->vring.avail = pa + vq->vring.num * sizeof(VRingDesc);
+ vq->vring.used = TARGET_PAGE_ALIGN(vq->vring.avail + offsetof(VRingAvail, ring[vq->vring.num]));
}
-static void virtqueue_init(VirtQueue *vq, void *p)
+static inline uint64_t vring_desc_addr(VirtQueue *vq, int i)
{
- vq->vring.desc = p;
- vq->vring.avail = p + vq->vring.num * sizeof(VRingDesc);
- vq->vring.used = (void *)TARGET_PAGE_ALIGN((unsigned long)&vq->vring.avail->ring[vq->vring.num]);
+ target_phys_addr_t pa;
+ pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, addr);
+ return ldq_phys(pa);
+}
+
+static inline uint32_t vring_desc_len(VirtQueue *vq, int i)
+{
+ target_phys_addr_t pa;
+ pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, len);
+ return ldl_phys(pa);
+}
+
+static inline uint16_t vring_desc_flags(VirtQueue *vq, int i)
+{
+ target_phys_addr_t pa;
+ pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, flags);
+ return lduw_phys(pa);
+}
+
+static inline uint16_t vring_desc_next(VirtQueue *vq, int i)
+{
+ target_phys_addr_t pa;
+ pa = vq->vring.desc + sizeof(VRingDesc) * i + offsetof(VRingDesc, next);
+ return lduw_phys(pa);
+}
+
+static inline uint16_t vring_avail_flags(VirtQueue *vq)
+{
+ target_phys_addr_t pa;
+ pa = vq->vring.avail + offsetof(VRingAvail, flags);
+ return lduw_phys(pa);
+}
+
+static inline uint16_t vring_avail_idx(VirtQueue *vq)
+{
+ target_phys_addr_t pa;
+ pa = vq->vring.avail + offsetof(VRingAvail, idx);
+ return lduw_phys(pa);
+}
+
+static inline uint16_t vring_avail_ring(VirtQueue *vq, int i)
+{
+ target_phys_addr_t pa;
+ pa = vq->vring.avail + offsetof(VRingAvail, ring[i]);
+ return lduw_phys(pa);
+}
+
+static inline void vring_used_ring_id(VirtQueue *vq, int i, uint32_t val)
+{
+ target_phys_addr_t pa;
+ pa = vq->vring.used + offsetof(VRingUsed, ring[i].id);
+ stl_phys(pa, val);
+}
+
+static inline void vring_used_ring_len(VirtQueue *vq, int i, uint32_t val)
+{
+ target_phys_addr_t pa;
+ pa = vq->vring.used + offsetof(VRingUsed, ring[i].len);
+ stl_phys(pa, val);
+}
+
+static uint16_t vring_used_idx(VirtQueue *vq)
+{
+ target_phys_addr_t pa;
+ pa = vq->vring.used + offsetof(VRingUsed, idx);
+ return lduw_phys(pa);
+}
+
+static inline void vring_used_idx_increment(VirtQueue *vq, uint16_t val)
+{
+ target_phys_addr_t pa;
+ pa = vq->vring.used + offsetof(VRingUsed, idx);
+ stw_phys(pa, vring_used_idx(vq) + val);
+}
+
+static inline void vring_used_flags_set_bit(VirtQueue *vq, int mask)
+{
+ target_phys_addr_t pa;
+ pa = vq->vring.used + offsetof(VRingUsed, flags);
+ stw_phys(pa, lduw_phys(pa) | mask);
+}
+
+static inline void vring_used_flags_unset_bit(VirtQueue *vq, int mask)
+{
+ target_phys_addr_t pa;
+ pa = vq->vring.used + offsetof(VRingUsed, flags);
+ stw_phys(pa, lduw_phys(pa) & ~mask);
+}
+
+void virtio_queue_set_notification(VirtQueue *vq, int enable)
+{
+ if (enable)
+ vring_used_flags_unset_bit(vq, VRING_USED_F_NO_NOTIFY);
+ else
+ vring_used_flags_set_bit(vq, VRING_USED_F_NO_NOTIFY);
+}
+
+int virtio_queue_ready(VirtQueue *vq)
+{
+ return vq->vring.avail != 0;
+}
+
+int virtio_queue_empty(VirtQueue *vq)
+{
+ return vring_avail_idx(vq) == vq->last_avail_idx;
}
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
unsigned int len, unsigned int idx)
{
- VRingUsedElem *used;
-
- idx += vq->vring.used->idx;
+ idx = (idx + vring_used_idx(vq)) % vq->vring.num;
/* Get a pointer to the next entry in the used ring. */
- used = &vq->vring.used->ring[idx % vq->vring.num];
- used->id = elem->index;
- used->len = len;
+ vring_used_ring_id(vq, idx, elem->index);
+ vring_used_ring_len(vq, idx, len);
}
void virtqueue_flush(VirtQueue *vq, unsigned int count)
{
/* Make sure buffer is written before we update index. */
wmb();
- vq->vring.used->idx += count;
+ vring_used_idx_increment(vq, count);
vq->inuse -= count;
}
@@ -137,12 +282,12 @@ void virtqueue_push(VirtQueue *vq, const VirtQueueElement *elem,
static int virtqueue_num_heads(VirtQueue *vq, unsigned int idx)
{
- uint16_t num_heads = vq->vring.avail->idx - idx;
+ uint16_t num_heads = vring_avail_idx(vq) - idx;
/* Check it isn't doing very strange things with descriptor numbers. */
if (num_heads > vq->vring.num)
errx(1, "Guest moved used index from %u to %u",
- idx, vq->vring.avail->idx);
+ idx, vring_avail_idx(vq));
return num_heads;
}
@@ -153,7 +298,7 @@ static unsigned int virtqueue_get_head(VirtQueue *vq, unsigned int idx)
/* Grab the next descriptor number they're advertising, and increment
* the index we've seen. */
- head = vq->vring.avail->ring[idx % vq->vring.num];
+ head = vring_avail_ring(vq, idx % vq->vring.num);
/* If their number is silly, that's a fatal mistake. */
if (head >= vq->vring.num)
@@ -167,11 +312,11 @@ static unsigned virtqueue_next_desc(VirtQueue *vq, unsigned int i)
unsigned int next;
/* If this descriptor says it doesn't chain, we're done. */
- if (!(vq->vring.desc[i].flags & VRING_DESC_F_NEXT))
+ if (!(vring_desc_flags(vq, i) & VRING_DESC_F_NEXT))
return vq->vring.num;
/* Check they're not leading us off end of descriptors. */
- next = vq->vring.desc[i].next;
+ next = vring_desc_next(vq, i);
/* Make sure compiler knows to grab that: we don't want it changing! */
wmb();
@@ -198,13 +343,13 @@ int virtqueue_avail_bytes(VirtQueue *vq, int in_bytes, int out_bytes)
if (++num_bufs > vq->vring.num)
errx(1, "Looped descriptor");
- if (vq->vring.desc[i].flags & VRING_DESC_F_WRITE) {
+ if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) {
if (in_bytes > 0 &&
- (in_total += vq->vring.desc[i].len) >= in_bytes)
+ (in_total += vring_desc_len(vq, i)) >= in_bytes)
return 1;
} else {
if (out_bytes > 0 &&
- (out_total += vq->vring.desc[i].len) >= out_bytes)
+ (out_total += vring_desc_len(vq, i)) >= out_bytes)
return 1;
}
} while ((i = virtqueue_next_desc(vq, i)) != vq->vring.num);
@@ -227,14 +372,14 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
do {
struct iovec *sg;
- if (vq->vring.desc[i].flags & VRING_DESC_F_WRITE)
+ if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE)
sg = &elem->in_sg[elem->in_num++];
else
sg = &elem->out_sg[elem->out_num++];
/* Grab the first descriptor, and check it's OK. */
- sg->iov_len = vq->vring.desc[i].len;
- sg->iov_base = virtio_map_gpa(vq->vring.desc[i].addr, sg->iov_len);
+ sg->iov_len = vring_desc_len(vq, i);
+ sg->iov_base = virtio_map_gpa(vring_desc_addr(vq, i), sg->iov_len);
if (sg->iov_base == NULL)
errx(1, "Invalid mapping\n");
@@ -277,9 +422,9 @@ void virtio_reset(void *opaque)
virtio_update_irq(vdev);
for(i = 0; i < VIRTIO_PCI_QUEUE_MAX; i++) {
- vdev->vq[i].vring.desc = NULL;
- vdev->vq[i].vring.avail = NULL;
- vdev->vq[i].vring.used = NULL;
+ vdev->vq[i].vring.desc = 0;
+ vdev->vq[i].vring.avail = 0;
+ vdev->vq[i].vring.used = 0;
vdev->vq[i].last_avail_idx = 0;
vdev->vq[i].pfn = 0;
}
@@ -304,9 +449,7 @@ static void virtio_ioport_write(void *opaque, uint32_t addr, uint32_t val)
if (pa == 0) {
virtio_reset(vdev);
} else {
- size_t size = virtqueue_size(vdev->vq[vdev->queue_sel].vring.num);
- virtqueue_init(&vdev->vq[vdev->queue_sel],
- virtio_map_gpa(pa, size));
+ virtqueue_init(&vdev->vq[vdev->queue_sel], pa);
}
break;
case VIRTIO_PCI_QUEUE_SEL:
@@ -507,8 +650,8 @@ VirtQueue *virtio_add_queue(VirtIODevice *vdev, int queue_size,
void virtio_notify(VirtIODevice *vdev, VirtQueue *vq)
{
/* Always notify when queue is empty */
- if ((vq->inuse || vq->vring.avail->idx != vq->last_avail_idx) &&
- (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT))
+ if ((vq->inuse || vring_avail_idx(vq) != vq->last_avail_idx) &&
+ (vring_avail_flags(vq) & VRING_AVAIL_F_NO_INTERRUPT))
return;
vdev->isr |= 0x01;
@@ -574,12 +717,10 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f)
qemu_get_be16s(f, &vdev->vq[i].last_avail_idx);
if (vdev->vq[i].pfn) {
- size_t size;
target_phys_addr_t pa;
pa = (ram_addr_t)vdev->vq[i].pfn << TARGET_PAGE_BITS;
- size = virtqueue_size(vdev->vq[i].vring.num);
- virtqueue_init(&vdev->vq[i], virtio_map_gpa(pa, size));
+ virtqueue_init(&vdev->vq[i], pa);
}
}
@@ -608,7 +749,7 @@ VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name,
vdev->status = 0;
vdev->isr = 0;
vdev->queue_sel = 0;
- memset(vdev->vq, 0, sizeof(vdev->vq));
+ vdev->vq = qemu_mallocz(sizeof(VirtQueue) * VIRTIO_PCI_QUEUE_MAX);
config = pci_dev->config;
config[0x00] = vendor & 0xFF;
diff --git a/qemu/hw/virtio.h b/qemu/hw/virtio.h
index 40c9e14..86dc36a 100644
--- a/qemu/hw/virtio.h
+++ b/qemu/hw/virtio.h
@@ -46,54 +46,11 @@
/* This means don't interrupt guest when buffer consumed. */
#define VRING_AVAIL_F_NO_INTERRUPT 1
+struct VirtQueue;
+
typedef struct VirtQueue VirtQueue;
typedef struct VirtIODevice VirtIODevice;
-typedef struct VRingDesc
-{
- uint64_t addr;
- uint32_t len;
- uint16_t flags;
- uint16_t next;
-} VRingDesc;
-
-typedef struct VRingAvail
-{
- uint16_t flags;
- uint16_t idx;
- uint16_t ring[0];
-} VRingAvail;
-
-typedef struct VRingUsedElem
-{
- uint32_t id;
- uint32_t len;
-} VRingUsedElem;
-
-typedef struct VRingUsed
-{
- uint16_t flags;
- uint16_t idx;
- VRingUsedElem ring[0];
-} VRingUsed;
-
-typedef struct VRing
-{
- unsigned int num;
- VRingDesc *desc;
- VRingAvail *avail;
- VRingUsed *used;
-} VRing;
-
-struct VirtQueue
-{
- VRing vring;
- uint32_t pfn;
- uint16_t last_avail_idx;
- int inuse;
- void (*handle_output)(VirtIODevice *vdev, VirtQueue *vq);
-};
-
#define VIRTQUEUE_MAX_SIZE 1024
typedef struct VirtQueueElement
@@ -123,7 +80,7 @@ struct VirtIODevice
void (*get_config)(VirtIODevice *vdev, uint8_t *config);
void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
void (*reset)(VirtIODevice *vdev);
- VirtQueue vq[VIRTIO_PCI_QUEUE_MAX];
+ VirtQueue *vq;
};
VirtIODevice *virtio_init_pci(PCIBus *bus, const char *name,
@@ -154,4 +111,10 @@ void virtio_load(VirtIODevice *vdev, QEMUFile *f);
void virtio_notify_config(VirtIODevice *vdev);
+void virtio_queue_set_notification(VirtQueue *vq, int enable);
+
+int virtio_queue_ready(VirtQueue *vq);
+
+int virtio_queue_empty(VirtQueue *vq);
+
#endif
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6/7] Do not modify VirtQueueElement
2008-12-03 17:26 ` [PATCH 5/7] Do not access virtio-rings directly Anthony Liguori
@ 2008-12-03 17:27 ` Anthony Liguori
2008-12-03 17:27 ` [PATCH 7/7] Optionally bounce the virtio buffers Anthony Liguori
2008-12-04 12:06 ` [PATCH 6/7] Do not modify VirtQueueElement Mark McLoughlin
0 siblings, 2 replies; 11+ messages in thread
From: Anthony Liguori @ 2008-12-03 17:27 UTC (permalink / raw)
To: kvm; +Cc: Avi Kivity, Mark McLoughlin, Anthony Liguori
Right now, virtio-net modifies the iovec structure in VirtQueueElement. This is
evil. This creates an impossible situation if we want to bounce iovec buffers
in VirtQueueElement as we lose track of the original buffers and the resulting
free results in very bad things.
I tried to refactor receive_headers() and iov_fill() to be able to skip the
header if present but failed miserably. Instead of spending more time trying to
get that to work, I simply decided to leave the code as-is and copy the iovec
to a temporary buffer.
I doubt there will be any performance impact as usually there are only a few
elements in the iovec anyway.
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/qemu/hw/virtio-net.c b/qemu/hw/virtio-net.c
index b64fb00..6493ff6 100644
--- a/qemu/hw/virtio-net.c
+++ b/qemu/hw/virtio-net.c
@@ -198,6 +198,7 @@ static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
while (offset < size) {
VirtQueueElement elem;
int len, total;
+ struct iovec sg[VIRTQUEUE_MAX_SIZE];
len = total = 0;
@@ -219,17 +220,19 @@ static void virtio_net_receive(void *opaque, const uint8_t *buf, int size)
exit(1);
}
+ memcpy(&sg, &elem.in_sg[0], sizeof(sg[0]) * elem.in_num);
+
if (i == 0) {
if (n->mergeable_rx_bufs)
- mhdr = (struct virtio_net_hdr_mrg_rxbuf *)elem.in_sg[0].iov_base;
+ mhdr = (struct virtio_net_hdr_mrg_rxbuf *)sg[0].iov_base;
- offset += receive_header(n, &elem.in_sg[0], elem.in_num,
+ offset += receive_header(n, sg, elem.in_num,
buf + offset, size - offset, hdr_len);
total += hdr_len;
}
/* copy in packet. ugh */
- len = iov_fill(&elem.in_sg[0], elem.in_num,
+ len = iov_fill(sg, elem.in_num,
buf + offset, size - offset);
total += len;
^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 7/7] Optionally bounce the virtio buffers
2008-12-03 17:27 ` [PATCH 6/7] Do not modify VirtQueueElement Anthony Liguori
@ 2008-12-03 17:27 ` Anthony Liguori
2008-12-11 9:36 ` [PATCH] kvm: qemu: virtio: enable VIRTIO_ZERO_COPY Mark McLoughlin
2008-12-04 12:06 ` [PATCH 6/7] Do not modify VirtQueueElement Mark McLoughlin
1 sibling, 1 reply; 11+ messages in thread
From: Anthony Liguori @ 2008-12-03 17:27 UTC (permalink / raw)
To: kvm; +Cc: Avi Kivity, Anthony Liguori
In the absence of a zero-copy API, we cannot touch physical memory directly.
This patch introduces a #define to control whether we touch buffers directly,
or bounce the buffers through cpu_physical_memory_rw.
The #define is needed for merging virtio into upstream QEMU since zero-copy will
not be accepted as-is. As a bonus, I also added physical memory dirtying
support to the zero-copy case so now live migration should work when using
virtio.
With this patch, virtio is mergable into upstream QEMU (except for virtio-net,
that's a different series though).
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
diff --git a/qemu/hw/virtio.c b/qemu/hw/virtio.c
index 1a58940..9396580 100644
--- a/qemu/hw/virtio.c
+++ b/qemu/hw/virtio.c
@@ -17,6 +17,8 @@
#include "virtio.h"
#include "sysemu.h"
+//#define VIRTIO_ZERO_COPY
+
/* from Linux's linux/virtio_pci.h */
/* A 32-bit r/o bitmask of the features supported by the host */
@@ -104,6 +106,7 @@ struct VirtQueue
#define VIRTIO_PCI_QUEUE_MAX 16
/* virt queue functions */
+#ifdef VIRTIO_ZERO_COPY
static void *virtio_map_gpa(target_phys_addr_t addr, size_t size)
{
ram_addr_t off;
@@ -138,6 +141,7 @@ static void *virtio_map_gpa(target_phys_addr_t addr, size_t size)
return phys_ram_base + off;
}
+#endif
static void virtqueue_init(VirtQueue *vq, target_phys_addr_t pa)
{
@@ -258,6 +262,38 @@ int virtio_queue_empty(VirtQueue *vq)
void virtqueue_fill(VirtQueue *vq, const VirtQueueElement *elem,
unsigned int len, unsigned int idx)
{
+ unsigned int offset;
+ int i;
+
+#ifndef VIRTIO_ZERO_COPY
+ for (i = 0; i < elem->out_num; i++)
+ qemu_free(elem->out_sg[i].iov_base);
+#endif
+
+ offset = 0;
+ for (i = 0; i < elem->in_num; i++) {
+ size_t size = MIN(len - offset, elem->in_sg[i].iov_len);
+
+#ifdef VIRTIO_ZERO_COPY
+ if (size) {
+ ram_addr_t addr = (uint8_t *)elem->in_sg[i].iov_base - phys_ram_base;
+ ram_addr_t off;
+
+ for (off = 0; off < size; off += TARGET_PAGE_SIZE)
+ cpu_physical_memory_set_dirty(addr + off);
+ }
+#else
+ if (size)
+ cpu_physical_memory_write(elem->in_addr[i],
+ elem->in_sg[i].iov_base,
+ size);
+
+ qemu_free(elem->in_sg[i].iov_base);
+#endif
+
+ offset += size;
+ }
+
idx = (idx + vring_used_idx(vq)) % vq->vring.num;
/* Get a pointer to the next entry in the used ring. */
@@ -372,14 +408,35 @@ int virtqueue_pop(VirtQueue *vq, VirtQueueElement *elem)
do {
struct iovec *sg;
- if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE)
+ if (vring_desc_flags(vq, i) & VRING_DESC_F_WRITE) {
+ elem->in_addr[elem->in_num] = vring_desc_addr(vq, i);
sg = &elem->in_sg[elem->in_num++];
- else
+ } else
sg = &elem->out_sg[elem->out_num++];
/* Grab the first descriptor, and check it's OK. */
sg->iov_len = vring_desc_len(vq, i);
+
+#ifdef VIRTIO_ZERO_COPY
sg->iov_base = virtio_map_gpa(vring_desc_addr(vq, i), sg->iov_len);
+#else
+ /* cap individual scatter element size to prevent unbounded allocations
+ of memory from the guest. Practically speaking, no virtio driver
+ will ever pass more than a page in each element. We set the cap to
+ be 2MB in case for some reason a large page makes it way into the
+ sg list. When we implement a zero copy API, this limitation will
+ disappear */
+ if (sg->iov_len > (2 << 20))
+ sg->iov_len = 2 << 20;
+
+ sg->iov_base = qemu_malloc(sg->iov_len);
+ if (sg->iov_base &&
+ !(vring_desc_flags(vq, i) & VRING_DESC_F_WRITE)) {
+ cpu_physical_memory_read(vring_desc_addr(vq, i),
+ sg->iov_base,
+ sg->iov_len);
+ }
+#endif
if (sg->iov_base == NULL)
errx(1, "Invalid mapping\n");
diff --git a/qemu/hw/virtio.h b/qemu/hw/virtio.h
index 86dc36a..f04e75f 100644
--- a/qemu/hw/virtio.h
+++ b/qemu/hw/virtio.h
@@ -58,6 +58,7 @@ typedef struct VirtQueueElement
unsigned int index;
unsigned int out_num;
unsigned int in_num;
+ target_phys_addr_t in_addr[VIRTQUEUE_MAX_SIZE];
struct iovec in_sg[VIRTQUEUE_MAX_SIZE];
struct iovec out_sg[VIRTQUEUE_MAX_SIZE];
} VirtQueueElement;
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 6/7] Do not modify VirtQueueElement
2008-12-03 17:27 ` [PATCH 6/7] Do not modify VirtQueueElement Anthony Liguori
2008-12-03 17:27 ` [PATCH 7/7] Optionally bounce the virtio buffers Anthony Liguori
@ 2008-12-04 12:06 ` Mark McLoughlin
1 sibling, 0 replies; 11+ messages in thread
From: Mark McLoughlin @ 2008-12-04 12:06 UTC (permalink / raw)
To: Anthony Liguori; +Cc: kvm, Avi Kivity
On Wed, 2008-12-03 at 11:27 -0600, Anthony Liguori wrote:
> Right now, virtio-net modifies the iovec structure in VirtQueueElement. This is
> evil. This creates an impossible situation if we want to bounce iovec buffers
> in VirtQueueElement as we lose track of the original buffers and the resulting
> free results in very bad things.
>
> I tried to refactor receive_headers() and iov_fill() to be able to skip the
> header if present but failed miserably. Instead of spending more time trying to
> get that to work, I simply decided to leave the code as-is and copy the iovec
> to a temporary buffer.
Sounds sensible to me.
We could perhaps make things a bit more clear by never using the guest
supplied header and always translating between the two header formats.
But whatever way we do it, if we want to avoid modifying the original
iovec structure, we need the temporary buffer.
Cheers,
Mark.
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 1/7] Fix whitespace in virtio
2008-12-03 17:26 [PATCH 1/7] Fix whitespace in virtio Anthony Liguori
2008-12-03 17:26 ` [PATCH 2/7] Create virtio-blk.h header Anthony Liguori
@ 2008-12-05 17:38 ` Avi Kivity
1 sibling, 0 replies; 11+ messages in thread
From: Avi Kivity @ 2008-12-05 17:38 UTC (permalink / raw)
To: Anthony Liguori; +Cc: kvm, Avi Kivity
Anthony Liguori wrote:
> Whoever originally wrote the virtio code quite rudely didn't configure their
> editor to use spaces instead of tabs. This patch corrects this for all virtio
> related files.
>
>
Applied all seven. Note the last patch added trailing whitespace, which
I removed, so this can cause a difference wrt qemu.
--
I have a truly marvellous patch that fixes the bug which this
signature is too narrow to contain.
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH] kvm: qemu: virtio: enable VIRTIO_ZERO_COPY
2008-12-03 17:27 ` [PATCH 7/7] Optionally bounce the virtio buffers Anthony Liguori
@ 2008-12-11 9:36 ` Mark McLoughlin
2008-12-14 8:39 ` Avi Kivity
0 siblings, 1 reply; 11+ messages in thread
From: Mark McLoughlin @ 2008-12-11 9:36 UTC (permalink / raw)
To: Avi Kivity; +Cc: kvm, Anthony Liguori
On Wed, 2008-12-03 at 11:27 -0600, Anthony Liguori wrote:
> In the absence of a zero-copy API, we cannot touch physical memory directly.
> This patch introduces a #define to control whether we touch buffers directly,
> or bounce the buffers through cpu_physical_memory_rw.
>
> The #define is needed for merging virtio into upstream QEMU since zero-copy will
> not be accepted as-is. As a bonus, I also added physical memory dirtying
> support to the zero-copy case so now live migration should work when using
> virtio.
>
> With this patch, virtio is mergable into upstream QEMU (except for virtio-net,
> that's a different series though).
>
> Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
>
> diff --git a/qemu/hw/virtio.c b/qemu/hw/virtio.c
> index 1a58940..9396580 100644
> --- a/qemu/hw/virtio.c
> +++ b/qemu/hw/virtio.c
> @@ -17,6 +17,8 @@
> #include "virtio.h"
> #include "sysemu.h"
>
> +//#define VIRTIO_ZERO_COPY
> +
From: Mark McLoughlin <markmc@redhat.com>
Subject: [PATCH] kvm: qemu: virtio: enable VIRTIO_ZERO_COPY
Anthony intended to enable VIRTIO_ZERO_COPY before submitting,
so do that now.
Fixes an oops in the bounce buffer malloc in virtqueue_pop()
I have seen twice so far. We still need to track this down,
but it's very hard to reproduce.
Signed-off-by: Mark McLoughlin <markmc@redhat.com>
---
qemu/hw/virtio.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/qemu/hw/virtio.c b/qemu/hw/virtio.c
index 16356e8..1d06fcc 100644
--- a/qemu/hw/virtio.c
+++ b/qemu/hw/virtio.c
@@ -16,7 +16,7 @@
#include "virtio.h"
#include "sysemu.h"
-//#define VIRTIO_ZERO_COPY
+#define VIRTIO_ZERO_COPY
/* from Linux's linux/virtio_pci.h */
--
1.5.4.3
^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH] kvm: qemu: virtio: enable VIRTIO_ZERO_COPY
2008-12-11 9:36 ` [PATCH] kvm: qemu: virtio: enable VIRTIO_ZERO_COPY Mark McLoughlin
@ 2008-12-14 8:39 ` Avi Kivity
0 siblings, 0 replies; 11+ messages in thread
From: Avi Kivity @ 2008-12-14 8:39 UTC (permalink / raw)
To: Mark McLoughlin; +Cc: Avi Kivity, kvm, Anthony Liguori
Mark McLoughlin wrote:
> Anthony intended to enable VIRTIO_ZERO_COPY before submitting,
> so do that now.
>
> Fixes an oops in the bounce buffer malloc in virtqueue_pop()
> I have seen twice so far. We still need to track this down,
> but it's very hard to reproduce.
>
>
Applied, thanks.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2008-12-14 8:39 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-12-03 17:26 [PATCH 1/7] Fix whitespace in virtio Anthony Liguori
2008-12-03 17:26 ` [PATCH 2/7] Create virtio-blk.h header Anthony Liguori
2008-12-03 17:26 ` [PATCH 3/7] Create virtio-net.h header Anthony Liguori
2008-12-03 17:26 ` [PATCH 4/7] Move virtio_balloon_init to virtio-balloon.h Anthony Liguori
2008-12-03 17:26 ` [PATCH 5/7] Do not access virtio-rings directly Anthony Liguori
2008-12-03 17:27 ` [PATCH 6/7] Do not modify VirtQueueElement Anthony Liguori
2008-12-03 17:27 ` [PATCH 7/7] Optionally bounce the virtio buffers Anthony Liguori
2008-12-11 9:36 ` [PATCH] kvm: qemu: virtio: enable VIRTIO_ZERO_COPY Mark McLoughlin
2008-12-14 8:39 ` Avi Kivity
2008-12-04 12:06 ` [PATCH 6/7] Do not modify VirtQueueElement Mark McLoughlin
2008-12-05 17:38 ` [PATCH 1/7] Fix whitespace in virtio Avi Kivity
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).