[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Qemu-devel] [PATCH RFC 8/8] virtio: add endian-ambivalent support t
From: |
Paolo Bonzini |
Subject: |
Re: [Qemu-devel] [PATCH RFC 8/8] virtio: add endian-ambivalent support to VirtIODevice |
Date: |
Thu, 29 May 2014 12:16:26 +0200 |
User-agent: |
Mozilla/5.0 (X11; Linux x86_64; rv:24.0) Gecko/20100101 Thunderbird/24.5.0 |
Il 29/05/2014 11:12, Greg Kurz ha scritto:
int virtio_load(VirtIODevice *vdev, QEMUFile *f)
{
[...]
nheads = vring_avail_idx(&vdev->vq[i]) - vdev->vq[i].last_avail_idx;
^^^^^^^^^^^
/* Check it isn't doing very strange things with descriptor
numbers. */
if (nheads > vdev->vq[i].vring.num) {
[...]
}
and
static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
{
[...]
/* 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)) {
[...]
}
If we stream subsections after the device descriptor as it is done
in VMState, these two will break because the device endian is stale.
The first one can be easily dealt with: just defer the sanity check
to a post_load function.
Good, we're lucky here.
The second is a bit more tricky: the
virtio serial migrates its config space (target endian) and the
active ports bitmap. The load code assumes max_nr_ports from the
config space tells the size of the ports bitmap... that means the
virtio migration protocol is also contaminated by target endianness. :-\
Ouch.
I guess we could break migration in the case of host endianness !=
target endianness, like this:
/* These three used to be fetched in target endianness and then
* stored as big endian. It ended up as little endian if host and
* target endianness doesn't match.
*
* Starting with qemu 2.1, we always store as big endian. The
* version wasn't bumped to avoid breaking backwards compatibility.
* We check the validity of max_nr_ports, and the incorrect-
* endianness max_nr_ports will be huge, which will abort migration
* anyway.
*/
uint16_t cols = tswap16(s->config.cols);
uint16_t rows = tswap16(s->config.rows);
uint32_t max_nr_ports = tswap32(s->config.max_nr_ports);
qemu_put_be16s(f, &cols);
qemu_put_be16s(f, &rows);
qemu_put_be32s(f, &max_nr_ports);
...
uint16_t cols, rows;
qemu_get_be16s(f, &cols);
qemu_get_be16s(f, &rows);
qemu_get_be32s(f, &max_nr_ports);
/* Convert back to target endianness when storing into the config
* space.
*/
s->config.cols = tswap16(cols);
s->config.rows = tswap16(rows);
if (max_nr_ports > tswap32(s->config.max_nr_ports) {
...
}
In the case the answer for above is "legacy virtio really sucks" then,
is it acceptable to not honor bug-compatibility with older versions and
fix the code ? :)
As long as the common cases don't break, yes. The question is what are
the common cases. Here I think the only non-obscure case that could
break is x86-on-PPC, and it's not that common.
Paolo
- Re: [Qemu-devel] [PATCH RFC 1/8] virtio: add subsections to the migration stream, (continued)
- [Qemu-devel] [PATCH RFC 2/8] virtio-net: migrate subsections, Greg Kurz, 2014/05/14
- [Qemu-devel] [PATCH RFC 3/8] virtio-blk: migrate subsections, Greg Kurz, 2014/05/14
- [Qemu-devel] [PATCH RFC 4/8] virtio-scsi: migrate subsections, Greg Kurz, 2014/05/14
- [Qemu-devel] [PATCH RFC 5/8] virtio-serial: migrate subsections, Greg Kurz, 2014/05/14
- [Qemu-devel] [PATCH RFC 6/8] virtio-balloon: migrate subsections, Greg Kurz, 2014/05/14
- [Qemu-devel] [PATCH RFC 7/8] virtio-rng: migrate subsections, Greg Kurz, 2014/05/14
- [Qemu-devel] [PATCH RFC 8/8] virtio: add endian-ambivalent support to VirtIODevice, Greg Kurz, 2014/05/14