Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into sta…
Browse files Browse the repository at this point in the history
…ging

virtio, pc: fixes and features

more guest error handling for virtio devices
virtio migration rework
pc fixes

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

# gpg: Signature made Mon 10 Oct 2016 00:39:11 BST
# gpg:                using RSA key 0x281F0DB8D28D5469
# gpg: Good signature from "Michael S. Tsirkin <mst@kernel.org>"
# gpg:                 aka "Michael S. Tsirkin <mst@redhat.com>"
# Primary key fingerprint: 0270 606B 6F3C DF3D 0B17  0970 C350 3912 AFBE 8E67
#      Subkey fingerprint: 5D09 FD08 71C8 F85B 94CA  8A0D 281F 0DB8 D28D 5469

* remotes/mst/tags/for_upstream: (33 commits)
  intel-iommu: Check IOAPIC's Trigger Mode against the one in IRTE
  virtio: cleanup VMSTATE_VIRTIO_DEVICE
  vhost-vsock: convert VMSTATE_VIRTIO_DEVICE
  virtio-rng: convert VMSTATE_VIRTIO_DEVICE
  virtio-balloon: convert VMSTATE_VIRTIO_DEVICE
  virtio-scsi: convert VMSTATE_VIRTIO_DEVICE
  virtio-input: convert VMSTATE_VIRTIO_DEVICE
  virtio-gpu: convert VMSTATE_VIRTIO_DEVICE
  virtio-serial: convert VMSTATE_VIRTIO_DEVICE
  virtio-9p: convert VMSTATE_VIRTIO_DEVICE
  virtio-net: convert VMSTATE_VIRTIO_DEVICE
  virtio-blk: convert VMSTATE_VIRTIO_DEVICE
  virtio: prepare change VMSTATE_VIRTIO_DEVICE macro
  net: don't poke at chardev internal QemuOpts
  virtio-scsi: handle virtio_scsi_set_config() error
  virtio-scsi: convert virtio_scsi_bad_req() to use virtio_error()
  virtio-net: handle virtio_net_flush_tx() errors
  virtio-net: handle virtio_net_receive() errors
  virtio-net: handle virtio_net_handle_ctrl() error
  virtio-blk: handle virtio_blk_handle_request() errors
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Oct 10, 2016
2 parents 0f183e6 + dea651a commit 627eae7
Show file tree
Hide file tree
Showing 34 changed files with 484 additions and 308 deletions.
1 change: 1 addition & 0 deletions hmp.c
Expand Up @@ -1974,6 +1974,7 @@ void hmp_chardev_add(Monitor *mon, const QDict *qdict)
error_setg(&err, "Parsing chardev args failed");
} else {
qemu_chr_new_from_opts(opts, NULL, &err);
qemu_opts_del(opts);
}
hmp_handle_error(mon, &err);
}
Expand Down
45 changes: 32 additions & 13 deletions hw/9pfs/virtio-9p-device.c
Expand Up @@ -41,28 +41,36 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
V9fsState *s = &v->state;
V9fsPDU *pdu;
ssize_t len;
VirtQueueElement *elem;

while ((pdu = pdu_alloc(s))) {
struct {
uint32_t size_le;
uint8_t id;
uint16_t tag_le;
} QEMU_PACKED out;
VirtQueueElement *elem;

elem = virtqueue_pop(vq, sizeof(VirtQueueElement));
if (!elem) {
pdu_free(pdu);
break;
goto out_free_pdu;
}

BUG_ON(elem->out_num == 0 || elem->in_num == 0);
QEMU_BUILD_BUG_ON(sizeof out != 7);
if (elem->in_num == 0) {
virtio_error(vdev,
"The guest sent a VirtFS request without space for "
"the reply");
goto out_free_req;
}
QEMU_BUILD_BUG_ON(sizeof(out) != 7);

v->elems[pdu->idx] = elem;
len = iov_to_buf(elem->out_sg, elem->out_num, 0,
&out, sizeof out);
BUG_ON(len != sizeof out);
&out, sizeof(out));
if (len != sizeof(out)) {
virtio_error(vdev, "The guest sent a malformed VirtFS request: "
"header size is %zd, should be 7", len);
goto out_free_req;
}

pdu->size = le32_to_cpu(out.size_le);

Expand All @@ -72,6 +80,14 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq)
qemu_co_queue_init(&pdu->complete);
pdu_submit(pdu);
}

return;

out_free_req:
virtqueue_detach_element(vq, elem, 0);
g_free(elem);
out_free_pdu:
pdu_free(pdu);
}

static uint64_t virtio_9p_get_features(VirtIODevice *vdev, uint64_t features,
Expand All @@ -97,11 +113,6 @@ static void virtio_9p_get_config(VirtIODevice *vdev, uint8_t *config)
g_free(cfg);
}

static int virtio_9p_load(QEMUFile *f, void *opaque, size_t size)
{
return virtio_load(VIRTIO_DEVICE(opaque), f, 1);
}

static void virtio_9p_device_realize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
Expand Down Expand Up @@ -168,7 +179,15 @@ void virtio_init_iov_from_pdu(V9fsPDU *pdu, struct iovec **piov,

/* virtio-9p device */

VMSTATE_VIRTIO_DEVICE(9p, 1, virtio_9p_load, virtio_vmstate_save);
static const VMStateDescription vmstate_virtio_9p = {
.name = "virtio-9p",
.minimum_version_id = 1,
.version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_VIRTIO_DEVICE,
VMSTATE_END_OF_LIST()
},
};

static Property virtio_9p_properties[] = {
DEFINE_PROP_STRING("mount_tag", V9fsVirtioState, state.fsconf.tag),
Expand Down
12 changes: 12 additions & 0 deletions hw/acpi/cpu.c
Expand Up @@ -4,6 +4,7 @@
#include "qapi/error.h"
#include "qapi-event.h"
#include "trace.h"
#include "sysemu/numa.h"

#define ACPI_CPU_HOTPLUG_REG_LEN 12
#define ACPI_CPU_SELECTOR_OFFSET_WR 0
Expand Down Expand Up @@ -503,6 +504,7 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,

/* build Processor object for each processor */
for (i = 0; i < arch_ids->len; i++) {
int j;
Aml *dev;
Aml *uid = aml_int(i);
GArray *madt_buf = g_array_new(0, 1, 1);
Expand Down Expand Up @@ -546,6 +548,16 @@ void build_cpus_aml(Aml *table, MachineState *machine, CPUHotplugFeatures opts,
aml_arg(1), aml_arg(2))
);
aml_append(dev, method);

/* Linux guests discard SRAT info for non-present CPUs
* as a result _PXM is required for all CPUs which might
* be hot-plugged. For simplicity, add it for all CPUs.
*/
j = numa_get_node_for_cpu(i);
if (j < nb_numa_nodes) {
aml_append(dev, aml_name_decl("_PXM", aml_int(j)));
}

aml_append(cpus_dev, dev);
}
}
Expand Down
6 changes: 2 additions & 4 deletions hw/arm/virt-acpi-build.c
Expand Up @@ -427,11 +427,9 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtGuestInfo *guest_info)
uint32_t *cpu_node = g_malloc0(guest_info->smp_cpus * sizeof(uint32_t));

for (i = 0; i < guest_info->smp_cpus; i++) {
for (j = 0; j < nb_numa_nodes; j++) {
if (test_bit(i, numa_info[j].node_cpu)) {
j = numa_get_node_for_cpu(i);
if (j < nb_numa_nodes) {
cpu_node[i] = j;
break;
}
}
}

Expand Down
7 changes: 3 additions & 4 deletions hw/arm/virt.c
Expand Up @@ -413,10 +413,9 @@ static void fdt_add_cpu_nodes(const VirtBoardInfo *vbi)
armcpu->mp_affinity);
}

for (i = 0; i < nb_numa_nodes; i++) {
if (test_bit(cpu, numa_info[i].node_cpu)) {
qemu_fdt_setprop_cell(vbi->fdt, nodename, "numa-node-id", i);
}
i = numa_get_node_for_cpu(cpu);
if (i < nb_numa_nodes) {
qemu_fdt_setprop_cell(vbi->fdt, nodename, "numa-node-id", i);
}

g_free(nodename);
Expand Down
72 changes: 42 additions & 30 deletions hw/block/virtio-blk.c
Expand Up @@ -29,8 +29,8 @@
#include "hw/virtio/virtio-bus.h"
#include "hw/virtio/virtio-access.h"

void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq,
VirtIOBlockReq *req)
static void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq,
VirtIOBlockReq *req)
{
req->dev = s;
req->vq = vq;
Expand All @@ -40,7 +40,7 @@ void virtio_blk_init_request(VirtIOBlock *s, VirtQueue *vq,
req->mr_next = NULL;
}

void virtio_blk_free_request(VirtIOBlockReq *req)
static void virtio_blk_free_request(VirtIOBlockReq *req)
{
if (req) {
g_free(req);
Expand Down Expand Up @@ -381,7 +381,7 @@ static int multireq_compare(const void *a, const void *b)
}
}

void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
static void virtio_blk_submit_multireq(BlockBackend *blk, MultiReqBuffer *mrb)
{
int i = 0, start = 0, num_reqs = 0, niov = 0, nb_sectors = 0;
uint32_t max_transfer;
Expand Down Expand Up @@ -468,30 +468,32 @@ static bool virtio_blk_sect_range_ok(VirtIOBlock *dev,
return true;
}

void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
static int virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
{
uint32_t type;
struct iovec *in_iov = req->elem.in_sg;
struct iovec *iov = req->elem.out_sg;
unsigned in_num = req->elem.in_num;
unsigned out_num = req->elem.out_num;
VirtIOBlock *s = req->dev;
VirtIODevice *vdev = VIRTIO_DEVICE(s);

if (req->elem.out_num < 1 || req->elem.in_num < 1) {
error_report("virtio-blk missing headers");
exit(1);
virtio_error(vdev, "virtio-blk missing headers");
return -1;
}

if (unlikely(iov_to_buf(iov, out_num, 0, &req->out,
sizeof(req->out)) != sizeof(req->out))) {
error_report("virtio-blk request outhdr too short");
exit(1);
virtio_error(vdev, "virtio-blk request outhdr too short");
return -1;
}

iov_discard_front(&iov, &out_num, sizeof(req->out));

if (in_iov[in_num - 1].iov_len < sizeof(struct virtio_blk_inhdr)) {
error_report("virtio-blk request inhdr too short");
exit(1);
virtio_error(vdev, "virtio-blk request inhdr too short");
return -1;
}

/* We always touch the last byte, so just see how big in_iov is. */
Expand Down Expand Up @@ -529,7 +531,7 @@ void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
block_acct_invalid(blk_get_stats(req->dev->blk),
is_write ? BLOCK_ACCT_WRITE : BLOCK_ACCT_READ);
virtio_blk_free_request(req);
return;
return 0;
}

block_acct_start(blk_get_stats(req->dev->blk),
Expand Down Expand Up @@ -576,6 +578,7 @@ void virtio_blk_handle_request(VirtIOBlockReq *req, MultiReqBuffer *mrb)
virtio_blk_req_complete(req, VIRTIO_BLK_S_UNSUPP);
virtio_blk_free_request(req);
}
return 0;
}

void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
Expand All @@ -586,7 +589,11 @@ void virtio_blk_handle_vq(VirtIOBlock *s, VirtQueue *vq)
blk_io_plug(s->blk);

while ((req = virtio_blk_get_request(s, vq))) {
virtio_blk_handle_request(req, &mrb);
if (virtio_blk_handle_request(req, &mrb)) {
virtqueue_detach_element(req->vq, &req->elem, 0);
virtio_blk_free_request(req);
break;
}
}

if (mrb.num_reqs) {
Expand Down Expand Up @@ -625,7 +632,18 @@ static void virtio_blk_dma_restart_bh(void *opaque)

while (req) {
VirtIOBlockReq *next = req->next;
virtio_blk_handle_request(req, &mrb);
if (virtio_blk_handle_request(req, &mrb)) {
/* Device is now broken and won't do any processing until it gets
* reset. Already queued requests will be lost: let's purge them.
*/
while (req) {
next = req->next;
virtqueue_detach_element(req->vq, &req->elem, 0);
virtio_blk_free_request(req);
req = next;
}
break;
}
req = next;
}

Expand Down Expand Up @@ -665,6 +683,7 @@ static void virtio_blk_reset(VirtIODevice *vdev)
while (s->rq) {
req = s->rq;
s->rq = req->next;
virtqueue_detach_element(req->vq, &req->elem, 0);
virtio_blk_free_request(req);
}

Expand Down Expand Up @@ -803,13 +822,6 @@ static void virtio_blk_set_status(VirtIODevice *vdev, uint8_t status)
}
}

static void virtio_blk_save(QEMUFile *f, void *opaque, size_t size)
{
VirtIODevice *vdev = VIRTIO_DEVICE(opaque);

virtio_save(vdev, f);
}

static void virtio_blk_save_device(VirtIODevice *vdev, QEMUFile *f)
{
VirtIOBlock *s = VIRTIO_BLK(vdev);
Expand All @@ -828,14 +840,6 @@ static void virtio_blk_save_device(VirtIODevice *vdev, QEMUFile *f)
qemu_put_sbyte(f, 0);
}

static int virtio_blk_load(QEMUFile *f, void *opaque, size_t size)
{
VirtIOBlock *s = opaque;
VirtIODevice *vdev = VIRTIO_DEVICE(s);

return virtio_load(vdev, f, 2);
}

static int virtio_blk_load_device(VirtIODevice *vdev, QEMUFile *f,
int version_id)
{
Expand Down Expand Up @@ -956,7 +960,15 @@ static void virtio_blk_instance_init(Object *obj)
DEVICE(obj), NULL);
}

VMSTATE_VIRTIO_DEVICE(blk, 2, virtio_blk_load, virtio_blk_save);
static const VMStateDescription vmstate_virtio_blk = {
.name = "virtio-blk",
.minimum_version_id = 2,
.version_id = 2,
.fields = (VMStateField[]) {
VMSTATE_VIRTIO_DEVICE,
VMSTATE_END_OF_LIST()
},
};

static Property virtio_blk_properties[] = {
DEFINE_BLOCK_PROPERTIES(VirtIOBlock, conf.conf),
Expand Down

0 comments on commit 627eae7

Please sign in to comment.