[Spice-commits] 25 commits - configure coroutine-ucontext.c hw/net hw/s390x hw/virtio include/hw include/sysemu include/ui migration.c qdev-monitor.c savevm.c tests/Makefile tests/fw_cfg-test.c tests/i440fx-test.c tests/libqos tests/libqtest.c ui/gtk.c util/iov.c

Gerd Hoffmann kraxel at kemper.freedesktop.org
Thu Apr 18 03:23:53 PDT 2013


 configure                      |    4 
 coroutine-ucontext.c           |    3 
 hw/net/virtio-net.c            |  244 ++++++++++++++++++++++-------------
 hw/s390x/s390-virtio-bus.c     |   33 ++--
 hw/s390x/s390-virtio-bus.h     |   13 +
 hw/s390x/virtio-ccw.c          |   35 ++---
 hw/s390x/virtio-ccw.h          |   13 +
 hw/virtio/virtio-pci.c         |  116 ++++++++--------
 hw/virtio/virtio-pci.h         |   15 +-
 include/hw/virtio/virtio-net.h |   15 ++
 include/hw/virtio/virtio.h     |   12 +
 include/sysemu/char.h          |    6 
 include/ui/qemu-pixman.h       |    3 
 migration.c                    |    2 
 qdev-monitor.c                 |    6 
 savevm.c                       |  114 ++++++++++++----
 tests/Makefile                 |   10 +
 tests/fw_cfg-test.c            |  141 ++++++++++++++++++++
 tests/i440fx-test.c            |  285 +++++++++++++++++++++++++++++++++++++++++
 tests/libqos/fw_cfg-pc.c       |   40 +++++
 tests/libqos/fw_cfg-pc.h       |   20 ++
 tests/libqos/fw_cfg.c          |   51 +++++++
 tests/libqos/fw_cfg.h          |   34 ++++
 tests/libqos/malloc-pc.c       |   71 ++++++++++
 tests/libqos/malloc-pc.h       |   20 ++
 tests/libqos/malloc.h          |   38 +++++
 tests/libqos/pci-pc.c          |  239 ++++++++++++++++++++++++++++++++++
 tests/libqos/pci-pc.h          |   20 ++
 tests/libqos/pci.c             |  151 +++++++++++++++++++++
 tests/libqos/pci.h             |   80 +++++++++++
 tests/libqtest.c               |   11 -
 ui/gtk.c                       |    3 
 util/iov.c                     |  104 ++++++++------
 33 files changed, 1675 insertions(+), 277 deletions(-)

New commits:
commit 1773d9ee6e7138e3956081670215e8bc0ae14828
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Apr 11 16:30:02 2013 +0200

    virtio-net: cleanup: init and exit function.
    
    This remove old init and exit function as they are no longer needed.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1365690602-22729-8-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 09890c1..4d2cdd2 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -1273,34 +1273,15 @@ void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features)
     n->config_size = config_size;
 }
 
-static VirtIODevice *virtio_net_common_init(DeviceState *dev, NICConf *conf,
-                                            virtio_net_conf *net,
-                                            uint32_t host_features,
-                                            VirtIONet **pn)
+static int virtio_net_device_init(VirtIODevice *vdev)
 {
-    VirtIONet *n = *pn;
-    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
-    int i, config_size = 0;
+    int i;
 
-    /*
-     * We have two cases here: the old virtio-net-pci device, and the
-     * refactored virtio-net.
-     */
-    if (n == NULL) {
-        /* virtio-net-pci */
-        for (i = 0; feature_sizes[i].flags != 0; i++) {
-            if (host_features & feature_sizes[i].flags) {
-                config_size = MAX(feature_sizes[i].end, config_size);
-            }
-        }
-        n = (VirtIONet *)virtio_common_init("virtio-net", VIRTIO_ID_NET,
-                                            config_size, sizeof(VirtIONet));
-        n->config_size = config_size;
-    } else {
-        /* virtio-net */
-        virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET,
-                                                    n->config_size);
-    }
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
+
+    virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET,
+                                  n->config_size);
 
     vdev->get_config = virtio_net_get_config;
     vdev->set_config = virtio_net_set_config;
@@ -1311,21 +1292,22 @@ static VirtIODevice *virtio_net_common_init(DeviceState *dev, NICConf *conf,
     vdev->set_status = virtio_net_set_status;
     vdev->guest_notifier_mask = virtio_net_guest_notifier_mask;
     vdev->guest_notifier_pending = virtio_net_guest_notifier_pending;
-    n->max_queues = MAX(conf->queues, 1);
+    n->max_queues = MAX(n->nic_conf.queues, 1);
     n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queues);
     n->vqs[0].rx_vq = virtio_add_queue(vdev, 256, virtio_net_handle_rx);
     n->curr_queues = 1;
     n->vqs[0].n = n;
-    n->tx_timeout = net->txtimer;
+    n->tx_timeout = n->net_conf.txtimer;
 
-    if (net->tx && strcmp(net->tx, "timer") && strcmp(net->tx, "bh")) {
+    if (n->net_conf.tx && strcmp(n->net_conf.tx, "timer")
+                       && strcmp(n->net_conf.tx, "bh")) {
         error_report("virtio-net: "
                      "Unknown option tx=%s, valid options: \"timer\" \"bh\"",
-                     net->tx);
+                     n->net_conf.tx);
         error_report("Defaulting to \"bh\"");
     }
 
-    if (net->tx && !strcmp(net->tx, "timer")) {
+    if (n->net_conf.tx && !strcmp(n->net_conf.tx, "timer")) {
         n->vqs[0].tx_vq = virtio_add_queue(vdev, 256,
                                            virtio_net_handle_tx_timer);
         n->vqs[0].tx_timer = qemu_new_timer_ns(vm_clock, virtio_net_tx_timer,
@@ -1336,11 +1318,12 @@ static VirtIODevice *virtio_net_common_init(DeviceState *dev, NICConf *conf,
         n->vqs[0].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[0]);
     }
     n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
-    qemu_macaddr_default_if_unset(&conf->macaddr);
-    memcpy(&n->mac[0], &conf->macaddr, sizeof(n->mac));
+    qemu_macaddr_default_if_unset(&n->nic_conf.macaddr);
+    memcpy(&n->mac[0], &n->nic_conf.macaddr, sizeof(n->mac));
     n->status = VIRTIO_NET_S_LINK_UP;
 
-    n->nic = qemu_new_nic(&net_virtio_info, conf, object_get_typename(OBJECT(dev)), dev->id, n);
+    n->nic = qemu_new_nic(&net_virtio_info, &n->nic_conf,
+                          object_get_typename(OBJECT(qdev)), qdev->id, n);
     peer_test_vnet_hdr(n);
     if (peer_has_vnet_hdr(n)) {
         for (i = 0; i < n->max_queues; i++) {
@@ -1351,10 +1334,10 @@ static VirtIODevice *virtio_net_common_init(DeviceState *dev, NICConf *conf,
         n->host_hdr_len = 0;
     }
 
-    qemu_format_nic_info_str(qemu_get_queue(n->nic), conf->macaddr.a);
+    qemu_format_nic_info_str(qemu_get_queue(n->nic), n->nic_conf.macaddr.a);
 
     n->vqs[0].tx_waiting = 0;
-    n->tx_burst = net->txburst;
+    n->tx_burst = n->net_conf.txburst;
     virtio_net_set_mrg_rx_bufs(n, 0);
     n->promisc = 1; /* for compatibility */
 
@@ -1362,67 +1345,11 @@ static VirtIODevice *virtio_net_common_init(DeviceState *dev, NICConf *conf,
 
     n->vlans = g_malloc0(MAX_VLAN >> 3);
 
-    n->qdev = dev;
-    register_savevm(dev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
+    n->qdev = qdev;
+    register_savevm(qdev, "virtio-net", -1, VIRTIO_NET_VM_VERSION,
                     virtio_net_save, virtio_net_load, n);
 
-    add_boot_device_path(conf->bootindex, dev, "/ethernet-phy at 0");
-
-    return vdev;
-}
-
-VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
-                              virtio_net_conf *net, uint32_t host_features)
-{
-    VirtIONet *n = NULL;
-    return virtio_net_common_init(dev, conf, net, host_features, &n);
-}
-
-void virtio_net_exit(VirtIODevice *vdev)
-{
-    VirtIONet *n = VIRTIO_NET(vdev);
-    int i;
-
-    /* This will stop vhost backend if appropriate. */
-    virtio_net_set_status(vdev, 0);
-
-    unregister_savevm(n->qdev, "virtio-net", n);
-
-    g_free(n->mac_table.macs);
-    g_free(n->vlans);
-
-    for (i = 0; i < n->max_queues; i++) {
-        VirtIONetQueue *q = &n->vqs[i];
-        NetClientState *nc = qemu_get_subqueue(n->nic, i);
-
-        qemu_purge_queued_packets(nc);
-
-        if (q->tx_timer) {
-            qemu_del_timer(q->tx_timer);
-            qemu_free_timer(q->tx_timer);
-        } else {
-            qemu_bh_delete(q->tx_bh);
-        }
-    }
-
-    g_free(n->vqs);
-    qemu_del_nic(n->nic);
-    virtio_cleanup(vdev);
-}
-
-static int virtio_net_device_init(VirtIODevice *vdev)
-{
-    DeviceState *qdev = DEVICE(vdev);
-    VirtIONet *n = VIRTIO_NET(vdev);
-
-    /*
-     * Initially, the new VirtIONet device will have a config size =
-     * sizeof(struct config), because we can't get host_features here.
-     */
-    if (virtio_net_common_init(qdev, &(n->nic_conf),
-                               &(n->net_conf), 0, &n) == NULL) {
-        return -1;
-    }
+    add_boot_device_path(n->nic_conf.bootindex, qdev, "/ethernet-phy at 0");
     return 0;
 }
 
commit 17a0ca55657114c055cb407291c1163e09b29973
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Apr 11 16:30:01 2013 +0200

    virtio-net: cleanup: use QOM cast.
    
    As the virtio-net-pci and virtio-net-s390 are switched to the new API,
    we can use QOM casts.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1365690602-22729-7-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index 988fe03..09890c1 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -65,17 +65,9 @@ static int vq2q(int queue_index)
  * - we could suppress RX interrupt if we were so inclined.
  */
 
-/*
- * Moving to QOM later in this serie.
- */
-static VirtIONet *to_virtio_net(VirtIODevice *vdev)
-{
-    return (VirtIONet *)vdev;
-}
-
 static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
 {
-    VirtIONet *n = to_virtio_net(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
     struct virtio_net_config netcfg;
 
     stw_p(&netcfg.status, n->status);
@@ -86,12 +78,12 @@ static void virtio_net_get_config(VirtIODevice *vdev, uint8_t *config)
 
 static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
 {
-    VirtIONet *n = to_virtio_net(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
     struct virtio_net_config netcfg = {};
 
     memcpy(&netcfg, config, n->config_size);
 
-    if (!(n->vdev.guest_features >> VIRTIO_NET_F_CTRL_MAC_ADDR & 1) &&
+    if (!(vdev->guest_features >> VIRTIO_NET_F_CTRL_MAC_ADDR & 1) &&
         memcmp(netcfg.mac, n->mac, ETH_ALEN)) {
         memcpy(n->mac, netcfg.mac, ETH_ALEN);
         qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
@@ -100,12 +92,14 @@ static void virtio_net_set_config(VirtIODevice *vdev, const uint8_t *config)
 
 static bool virtio_net_started(VirtIONet *n, uint8_t status)
 {
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
     return (status & VIRTIO_CONFIG_S_DRIVER_OK) &&
-        (n->status & VIRTIO_NET_S_LINK_UP) && n->vdev.vm_running;
+        (n->status & VIRTIO_NET_S_LINK_UP) && vdev->vm_running;
 }
 
 static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
 {
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
     NetClientState *nc = qemu_get_queue(n->nic);
     int queues = n->multiqueue ? n->max_queues : 1;
 
@@ -126,25 +120,25 @@ static void virtio_net_vhost_status(VirtIONet *n, uint8_t status)
     }
     if (!n->vhost_started) {
         int r;
-        if (!vhost_net_query(tap_get_vhost_net(nc->peer), &n->vdev)) {
+        if (!vhost_net_query(tap_get_vhost_net(nc->peer), vdev)) {
             return;
         }
         n->vhost_started = 1;
-        r = vhost_net_start(&n->vdev, n->nic->ncs, queues);
+        r = vhost_net_start(vdev, n->nic->ncs, queues);
         if (r < 0) {
             error_report("unable to start vhost net: %d: "
                          "falling back on userspace virtio", -r);
             n->vhost_started = 0;
         }
     } else {
-        vhost_net_stop(&n->vdev, n->nic->ncs, queues);
+        vhost_net_stop(vdev, n->nic->ncs, queues);
         n->vhost_started = 0;
     }
 }
 
 static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
 {
-    VirtIONet *n = to_virtio_net(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
     VirtIONetQueue *q;
     int i;
     uint8_t queue_status;
@@ -184,6 +178,7 @@ static void virtio_net_set_status(struct VirtIODevice *vdev, uint8_t status)
 static void virtio_net_set_link_status(NetClientState *nc)
 {
     VirtIONet *n = qemu_get_nic_opaque(nc);
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
     uint16_t old_status = n->status;
 
     if (nc->link_down)
@@ -192,14 +187,14 @@ static void virtio_net_set_link_status(NetClientState *nc)
         n->status |= VIRTIO_NET_S_LINK_UP;
 
     if (n->status != old_status)
-        virtio_notify_config(&n->vdev);
+        virtio_notify_config(vdev);
 
-    virtio_net_set_status(&n->vdev, n->vdev.status);
+    virtio_net_set_status(vdev, vdev->status);
 }
 
 static void virtio_net_reset(VirtIODevice *vdev)
 {
-    VirtIONet *n = to_virtio_net(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
 
     /* Reset back to compatibility mode */
     n->promisc = 1;
@@ -318,7 +313,7 @@ static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue, int ctrl);
 
 static uint32_t virtio_net_get_features(VirtIODevice *vdev, uint32_t features)
 {
-    VirtIONet *n = to_virtio_net(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
     NetClientState *nc = qemu_get_queue(n->nic);
 
     features |= (1 << VIRTIO_NET_F_MAC);
@@ -366,7 +361,7 @@ static uint32_t virtio_net_bad_features(VirtIODevice *vdev)
 
 static void virtio_net_set_features(VirtIODevice *vdev, uint32_t features)
 {
-    VirtIONet *n = to_virtio_net(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
     int i;
 
     virtio_net_set_multiqueue(n, !!(features & (1 << VIRTIO_NET_F_MQ)),
@@ -534,6 +529,7 @@ static int virtio_net_handle_vlan_table(VirtIONet *n, uint8_t cmd,
 static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
                                 struct iovec *iov, unsigned int iov_cnt)
 {
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
     struct virtio_net_ctrl_mq mq;
     size_t s;
     uint16_t queues;
@@ -559,14 +555,14 @@ static int virtio_net_handle_mq(VirtIONet *n, uint8_t cmd,
     n->curr_queues = queues;
     /* stop the backend before changing the number of queues to avoid handling a
      * disabled queue */
-    virtio_net_set_status(&n->vdev, n->vdev.status);
+    virtio_net_set_status(vdev, vdev->status);
     virtio_net_set_queues(n);
 
     return VIRTIO_NET_OK;
 }
 static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIONet *n = to_virtio_net(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
     struct virtio_net_ctrl_hdr ctrl;
     virtio_net_ctrl_ack status = VIRTIO_NET_ERR;
     VirtQueueElement elem;
@@ -609,7 +605,7 @@ static void virtio_net_handle_ctrl(VirtIODevice *vdev, VirtQueue *vq)
 
 static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIONet *n = to_virtio_net(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
     int queue_index = vq2q(virtio_get_queue_index(vq));
 
     qemu_flush_queued_packets(qemu_get_subqueue(n->nic, queue_index));
@@ -618,9 +614,10 @@ static void virtio_net_handle_rx(VirtIODevice *vdev, VirtQueue *vq)
 static int virtio_net_can_receive(NetClientState *nc)
 {
     VirtIONet *n = qemu_get_nic_opaque(nc);
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
     VirtIONetQueue *q = virtio_net_get_subqueue(nc);
 
-    if (!n->vdev.vm_running) {
+    if (!vdev->vm_running) {
         return 0;
     }
 
@@ -629,7 +626,7 @@ static int virtio_net_can_receive(NetClientState *nc)
     }
 
     if (!virtio_queue_ready(q->rx_vq) ||
-        !(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+        !(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
         return 0;
     }
 
@@ -759,6 +756,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
 {
     VirtIONet *n = qemu_get_nic_opaque(nc);
     VirtIONetQueue *q = virtio_net_get_subqueue(nc);
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
     struct iovec mhdr_sg[VIRTQUEUE_MAX_SIZE];
     struct virtio_net_hdr_mrg_rxbuf mhdr;
     unsigned mhdr_cnt = 0;
@@ -792,7 +790,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
                     "i %zd mergeable %d offset %zd, size %zd, "
                     "guest hdr len %zd, host hdr len %zd guest features 0x%x",
                     i, n->mergeable_rx_bufs, offset, size,
-                    n->guest_hdr_len, n->host_hdr_len, n->vdev.guest_features);
+                    n->guest_hdr_len, n->host_hdr_len, vdev->guest_features);
             exit(1);
         }
 
@@ -849,7 +847,7 @@ static ssize_t virtio_net_receive(NetClientState *nc, const uint8_t *buf, size_t
     }
 
     virtqueue_flush(q->rx_vq, i);
-    virtio_notify(&n->vdev, q->rx_vq);
+    virtio_notify(vdev, q->rx_vq);
 
     return size;
 }
@@ -860,9 +858,10 @@ static void virtio_net_tx_complete(NetClientState *nc, ssize_t len)
 {
     VirtIONet *n = qemu_get_nic_opaque(nc);
     VirtIONetQueue *q = virtio_net_get_subqueue(nc);
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
 
     virtqueue_push(q->tx_vq, &q->async_tx.elem, 0);
-    virtio_notify(&n->vdev, q->tx_vq);
+    virtio_notify(vdev, q->tx_vq);
 
     q->async_tx.elem.out_num = q->async_tx.len = 0;
 
@@ -874,14 +873,15 @@ static void virtio_net_tx_complete(NetClientState *nc, ssize_t len)
 static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
 {
     VirtIONet *n = q->n;
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
     VirtQueueElement elem;
     int32_t num_packets = 0;
     int queue_index = vq2q(virtio_get_queue_index(q->tx_vq));
-    if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)) {
+    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
         return num_packets;
     }
 
-    assert(n->vdev.vm_running);
+    assert(vdev->vm_running);
 
     if (q->async_tx.elem.out_num) {
         virtio_queue_set_notification(q->tx_vq, 0);
@@ -930,7 +930,7 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
         len += ret;
 
         virtqueue_push(q->tx_vq, &elem, 0);
-        virtio_notify(&n->vdev, q->tx_vq);
+        virtio_notify(vdev, q->tx_vq);
 
         if (++num_packets >= n->tx_burst) {
             break;
@@ -941,11 +941,11 @@ static int32_t virtio_net_flush_tx(VirtIONetQueue *q)
 
 static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIONet *n = to_virtio_net(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
     VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))];
 
     /* This happens when device was stopped but VCPU wasn't. */
-    if (!n->vdev.vm_running) {
+    if (!vdev->vm_running) {
         q->tx_waiting = 1;
         return;
     }
@@ -965,7 +965,7 @@ static void virtio_net_handle_tx_timer(VirtIODevice *vdev, VirtQueue *vq)
 
 static void virtio_net_handle_tx_bh(VirtIODevice *vdev, VirtQueue *vq)
 {
-    VirtIONet *n = to_virtio_net(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
     VirtIONetQueue *q = &n->vqs[vq2q(virtio_get_queue_index(vq))];
 
     if (unlikely(q->tx_waiting)) {
@@ -973,7 +973,7 @@ static void virtio_net_handle_tx_bh(VirtIODevice *vdev, VirtQueue *vq)
     }
     q->tx_waiting = 1;
     /* This happens when device was stopped but VCPU wasn't. */
-    if (!n->vdev.vm_running) {
+    if (!vdev->vm_running) {
         return;
     }
     virtio_queue_set_notification(vq, 0);
@@ -984,13 +984,15 @@ static void virtio_net_tx_timer(void *opaque)
 {
     VirtIONetQueue *q = opaque;
     VirtIONet *n = q->n;
-    assert(n->vdev.vm_running);
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
+    assert(vdev->vm_running);
 
     q->tx_waiting = 0;
 
     /* Just in case the driver is not ready on more */
-    if (!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK))
+    if (!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK)) {
         return;
+    }
 
     virtio_queue_set_notification(q->tx_vq, 1);
     virtio_net_flush_tx(q);
@@ -1000,15 +1002,17 @@ static void virtio_net_tx_bh(void *opaque)
 {
     VirtIONetQueue *q = opaque;
     VirtIONet *n = q->n;
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
     int32_t ret;
 
-    assert(n->vdev.vm_running);
+    assert(vdev->vm_running);
 
     q->tx_waiting = 0;
 
     /* Just in case the driver is not ready on more */
-    if (unlikely(!(n->vdev.status & VIRTIO_CONFIG_S_DRIVER_OK)))
+    if (unlikely(!(vdev->status & VIRTIO_CONFIG_S_DRIVER_OK))) {
         return;
+    }
 
     ret = virtio_net_flush_tx(q);
     if (ret == -EBUSY) {
@@ -1036,7 +1040,7 @@ static void virtio_net_tx_bh(void *opaque)
 
 static void virtio_net_set_multiqueue(VirtIONet *n, int multiqueue, int ctrl)
 {
-    VirtIODevice *vdev = &n->vdev;
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
     int i, max = multiqueue ? n->max_queues : 1;
 
     n->multiqueue = multiqueue;
@@ -1074,11 +1078,12 @@ static void virtio_net_save(QEMUFile *f, void *opaque)
 {
     int i;
     VirtIONet *n = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
 
     /* At this point, backend must be stopped, otherwise
      * it might keep writing to memory. */
     assert(!n->vhost_started);
-    virtio_save(&n->vdev, f);
+    virtio_save(vdev, f);
 
     qemu_put_buffer(f, n->mac, ETH_ALEN);
     qemu_put_be32(f, n->vqs[0].tx_waiting);
@@ -1109,12 +1114,13 @@ static void virtio_net_save(QEMUFile *f, void *opaque)
 static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
 {
     VirtIONet *n = opaque;
+    VirtIODevice *vdev = VIRTIO_DEVICE(n);
     int ret, i, link_down;
 
     if (version_id < 2 || version_id > VIRTIO_NET_VM_VERSION)
         return -EINVAL;
 
-    ret = virtio_load(&n->vdev, f);
+    ret = virtio_load(vdev, f);
     if (ret) {
         return ret;
     }
@@ -1163,11 +1169,11 @@ static int virtio_net_load(QEMUFile *f, void *opaque, int version_id)
 
         if (n->has_vnet_hdr) {
             tap_set_offload(qemu_get_queue(n->nic)->peer,
-                    (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
-                    (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
-                    (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
-                    (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_ECN)  & 1,
-                    (n->vdev.guest_features >> VIRTIO_NET_F_GUEST_UFO)  & 1);
+                    (vdev->guest_features >> VIRTIO_NET_F_GUEST_CSUM) & 1,
+                    (vdev->guest_features >> VIRTIO_NET_F_GUEST_TSO4) & 1,
+                    (vdev->guest_features >> VIRTIO_NET_F_GUEST_TSO6) & 1,
+                    (vdev->guest_features >> VIRTIO_NET_F_GUEST_ECN)  & 1,
+                    (vdev->guest_features >> VIRTIO_NET_F_GUEST_UFO)  & 1);
         }
     }
 
@@ -1240,7 +1246,7 @@ static NetClientInfo net_virtio_info = {
 
 static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
 {
-    VirtIONet *n = to_virtio_net(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
     NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
     assert(n->vhost_started);
     return vhost_net_virtqueue_pending(tap_get_vhost_net(nc->peer), idx);
@@ -1249,7 +1255,7 @@ static bool virtio_net_guest_notifier_pending(VirtIODevice *vdev, int idx)
 static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
                                            bool mask)
 {
-    VirtIONet *n = to_virtio_net(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
     NetClientState *nc = qemu_get_subqueue(n->nic, vq2q(idx));
     assert(n->vhost_started);
     vhost_net_virtqueue_mask(tap_get_vhost_net(nc->peer),
@@ -1273,6 +1279,7 @@ static VirtIODevice *virtio_net_common_init(DeviceState *dev, NICConf *conf,
                                             VirtIONet **pn)
 {
     VirtIONet *n = *pn;
+    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     int i, config_size = 0;
 
     /*
@@ -1295,18 +1302,18 @@ static VirtIODevice *virtio_net_common_init(DeviceState *dev, NICConf *conf,
                                                     n->config_size);
     }
 
-    n->vdev.get_config = virtio_net_get_config;
-    n->vdev.set_config = virtio_net_set_config;
-    n->vdev.get_features = virtio_net_get_features;
-    n->vdev.set_features = virtio_net_set_features;
-    n->vdev.bad_features = virtio_net_bad_features;
-    n->vdev.reset = virtio_net_reset;
-    n->vdev.set_status = virtio_net_set_status;
-    n->vdev.guest_notifier_mask = virtio_net_guest_notifier_mask;
-    n->vdev.guest_notifier_pending = virtio_net_guest_notifier_pending;
+    vdev->get_config = virtio_net_get_config;
+    vdev->set_config = virtio_net_set_config;
+    vdev->get_features = virtio_net_get_features;
+    vdev->set_features = virtio_net_set_features;
+    vdev->bad_features = virtio_net_bad_features;
+    vdev->reset = virtio_net_reset;
+    vdev->set_status = virtio_net_set_status;
+    vdev->guest_notifier_mask = virtio_net_guest_notifier_mask;
+    vdev->guest_notifier_pending = virtio_net_guest_notifier_pending;
     n->max_queues = MAX(conf->queues, 1);
     n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queues);
-    n->vqs[0].rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
+    n->vqs[0].rx_vq = virtio_add_queue(vdev, 256, virtio_net_handle_rx);
     n->curr_queues = 1;
     n->vqs[0].n = n;
     n->tx_timeout = net->txtimer;
@@ -1319,16 +1326,16 @@ static VirtIODevice *virtio_net_common_init(DeviceState *dev, NICConf *conf,
     }
 
     if (net->tx && !strcmp(net->tx, "timer")) {
-        n->vqs[0].tx_vq = virtio_add_queue(&n->vdev, 256,
+        n->vqs[0].tx_vq = virtio_add_queue(vdev, 256,
                                            virtio_net_handle_tx_timer);
         n->vqs[0].tx_timer = qemu_new_timer_ns(vm_clock, virtio_net_tx_timer,
                                                &n->vqs[0]);
     } else {
-        n->vqs[0].tx_vq = virtio_add_queue(&n->vdev, 256,
+        n->vqs[0].tx_vq = virtio_add_queue(vdev, 256,
                                            virtio_net_handle_tx_bh);
         n->vqs[0].tx_bh = qemu_bh_new(virtio_net_tx_bh, &n->vqs[0]);
     }
-    n->ctrl_vq = virtio_add_queue(&n->vdev, 64, virtio_net_handle_ctrl);
+    n->ctrl_vq = virtio_add_queue(vdev, 64, virtio_net_handle_ctrl);
     qemu_macaddr_default_if_unset(&conf->macaddr);
     memcpy(&n->mac[0], &conf->macaddr, sizeof(n->mac));
     n->status = VIRTIO_NET_S_LINK_UP;
@@ -1361,7 +1368,7 @@ static VirtIODevice *virtio_net_common_init(DeviceState *dev, NICConf *conf,
 
     add_boot_device_path(conf->bootindex, dev, "/ethernet-phy at 0");
 
-    return &n->vdev;
+    return vdev;
 }
 
 VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
@@ -1373,7 +1380,7 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
 
 void virtio_net_exit(VirtIODevice *vdev)
 {
-    VirtIONet *n = DO_UPCAST(VirtIONet, vdev, vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
     int i;
 
     /* This will stop vhost backend if appropriate. */
@@ -1400,7 +1407,7 @@ void virtio_net_exit(VirtIODevice *vdev)
 
     g_free(n->vqs);
     qemu_del_nic(n->nic);
-    virtio_cleanup(&n->vdev);
+    virtio_cleanup(vdev);
 }
 
 static int virtio_net_device_init(VirtIODevice *vdev)
@@ -1449,7 +1456,7 @@ static int virtio_net_device_exit(DeviceState *qdev)
 
     g_free(n->vqs);
     qemu_del_nic(n->nic);
-    virtio_common_cleanup(&n->vdev);
+    virtio_common_cleanup(vdev);
 
     return 0;
 }
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index 9fbb506..ce4ab50 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -153,7 +153,7 @@ typedef struct VirtIONetQueue {
 } VirtIONetQueue;
 
 typedef struct VirtIONet {
-    VirtIODevice vdev;
+    VirtIODevice parent_obj;
     uint8_t mac[ETH_ALEN];
     uint16_t status;
     VirtIONetQueue *vqs;
commit 89334c8b6baebb1e84cd9bb6e796683e53391769
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Apr 11 16:30:00 2013 +0200

    virtio-net-ccw: switch to the new API.
    
    Here the virtio-net-ccw is modified for the new API. The device
    virtio-net-ccw extends virtio-ccw-device as before. It creates and
    connects a virtio-net-device during the init. The properties are not modified.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1365690602-22729-6-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 216c983..e9e7509 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -551,23 +551,25 @@ static int virtio_ccw_exit(VirtioCcwDevice *dev)
     return 0;
 }
 
-static int virtio_ccw_net_init(VirtioCcwDevice *dev)
+static int virtio_ccw_net_init(VirtioCcwDevice *ccw_dev)
 {
-    VirtIODevice *vdev;
+    VirtIONetCcw *dev = VIRTIO_NET_CCW(ccw_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
 
-    vdev = virtio_net_init((DeviceState *)dev, &dev->nic, &dev->net,
-                           dev->host_features[0]);
-    if (!vdev) {
+    virtio_net_set_config_size(&dev->vdev, ccw_dev->host_features[0]);
+    qdev_set_parent_bus(vdev, BUS(&ccw_dev->bus));
+    if (qdev_init(vdev) < 0) {
         return -1;
     }
 
-    return virtio_ccw_device_init(dev, vdev);
+    return virtio_ccw_device_init(ccw_dev, VIRTIO_DEVICE(vdev));
 }
 
-static int virtio_ccw_net_exit(VirtioCcwDevice *dev)
+static void virtio_ccw_net_instance_init(Object *obj)
 {
-    virtio_net_exit(dev->vdev);
-    return virtio_ccw_exit(dev);
+    VirtIONetCcw *dev = VIRTIO_NET_CCW(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_NET);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 }
 
 static int virtio_ccw_blk_init(VirtioCcwDevice *ccw_dev)
@@ -768,8 +770,8 @@ static const VirtIOBindings virtio_ccw_bindings = {
 static Property virtio_ccw_net_properties[] = {
     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
     DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features[0]),
-    DEFINE_NIC_PROPERTIES(VirtioCcwDevice, nic),
-    DEFINE_VIRTIO_NET_PROPERTIES(VirtioCcwDevice, net),
+    DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetCcw, vdev.net_conf),
+    DEFINE_NIC_PROPERTIES(VirtIONetCcw, vdev.nic_conf),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -779,15 +781,16 @@ static void virtio_ccw_net_class_init(ObjectClass *klass, void *data)
     VirtIOCCWDeviceClass *k = VIRTIO_CCW_DEVICE_CLASS(klass);
 
     k->init = virtio_ccw_net_init;
-    k->exit = virtio_ccw_net_exit;
+    k->exit = virtio_ccw_exit;
     dc->reset = virtio_ccw_reset;
     dc->props = virtio_ccw_net_properties;
 }
 
 static const TypeInfo virtio_ccw_net = {
-    .name          = "virtio-net-ccw",
+    .name          = TYPE_VIRTIO_NET_CCW,
     .parent        = TYPE_VIRTIO_CCW_DEVICE,
-    .instance_size = sizeof(VirtioCcwDevice),
+    .instance_size = sizeof(VirtIONetCcw),
+    .instance_init = virtio_ccw_net_instance_init,
     .class_init    = virtio_ccw_net_class_init,
 };
 
diff --git a/hw/s390x/virtio-ccw.h b/hw/s390x/virtio-ccw.h
index 2208a11..35ab1a5 100644
--- a/hw/s390x/virtio-ccw.h
+++ b/hw/s390x/virtio-ccw.h
@@ -73,9 +73,7 @@ struct VirtioCcwDevice {
     SubchDev *sch;
     VirtIODevice *vdev;
     char *bus_id;
-    NICConf nic;
     uint32_t host_features[VIRTIO_CCW_FEATURE_SIZE];
-    virtio_net_conf net;
     VirtIORNGConf rng;
     VirtioBusState bus;
     /* Guest provided values: */
@@ -137,6 +135,17 @@ typedef struct VirtioSerialCcw {
     VirtIOSerial vdev;
 } VirtioSerialCcw;
 
+/* virtio-net-ccw */
+
+#define TYPE_VIRTIO_NET_CCW "virtio-net-ccw"
+#define VIRTIO_NET_CCW(obj) \
+        OBJECT_CHECK(VirtIONetCcw, (obj), TYPE_VIRTIO_NET_CCW)
+
+typedef struct VirtIONetCcw {
+    VirtioCcwDevice parent_obj;
+    VirtIONet vdev;
+} VirtIONetCcw;
+
 VirtualCssBus *virtual_css_bus_init(void);
 void virtio_ccw_device_update_status(SubchDev *sch);
 VirtIODevice *virtio_ccw_get_vdev(SubchDev *sch);
commit 74b4fe3d79098b72813e461af565557bb5d35649
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Apr 11 16:29:59 2013 +0200

    virtio-net-s390: switch to the new API.
    
    Here the virtio-net-s390 is modified for the new API. The device
    virtio-net-s390 extends virtio-s390-device as before. It creates and
    connects a virtio-net-device during the init. The properties are not modified.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1365690602-22729-5-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index 2708af8..ca0e301 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -149,17 +149,25 @@ static int s390_virtio_device_init(VirtIOS390Device *dev, VirtIODevice *vdev)
     return 0;
 }
 
-static int s390_virtio_net_init(VirtIOS390Device *dev)
+static int s390_virtio_net_init(VirtIOS390Device *s390_dev)
 {
-    VirtIODevice *vdev;
+    VirtIONetS390 *dev = VIRTIO_NET_S390(s390_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
 
-    vdev = virtio_net_init((DeviceState *)dev, &dev->nic, &dev->net,
-                           dev->host_features);
-    if (!vdev) {
+    virtio_net_set_config_size(&dev->vdev, s390_dev->host_features);
+    qdev_set_parent_bus(vdev, BUS(&s390_dev->bus));
+    if (qdev_init(vdev) < 0) {
         return -1;
     }
 
-    return s390_virtio_device_init(dev, vdev);
+    return s390_virtio_device_init(s390_dev, VIRTIO_DEVICE(vdev));
+}
+
+static void s390_virtio_net_instance_init(Object *obj)
+{
+    VirtIONetS390 *dev = VIRTIO_NET_S390(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_NET);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
 }
 
 static int s390_virtio_blk_init(VirtIOS390Device *s390_dev)
@@ -425,9 +433,9 @@ static const VirtIOBindings virtio_s390_bindings = {
 };
 
 static Property s390_virtio_net_properties[] = {
-    DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic),
+    DEFINE_NIC_PROPERTIES(VirtIONetS390, vdev.nic_conf),
     DEFINE_VIRTIO_NET_FEATURES(VirtIOS390Device, host_features),
-    DEFINE_VIRTIO_NET_PROPERTIES(VirtIOS390Device, net),
+    DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetS390, vdev.net_conf),
     DEFINE_PROP_END_OF_LIST(),
 };
 
@@ -441,9 +449,10 @@ static void s390_virtio_net_class_init(ObjectClass *klass, void *data)
 }
 
 static const TypeInfo s390_virtio_net = {
-    .name          = "virtio-net-s390",
+    .name          = TYPE_VIRTIO_NET_S390,
     .parent        = TYPE_VIRTIO_S390_DEVICE,
-    .instance_size = sizeof(VirtIOS390Device),
+    .instance_size = sizeof(VirtIONetS390),
+    .instance_init = s390_virtio_net_instance_init,
     .class_init    = s390_virtio_net_class_init,
 };
 
diff --git a/hw/s390x/s390-virtio-bus.h b/hw/s390x/s390-virtio-bus.h
index 1daf753..925ed2b 100644
--- a/hw/s390x/s390-virtio-bus.h
+++ b/hw/s390x/s390-virtio-bus.h
@@ -89,9 +89,7 @@ struct VirtIOS390Device {
     ram_addr_t feat_offs;
     uint8_t feat_len;
     VirtIODevice *vdev;
-    NICConf nic;
     uint32_t host_features;
-    virtio_net_conf net;
     VirtIORNGConf rng;
     VirtioBusState bus;
 };
@@ -151,4 +149,15 @@ typedef struct VirtIOSerialS390 {
     VirtIOSerial vdev;
 } VirtIOSerialS390;
 
+/* virtio-net-s390 */
+
+#define TYPE_VIRTIO_NET_S390 "virtio-net-s390"
+#define VIRTIO_NET_S390(obj) \
+        OBJECT_CHECK(VirtIONetS390, (obj), TYPE_VIRTIO_NET_S390)
+
+typedef struct VirtIONetS390 {
+    VirtIOS390Device parent_obj;
+    VirtIONet vdev;
+} VirtIONetS390;
+
 #endif
commit e37da3945fa2fde161e1b217f937fc318c4b7639
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Apr 11 16:29:58 2013 +0200

    virtio-net-pci: switch to the new API.
    
    Here the virtio-net-pci is modified for the new API. The device
    virtio-net-pci extends virtio-pci. It creates and connects a
    virtio-net-device during the init. The properties are not changed.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1365690602-22729-4-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index 25ece1b..e2d1693 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -943,31 +943,6 @@ static void virtio_exit_pci(PCIDevice *pci_dev)
     msix_uninit_exclusive_bar(pci_dev);
 }
 
-static int virtio_net_init_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-    VirtIODevice *vdev;
-
-    vdev = virtio_net_init(&pci_dev->qdev, &proxy->nic, &proxy->net,
-                           proxy->host_features);
-
-    vdev->nvectors = proxy->nvectors;
-    virtio_init_pci(proxy, vdev);
-
-    /* make the actual value visible */
-    proxy->nvectors = vdev->nvectors;
-    return 0;
-}
-
-static void virtio_net_exit_pci(PCIDevice *pci_dev)
-{
-    VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
-
-    virtio_pci_stop_ioeventfd(proxy);
-    virtio_net_exit(proxy->vdev);
-    virtio_exit_pci(pci_dev);
-}
-
 static int virtio_rng_init_pci(PCIDevice *pci_dev)
 {
     VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
@@ -1003,38 +978,6 @@ static void virtio_rng_exit_pci(PCIDevice *pci_dev)
     virtio_exit_pci(pci_dev);
 }
 
-static Property virtio_net_properties[] = {
-    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
-    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
-    DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
-    DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
-    DEFINE_VIRTIO_NET_PROPERTIES(VirtIOPCIProxy, net),
-    DEFINE_PROP_END_OF_LIST(),
-};
-
-static void virtio_net_class_init(ObjectClass *klass, void *data)
-{
-    DeviceClass *dc = DEVICE_CLASS(klass);
-    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
-    k->init = virtio_net_init_pci;
-    k->exit = virtio_net_exit_pci;
-    k->romfile = "efi-virtio.rom";
-    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
-    k->device_id = PCI_DEVICE_ID_VIRTIO_NET;
-    k->revision = VIRTIO_PCI_ABI_VERSION;
-    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
-    dc->reset = virtio_pci_reset;
-    dc->props = virtio_net_properties;
-}
-
-static const TypeInfo virtio_net_info = {
-    .name          = "virtio-net-pci",
-    .parent        = TYPE_PCI_DEVICE,
-    .instance_size = sizeof(VirtIOPCIProxy),
-    .class_init    = virtio_net_class_init,
-};
-
 static void virtio_rng_initfn(Object *obj)
 {
     PCIDevice *pci_dev = PCI_DEVICE(obj);
@@ -1493,6 +1436,61 @@ static const TypeInfo virtio_serial_pci_info = {
     .class_init    = virtio_serial_pci_class_init,
 };
 
+/* virtio-net-pci */
+
+static Property virtio_net_properties[] = {
+    DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags,
+                    VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, false),
+    DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
+    DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
+    DEFINE_NIC_PROPERTIES(VirtIONetPCI, vdev.nic_conf),
+    DEFINE_VIRTIO_NET_PROPERTIES(VirtIONetPCI, vdev.net_conf),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static int virtio_net_pci_init(VirtIOPCIProxy *vpci_dev)
+{
+    VirtIONetPCI *dev = VIRTIO_NET_PCI(vpci_dev);
+    DeviceState *vdev = DEVICE(&dev->vdev);
+
+    virtio_net_set_config_size(&dev->vdev, vpci_dev->host_features);
+    qdev_set_parent_bus(vdev, BUS(&vpci_dev->bus));
+    if (qdev_init(vdev) < 0) {
+        return -1;
+    }
+    return 0;
+}
+
+static void virtio_net_pci_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    VirtioPCIClass *vpciklass = VIRTIO_PCI_CLASS(klass);
+
+    k->romfile = "efi-virtio.rom";
+    k->vendor_id = PCI_VENDOR_ID_REDHAT_QUMRANET;
+    k->device_id = PCI_DEVICE_ID_VIRTIO_NET;
+    k->revision = VIRTIO_PCI_ABI_VERSION;
+    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
+    dc->props = virtio_net_properties;
+    vpciklass->init = virtio_net_pci_init;
+}
+
+static void virtio_net_pci_instance_init(Object *obj)
+{
+    VirtIONetPCI *dev = VIRTIO_NET_PCI(obj);
+    object_initialize(OBJECT(&dev->vdev), TYPE_VIRTIO_NET);
+    object_property_add_child(obj, "virtio-backend", OBJECT(&dev->vdev), NULL);
+}
+
+static const TypeInfo virtio_net_pci_info = {
+    .name          = TYPE_VIRTIO_NET_PCI,
+    .parent        = TYPE_VIRTIO_PCI,
+    .instance_size = sizeof(VirtIONetPCI),
+    .instance_init = virtio_net_pci_instance_init,
+    .class_init    = virtio_net_pci_class_init,
+};
+
 /* virtio-pci-bus */
 
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev)
@@ -1531,7 +1529,6 @@ static const TypeInfo virtio_pci_bus_info = {
 
 static void virtio_pci_register_types(void)
 {
-    type_register_static(&virtio_net_info);
     type_register_static(&virtio_rng_info);
     type_register_static(&virtio_pci_bus_info);
     type_register_static(&virtio_pci_info);
@@ -1542,6 +1539,7 @@ static void virtio_pci_register_types(void)
     type_register_static(&virtio_scsi_pci_info);
     type_register_static(&virtio_balloon_pci_info);
     type_register_static(&virtio_serial_pci_info);
+    type_register_static(&virtio_net_pci_info);
 }
 
 type_init(virtio_pci_register_types)
diff --git a/hw/virtio/virtio-pci.h b/hw/virtio/virtio-pci.h
index 879cc83..aa67561 100644
--- a/hw/virtio/virtio-pci.h
+++ b/hw/virtio/virtio-pci.h
@@ -30,6 +30,7 @@ typedef struct VirtIOBlkPCI VirtIOBlkPCI;
 typedef struct VirtIOSCSIPCI VirtIOSCSIPCI;
 typedef struct VirtIOBalloonPCI VirtIOBalloonPCI;
 typedef struct VirtIOSerialPCI VirtIOSerialPCI;
+typedef struct VirtIONetPCI VirtIONetPCI;
 
 /* virtio-pci-bus */
 
@@ -78,12 +79,10 @@ struct VirtIOPCIProxy {
     uint32_t flags;
     uint32_t class_code;
     uint32_t nvectors;
-    NICConf nic;
     uint32_t host_features;
 #ifdef CONFIG_VIRTFS
     V9fsConf fsconf;
 #endif
-    virtio_net_conf net;
     VirtIORNGConf rng;
     bool ioeventfd_disabled;
     bool ioeventfd_started;
@@ -142,6 +141,18 @@ struct VirtIOSerialPCI {
     VirtIOSerial vdev;
 };
 
+/*
+ * virtio-net-pci: This extends VirtioPCIProxy.
+ */
+#define TYPE_VIRTIO_NET_PCI "virtio-net-pci"
+#define VIRTIO_NET_PCI(obj) \
+        OBJECT_CHECK(VirtIONetPCI, (obj), TYPE_VIRTIO_NET_PCI)
+
+struct VirtIONetPCI {
+    VirtIOPCIProxy parent_obj;
+    VirtIONet vdev;
+};
+
 void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev);
 void virtio_pci_bus_new(VirtioBusState *bus, VirtIOPCIProxy *dev);
 
commit 17ec5a8686143da66208273d355f2eeb09807614
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Apr 11 16:29:57 2013 +0200

    virtio-net: add the virtio-net device.
    
    Create virtio-net-device which extends virtio-device, so it can be connected on
    virtio-bus.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1365690602-22729-3-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c
index bc8fd43..988fe03 100644
--- a/hw/net/virtio-net.c
+++ b/hw/net/virtio-net.c
@@ -20,6 +20,7 @@
 #include "qemu/timer.h"
 #include "hw/virtio/virtio-net.h"
 #include "net/vhost_net.h"
+#include "hw/virtio/virtio-bus.h"
 
 #define VIRTIO_NET_VM_VERSION    11
 
@@ -64,6 +65,9 @@ static int vq2q(int queue_index)
  * - we could suppress RX interrupt if we were so inclined.
  */
 
+/*
+ * Moving to QOM later in this serie.
+ */
 static VirtIONet *to_virtio_net(VirtIODevice *vdev)
 {
     return (VirtIONet *)vdev;
@@ -1252,22 +1256,45 @@ static void virtio_net_guest_notifier_mask(VirtIODevice *vdev, int idx,
                              vdev, idx, mask);
 }
 
-VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
-                              virtio_net_conf *net, uint32_t host_features)
+void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features)
 {
-    VirtIONet *n;
     int i, config_size = 0;
-
     for (i = 0; feature_sizes[i].flags != 0; i++) {
         if (host_features & feature_sizes[i].flags) {
             config_size = MAX(feature_sizes[i].end, config_size);
         }
     }
+    n->config_size = config_size;
+}
+
+static VirtIODevice *virtio_net_common_init(DeviceState *dev, NICConf *conf,
+                                            virtio_net_conf *net,
+                                            uint32_t host_features,
+                                            VirtIONet **pn)
+{
+    VirtIONet *n = *pn;
+    int i, config_size = 0;
 
-    n = (VirtIONet *)virtio_common_init("virtio-net", VIRTIO_ID_NET,
-                                        config_size, sizeof(VirtIONet));
+    /*
+     * We have two cases here: the old virtio-net-pci device, and the
+     * refactored virtio-net.
+     */
+    if (n == NULL) {
+        /* virtio-net-pci */
+        for (i = 0; feature_sizes[i].flags != 0; i++) {
+            if (host_features & feature_sizes[i].flags) {
+                config_size = MAX(feature_sizes[i].end, config_size);
+            }
+        }
+        n = (VirtIONet *)virtio_common_init("virtio-net", VIRTIO_ID_NET,
+                                            config_size, sizeof(VirtIONet));
+        n->config_size = config_size;
+    } else {
+        /* virtio-net */
+        virtio_init(VIRTIO_DEVICE(n), "virtio-net", VIRTIO_ID_NET,
+                                                    n->config_size);
+    }
 
-    n->config_size = config_size;
     n->vdev.get_config = virtio_net_get_config;
     n->vdev.set_config = virtio_net_set_config;
     n->vdev.get_features = virtio_net_get_features;
@@ -1337,6 +1364,13 @@ VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
     return &n->vdev;
 }
 
+VirtIODevice *virtio_net_init(DeviceState *dev, NICConf *conf,
+                              virtio_net_conf *net, uint32_t host_features)
+{
+    VirtIONet *n = NULL;
+    return virtio_net_common_init(dev, conf, net, host_features, &n);
+}
+
 void virtio_net_exit(VirtIODevice *vdev)
 {
     VirtIONet *n = DO_UPCAST(VirtIONet, vdev, vdev);
@@ -1368,3 +1402,107 @@ void virtio_net_exit(VirtIODevice *vdev)
     qemu_del_nic(n->nic);
     virtio_cleanup(&n->vdev);
 }
+
+static int virtio_net_device_init(VirtIODevice *vdev)
+{
+    DeviceState *qdev = DEVICE(vdev);
+    VirtIONet *n = VIRTIO_NET(vdev);
+
+    /*
+     * Initially, the new VirtIONet device will have a config size =
+     * sizeof(struct config), because we can't get host_features here.
+     */
+    if (virtio_net_common_init(qdev, &(n->nic_conf),
+                               &(n->net_conf), 0, &n) == NULL) {
+        return -1;
+    }
+    return 0;
+}
+
+static int virtio_net_device_exit(DeviceState *qdev)
+{
+    VirtIONet *n = VIRTIO_NET(qdev);
+    VirtIODevice *vdev = VIRTIO_DEVICE(qdev);
+    int i;
+
+    /* This will stop vhost backend if appropriate. */
+    virtio_net_set_status(vdev, 0);
+
+    unregister_savevm(qdev, "virtio-net", n);
+
+    g_free(n->mac_table.macs);
+    g_free(n->vlans);
+
+    for (i = 0; i < n->max_queues; i++) {
+        VirtIONetQueue *q = &n->vqs[i];
+        NetClientState *nc = qemu_get_subqueue(n->nic, i);
+
+        qemu_purge_queued_packets(nc);
+
+        if (q->tx_timer) {
+            qemu_del_timer(q->tx_timer);
+            qemu_free_timer(q->tx_timer);
+        } else {
+            qemu_bh_delete(q->tx_bh);
+        }
+    }
+
+    g_free(n->vqs);
+    qemu_del_nic(n->nic);
+    virtio_common_cleanup(&n->vdev);
+
+    return 0;
+}
+
+static void virtio_net_instance_init(Object *obj)
+{
+    VirtIONet *n = VIRTIO_NET(obj);
+
+    /*
+     * The default config_size is sizeof(struct virtio_net_config).
+     * Can be overriden with virtio_net_set_config_size.
+     */
+    n->config_size = sizeof(struct virtio_net_config);
+}
+
+static Property virtio_net_properties[] = {
+    DEFINE_NIC_PROPERTIES(VirtIONet, nic_conf),
+    DEFINE_PROP_UINT32("x-txtimer", VirtIONet, net_conf.txtimer,
+                                               TX_TIMER_INTERVAL),
+    DEFINE_PROP_INT32("x-txburst", VirtIONet, net_conf.txburst, TX_BURST),
+    DEFINE_PROP_STRING("tx", VirtIONet, net_conf.tx),
+    DEFINE_PROP_END_OF_LIST(),
+};
+
+static void virtio_net_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
+    dc->exit = virtio_net_device_exit;
+    dc->props = virtio_net_properties;
+    vdc->init = virtio_net_device_init;
+    vdc->get_config = virtio_net_get_config;
+    vdc->set_config = virtio_net_set_config;
+    vdc->get_features = virtio_net_get_features;
+    vdc->set_features = virtio_net_set_features;
+    vdc->bad_features = virtio_net_bad_features;
+    vdc->reset = virtio_net_reset;
+    vdc->set_status = virtio_net_set_status;
+    vdc->guest_notifier_mask = virtio_net_guest_notifier_mask;
+    vdc->guest_notifier_pending = virtio_net_guest_notifier_pending;
+}
+
+static const TypeInfo virtio_net_info = {
+    .name = TYPE_VIRTIO_NET,
+    .parent = TYPE_VIRTIO_DEVICE,
+    .instance_size = sizeof(VirtIONet),
+    .instance_init = virtio_net_instance_init,
+    .class_init = virtio_net_class_init,
+};
+
+static void virtio_register_types(void)
+{
+    type_register_static(&virtio_net_info);
+}
+
+type_init(virtio_register_types)
diff --git a/hw/s390x/s390-virtio-bus.c b/hw/s390x/s390-virtio-bus.c
index a71c145..2708af8 100644
--- a/hw/s390x/s390-virtio-bus.c
+++ b/hw/s390x/s390-virtio-bus.c
@@ -427,11 +427,7 @@ static const VirtIOBindings virtio_s390_bindings = {
 static Property s390_virtio_net_properties[] = {
     DEFINE_NIC_PROPERTIES(VirtIOS390Device, nic),
     DEFINE_VIRTIO_NET_FEATURES(VirtIOS390Device, host_features),
-    DEFINE_PROP_UINT32("x-txtimer", VirtIOS390Device,
-                       net.txtimer, TX_TIMER_INTERVAL),
-    DEFINE_PROP_INT32("x-txburst", VirtIOS390Device,
-                      net.txburst, TX_BURST),
-    DEFINE_PROP_STRING("tx", VirtIOS390Device, net.tx),
+    DEFINE_VIRTIO_NET_PROPERTIES(VirtIOS390Device, net),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/s390x/virtio-ccw.c b/hw/s390x/virtio-ccw.c
index 666df78..216c983 100644
--- a/hw/s390x/virtio-ccw.c
+++ b/hw/s390x/virtio-ccw.c
@@ -769,11 +769,7 @@ static Property virtio_ccw_net_properties[] = {
     DEFINE_PROP_STRING("devno", VirtioCcwDevice, bus_id),
     DEFINE_VIRTIO_NET_FEATURES(VirtioCcwDevice, host_features[0]),
     DEFINE_NIC_PROPERTIES(VirtioCcwDevice, nic),
-    DEFINE_PROP_UINT32("x-txtimer", VirtioCcwDevice,
-                       net.txtimer, TX_TIMER_INTERVAL),
-    DEFINE_PROP_INT32("x-txburst", VirtioCcwDevice,
-                      net.txburst, TX_BURST),
-    DEFINE_PROP_STRING("tx", VirtioCcwDevice, net.tx),
+    DEFINE_VIRTIO_NET_PROPERTIES(VirtioCcwDevice, net),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index fdf7377..25ece1b 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -1008,9 +1008,7 @@ static Property virtio_net_properties[] = {
     DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 3),
     DEFINE_VIRTIO_NET_FEATURES(VirtIOPCIProxy, host_features),
     DEFINE_NIC_PROPERTIES(VirtIOPCIProxy, nic),
-    DEFINE_PROP_UINT32("x-txtimer", VirtIOPCIProxy, net.txtimer, TX_TIMER_INTERVAL),
-    DEFINE_PROP_INT32("x-txburst", VirtIOPCIProxy, net.txburst, TX_BURST),
-    DEFINE_PROP_STRING("tx", VirtIOPCIProxy, net.tx),
+    DEFINE_VIRTIO_NET_PROPERTIES(VirtIOPCIProxy, net),
     DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/include/hw/virtio/virtio-net.h b/include/hw/virtio/virtio-net.h
index d2cc996..9fbb506 100644
--- a/include/hw/virtio/virtio-net.h
+++ b/include/hw/virtio/virtio-net.h
@@ -17,6 +17,10 @@
 #include "hw/virtio/virtio.h"
 #include "hw/pci/pci.h"
 
+#define TYPE_VIRTIO_NET "virtio-net-device"
+#define VIRTIO_NET(obj) \
+        OBJECT_CHECK(VirtIONet, (obj), TYPE_VIRTIO_NET)
+
 #define ETH_ALEN    6
 
 /* from Linux's virtio_net.h */
@@ -177,6 +181,8 @@ typedef struct VirtIONet {
         uint8_t *macs;
     } mac_table;
     uint32_t *vlans;
+    virtio_net_conf net_conf;
+    NICConf nic_conf;
     DeviceState *qdev;
     int multiqueue;
     uint16_t max_queues;
@@ -243,4 +249,11 @@ struct virtio_net_ctrl_mq {
         DEFINE_PROP_BIT("ctrl_mac_addr", _state, _field, VIRTIO_NET_F_CTRL_MAC_ADDR, true), \
         DEFINE_PROP_BIT("mq", _state, _field, VIRTIO_NET_F_MQ, false)
 
+#define DEFINE_VIRTIO_NET_PROPERTIES(_state, _field)                           \
+    DEFINE_PROP_UINT32("x-txtimer", _state, _field.txtimer, TX_TIMER_INTERVAL),\
+    DEFINE_PROP_INT32("x-txburst", _state, _field.txburst, TX_BURST),          \
+    DEFINE_PROP_STRING("tx", _state, _field.tx)
+
+void virtio_net_set_config_size(VirtIONet *n, uint32_t host_features);
+
 #endif
commit 6a87acf7df4b31ca0896b95b86dac9698420a9ed
Author: KONRAD Frederic <fred.konrad at greensocs.com>
Date:   Thu Apr 11 16:29:56 2013 +0200

    virtio: add two functions to VirtioDeviceClass.
    
    Recent changes need two functions to VirtioDevice. This just add them
    into VirtioDeviceClass.
    
    Signed-off-by: KONRAD Frederic <fred.konrad at greensocs.com>
    Tested-by: Cornelia Huck <cornelia.huck at de.ibm.com>
    Message-id: 1365690602-22729-2-git-send-email-fred.konrad at greensocs.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h
index 7e24b2b..b21e5c2 100644
--- a/include/hw/virtio/virtio.h
+++ b/include/hw/virtio/virtio.h
@@ -171,6 +171,18 @@ typedef struct VirtioDeviceClass {
     void (*set_config)(VirtIODevice *vdev, const uint8_t *config);
     void (*reset)(VirtIODevice *vdev);
     void (*set_status)(VirtIODevice *vdev, uint8_t val);
+    /* Test and clear event pending status.
+     * Should be called after unmask to avoid losing events.
+     * If backend does not support masking,
+     * must check in frontend instead.
+     */
+    bool (*guest_notifier_pending)(VirtIODevice *vdev, int n);
+    /* Mask/unmask events from this vq. Any events reported
+     * while masked will become pending.
+     * If backend does not support masking,
+     * must mask in frontend instead.
+     */
+    void (*guest_notifier_mask)(VirtIODevice *vdev, int n, bool mask);
 } VirtioDeviceClass;
 
 void virtio_init(VirtIODevice *vdev, const char *name,
commit e6f53fd514bbdcf63a5905536ff4d0effc146742
Author: Markus Armbruster <armbru at redhat.com>
Date:   Tue Apr 16 13:51:06 2013 +0200

    Fix warnings suppressors to honor --disable-werror
    
    Replace
    
        #pragma GCC diagnostic ignored FOO
        [Troublesome code...]
        #pragma GCC diagnostic error FOO
    
    by
    
        #pragma GCC diagnostic push
        #pragma GCC diagnostic ignored FOO
        [Troublesome code...]
        #pragma GCC diagnostic pop
    
    Broken in commit 3f4349d, commit 092bb30, and commit c95e308.
    
    Signed-off-by: Markus Armbruster <armbru at redhat.com>
    Tested-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Reviewed-by: Paolo Bonzini <pbonzini at redhat.com>
    Message-id: 1366113066-1340-1-git-send-email-armbru at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/configure b/configure
index 0fb9a93..de93345 100755
--- a/configure
+++ b/configure
@@ -3268,8 +3268,10 @@ fi
 
 pragma_disable_unused_but_set=no
 cat > $TMPC << EOF
+#pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
+#pragma GCC diagnostic pop
 
 int main(void) {
     return 0;
diff --git a/coroutine-ucontext.c b/coroutine-ucontext.c
index 867a662..4bf2cde 100644
--- a/coroutine-ucontext.c
+++ b/coroutine-ucontext.c
@@ -169,6 +169,7 @@ Coroutine *qemu_coroutine_new(void)
 #ifdef CONFIG_VALGRIND_H
 #ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
 /* Work around an unused variable in the valgrind.h macro... */
+#pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
 #endif
 static inline void valgrind_stack_deregister(CoroutineUContext *co)
@@ -176,7 +177,7 @@ static inline void valgrind_stack_deregister(CoroutineUContext *co)
     VALGRIND_STACK_DEREGISTER(co->valgrind_stack_id);
 }
 #ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
-#pragma GCC diagnostic error "-Wunused-but-set-variable"
+#pragma GCC diagnostic pop
 #endif
 #endif
 
diff --git a/include/ui/qemu-pixman.h b/include/ui/qemu-pixman.h
index f012ec5..ba970f8 100644
--- a/include/ui/qemu-pixman.h
+++ b/include/ui/qemu-pixman.h
@@ -8,11 +8,12 @@
 
 /* pixman-0.16.0 headers have a redundant declaration */
 #ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
+#pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wredundant-decls"
 #endif
 #include <pixman.h>
 #ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
-#pragma GCC diagnostic error "-Wredundant-decls"
+#pragma GCC diagnostic pop
 #endif
 
 #include "qemu/typedefs.h"
diff --git a/ui/gtk.c b/ui/gtk.c
index d48529a..b46997a 100644
--- a/ui/gtk.c
+++ b/ui/gtk.c
@@ -38,11 +38,12 @@
 
 #ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
 /* Work around an -Wstrict-prototypes warning in GTK headers */
+#pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wstrict-prototypes"
 #endif
 #include <gtk/gtk.h>
 #ifdef CONFIG_PRAGMA_DIAGNOSTIC_AVAILABLE
-#pragma GCC diagnostic error "-Wstrict-prototypes"
+#pragma GCC diagnostic pop
 #endif
 
 
commit bf2a38d41e304ccd92191327248fd32f14ff11d2
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 16 09:45:21 2013 -0500

    fw_cfg: add qtest test case
    
    This validates some basic characteristics of fw_cfg.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1366123521-4330-8-git-send-email-aliguori at us.ibm.com

diff --git a/tests/Makefile b/tests/Makefile
index 6c4b910..72bf2cd 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -55,6 +55,7 @@ check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
 gcov-files-i386-y += hw/hd-geometry.c
 check-qtest-i386-y += tests/rtc-test$(EXESUF)
 check-qtest-i386-y += tests/i440fx-test$(EXESUF)
+check-qtest-i386-y += tests/fw_cfg-test$(EXESUF)
 check-qtest-x86_64-y = $(check-qtest-i386-y)
 gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c
 gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
@@ -127,6 +128,7 @@ tests/fdc-test$(EXESUF): tests/fdc-test.o
 tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o
 tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
+tests/fw_cfg-test$(EXESUF): tests/fw_cfg-test.o $(libqos-pc-obj-y)
 
 # QTest rules
 
diff --git a/tests/fw_cfg-test.c b/tests/fw_cfg-test.c
new file mode 100644
index 0000000..c284c4d
--- /dev/null
+++ b/tests/fw_cfg-test.c
@@ -0,0 +1,141 @@
+/*
+ * qtest fw_cfg test case
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#define NO_QEMU_PROTOS
+
+#include "libqtest.h"
+#include "hw/nvram/fw_cfg.h"
+#include "libqos/fw_cfg-pc.h"
+
+#include <string.h>
+#include <glib.h>
+
+static uint64_t ram_size = 128 << 20;
+static uint16_t nb_cpus = 1;
+static uint16_t max_cpus = 1;
+static uint64_t nb_nodes = 0;
+static uint16_t boot_menu = 0;
+static QFWCFG *fw_cfg = NULL;
+
+static void test_fw_cfg_signature(void)
+{
+    char buf[5];
+
+    qfw_cfg_get(fw_cfg, FW_CFG_SIGNATURE, buf, 4);
+    buf[4] = 0;
+
+    g_assert_cmpstr(buf, ==, "QEMU");
+}
+
+static void test_fw_cfg_id(void)
+{
+    g_assert_cmpint(qfw_cfg_get_u32(fw_cfg, FW_CFG_ID), ==, 1);
+}
+
+static void test_fw_cfg_uuid(void)
+{
+    uint8_t buf[16];
+    static const uint8_t uuid[16] = {
+        0x46, 0x00, 0xcb, 0x32, 0x38, 0xec, 0x4b, 0x2f,
+        0x8a, 0xcb, 0x81, 0xc6, 0xea, 0x54, 0xf2, 0xd8,
+    };
+
+    qfw_cfg_get(fw_cfg, FW_CFG_UUID, buf, 16);
+    g_assert(memcmp(buf, uuid, sizeof(buf)) == 0);
+}
+
+static void test_fw_cfg_ram_size(void)
+{
+    g_assert_cmpint(qfw_cfg_get_u64(fw_cfg, FW_CFG_RAM_SIZE), ==, ram_size);
+}
+
+static void test_fw_cfg_nographic(void)
+{
+    g_assert_cmpint(qfw_cfg_get_u16(fw_cfg, FW_CFG_NOGRAPHIC), ==, 0);
+}
+
+static void test_fw_cfg_nb_cpus(void)
+{
+    g_assert_cmpint(qfw_cfg_get_u16(fw_cfg, FW_CFG_NB_CPUS), ==, nb_cpus);
+}
+
+static void test_fw_cfg_max_cpus(void)
+{
+    g_assert_cmpint(qfw_cfg_get_u16(fw_cfg, FW_CFG_MAX_CPUS), ==, max_cpus);
+}
+
+static void test_fw_cfg_numa(void)
+{
+    uint64_t *cpu_mask;
+    uint64_t *node_mask;
+
+    g_assert_cmpint(qfw_cfg_get_u64(fw_cfg, FW_CFG_NUMA), ==, nb_nodes);
+
+    cpu_mask = g_malloc0(sizeof(uint64_t) * max_cpus);
+    node_mask = g_malloc0(sizeof(uint64_t) * nb_nodes);
+
+    qfw_cfg_read_data(fw_cfg, cpu_mask, sizeof(uint64_t) * max_cpus);
+    qfw_cfg_read_data(fw_cfg, node_mask, sizeof(uint64_t) * nb_nodes);
+
+    if (nb_nodes) {
+        g_assert(cpu_mask[0] & 0x01);
+        g_assert_cmpint(node_mask[0], ==, ram_size);
+    }
+
+    g_free(node_mask);
+    g_free(cpu_mask);
+}
+
+static void test_fw_cfg_boot_menu(void)
+{
+    g_assert_cmpint(qfw_cfg_get_u16(fw_cfg, FW_CFG_BOOT_MENU), ==, boot_menu);
+}
+
+int main(int argc, char **argv)
+{
+    QTestState *s;
+    char *cmdline;
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+
+    fw_cfg = pc_fw_cfg_init();
+
+    g_test_add_func("/fw_cfg/signature", test_fw_cfg_signature);
+    g_test_add_func("/fw_cfg/id", test_fw_cfg_id);
+    g_test_add_func("/fw_cfg/uuid", test_fw_cfg_uuid);
+    g_test_add_func("/fw_cfg/ram_size", test_fw_cfg_ram_size);
+    g_test_add_func("/fw_cfg/nographic", test_fw_cfg_nographic);
+    g_test_add_func("/fw_cfg/nb_cpus", test_fw_cfg_nb_cpus);
+#if 0
+    g_test_add_func("/fw_cfg/machine_id", test_fw_cfg_machine_id);
+    g_test_add_func("/fw_cfg/kernel", test_fw_cfg_kernel);
+    g_test_add_func("/fw_cfg/initrd", test_fw_cfg_initrd);
+    g_test_add_func("/fw_cfg/boot_device", test_fw_cfg_boot_device);
+#endif
+    g_test_add_func("/fw_cfg/max_cpus", test_fw_cfg_max_cpus);
+    g_test_add_func("/fw_cfg/numa", test_fw_cfg_numa);
+    g_test_add_func("/fw_cfg/boot_menu", test_fw_cfg_boot_menu);
+
+    cmdline = g_strdup_printf("-display none "
+                              "-uuid 4600cb32-38ec-4b2f-8acb-81c6ea54f2d8 ");
+    s = qtest_start(cmdline);
+    g_free(cmdline);
+
+    ret = g_test_run();
+
+    if (s) {
+        qtest_quit(s);
+    }
+
+    return ret;
+}
commit a875711af9518f0878e084aef00c323098b8f972
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 16 09:45:20 2013 -0500

    i440fx-test: add test for PAM functionality
    
    This tests PAM settings for the i440fx.  This test does a lot of
    byte MMIO which is fairly slow with qtest today.  But the test
    does complete in under 2 seconds.
    
    We don't fully emulate PAM largely because of limitations with
    KVM so we #if 0 that part of the test case.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1366123521-4330-7-git-send-email-aliguori at us.ibm.com

diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c
index 6fba741..08ce820 100644
--- a/tests/i440fx-test.c
+++ b/tests/i440fx-test.c
@@ -17,10 +17,12 @@
 #include "hw/pci/pci_regs.h"
 
 #include <glib.h>
-#include <stdio.h>
+#include <string.h>
 
 #define BROKEN 1
 
+#define ARRAY_SIZE(array) (sizeof(array) / sizeof((array)[0]))
+
 typedef struct TestData
 {
     int num_cpus;
@@ -119,6 +121,139 @@ static void test_i440fx_defaults(gconstpointer opaque)
     g_assert_cmpint(qpci_config_readb(dev, 0x93), ==, 0x00); /* TRC */
 }
 
+#define PAM_RE 1
+#define PAM_WE 2
+
+static void pam_set(QPCIDevice *dev, int index, int flags)
+{
+    int regno = 0x59 + (index / 2);
+    uint8_t reg;
+
+    reg = qpci_config_readb(dev, regno);
+    if (index & 1) {
+        reg = (reg & 0x0F) | (flags << 4);
+    } else {
+        reg = (reg & 0xF0) | flags;
+    }
+    qpci_config_writeb(dev, regno, reg);
+}
+
+static gboolean verify_area(uint32_t start, uint32_t end, uint8_t value)
+{
+    uint32_t size = end - start + 1;
+    gboolean ret = TRUE;
+    uint8_t *data;
+    int i;
+
+    data = g_malloc0(size);
+    memread(start, data, size);
+
+    g_test_message("verify_area: data[0] = 0x%x", data[0]);
+
+    for (i = 0; i < size; i++) {
+        if (data[i] != value) {
+            ret = FALSE;
+            break;
+        }
+    }
+
+    g_free(data);
+
+    return ret;
+}
+
+static void write_area(uint32_t start, uint32_t end, uint8_t value)
+{
+    uint32_t size = end - start + 1;
+    uint8_t *data;
+
+    data = g_malloc0(size);
+    memset(data, value, size);
+    memwrite(start, data, size);
+
+    g_free(data);
+}
+
+static void test_i440fx_pam(gconstpointer opaque)
+{
+    const TestData *s = opaque;
+    QPCIDevice *dev;
+    int i;
+    static struct {
+        uint32_t start;
+        uint32_t end;
+    } pam_area[] = {
+        { 0, 0 },             /* Reserved */
+        { 0xF0000, 0xFFFFF }, /* BIOS Area */
+        { 0xC0000, 0xC3FFF }, /* Option ROM */
+        { 0xC4000, 0xC7FFF }, /* Option ROM */
+        { 0xC8000, 0xCBFFF }, /* Option ROM */
+        { 0xCC000, 0xCFFFF }, /* Option ROM */
+        { 0xD0000, 0xD3FFF }, /* Option ROM */
+        { 0xD4000, 0xD7FFF }, /* Option ROM */
+        { 0xD8000, 0xDBFFF }, /* Option ROM */
+        { 0xDC000, 0xDFFFF }, /* Option ROM */
+        { 0xE0000, 0xE3FFF }, /* BIOS Extension */
+        { 0xE4000, 0xE7FFF }, /* BIOS Extension */
+        { 0xE8000, 0xEBFFF }, /* BIOS Extension */
+        { 0xEC000, 0xEFFFF }, /* BIOS Extension */
+    };
+
+    dev = qpci_device_find(s->bus, QPCI_DEVFN(0, 0));
+    g_assert(dev != NULL);
+
+    for (i = 0; i < ARRAY_SIZE(pam_area); i++) {
+        if (pam_area[i].start == pam_area[i].end) {
+            continue;
+        }
+
+        g_test_message("Checking area 0x%05x..0x%05x",
+                       pam_area[i].start, pam_area[i].end);
+        /* Switch to RE for the area */
+        pam_set(dev, i, PAM_RE);
+        /* Verify the RAM is all zeros */
+        g_assert(verify_area(pam_area[i].start, pam_area[i].end, 0));
+
+        /* Switch to WE for the area */
+        pam_set(dev, i, PAM_RE | PAM_WE);
+        /* Write out a non-zero mask to the full area */
+        write_area(pam_area[i].start, pam_area[i].end, 0x42);
+
+#ifndef BROKEN
+        /* QEMU only supports a limited form of PAM */
+
+        /* Switch to !RE for the area */
+        pam_set(dev, i, PAM_WE);
+        /* Verify the area is not our mask */
+        g_assert(!verify_area(pam_area[i].start, pam_area[i].end, 0x42));
+#endif
+
+        /* Verify the area is our new mask */
+        g_assert(verify_area(pam_area[i].start, pam_area[i].end, 0x42));
+
+        /* Write out a new mask */
+        write_area(pam_area[i].start, pam_area[i].end, 0x82);
+
+#ifndef BROKEN
+        /* QEMU only supports a limited form of PAM */
+
+        /* Verify the area is not our mask */
+        g_assert(!verify_area(pam_area[i].start, pam_area[i].end, 0x82));
+
+        /* Switch to RE for the area */
+        pam_set(dev, i, PAM_RE | PAM_WE);
+#endif
+        /* Verify the area is our new mask */
+        g_assert(verify_area(pam_area[i].start, pam_area[i].end, 0x82));
+
+        /* Reset area */
+        pam_set(dev, i, 0);
+
+        /* Verify the area is not our new mask */
+        g_assert(!verify_area(pam_area[i].start, pam_area[i].end, 0x82));
+    }
+}
+
 int main(int argc, char **argv)
 {
     QTestState *s;
@@ -137,6 +272,8 @@ int main(int argc, char **argv)
     data.bus = qpci_init_pc();
 
     g_test_add_data_func("/i440fx/defaults", &data, test_i440fx_defaults);
+    g_test_add_data_func("/i440fx/pam", &data, test_i440fx_pam);
+    
 
     ret = g_test_run();
 
commit 9bda413c96c3c7cced25ee4509c74d71e40f094d
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 16 09:45:19 2013 -0500

    i440fx-test: add test to compare default register values
    
    This test compares all of the default register values against the
    spec.  It turns out we deviate in quite a few places.  These
    places are really only visible to the BIOS though which is why
    this hasn't created any problems.
    
    The deviation actually happens in the core PCI layer so I suspect
    it's not a simple fix if we really care to fix it.  For now, just
    disable the affected checks.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1366123521-4330-6-git-send-email-aliguori at us.ibm.com

diff --git a/tests/Makefile b/tests/Makefile
index cafbb27..6c4b910 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -54,6 +54,7 @@ gcov-files-i386-y = hw/fdc.c
 check-qtest-i386-y += tests/hd-geo-test$(EXESUF)
 gcov-files-i386-y += hw/hd-geometry.c
 check-qtest-i386-y += tests/rtc-test$(EXESUF)
+check-qtest-i386-y += tests/i440fx-test$(EXESUF)
 check-qtest-x86_64-y = $(check-qtest-i386-y)
 gcov-files-i386-y += i386-softmmu/hw/mc146818rtc.c
 gcov-files-x86_64-y = $(subst i386-softmmu/,x86_64-softmmu/,$(gcov-files-i386-y))
@@ -125,6 +126,7 @@ tests/m48t59-test$(EXESUF): tests/m48t59-test.o
 tests/fdc-test$(EXESUF): tests/fdc-test.o
 tests/hd-geo-test$(EXESUF): tests/hd-geo-test.o
 tests/tmp105-test$(EXESUF): tests/tmp105-test.o
+tests/i440fx-test$(EXESUF): tests/i440fx-test.o $(libqos-pc-obj-y)
 
 # QTest rules
 
diff --git a/tests/i440fx-test.c b/tests/i440fx-test.c
new file mode 100644
index 0000000..6fba741
--- /dev/null
+++ b/tests/i440fx-test.c
@@ -0,0 +1,148 @@
+/*
+ * qtest I440FX test case
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "libqos/pci.h"
+#include "libqos/pci-pc.h"
+#include "libqtest.h"
+
+#include "hw/pci/pci_regs.h"
+
+#include <glib.h>
+#include <stdio.h>
+
+#define BROKEN 1
+
+typedef struct TestData
+{
+    int num_cpus;
+    QPCIBus *bus;
+} TestData;
+
+static void test_i440fx_defaults(gconstpointer opaque)
+{
+    const TestData *s = opaque;
+    QPCIDevice *dev;
+    uint32_t value;
+
+    dev = qpci_device_find(s->bus, QPCI_DEVFN(0, 0));
+    g_assert(dev != NULL);
+
+    /* 3.2.2 */
+    g_assert_cmpint(qpci_config_readw(dev, PCI_VENDOR_ID), ==, 0x8086);
+    /* 3.2.3 */
+    g_assert_cmpint(qpci_config_readw(dev, PCI_DEVICE_ID), ==, 0x1237);
+#ifndef BROKEN
+    /* 3.2.4 */
+    g_assert_cmpint(qpci_config_readw(dev, PCI_COMMAND), ==, 0x0006);
+    /* 3.2.5 */
+    g_assert_cmpint(qpci_config_readw(dev, PCI_STATUS), ==, 0x0280);
+#endif
+    /* 3.2.7 */
+    g_assert_cmpint(qpci_config_readb(dev, PCI_CLASS_PROG), ==, 0x00);
+    g_assert_cmpint(qpci_config_readw(dev, PCI_CLASS_DEVICE), ==, 0x0600);
+    /* 3.2.8 */
+    g_assert_cmpint(qpci_config_readb(dev, PCI_LATENCY_TIMER), ==, 0x00);
+    /* 3.2.9 */
+    g_assert_cmpint(qpci_config_readb(dev, PCI_HEADER_TYPE), ==, 0x00);
+    /* 3.2.10 */
+    g_assert_cmpint(qpci_config_readb(dev, PCI_BIST), ==, 0x00);
+
+    /* 3.2.11 */
+    value = qpci_config_readw(dev, 0x50); /* PMCCFG */
+    if (s->num_cpus == 1) { /* WPE */
+        g_assert(!(value & (1 << 15)));
+    } else {
+        g_assert((value & (1 << 15)));
+    }
+
+    g_assert(!(value & (1 << 6))); /* EPTE */
+
+    /* 3.2.12 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x52), ==, 0x00); /* DETURBO */
+    /* 3.2.13 */
+#ifndef BROKEN
+    g_assert_cmpint(qpci_config_readb(dev, 0x53), ==, 0x80); /* DBC */
+#endif
+    /* 3.2.14 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x54), ==, 0x00); /* AXC */
+    /* 3.2.15 */
+    g_assert_cmpint(qpci_config_readw(dev, 0x55), ==, 0x0000); /* DRT */
+#ifndef BROKEN
+    /* 3.2.16 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x57), ==, 0x01); /* DRAMC */
+    /* 3.2.17 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x58), ==, 0x10); /* DRAMT */
+#endif
+    /* 3.2.18 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x59), ==, 0x00); /* PAM0 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x5A), ==, 0x00); /* PAM1 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x5B), ==, 0x00); /* PAM2 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x5C), ==, 0x00); /* PAM3 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x5D), ==, 0x00); /* PAM4 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x5E), ==, 0x00); /* PAM5 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x5F), ==, 0x00); /* PAM6 */
+#ifndef BROKEN
+    /* 3.2.19 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x60), ==, 0x01); /* DRB0 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x61), ==, 0x01); /* DRB1 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x62), ==, 0x01); /* DRB2 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x63), ==, 0x01); /* DRB3 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x64), ==, 0x01); /* DRB4 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x65), ==, 0x01); /* DRB5 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x66), ==, 0x01); /* DRB6 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x67), ==, 0x01); /* DRB7 */
+#endif
+    /* 3.2.20 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x68), ==, 0x00); /* FDHC */
+    /* 3.2.21 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x70), ==, 0x00); /* MTT */
+#ifndef BROKEN
+    /* 3.2.22 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x71), ==, 0x10); /* CLT */
+#endif
+    /* 3.2.23 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x72), ==, 0x02); /* SMRAM */
+    /* 3.2.24 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x90), ==, 0x00); /* ERRCMD */
+    /* 3.2.25 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x91), ==, 0x00); /* ERRSTS */
+    /* 3.2.26 */
+    g_assert_cmpint(qpci_config_readb(dev, 0x93), ==, 0x00); /* TRC */
+}
+
+int main(int argc, char **argv)
+{
+    QTestState *s;
+    TestData data;
+    char *cmdline;
+    int ret;
+
+    g_test_init(&argc, &argv, NULL);
+
+    data.num_cpus = 1;
+
+    cmdline = g_strdup_printf("-display none -smp %d", data.num_cpus);
+    s = qtest_start(cmdline);
+    g_free(cmdline);
+
+    data.bus = qpci_init_pc();
+
+    g_test_add_data_func("/i440fx/defaults", &data, test_i440fx_defaults);
+
+    ret = g_test_run();
+
+    if (s) {
+        qtest_quit(s);
+    }
+
+    return ret;
+}
commit 8a0743cf747c659a3443e722a832c8f21f1cc774
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 16 09:45:18 2013 -0500

    libqos: add malloc support
    
    This is a very simple allocator for the PC platform.  It should
    be possible to add backends for other platforms.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1366123521-4330-5-git-send-email-aliguori at us.ibm.com

diff --git a/tests/Makefile b/tests/Makefile
index ce91980..cafbb27 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -118,6 +118,7 @@ tests/test-mul64$(EXESUF): tests/test-mul64.o libqemuutil.a
 
 libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o
 libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o tests/libqos/fw_cfg-pc.o
+libqos-pc-obj-y += tests/libqos/malloc-pc.o
 
 tests/rtc-test$(EXESUF): tests/rtc-test.o
 tests/m48t59-test$(EXESUF): tests/m48t59-test.o
diff --git a/tests/libqos/malloc-pc.c b/tests/libqos/malloc-pc.c
new file mode 100644
index 0000000..adc36c4
--- /dev/null
+++ b/tests/libqos/malloc-pc.c
@@ -0,0 +1,71 @@
+/*
+ * libqos malloc support for PC
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "libqos/malloc-pc.h"
+#include "libqos/fw_cfg-pc.h"
+
+#define NO_QEMU_PROTOS
+#include "hw/nvram/fw_cfg.h"
+
+#include "qemu-common.h"
+#include <glib.h>
+
+#define PAGE_SIZE (4096)
+
+typedef struct PCAlloc
+{
+    QGuestAllocator alloc;
+
+    uint64_t start;
+    uint64_t end;
+} PCAlloc;
+
+static uint64_t pc_alloc(QGuestAllocator *allocator, size_t size)
+{
+    PCAlloc *s = container_of(allocator, PCAlloc, alloc);
+    uint64_t addr;
+
+
+    size += (PAGE_SIZE - 1);
+    size &= PAGE_SIZE;
+
+    g_assert_cmpint((s->start + size), <=, s->end);
+
+    addr = s->start;
+    s->start += size;
+
+    return addr;
+}
+
+static void pc_free(QGuestAllocator *allocator, uint64_t addr)
+{
+}
+
+QGuestAllocator *pc_alloc_init(void)
+{
+    PCAlloc *s = g_malloc0(sizeof(*s));
+    uint64_t ram_size;
+    QFWCFG *fw_cfg = pc_fw_cfg_init();
+
+    s->alloc.alloc = pc_alloc;
+    s->alloc.free = pc_free;
+
+    ram_size = qfw_cfg_get_u64(fw_cfg, FW_CFG_RAM_SIZE);
+
+    /* Start at 1MB */
+    s->start = 1 << 20;
+
+    /* Respect PCI hole */
+    s->end = MIN(ram_size, 0xE0000000);
+
+    return &s->alloc;
+}
diff --git a/tests/libqos/malloc-pc.h b/tests/libqos/malloc-pc.h
new file mode 100644
index 0000000..ff964ab
--- /dev/null
+++ b/tests/libqos/malloc-pc.h
@@ -0,0 +1,20 @@
+/*
+ * libqos malloc support for PC
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBQOS_MALLOC_PC_H
+#define LIBQOS_MALLOC_PC_H
+
+#include "libqos/malloc.h"
+
+QGuestAllocator *pc_alloc_init(void);
+
+#endif
diff --git a/tests/libqos/malloc.h b/tests/libqos/malloc.h
new file mode 100644
index 0000000..46f6000
--- /dev/null
+++ b/tests/libqos/malloc.h
@@ -0,0 +1,38 @@
+/*
+ * libqos malloc support
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBQOS_MALLOC_H
+#define LIBQOS_MALLOC_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+typedef struct QGuestAllocator QGuestAllocator;
+
+struct QGuestAllocator
+{
+    uint64_t (*alloc)(QGuestAllocator *allocator, size_t size);
+    void (*free)(QGuestAllocator *allocator, uint64_t addr);
+};
+
+/* Always returns page aligned values */
+static inline uint64_t guest_alloc(QGuestAllocator *allocator, size_t size)
+{
+    return allocator->alloc(allocator, size);
+}
+
+static inline void guest_free(QGuestAllocator *allocator, uint64_t addr)
+{
+    allocator->alloc(allocator, addr);
+}
+
+#endif
commit 234c69c5f92f18d7692e859d2784edb17a88873f
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 16 09:45:17 2013 -0500

    libqos: add fw_cfg support
    
    fw_cfg is needed to get the top of memory which is necessary for
    doing PCI allocation and allocating RAM for DMA.
    
    Add a PC version of fw_cfg and enough abstraction to support other
    platforms.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1366123521-4330-4-git-send-email-aliguori at us.ibm.com

diff --git a/tests/Makefile b/tests/Makefile
index 5303b29..ce91980 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -116,8 +116,8 @@ tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(
 
 tests/test-mul64$(EXESUF): tests/test-mul64.o libqemuutil.a
 
-libqos-obj-y = tests/libqos/pci.o
-libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
+libqos-obj-y = tests/libqos/pci.o tests/libqos/fw_cfg.o
+libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o tests/libqos/fw_cfg-pc.o
 
 tests/rtc-test$(EXESUF): tests/rtc-test.o
 tests/m48t59-test$(EXESUF): tests/m48t59-test.o
diff --git a/tests/libqos/fw_cfg-pc.c b/tests/libqos/fw_cfg-pc.c
new file mode 100644
index 0000000..613604d
--- /dev/null
+++ b/tests/libqos/fw_cfg-pc.c
@@ -0,0 +1,40 @@
+/*
+ * libqos fw_cfg support for PC
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "libqos/fw_cfg-pc.h"
+#include "libqtest.h"
+#include <glib.h>
+
+static void pc_fw_cfg_select(QFWCFG *fw_cfg, uint16_t key)
+{
+    outw(0x510, key);
+}
+
+static void pc_fw_cfg_read(QFWCFG *fw_cfg, void *data, size_t len)
+{
+    uint8_t *ptr = data;
+    int i;
+
+    for (i = 0; i < len; i++) {
+        ptr[i] = inb(0x511);
+    }
+}
+
+QFWCFG *pc_fw_cfg_init(void)
+{
+    QFWCFG *fw_cfg = g_malloc0(sizeof(*fw_cfg));
+
+    fw_cfg->select = pc_fw_cfg_select;
+    fw_cfg->read = pc_fw_cfg_read;
+
+    return fw_cfg;
+}
diff --git a/tests/libqos/fw_cfg-pc.h b/tests/libqos/fw_cfg-pc.h
new file mode 100644
index 0000000..444bd79
--- /dev/null
+++ b/tests/libqos/fw_cfg-pc.h
@@ -0,0 +1,20 @@
+/*
+ * libqos fw_cfg support for PC
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBQOS_FW_CFG_PC_H
+#define LIBQOS_FW_CFG_PC_H
+
+#include "libqos/fw_cfg.h"
+
+QFWCFG *pc_fw_cfg_init(void);
+
+#endif
diff --git a/tests/libqos/fw_cfg.c b/tests/libqos/fw_cfg.c
new file mode 100644
index 0000000..799139e
--- /dev/null
+++ b/tests/libqos/fw_cfg.c
@@ -0,0 +1,51 @@
+/*
+ * libqos fw_cfg support
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "libqos/fw_cfg.h"
+
+void qfw_cfg_select(QFWCFG *fw_cfg, uint16_t key)
+{
+    fw_cfg->select(fw_cfg, key);
+}
+
+void qfw_cfg_read_data(QFWCFG *fw_cfg, void *data, size_t len)
+{
+    fw_cfg->read(fw_cfg, data, len);
+}
+
+void qfw_cfg_get(QFWCFG *fw_cfg, uint16_t key, void *data, size_t len)
+{
+    qfw_cfg_select(fw_cfg, key);
+    qfw_cfg_read_data(fw_cfg, data, len);
+}
+
+uint16_t qfw_cfg_get_u16(QFWCFG *fw_cfg, uint16_t key)
+{
+    uint16_t value;
+    qfw_cfg_get(fw_cfg, key, &value, sizeof(value));
+    return value;
+}
+
+uint32_t qfw_cfg_get_u32(QFWCFG *fw_cfg, uint16_t key)
+{
+    uint32_t value;
+    qfw_cfg_get(fw_cfg, key, &value, sizeof(value));
+    return value;
+}
+
+uint64_t qfw_cfg_get_u64(QFWCFG *fw_cfg, uint16_t key)
+{
+    uint64_t value;
+    qfw_cfg_get(fw_cfg, key, &value, sizeof(value));
+    return value;
+}
+
diff --git a/tests/libqos/fw_cfg.h b/tests/libqos/fw_cfg.h
new file mode 100644
index 0000000..44fc42b
--- /dev/null
+++ b/tests/libqos/fw_cfg.h
@@ -0,0 +1,34 @@
+/*
+ * libqos fw_cfg support
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBQOS_FW_CFG_H
+#define LIBQOS_FW_CFG_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+typedef struct QFWCFG QFWCFG;
+
+struct QFWCFG
+{
+    void (*select)(QFWCFG *fw_cfg, uint16_t key);
+    void (*read)(QFWCFG *fw_cfg, void *data, size_t len);
+};
+
+void qfw_cfg_select(QFWCFG *fw_cfg, uint16_t key);
+void qfw_cfg_read_data(QFWCFG *fw_cfg, void *data, size_t len);
+void qfw_cfg_get(QFWCFG *fw_cfg, uint16_t key, void *data, size_t len);
+uint16_t qfw_cfg_get_u16(QFWCFG *fw_cfg, uint16_t key);
+uint32_t qfw_cfg_get_u32(QFWCFG *fw_cfg, uint16_t key);
+uint64_t qfw_cfg_get_u64(QFWCFG *fw_cfg, uint16_t key);
+
+#endif
commit c4efe1cada311b9dc0df5beb71c4227ff3414aa1
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 16 09:45:16 2013 -0500

    qtest: add libqos including PCI support
    
    This includes basic PCI support for the PC platform.  Enough
    abstraction should be present to support non-PC platforms too.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1366123521-4330-3-git-send-email-aliguori at us.ibm.com

diff --git a/configure b/configure
index 4c4f6f6..0fb9a93 100755
--- a/configure
+++ b/configure
@@ -4511,7 +4511,7 @@ if [ "$pixman" = "internal" ]; then
 fi
 
 # build tree in object directory in case the source is not in the current directory
-DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32"
+DIRS="tests tests/tcg tests/tcg/cris tests/tcg/lm32 tests/libqos"
 DIRS="$DIRS pc-bios/optionrom pc-bios/spapr-rtas"
 DIRS="$DIRS roms/seabios roms/vgabios"
 DIRS="$DIRS qapi-generated"
diff --git a/tests/Makefile b/tests/Makefile
index 7fa15c6..5303b29 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -77,6 +77,7 @@ test-obj-y = tests/check-qint.o tests/check-qstring.o tests/check-qdict.o \
 test-qapi-obj-y = tests/test-qapi-visit.o tests/test-qapi-types.o
 
 $(test-obj-y): QEMU_INCLUDES += -Itests
+QEMU_CFLAGS += -I$(SRC_PATH)/tests
 
 tests/test-x86-cpuid.o: QEMU_INCLUDES += -I$(SRC_PATH)/target-i386
 
@@ -105,7 +106,6 @@ tests/test-qmp-commands.h tests/test-qmp-marshal.c :\
 $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
 	$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o tests -p "test-" < $<, "  GEN   $@")
 
-
 tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
 tests/test-string-input-visitor$(EXESUF): tests/test-string-input-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
 tests/test-qmp-output-visitor$(EXESUF): tests/test-qmp-output-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a
@@ -116,6 +116,9 @@ tests/test-visitor-serialization$(EXESUF): tests/test-visitor-serialization.o $(
 
 tests/test-mul64$(EXESUF): tests/test-mul64.o libqemuutil.a
 
+libqos-obj-y = tests/libqos/pci.o
+libqos-pc-obj-y = $(libqos-obj-y) tests/libqos/pci-pc.o
+
 tests/rtc-test$(EXESUF): tests/rtc-test.o
 tests/m48t59-test$(EXESUF): tests/m48t59-test.o
 tests/fdc-test$(EXESUF): tests/fdc-test.o
diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
new file mode 100644
index 0000000..3bde8ab
--- /dev/null
+++ b/tests/libqos/pci-pc.c
@@ -0,0 +1,239 @@
+/*
+ * libqos PCI bindings for PC
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "libqtest.h"
+#include "libqos/pci-pc.h"
+
+#include "hw/pci/pci_regs.h"
+
+#include "qemu-common.h"
+#include "qemu/host-utils.h"
+
+#include <glib.h>
+
+typedef struct QPCIBusPC
+{
+    QPCIBus bus;
+
+    uint32_t pci_hole_start;
+    uint32_t pci_hole_size;
+    uint32_t pci_hole_alloc;
+
+    uint16_t pci_iohole_start;
+    uint16_t pci_iohole_size;
+    uint16_t pci_iohole_alloc;
+} QPCIBusPC;
+
+static uint8_t qpci_pc_io_readb(QPCIBus *bus, void *addr)
+{
+    uintptr_t port = (uintptr_t)addr;
+    uint8_t value;
+
+    if (port < 0x10000) {
+        value = inb(port);
+    } else {
+        memread(port, &value, sizeof(value));
+    }
+
+    return value;
+}
+
+static uint16_t qpci_pc_io_readw(QPCIBus *bus, void *addr)
+{
+    uintptr_t port = (uintptr_t)addr;
+    uint16_t value;
+
+    if (port < 0x10000) {
+        value = inw(port);
+    } else {
+        memread(port, &value, sizeof(value));
+    }
+
+    return value;
+}
+
+static uint32_t qpci_pc_io_readl(QPCIBus *bus, void *addr)
+{
+    uintptr_t port = (uintptr_t)addr;
+    uint32_t value;
+
+    if (port < 0x10000) {
+        value = inl(port);
+    } else {
+        memread(port, &value, sizeof(value));
+    }
+
+    return value;
+}
+
+static void qpci_pc_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
+{
+    uintptr_t port = (uintptr_t)addr;
+
+    if (port < 0x10000) {
+        outb(port, value);
+    } else {
+        memwrite(port, &value, sizeof(value));
+    }
+}
+
+static void qpci_pc_io_writew(QPCIBus *bus, void *addr, uint16_t value)
+{
+    uintptr_t port = (uintptr_t)addr;
+
+    if (port < 0x10000) {
+        outw(port, value);
+    } else {
+        memwrite(port, &value, sizeof(value));
+    }
+}
+
+static void qpci_pc_io_writel(QPCIBus *bus, void *addr, uint32_t value)
+{
+    uintptr_t port = (uintptr_t)addr;
+
+    if (port < 0x10000) {
+        outl(port, value);
+    } else {
+        memwrite(port, &value, sizeof(value));
+    }
+}
+
+static uint8_t qpci_pc_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
+{
+    outl(0xcf8, (1 << 31) | (devfn << 8) | offset);
+    return inb(0xcfc);
+}
+
+static uint16_t qpci_pc_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
+{
+    outl(0xcf8, (1 << 31) | (devfn << 8) | offset);
+    return inw(0xcfc);
+}
+
+static uint32_t qpci_pc_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
+{
+    outl(0xcf8, (1 << 31) | (devfn << 8) | offset);
+    return inl(0xcfc);
+}
+
+static void qpci_pc_config_writeb(QPCIBus *bus, int devfn, uint8_t offset, uint8_t value)
+{
+    outl(0xcf8, (1 << 31) | (devfn << 8) | offset);
+    outb(0xcfc, value);
+}
+
+static void qpci_pc_config_writew(QPCIBus *bus, int devfn, uint8_t offset, uint16_t value)
+{
+    outl(0xcf8, (1 << 31) | (devfn << 8) | offset);
+    outw(0xcfc, value);
+}
+
+static void qpci_pc_config_writel(QPCIBus *bus, int devfn, uint8_t offset, uint32_t value)
+{
+    outl(0xcf8, (1 << 31) | (devfn << 8) | offset);
+    outl(0xcfc, value);
+}
+
+static void *qpci_pc_iomap(QPCIBus *bus, QPCIDevice *dev, int barno)
+{
+    QPCIBusPC *s = container_of(bus, QPCIBusPC, bus);
+    static const int bar_reg_map[] = {
+        PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
+        PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
+    };
+    int bar_reg;
+    uint32_t addr;
+    uint64_t size;
+    uint32_t io_type;
+
+    g_assert(barno >= 0 && barno <= 5);
+    bar_reg = bar_reg_map[barno];
+
+    qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
+    addr = qpci_config_readl(dev, bar_reg);
+
+    io_type = addr & PCI_BASE_ADDRESS_SPACE;
+    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
+        addr &= PCI_BASE_ADDRESS_IO_MASK;
+    } else {
+        addr &= PCI_BASE_ADDRESS_MEM_MASK;
+    }
+
+    size = (1ULL << ctzl(addr));
+    if (size == 0) {
+        return NULL;
+    }
+
+    if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
+        uint16_t loc;
+
+        g_assert((s->pci_iohole_alloc + size) <= s->pci_iohole_size);
+        loc = s->pci_iohole_start + s->pci_iohole_alloc;
+        s->pci_iohole_alloc += size;
+
+        qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
+
+        return (void *)(intptr_t)loc;
+    } else {
+        uint64_t loc;
+
+        g_assert((s->pci_hole_alloc + size) <= s->pci_hole_size);
+        loc = s->pci_hole_start + s->pci_hole_alloc;
+        s->pci_hole_alloc += size;
+
+        qpci_config_writel(dev, bar_reg, loc);
+
+        return (void *)(intptr_t)loc;
+    }
+}
+
+static void qpci_pc_iounmap(QPCIBus *bus, void *data)
+{
+    /* FIXME */
+}
+
+QPCIBus *qpci_init_pc(void)
+{
+    QPCIBusPC *ret;
+
+    ret = g_malloc(sizeof(*ret));
+
+    ret->bus.io_readb = qpci_pc_io_readb;
+    ret->bus.io_readw = qpci_pc_io_readw;
+    ret->bus.io_readl = qpci_pc_io_readl;
+
+    ret->bus.io_writeb = qpci_pc_io_writeb;
+    ret->bus.io_writew = qpci_pc_io_writew;
+    ret->bus.io_writel = qpci_pc_io_writel;
+
+    ret->bus.config_readb = qpci_pc_config_readb;
+    ret->bus.config_readw = qpci_pc_config_readw;
+    ret->bus.config_readl = qpci_pc_config_readl;
+
+    ret->bus.config_writeb = qpci_pc_config_writeb;
+    ret->bus.config_writew = qpci_pc_config_writew;
+    ret->bus.config_writel = qpci_pc_config_writel;
+
+    ret->bus.iomap = qpci_pc_iomap;
+    ret->bus.iounmap = qpci_pc_iounmap;
+
+    ret->pci_hole_start = 0xE0000000;
+    ret->pci_hole_size = 0x20000000;
+    ret->pci_hole_alloc = 0;
+
+    ret->pci_iohole_start = 0xc000;
+    ret->pci_iohole_size = 0x4000;
+    ret->pci_iohole_alloc = 0;
+
+    return &ret->bus;
+}
diff --git a/tests/libqos/pci-pc.h b/tests/libqos/pci-pc.h
new file mode 100644
index 0000000..4f7475f
--- /dev/null
+++ b/tests/libqos/pci-pc.h
@@ -0,0 +1,20 @@
+/*
+ * libqos PCI bindings for PC
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBQOS_PCI_PC_H
+#define LIBQOS_PCI_PC_H
+
+#include "libqos/pci.h"
+
+QPCIBus *qpci_init_pc(void);
+
+#endif
diff --git a/tests/libqos/pci.c b/tests/libqos/pci.c
new file mode 100644
index 0000000..95e287b
--- /dev/null
+++ b/tests/libqos/pci.c
@@ -0,0 +1,151 @@
+/*
+ * libqos PCI bindings
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "libqos/pci.h"
+
+#include "hw/pci/pci_regs.h"
+#include <glib.h>
+
+#include <stdio.h>
+
+void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
+                         void (*func)(QPCIDevice *dev, int devfn, void *data),
+                         void *data)
+{
+    int slot;
+
+    for (slot = 0; slot < 32; slot++) {
+        int fn;
+
+        for (fn = 0; fn < 8; fn++) {
+            QPCIDevice *dev;
+
+            dev = qpci_device_find(bus, QPCI_DEVFN(slot, fn));
+            if (!dev) {
+                continue;
+            }
+
+            if (vendor_id != -1 &&
+                qpci_config_readw(dev, PCI_VENDOR_ID) != vendor_id) {
+                continue;
+            }
+
+            if (device_id != -1 &&
+                qpci_config_readw(dev, PCI_DEVICE_ID) != device_id) {
+                continue;
+            }
+
+            func(dev, QPCI_DEVFN(slot, fn), data);
+        }
+    }
+}
+
+QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn)
+{
+    QPCIDevice *dev;
+
+    dev = g_malloc0(sizeof(*dev));
+    dev->bus = bus;
+    dev->devfn = devfn;
+
+    if (qpci_config_readw(dev, PCI_VENDOR_ID) == 0xFFFF) {
+        g_free(dev);
+        return NULL;
+    }
+
+    return dev;
+}
+
+void qpci_device_enable(QPCIDevice *dev)
+{
+    uint16_t cmd;
+
+    /* FIXME -- does this need to be a bus callout? */
+    cmd = qpci_config_readw(dev, PCI_COMMAND);
+    cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+    qpci_config_writew(dev, PCI_COMMAND, cmd);
+}
+
+uint8_t qpci_config_readb(QPCIDevice *dev, uint8_t offset)
+{
+    return dev->bus->config_readb(dev->bus, dev->devfn, offset);
+}
+
+uint16_t qpci_config_readw(QPCIDevice *dev, uint8_t offset)
+{
+    return dev->bus->config_readw(dev->bus, dev->devfn, offset);
+}
+
+uint32_t qpci_config_readl(QPCIDevice *dev, uint8_t offset)
+{
+    return dev->bus->config_readl(dev->bus, dev->devfn, offset);
+}
+
+
+void qpci_config_writeb(QPCIDevice *dev, uint8_t offset, uint8_t value)
+{
+    dev->bus->config_writeb(dev->bus, dev->devfn, offset, value);
+}
+
+void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value)
+{
+    dev->bus->config_writew(dev->bus, dev->devfn, offset, value);
+}
+
+void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value)
+{
+    dev->bus->config_writew(dev->bus, dev->devfn, offset, value);
+}
+
+
+uint8_t qpci_io_readb(QPCIDevice *dev, void *data)
+{
+    return dev->bus->io_readb(dev->bus, data);
+}
+
+uint16_t qpci_io_readw(QPCIDevice *dev, void *data)
+{
+    return dev->bus->io_readw(dev->bus, data);
+}
+
+uint32_t qpci_io_readl(QPCIDevice *dev, void *data)
+{
+    return dev->bus->io_readl(dev->bus, data);
+}
+
+
+void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value)
+{
+    dev->bus->io_writeb(dev->bus, data, value);
+}
+
+void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value)
+{
+    dev->bus->io_writew(dev->bus, data, value);
+}
+
+void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value)
+{
+    dev->bus->io_writel(dev->bus, data, value);
+}
+
+void *qpci_iomap(QPCIDevice *dev, int barno)
+{
+    return dev->bus->iomap(dev->bus, dev, barno);
+}
+
+void qpci_iounmap(QPCIDevice *dev, void *data)
+{
+    dev->bus->iounmap(dev->bus, data);
+}
+
+
diff --git a/tests/libqos/pci.h b/tests/libqos/pci.h
new file mode 100644
index 0000000..3439431
--- /dev/null
+++ b/tests/libqos/pci.h
@@ -0,0 +1,80 @@
+/*
+ * libqos PCI bindings
+ *
+ * Copyright IBM, Corp. 2012-2013
+ *
+ * Authors:
+ *  Anthony Liguori   <aliguori at us.ibm.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef LIBQOS_PCI_H
+#define LIBQOS_PCI_H
+
+#include <stdint.h>
+
+#define QPCI_DEVFN(dev, fn) (((dev) << 3) | (fn))
+
+typedef struct QPCIDevice QPCIDevice;
+typedef struct QPCIBus QPCIBus;
+
+struct QPCIBus
+{
+    uint8_t (*io_readb)(QPCIBus *bus, void *addr);
+    uint16_t (*io_readw)(QPCIBus *bus, void *addr);
+    uint32_t (*io_readl)(QPCIBus *bus, void *addr);
+
+    void (*io_writeb)(QPCIBus *bus, void *addr, uint8_t value);
+    void (*io_writew)(QPCIBus *bus, void *addr, uint16_t value);
+    void (*io_writel)(QPCIBus *bus, void *addr, uint32_t value);
+
+    uint8_t (*config_readb)(QPCIBus *bus, int devfn, uint8_t offset);
+    uint16_t (*config_readw)(QPCIBus *bus, int devfn, uint8_t offset);
+    uint32_t (*config_readl)(QPCIBus *bus, int devfn, uint8_t offset);
+
+    void (*config_writeb)(QPCIBus *bus, int devfn,
+                          uint8_t offset, uint8_t value);
+    void (*config_writew)(QPCIBus *bus, int devfn,
+                          uint8_t offset, uint16_t value);
+    void (*config_writel)(QPCIBus *bus, int devfn,
+                          uint8_t offset, uint32_t value);
+
+    void *(*iomap)(QPCIBus *bus, QPCIDevice *dev, int barno);
+    void (*iounmap)(QPCIBus *bus, void *data);
+};
+
+struct QPCIDevice
+{
+    QPCIBus *bus;
+    int devfn;
+};
+
+void qpci_device_foreach(QPCIBus *bus, int vendor_id, int device_id,
+                         void (*func)(QPCIDevice *dev, int devfn, void *data),
+                         void *data);
+QPCIDevice *qpci_device_find(QPCIBus *bus, int devfn);
+
+void qpci_device_enable(QPCIDevice *dev);
+
+uint8_t qpci_config_readb(QPCIDevice *dev, uint8_t offset);
+uint16_t qpci_config_readw(QPCIDevice *dev, uint8_t offset);
+uint32_t qpci_config_readl(QPCIDevice *dev, uint8_t offset);
+
+void qpci_config_writeb(QPCIDevice *dev, uint8_t offset, uint8_t value);
+void qpci_config_writew(QPCIDevice *dev, uint8_t offset, uint16_t value);
+void qpci_config_writel(QPCIDevice *dev, uint8_t offset, uint32_t value);
+
+uint8_t qpci_io_readb(QPCIDevice *dev, void *data);
+uint16_t qpci_io_readw(QPCIDevice *dev, void *data);
+uint32_t qpci_io_readl(QPCIDevice *dev, void *data);
+
+void qpci_io_writeb(QPCIDevice *dev, void *data, uint8_t value);
+void qpci_io_writew(QPCIDevice *dev, void *data, uint16_t value);
+void qpci_io_writel(QPCIDevice *dev, void *data, uint32_t value);
+
+void *qpci_iomap(QPCIDevice *dev, int barno);
+void qpci_iounmap(QPCIDevice *dev, void *data);
+
+#endif
commit 8a8fd63734944bf6f7111596bd9cc9db6afb9b7c
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Tue Apr 16 09:45:15 2013 -0500

    qtest: don't use system command to avoid double fork
    
    Currently we waitpid on the child process we spawn off that does
    nothing more than system() another process.  While this does not
    appear to be incorrect, it's wasteful and confusing so get rid of
    it.
    
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>
    Message-id: 1366123521-4330-2-git-send-email-aliguori at us.ibm.com

diff --git a/tests/libqtest.c b/tests/libqtest.c
index 389596a..884f959 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -107,7 +107,7 @@ static pid_t qtest_qemu_pid(QTestState *s)
 QTestState *qtest_init(const char *extra_args)
 {
     QTestState *s;
-    int sock, qmpsock, ret, i;
+    int sock, qmpsock, i;
     gchar *pid_file;
     gchar *command;
     const char *qemu_binary;
@@ -136,10 +136,8 @@ QTestState *qtest_init(const char *extra_args)
                                   "%s", qemu_binary, s->socket_path,
                                   s->qmp_socket_path, pid_file,
                                   extra_args ?: "");
-
-        ret = system(command);
-        exit(ret);
-        g_free(command);
+        execlp("/bin/sh", "sh", "-c", command, NULL);
+        exit(1);
     }
 
     s->fd = socket_accept(sock);
@@ -169,9 +167,8 @@ void qtest_quit(QTestState *s)
 
     pid_t pid = qtest_qemu_pid(s);
     if (pid != -1) {
-        /* kill QEMU, but wait for the child created by us to run system() */
         kill(pid, SIGTERM);
-        waitpid(s->child_pid, &status, 0);
+        waitpid(pid, &status, 0);
     }
 
     unlink(s->pid_file);
commit 4aead69241e010c3cda624084e3872aa9f7dcaef
Author: Eric Blake <eblake at redhat.com>
Date:   Tue Apr 16 15:50:41 2013 -0600

    migration: reflect incoming failure to shell
    
    Management apps like libvirt don't know to pay attention to
    stderr unless there is a non-zero exit status.
    
    * migration.c (process_incoming_migration_co): Exit with non-zero
    status on failure.
    
    Signed-off-by: Eric Blake <eblake at redhat.com>
    Message-id: 1366149041-626-1-git-send-email-eblake at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/migration.c b/migration.c
index 3b4b467..3eb0fad 100644
--- a/migration.c
+++ b/migration.c
@@ -99,7 +99,7 @@ static void process_incoming_migration_co(void *opaque)
     qemu_fclose(f);
     if (ret < 0) {
         fprintf(stderr, "load of migration failed\n");
-        exit(0);
+        exit(EXIT_FAILURE);
     }
     qemu_announce_self();
     DPRINTF("successfully loaded vm state\n");
commit 95e2af98d4edb59780e47da2085ea9133f6466bb
Author: Alexey Kardashevskiy <aik at ozlabs.ru>
Date:   Wed Apr 17 17:49:00 2013 +1000

    qbus: remove wrong error messages
    
    The existing code shows the "Bus '%s' is full" message even if name
    is specified and different from bus->name (i.e. match=0).
    
    The patch excludes unnecessary error message.
    
    Signed-off-by: Alexey Kardashevskiy <aik at ozlabs.ru>
    Message-id: 1366184940-13516-1-git-send-email-aik at ozlabs.ru
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/qdev-monitor.c b/qdev-monitor.c
index 73d7946..2cb5600 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -292,11 +292,9 @@ static BusState *qbus_find_recursive(BusState *bus, const char *name,
 
     if (name && (strcmp(bus->name, name) != 0)) {
         match = 0;
-    }
-    if (bus_typename && !object_dynamic_cast(OBJECT(bus), bus_typename)) {
+    } else if (bus_typename && !object_dynamic_cast(OBJECT(bus), bus_typename)) {
         match = 0;
-    }
-    if ((bus_class->max_dev != 0) && (bus_class->max_dev <= bus->max_index)) {
+    } else if ((bus_class->max_dev != 0) && (bus_class->max_dev <= bus->max_index)) {
         if (name != NULL) {
             /* bus was explicitly specified: return an error. */
             qerror_report(ERROR_CLASS_GENERIC_ERROR, "Bus '%s' is full",
commit bd5ac20325ed67eb8f1af719d76aad6ad80e5697
Author: Lei Li <lilei at linux.vnet.ibm.com>
Date:   Wed Apr 17 16:46:54 2013 +0800

    chardev: remove the headers of Memory chardev driver
    
    Memory chardev driver is no longer used, and Commit:
    4bf0bb8014ac2ac61b1004f5d92b2a4594d48017 has droped
    it but the headers, so clean it up.
    
    Signed-off-by: Lei Li <lilei at linux.vnet.ibm.com>
    Message-id: 1366188414-24214-1-git-send-email-lilei at linux.vnet.ibm.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index 9d1ea46..5e42c90 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -289,12 +289,6 @@ CharDriverState *qemu_chr_open_eventfd(int eventfd);
 
 extern int term_escape_char;
 
-/* memory chardev */
-void qemu_chr_init_mem(CharDriverState *chr);
-void qemu_chr_close_mem(CharDriverState *chr);
-QString *qemu_chr_mem_to_qs(CharDriverState *chr);
-size_t qemu_chr_mem_osize(const CharDriverState *chr);
-
 CharDriverState *qemu_char_get_next_serial(void);
 
 /* msmouse */
commit 20781f9c0057bc00cc74b684b3dc57730cdf83f0
Merge: e0a83fc e9d8fbf
Author: Anthony Liguori <aliguori at us.ibm.com>
Date:   Wed Apr 17 10:14:07 2013 -0500

    Merge remote-tracking branch 'bonzini/migration-writev' into staging
    
    # By Paolo Bonzini
    # Via Paolo Bonzini
    * bonzini/migration-writev:
      qemu-file: do not use stdio for qemu_fdopen
      iov: handle partial writes from sendmsg and recvmsg
      iov: reorganize iov_send_recv, part 3
      iov: reorganize iov_send_recv, part 2
      iov: reorganize iov_send_recv, part 1
      qemu-file: drop socket_put_buffer
    
    Message-id: 1366192012-14872-1-git-send-email-pbonzini at redhat.com
    Signed-off-by: Anthony Liguori <aliguori at us.ibm.com>

commit e9d8fbf53a33983c81d67d18e1baa914eb16cdea
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 27 17:36:32 2013 +0100

    qemu-file: do not use stdio for qemu_fdopen
    
    This uses system calls directly for Unix file descriptors, so that the
    efficient writev_buffer can be used.  Pay attention to the possibility
    of partial writes in writev.
    
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wassermann <owasserm at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/savevm.c b/savevm.c
index ffabbff..31dcce9 100644
--- a/savevm.c
+++ b/savevm.c
@@ -356,9 +356,94 @@ static const QEMUFileOps stdio_file_write_ops = {
     .close =      stdio_fclose
 };
 
+static ssize_t unix_writev_buffer(void *opaque, struct iovec *iov, int iovcnt,
+                                  int64_t pos)
+{
+    QEMUFileSocket *s = opaque;
+    ssize_t len, offset;
+    ssize_t size = iov_size(iov, iovcnt);
+    ssize_t total = 0;
+
+    assert(iovcnt > 0);
+    offset = 0;
+    while (size > 0) {
+        /* Find the next start position; skip all full-sized vector elements  */
+        while (offset >= iov[0].iov_len) {
+            offset -= iov[0].iov_len;
+            iov++, iovcnt--;
+        }
+
+        /* skip `offset' bytes from the (now) first element, undo it on exit */
+        assert(iovcnt > 0);
+        iov[0].iov_base += offset;
+        iov[0].iov_len -= offset;
+
+        do {
+            len = writev(s->fd, iov, iovcnt);
+        } while (len == -1 && errno == EINTR);
+        if (len == -1) {
+            return -errno;
+        }
+
+        /* Undo the changes above */
+        iov[0].iov_base -= offset;
+        iov[0].iov_len += offset;
+
+        /* Prepare for the next iteration */
+        offset += len;
+        total += len;
+        size -= len;
+    }
+
+    return total;
+}
+
+static int unix_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
+{
+    QEMUFileSocket *s = opaque;
+    ssize_t len;
+
+    for (;;) {
+        len = read(s->fd, buf, size);
+        if (len != -1) {
+            break;
+        }
+        if (errno == EAGAIN) {
+            yield_until_fd_readable(s->fd);
+        } else if (errno != EINTR) {
+            break;
+        }
+    }
+
+    if (len == -1) {
+        len = -errno;
+    }
+    return len;
+}
+
+static int unix_close(void *opaque)
+{
+    QEMUFileSocket *s = opaque;
+    close(s->fd);
+    g_free(s);
+    return 0;
+}
+
+static const QEMUFileOps unix_read_ops = {
+    .get_fd =     socket_get_fd,
+    .get_buffer = unix_get_buffer,
+    .close =      unix_close
+};
+
+static const QEMUFileOps unix_write_ops = {
+    .get_fd =     socket_get_fd,
+    .writev_buffer = unix_writev_buffer,
+    .close =      unix_close
+};
+
 QEMUFile *qemu_fdopen(int fd, const char *mode)
 {
-    QEMUFileStdio *s;
+    QEMUFileSocket *s;
 
     if (mode == NULL ||
 	(mode[0] != 'r' && mode[0] != 'w') ||
@@ -367,21 +452,15 @@ QEMUFile *qemu_fdopen(int fd, const char *mode)
         return NULL;
     }
 
-    s = g_malloc0(sizeof(QEMUFileStdio));
-    s->stdio_file = fdopen(fd, mode);
-    if (!s->stdio_file)
-        goto fail;
+    s = g_malloc0(sizeof(QEMUFileSocket));
+    s->fd = fd;
 
     if(mode[0] == 'r') {
-        s->file = qemu_fopen_ops(s, &stdio_file_read_ops);
+        s->file = qemu_fopen_ops(s, &unix_read_ops);
     } else {
-        s->file = qemu_fopen_ops(s, &stdio_file_write_ops);
+        s->file = qemu_fopen_ops(s, &unix_write_ops);
     }
     return s->file;
-
-fail:
-    g_free(s);
-    return NULL;
 }
 
 static const QEMUFileOps socket_read_ops = {
commit 83f75c26e8e791311900d0e2a4cc9379abedb85c
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 27 17:36:31 2013 +0100

    iov: handle partial writes from sendmsg and recvmsg
    
    Partial writes can still happen in sendmsg and recvmsg, if a
    signal is received in the middle of a write.  To handle this,
    retry the operation with a new offset/bytes pair.
    
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wassermann <owasserm at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/util/iov.c b/util/iov.c
index f14ff0b..d32226d 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -144,63 +144,71 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
                       size_t offset, size_t bytes,
                       bool do_send)
 {
+    ssize_t total = 0;
     ssize_t ret;
     size_t orig_len, tail;
     unsigned niov;
 
-    if (bytes == 0) {
-        /* Catch the do-nothing case early, as otherwise we will pass an
-         * empty iovec to sendmsg/recvmsg(), and not all implementations
-         * accept this.
-         */
-        return 0;
-    }
-
-    /* Find the start position, skipping `offset' bytes:
-     * first, skip all full-sized vector elements, */
-    for (niov = 0; niov < iov_cnt && offset >= iov[niov].iov_len; ++niov) {
-        offset -= iov[niov].iov_len;
-    }
+    while (bytes > 0) {
+        /* Find the start position, skipping `offset' bytes:
+         * first, skip all full-sized vector elements, */
+        for (niov = 0; niov < iov_cnt && offset >= iov[niov].iov_len; ++niov) {
+            offset -= iov[niov].iov_len;
+        }
 
-    /* niov == iov_cnt would only be valid if bytes == 0, which
-     * we already ruled out above.  */
-    assert(niov < iov_cnt);
-    iov += niov;
-    iov_cnt -= niov;
-
-    if (offset) {
-        /* second, skip `offset' bytes from the (now) first element,
-         * undo it on exit */
-        iov[0].iov_base += offset;
-        iov[0].iov_len -= offset;
-    }
-    /* Find the end position skipping `bytes' bytes: */
-    /* first, skip all full-sized elements */
-    tail = bytes;
-    for (niov = 0; niov < iov_cnt && iov[niov].iov_len <= tail; ++niov) {
-        tail -= iov[niov].iov_len;
-    }
-    if (tail) {
-        /* second, fixup the last element, and remember the original
-         * length */
+        /* niov == iov_cnt would only be valid if bytes == 0, which
+         * we already ruled out in the loop condition.  */
         assert(niov < iov_cnt);
-        assert(iov[niov].iov_len > tail);
-        orig_len = iov[niov].iov_len;
-        iov[niov++].iov_len = tail;
-    }
+        iov += niov;
+        iov_cnt -= niov;
+
+        if (offset) {
+            /* second, skip `offset' bytes from the (now) first element,
+             * undo it on exit */
+            iov[0].iov_base += offset;
+            iov[0].iov_len -= offset;
+        }
+        /* Find the end position skipping `bytes' bytes: */
+        /* first, skip all full-sized elements */
+        tail = bytes;
+        for (niov = 0; niov < iov_cnt && iov[niov].iov_len <= tail; ++niov) {
+            tail -= iov[niov].iov_len;
+        }
+        if (tail) {
+            /* second, fixup the last element, and remember the original
+             * length */
+            assert(niov < iov_cnt);
+            assert(iov[niov].iov_len > tail);
+            orig_len = iov[niov].iov_len;
+            iov[niov++].iov_len = tail;
+        }
 
-    ret = do_send_recv(sockfd, iov, niov, do_send);
+        ret = do_send_recv(sockfd, iov, niov, do_send);
 
-    /* Undo the changes above */
-    if (tail) {
-        iov[niov-1].iov_len = orig_len;
-    }
-    if (offset) {
-        iov[0].iov_base -= offset;
-        iov[0].iov_len += offset;
+        /* Undo the changes above before checking for errors */
+        if (tail) {
+            iov[niov-1].iov_len = orig_len;
+        }
+        if (offset) {
+            iov[0].iov_base -= offset;
+            iov[0].iov_len += offset;
+        }
+
+        if (ret < 0) {
+            assert(errno != EINTR);
+            if (errno == EAGAIN && total > 0) {
+                return total;
+            }
+            return -1;
+        }
+
+        /* Prepare for the next iteration */
+        offset += ret;
+        total += ret;
+        bytes -= ret;
     }
 
-    return ret;
+    return total;
 }
 
 
commit f48869ad2825b640911666bb091cedb1e1d6ad5e
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 27 17:36:30 2013 +0100

    iov: reorganize iov_send_recv, part 3
    
    "si" and "ei" are merged in a single variable.
    
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wassermann <owasserm at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/util/iov.c b/util/iov.c
index 110d18e..f14ff0b 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -146,7 +146,7 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
 {
     ssize_t ret;
     size_t orig_len, tail;
-    unsigned si, ei;            /* start and end indexes */
+    unsigned niov;
 
     if (bytes == 0) {
         /* Catch the do-nothing case early, as otherwise we will pass an
@@ -158,15 +158,15 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
 
     /* Find the start position, skipping `offset' bytes:
      * first, skip all full-sized vector elements, */
-    for (si = 0; si < iov_cnt && offset >= iov[si].iov_len; ++si) {
-        offset -= iov[si].iov_len;
+    for (niov = 0; niov < iov_cnt && offset >= iov[niov].iov_len; ++niov) {
+        offset -= iov[niov].iov_len;
     }
 
-    /* si == iov_cnt would only be valid if bytes == 0, which
+    /* niov == iov_cnt would only be valid if bytes == 0, which
      * we already ruled out above.  */
-    assert(si < iov_cnt);
-    iov += si;
-    iov_cnt -= si;
+    assert(niov < iov_cnt);
+    iov += niov;
+    iov_cnt -= niov;
 
     if (offset) {
         /* second, skip `offset' bytes from the (now) first element,
@@ -177,23 +177,23 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
     /* Find the end position skipping `bytes' bytes: */
     /* first, skip all full-sized elements */
     tail = bytes;
-    for (ei = 0; ei < iov_cnt && iov[ei].iov_len <= tail; ++ei) {
-        tail -= iov[ei].iov_len;
+    for (niov = 0; niov < iov_cnt && iov[niov].iov_len <= tail; ++niov) {
+        tail -= iov[niov].iov_len;
     }
     if (tail) {
         /* second, fixup the last element, and remember the original
          * length */
-        assert(ei < iov_cnt);
-        assert(iov[ei].iov_len > tail);
-        orig_len = iov[ei].iov_len;
-        iov[ei++].iov_len = tail;
+        assert(niov < iov_cnt);
+        assert(iov[niov].iov_len > tail);
+        orig_len = iov[niov].iov_len;
+        iov[niov++].iov_len = tail;
     }
 
-    ret = do_send_recv(sockfd, iov, ei, do_send);
+    ret = do_send_recv(sockfd, iov, niov, do_send);
 
     /* Undo the changes above */
     if (tail) {
-        iov[ei-1].iov_len = orig_len;
+        iov[niov-1].iov_len = orig_len;
     }
     if (offset) {
         iov[0].iov_base -= offset;
commit 5209d6753c90a3d6411abd0729a9cca3775dce3f
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 27 17:36:29 2013 +0100

    iov: reorganize iov_send_recv, part 2
    
    Do not touch the "bytes" argument anymore.  Instead, remember the
    original length of the last iovec if we touch it, and restore it
    afterwards.
    
    This requires undoing the changes in opposite order.  The previous
    algorithm didn't care.
    
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wassermann <owasserm at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/util/iov.c b/util/iov.c
index adb9a70..110d18e 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -145,7 +145,9 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
                       bool do_send)
 {
     ssize_t ret;
+    size_t orig_len, tail;
     unsigned si, ei;            /* start and end indexes */
+
     if (bytes == 0) {
         /* Catch the do-nothing case early, as otherwise we will pass an
          * empty iovec to sendmsg/recvmsg(), and not all implementations
@@ -174,31 +176,29 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
     }
     /* Find the end position skipping `bytes' bytes: */
     /* first, skip all full-sized elements */
-    for (ei = 0; ei < iov_cnt && iov[ei].iov_len <= bytes; ++ei) {
-        bytes -= iov[ei].iov_len;
+    tail = bytes;
+    for (ei = 0; ei < iov_cnt && iov[ei].iov_len <= tail; ++ei) {
+        tail -= iov[ei].iov_len;
     }
-    if (bytes) {
-        /* second, fixup the last element, and remember
-         * the length we've cut from the end of it in `bytes' */
-        size_t tail;
+    if (tail) {
+        /* second, fixup the last element, and remember the original
+         * length */
         assert(ei < iov_cnt);
-        assert(iov[ei].iov_len > bytes);
-        tail = iov[ei].iov_len - bytes;
-        iov[ei].iov_len = bytes;
-        bytes = tail;  /* bytes is now equal to the tail size */
-        ++ei;
+        assert(iov[ei].iov_len > tail);
+        orig_len = iov[ei].iov_len;
+        iov[ei++].iov_len = tail;
     }
 
     ret = do_send_recv(sockfd, iov, ei, do_send);
 
     /* Undo the changes above */
+    if (tail) {
+        iov[ei-1].iov_len = orig_len;
+    }
     if (offset) {
         iov[0].iov_base -= offset;
         iov[0].iov_len += offset;
     }
-    if (bytes) {
-        iov[ei-1].iov_len += bytes;
-    }
 
     return ret;
 }
commit cb6247a7e3e07ead908d2e7fbc8848cc2e135056
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 27 17:36:28 2013 +0100

    iov: reorganize iov_send_recv, part 1
    
    Once the initial part of the iov is dropped, it is not used anymore.
    Modify iov/iovcnt directly instead of adjusting them with the "si"
    variable.
    
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wassermann <owasserm at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/util/iov.c b/util/iov.c
index 9dae318..adb9a70 100644
--- a/util/iov.c
+++ b/util/iov.c
@@ -159,16 +159,22 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
     for (si = 0; si < iov_cnt && offset >= iov[si].iov_len; ++si) {
         offset -= iov[si].iov_len;
     }
+
+    /* si == iov_cnt would only be valid if bytes == 0, which
+     * we already ruled out above.  */
+    assert(si < iov_cnt);
+    iov += si;
+    iov_cnt -= si;
+
     if (offset) {
-        assert(si < iov_cnt);
         /* second, skip `offset' bytes from the (now) first element,
          * undo it on exit */
-        iov[si].iov_base += offset;
-        iov[si].iov_len -= offset;
+        iov[0].iov_base += offset;
+        iov[0].iov_len -= offset;
     }
     /* Find the end position skipping `bytes' bytes: */
     /* first, skip all full-sized elements */
-    for (ei = si; ei < iov_cnt && iov[ei].iov_len <= bytes; ++ei) {
+    for (ei = 0; ei < iov_cnt && iov[ei].iov_len <= bytes; ++ei) {
         bytes -= iov[ei].iov_len;
     }
     if (bytes) {
@@ -183,12 +189,12 @@ ssize_t iov_send_recv(int sockfd, struct iovec *iov, unsigned iov_cnt,
         ++ei;
     }
 
-    ret = do_send_recv(sockfd, iov + si, ei - si, do_send);
+    ret = do_send_recv(sockfd, iov, ei, do_send);
 
     /* Undo the changes above */
     if (offset) {
-        iov[si].iov_base -= offset;
-        iov[si].iov_len += offset;
+        iov[0].iov_base -= offset;
+        iov[0].iov_len += offset;
     }
     if (bytes) {
         iov[ei-1].iov_len += bytes;
commit 15711565f66de53c22c3a9faee04fc2092409ce4
Author: Paolo Bonzini <pbonzini at redhat.com>
Date:   Wed Mar 27 17:36:27 2013 +0100

    qemu-file: drop socket_put_buffer
    
    It is enough to implement one of socket_writev_buffer and
    socket_put_buffer.
    
    Reviewed-by: Juan Quintela <quintela at redhat.com>
    Reviewed-by: Orit Wassermann <owasserm at redhat.com>
    Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>

diff --git a/savevm.c b/savevm.c
index 53515cb..ffabbff 100644
--- a/savevm.c
+++ b/savevm.c
@@ -219,18 +219,6 @@ static int socket_get_buffer(void *opaque, uint8_t *buf, int64_t pos, int size)
     return len;
 }
 
-static int socket_put_buffer(void *opaque, const uint8_t *buf, int64_t pos, int size)
-{
-    QEMUFileSocket *s = opaque;
-    ssize_t len;
-
-    len = qemu_send_full(s->fd, buf, size, 0);
-    if (len < size) {
-        len = -socket_error();
-    }
-    return len;
-}
-
 static int socket_close(void *opaque)
 {
     QEMUFileSocket *s = opaque;
@@ -404,7 +392,6 @@ static const QEMUFileOps socket_read_ops = {
 
 static const QEMUFileOps socket_write_ops = {
     .get_fd =     socket_get_fd,
-    .put_buffer = socket_put_buffer,
     .writev_buffer = socket_writev_buffer,
     .close =      socket_close
 };


More information about the Spice-commits mailing list