Commit 9328cfd2 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging



pc,vhost,virtio fixes, enhancements

virtio bi-endian support
new command to resync RTC
misc bugfixes and cleanups

Signed-off-by: default avatarMichael S. Tsirkin <mst@redhat.com>

# gpg: Signature made Sun 29 Jun 2014 17:41:13 BST using RSA key ID D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"

* remotes/mst/tags/for_upstream: (37 commits)
  tests: add human format test for string output visitor
  vhost-net: disable when cross-endian
  target-ppc: enable virtio endian ambivalent support
  virtio-9p: use virtio wrappers to access headers
  virtio-serial-bus: use virtio wrappers to access headers
  virtio-scsi: use virtio wrappers to access headers
  virtio-blk: use virtio wrappers to access headers
  virtio-balloon: use virtio wrappers to access page frame numbers
  virtio-net: use virtio wrappers to access headers
  virtio: allow byte swapping for vring
  virtio: memory accessors for endian-ambivalent targets
  virtio: add endian-ambivalent support to VirtIODevice
  cpu: introduce CPUClass::virtio_is_big_endian()
  exec: introduce target_words_bigendian() helper
  virtio: add subsections to the migration stream
  virtio-rng: implement per-device migration calls
  virtio-balloon: implement per-device migration calls
  virtio-serial: implement per-device migration calls
  virtio-blk: implement per-device migration calls
  virtio-net: implement per-device migration calls
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 4f9c5be9 b4900c0e
Loading
Loading
Loading
Loading
+18 −18
Original line number Diff line number Diff line
@@ -78,14 +78,14 @@ Depending on the request type, payload can be:
   Padding: 32-bit

   A region is:
   ---------------------------------------
   | guest address | size | user address |
   ---------------------------------------
   -----------------------------------------------------
   | guest address | size | user address | mmap offset |
   -----------------------------------------------------

   Guest address: a 64-bit guest address of the region
   Size: a 64-bit size
   User address: a 64-bit user address

   mmap offset: 64-bit offset where region starts in the mapped memory

In QEMU the vhost-user message is implemented with the following struct:

@@ -132,7 +132,7 @@ Message types

 * VHOST_USER_GET_FEATURES

      Id: 2
      Id: 1
      Equivalent ioctl: VHOST_GET_FEATURES
      Master payload: N/A
      Slave payload: u64
@@ -141,7 +141,7 @@ Message types

 * VHOST_USER_SET_FEATURES

      Id: 3
      Id: 2
      Ioctl: VHOST_SET_FEATURES
      Master payload: u64

@@ -149,7 +149,7 @@ Message types

 * VHOST_USER_SET_OWNER

      Id: 4
      Id: 3
      Equivalent ioctl: VHOST_SET_OWNER
      Master payload: N/A

@@ -159,7 +159,7 @@ Message types

 * VHOST_USER_RESET_OWNER

      Id: 5
      Id: 4
      Equivalent ioctl: VHOST_RESET_OWNER
      Master payload: N/A

@@ -168,7 +168,7 @@ Message types

 * VHOST_USER_SET_MEM_TABLE

      Id: 6
      Id: 5
      Equivalent ioctl: VHOST_SET_MEM_TABLE
      Master payload: memory regions description

@@ -179,7 +179,7 @@ Message types

 * VHOST_USER_SET_LOG_BASE

      Id: 7
      Id: 6
      Equivalent ioctl: VHOST_SET_LOG_BASE
      Master payload: u64

@@ -187,7 +187,7 @@ Message types

 * VHOST_USER_SET_LOG_FD

      Id: 8
      Id: 7
      Equivalent ioctl: VHOST_SET_LOG_FD
      Master payload: N/A

@@ -195,7 +195,7 @@ Message types

 * VHOST_USER_SET_VRING_NUM

      Id: 9
      Id: 8
      Equivalent ioctl: VHOST_SET_VRING_NUM
      Master payload: vring state description

@@ -203,7 +203,7 @@ Message types

 * VHOST_USER_SET_VRING_ADDR

      Id: 10
      Id: 9
      Equivalent ioctl: VHOST_SET_VRING_ADDR
      Master payload: vring address description
      Slave payload: N/A
@@ -212,7 +212,7 @@ Message types

 * VHOST_USER_SET_VRING_BASE

      Id: 11
      Id: 10
      Equivalent ioctl: VHOST_SET_VRING_BASE
      Master payload: vring state description

@@ -220,7 +220,7 @@ Message types

 * VHOST_USER_GET_VRING_BASE

      Id: 12
      Id: 11
      Equivalent ioctl: VHOST_USER_GET_VRING_BASE
      Master payload: vring state description
      Slave payload: vring state description
@@ -229,7 +229,7 @@ Message types

 * VHOST_USER_SET_VRING_KICK

      Id: 13
      Id: 12
      Equivalent ioctl: VHOST_SET_VRING_KICK
      Master payload: u64

@@ -242,7 +242,7 @@ Message types

 * VHOST_USER_SET_VRING_CALL

      Id: 14
      Id: 13
      Equivalent ioctl: VHOST_SET_VRING_CALL
      Master payload: u64

@@ -255,7 +255,7 @@ Message types

 * VHOST_USER_SET_VRING_ERR

      Id: 15
      Id: 14
      Equivalent ioctl: VHOST_SET_VRING_ERR
      Master payload: u64

+9 −6
Original line number Diff line number Diff line
@@ -1456,6 +1456,13 @@ int qemu_get_ram_fd(ram_addr_t addr)
    return block->fd;
}

void *qemu_get_ram_block_host_ptr(ram_addr_t addr)
{
    RAMBlock *block = qemu_get_ram_block(addr);

    return block->host;
}

/* Return a host pointer to ram allocated with qemu_ram_alloc.
   With the exception of the softmmu code in this file, this should
   only be used for local memory (e.g. video ram) that the device owns,
@@ -2752,14 +2759,12 @@ int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
}
#endif

#if !defined(CONFIG_USER_ONLY)

/*
 * A helper function for the _utterly broken_ virtio device model to find out if
 * it's running on a big endian machine. Don't do this at home kids!
 */
bool virtio_is_big_endian(void);
bool virtio_is_big_endian(void)
bool target_words_bigendian(void);
bool target_words_bigendian(void)
{
#if defined(TARGET_WORDS_BIGENDIAN)
    return true;
@@ -2768,8 +2773,6 @@ bool virtio_is_big_endian(void)
#endif
}

#endif

#ifndef CONFIG_USER_ONLY
bool cpu_physical_memory_is_io(hwaddr phys_addr)
{
+2 −1
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@
#include "fsdev/qemu-fsdev.h"
#include "virtio-9p-xattr.h"
#include "virtio-9p-coth.h"
#include "hw/virtio/virtio-access.h"

static uint32_t virtio_9p_get_features(VirtIODevice *vdev, uint32_t features)
{
@@ -34,7 +35,7 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)

    len = strlen(s->tag);
    cfg = g_malloc0(sizeof(struct virtio_9p_config) + len);
    stw_p(&cfg->tag_len, len);
    virtio_stw_p(vdev, &cfg->tag_len, len);
    /* We don't copy the terminating null to config space */
    memcpy(cfg->tag, s->tag, len);
    memcpy(config, cfg, s->config_size);
+37 −25
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
# include <scsi/sg.h>
#endif
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"

static VirtIOBlockReq *virtio_blk_alloc_request(VirtIOBlock *s)
{
@@ -88,7 +89,8 @@ static void virtio_blk_rw_complete(void *opaque, int ret)
    trace_virtio_blk_rw_complete(req, ret);

    if (ret) {
        bool is_read = !(ldl_p(&req->out.type) & VIRTIO_BLK_T_OUT);
        int p = virtio_ldl_p(VIRTIO_DEVICE(req->dev), &req->out.type);
        bool is_read = !(p & VIRTIO_BLK_T_OUT);
        if (virtio_blk_handle_rw_error(req, -ret, is_read))
            return;
    }
@@ -130,6 +132,8 @@ int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
{
    int status = VIRTIO_BLK_S_OK;
    struct virtio_scsi_inhdr *scsi = NULL;
    VirtIODevice *vdev = VIRTIO_DEVICE(blk);

#ifdef __linux__
    int i;
    struct sg_io_hdr hdr;
@@ -224,12 +228,12 @@ int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
        hdr.status = CHECK_CONDITION;
    }

    stl_p(&scsi->errors,
    virtio_stl_p(vdev, &scsi->errors,
                 hdr.status | (hdr.msg_status << 8) |
                 (hdr.host_status << 16) | (hdr.driver_status << 24));
    stl_p(&scsi->residual, hdr.resid);
    stl_p(&scsi->sense_len, hdr.sb_len_wr);
    stl_p(&scsi->data_len, hdr.dxfer_len);
    virtio_stl_p(vdev, &scsi->residual, hdr.resid);
    virtio_stl_p(vdev, &scsi->sense_len, hdr.sb_len_wr);
    virtio_stl_p(vdev, &scsi->data_len, hdr.dxfer_len);

    return status;
#else
@@ -239,7 +243,7 @@ int virtio_blk_handle_scsi_req(VirtIOBlock *blk,
fail:
    /* Just put anything nonzero so that the ioctl fails in the guest.  */
    if (scsi) {
        stl_p(&scsi->errors, 255);
        virtio_stl_p(vdev, &scsi->errors, 255);
    }
    return status;
}
@@ -289,7 +293,7 @@ static void virtio_blk_handle_write(VirtIOBlockReq *req, MultiReqBuffer *mrb)
    BlockRequest *blkreq;
    uint64_t sector;

    sector = ldq_p(&req->out.sector);
    sector = virtio_ldq_p(VIRTIO_DEVICE(req->dev), &req->out.sector);

    bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_WRITE);

@@ -323,7 +327,7 @@ static void virtio_blk_handle_read(VirtIOBlockReq *req)
{
    uint64_t sector;

    sector = ldq_p(&req->out.sector);
    sector = virtio_ldq_p(VIRTIO_DEVICE(req->dev), &req->out.sector);

    bdrv_acct_start(req->dev->bs, &req->acct, req->qiov.size, BDRV_ACCT_READ);

@@ -374,7 +378,7 @@ void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
              - sizeof(struct virtio_blk_inhdr);
    iov_discard_back(in_iov, &in_num, sizeof(struct virtio_blk_inhdr));

    type = ldl_p(&req->out.type);
    type = virtio_ldl_p(VIRTIO_DEVICE(req->dev), &req->out.type);

    if (type & VIRTIO_BLK_T_FLUSH) {
        virtio_blk_handle_flush(req, mrb);
@@ -504,12 +508,12 @@ static void virtio_blk_update_config(VirtIODevice *vdev, uint8_t *config)

    bdrv_get_geometry(s->bs, &capacity);
    memset(&blkcfg, 0, sizeof(blkcfg));
    stq_p(&blkcfg.capacity, capacity);
    stl_p(&blkcfg.seg_max, 128 - 2);
    stw_p(&blkcfg.cylinders, s->conf->cyls);
    stl_p(&blkcfg.blk_size, blk_size);
    stw_p(&blkcfg.min_io_size, s->conf->min_io_size / blk_size);
    stw_p(&blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
    virtio_stq_p(vdev, &blkcfg.capacity, capacity);
    virtio_stl_p(vdev, &blkcfg.seg_max, 128 - 2);
    virtio_stw_p(vdev, &blkcfg.cylinders, s->conf->cyls);
    virtio_stl_p(vdev, &blkcfg.blk_size, blk_size);
    virtio_stw_p(vdev, &blkcfg.min_io_size, s->conf->min_io_size / blk_size);
    virtio_stw_p(vdev, &blkcfg.opt_io_size, s->conf->opt_io_size / blk_size);
    blkcfg.heads = s->conf->heads;
    /*
     * We must ensure that the block device capacity is a multiple of
@@ -611,11 +615,15 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)

static void virtio_blk_save(QEMUFile *f, void *opaque)
{
    VirtIOBlock *s = opaque;
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
    VirtIOBlockReq *req = s->rq;
    VirtIODevice *vdev = VIRTIO_DEVICE(opaque);

    virtio_save(vdev, f);
}
    
static void virtio_blk_save_device(VirtIODevice *vdev, QEMUFile *f)
{
    VirtIOBlock *s = VIRTIO_BLK(vdev);
    VirtIOBlockReq *req = s->rq;

    while (req) {
        qemu_put_sbyte(f, 1);
@@ -630,16 +638,18 @@ static int virtio_blk_load(QEMUFile *f, void *opaque, int version_id)
{
    VirtIOBlock *s = opaque;
    VirtIODevice *vdev = VIRTIO_DEVICE(s);
    int ret;

    if (version_id != 2)
        return -EINVAL;

    ret = virtio_load(vdev, f);
    if (ret) {
        return ret;
    return virtio_load(vdev, f, version_id);
}

static int virtio_blk_load_device(VirtIODevice *vdev, QEMUFile *f,
                                  int version_id)
{
    VirtIOBlock *s = VIRTIO_BLK(vdev);

    while (qemu_get_sbyte(f)) {
        VirtIOBlockReq *req = virtio_blk_alloc_request(s);
        qemu_get_buffer(f, (unsigned char *)req->elem,
@@ -799,6 +809,8 @@ static void virtio_blk_class_init(ObjectClass *klass, void *data)
    vdc->get_features = virtio_blk_get_features;
    vdc->set_status = virtio_blk_set_status;
    vdc->reset = virtio_blk_reset;
    vdc->save = virtio_blk_save_device;
    vdc->load = virtio_blk_load_device;
}

static const TypeInfo virtio_device_info = {
+56 −38
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@
#include "hw/sysbus.h"
#include "trace.h"
#include "hw/virtio/virtio-serial.h"
#include "hw/virtio/virtio-access.h"

static VirtIOSerialPort *find_port_by_id(VirtIOSerial *vser, uint32_t id)
{
@@ -183,11 +184,12 @@ static size_t send_control_msg(VirtIOSerial *vser, void *buf, size_t len)
static size_t send_control_event(VirtIOSerial *vser, uint32_t port_id,
                                 uint16_t event, uint16_t value)
{
    VirtIODevice *vdev = VIRTIO_DEVICE(vser);
    struct virtio_console_control cpkt;

    stl_p(&cpkt.id, port_id);
    stw_p(&cpkt.event, event);
    stw_p(&cpkt.value, value);
    virtio_stl_p(vdev, &cpkt.id, port_id);
    virtio_stw_p(vdev, &cpkt.event, event);
    virtio_stw_p(vdev, &cpkt.value, value);

    trace_virtio_serial_send_control_event(port_id, event, value);
    return send_control_msg(vser, &cpkt, sizeof(cpkt));
@@ -278,6 +280,7 @@ void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
/* Guest wants to notify us of some event */
static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
{
    VirtIODevice *vdev = VIRTIO_DEVICE(vser);
    struct VirtIOSerialPort *port;
    VirtIOSerialPortClass *vsc;
    struct virtio_console_control cpkt, *gcpkt;
@@ -291,8 +294,8 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
        return;
    }

    cpkt.event = lduw_p(&gcpkt->event);
    cpkt.value = lduw_p(&gcpkt->value);
    cpkt.event = virtio_lduw_p(vdev, &gcpkt->event);
    cpkt.value = virtio_lduw_p(vdev, &gcpkt->value);

    trace_virtio_serial_handle_control_message(cpkt.event, cpkt.value);

@@ -312,10 +315,10 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
        return;
    }

    port = find_port_by_id(vser, ldl_p(&gcpkt->id));
    port = find_port_by_id(vser, virtio_ldl_p(vdev, &gcpkt->id));
    if (!port) {
        error_report("virtio-serial-bus: Unexpected port id %u for device %s",
                     ldl_p(&gcpkt->id), vser->bus.qbus.name);
                     virtio_ldl_p(vdev, &gcpkt->id), vser->bus.qbus.name);
        return;
    }

@@ -342,9 +345,9 @@ static void handle_control_message(VirtIOSerial *vser, void *buf, size_t len)
        }

        if (port->name) {
            stl_p(&cpkt.id, port->id);
            stw_p(&cpkt.event, VIRTIO_CONSOLE_PORT_NAME);
            stw_p(&cpkt.value, 1);
            virtio_stl_p(vdev, &cpkt.id, port->id);
            virtio_stw_p(vdev, &cpkt.event, VIRTIO_CONSOLE_PORT_NAME);
            virtio_stw_p(vdev, &cpkt.value, 1);

            buffer_len = sizeof(cpkt) + strlen(port->name) + 1;
            buffer = g_malloc(buffer_len);
@@ -510,18 +513,25 @@ static void vser_reset(VirtIODevice *vdev)

    vser = VIRTIO_SERIAL(vdev);
    guest_reset(vser);

    /* In case we have switched endianness */
    vser->config.max_nr_ports =
        virtio_tswap32(vdev, vser->serial.max_virtserial_ports);
}

static void virtio_serial_save(QEMUFile *f, void *opaque)
{
    VirtIOSerial *s = VIRTIO_SERIAL(opaque);
    /* The virtio device */
    virtio_save(VIRTIO_DEVICE(opaque), f);
}

static void virtio_serial_save_device(VirtIODevice *vdev, QEMUFile *f)
{
    VirtIOSerial *s = VIRTIO_SERIAL(vdev);
    VirtIOSerialPort *port;
    uint32_t nr_active_ports;
    unsigned int i, max_nr_ports;

    /* The virtio device */
    virtio_save(VIRTIO_DEVICE(s), f);

    /* The config space */
    qemu_put_be16s(f, &s->config.cols);
    qemu_put_be16s(f, &s->config.rows);
@@ -529,7 +539,7 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
    qemu_put_be32s(f, &s->config.max_nr_ports);

    /* The ports map */
    max_nr_ports = tswap32(s->config.max_nr_ports);
    max_nr_ports = virtio_tswap32(vdev, s->config.max_nr_ports);
    for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
        qemu_put_be32s(f, &s->ports_map[i]);
    }
@@ -659,36 +669,39 @@ static int fetch_active_ports_list(QEMUFile *f, int version_id,

static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
{
    VirtIOSerial *s = VIRTIO_SERIAL(opaque);
    uint32_t max_nr_ports, nr_active_ports, ports_map;
    unsigned int i;
    int ret;

    if (version_id > 3) {
        return -EINVAL;
    }

    /* The virtio device */
    ret = virtio_load(VIRTIO_DEVICE(s), f);
    if (ret) {
        return ret;
    return virtio_load(VIRTIO_DEVICE(opaque), f, version_id);
}

static int virtio_serial_load_device(VirtIODevice *vdev, QEMUFile *f,
                                     int version_id)
{
    VirtIOSerial *s = VIRTIO_SERIAL(vdev);
    uint32_t max_nr_ports, nr_active_ports, ports_map;
    unsigned int i;
    int ret;
    uint32_t tmp;

    if (version_id < 2) {
        return 0;
    }

    /* The config space */
    qemu_get_be16s(f, &s->config.cols);
    qemu_get_be16s(f, &s->config.rows);

    qemu_get_be32s(f, &max_nr_ports);
    tswap32s(&max_nr_ports);
    if (max_nr_ports > tswap32(s->config.max_nr_ports)) {
        /* Source could have had more ports than us. Fail migration. */
        return -EINVAL;
    }
    /* Unused */
    qemu_get_be16s(f, (uint16_t *) &tmp);
    qemu_get_be16s(f, (uint16_t *) &tmp);
    qemu_get_be32s(f, &tmp);

    /* Note: this is the only location where we use tswap32() instead of
     * virtio_tswap32() because:
     * - virtio_tswap32() only makes sense when the device is fully restored
     * - the target endianness that was used to populate s->config is
     *   necessarly the default one
     */
    max_nr_ports = tswap32(s->config.max_nr_ports);
    for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
        qemu_get_be32s(f, &ports_map);

@@ -751,9 +764,10 @@ static void virtser_bus_dev_print(Monitor *mon, DeviceState *qdev, int indent)
/* This function is only used if a port id is not provided by the user */
static uint32_t find_free_port_id(VirtIOSerial *vser)
{
    VirtIODevice *vdev = VIRTIO_DEVICE(vser);
    unsigned int i, max_nr_ports;

    max_nr_ports = tswap32(vser->config.max_nr_ports);
    max_nr_ports = virtio_tswap32(vdev, vser->config.max_nr_ports);
    for (i = 0; i < (max_nr_ports + 31) / 32; i++) {
        uint32_t map, bit;

@@ -806,6 +820,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp)
    VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
    VirtIOSerialPortClass *vsc = VIRTIO_SERIAL_PORT_GET_CLASS(port);
    VirtIOSerialBus *bus = VIRTIO_SERIAL_BUS(qdev_get_parent_bus(dev));
    VirtIODevice *vdev = VIRTIO_DEVICE(bus->vser);
    int max_nr_ports;
    bool plugging_port0;
    Error *err = NULL;
@@ -841,7 +856,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp)
        }
    }

    max_nr_ports = tswap32(port->vser->config.max_nr_ports);
    max_nr_ports = virtio_tswap32(vdev, port->vser->config.max_nr_ports);
    if (port->id >= max_nr_ports) {
        error_setg(errp, "virtio-serial-bus: Out-of-range port id specified, "
                         "max. allowed: %u", max_nr_ports - 1);
@@ -863,7 +878,7 @@ static void virtser_port_device_realize(DeviceState *dev, Error **errp)
    add_port(port->vser, port->id);

    /* Send an update to the guest about this new port added */
    virtio_notify_config(VIRTIO_DEVICE(port->vser));
    virtio_notify_config(vdev);
}

static void virtser_port_device_unrealize(DeviceState *dev, Error **errp)
@@ -942,7 +957,8 @@ static void virtio_serial_device_realize(DeviceState *dev, Error **errp)
        vser->ovqs[i] = virtio_add_queue(vdev, 128, handle_output);
    }

    vser->config.max_nr_ports = tswap32(vser->serial.max_virtserial_ports);
    vser->config.max_nr_ports =
        virtio_tswap32(vdev, vser->serial.max_virtserial_ports);
    vser->ports_map = g_malloc0(((vser->serial.max_virtserial_ports + 31) / 32)
        * sizeof(vser->ports_map[0]));
    /*
@@ -1019,6 +1035,8 @@ static void virtio_serial_class_init(ObjectClass *klass, void *data)
    vdc->get_config = get_config;
    vdc->set_status = set_status;
    vdc->reset = vser_reset;
    vdc->save = virtio_serial_save_device;
    vdc->load = virtio_serial_load_device;
}

static const TypeInfo virtio_device_info = {
Loading