virtio 1.0 defines config space as LE, as opposed to pre-1.0 which was native endian. Add API for transports to execute word/dword accesses in little endian format - will be useful for mmio and pci (byte access is also wrapped, for completeness). For simplicity, we still keep config in host native endian format, byteswap to LE on guest access. Signed-off-by: Michael S. Tsirkin <mst at redhat.com> --- include/hw/virtio/virtio.h | 6 +++ hw/virtio/virtio.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index df09993..7a6a9d1 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -227,6 +227,12 @@ uint32_t virtio_config_readl(VirtIODevice *vdev, uint32_t addr); void virtio_config_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data); void virtio_config_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data); void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data); +uint32_t virtio_config_modern_readb(VirtIODevice *vdev, uint32_t addr); +uint32_t virtio_config_modern_readw(VirtIODevice *vdev, uint32_t addr); +uint32_t virtio_config_modern_readl(VirtIODevice *vdev, uint32_t addr); +void virtio_config_modern_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data); +void virtio_config_modern_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data); +void virtio_config_modern_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data); void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr); hwaddr virtio_queue_get_addr(VirtIODevice *vdev, int n); void virtio_queue_set_num(VirtIODevice *vdev, int n, int num); diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index 75abc1f..b098f44 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -729,6 +729,99 @@ void virtio_config_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data) } } +uint32_t virtio_config_modern_readb(VirtIODevice *vdev, uint32_t addr) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint8_t val; + + if (addr + sizeof(val) > vdev->config_len) { + return (uint32_t)-1; + } + + k->get_config(vdev, vdev->config); + + val = ldub_p(vdev->config + addr); + return val; +} + +uint32_t virtio_config_modern_readw(VirtIODevice *vdev, uint32_t addr) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint16_t val; + + if (addr + sizeof(val) > vdev->config_len) { + return (uint32_t)-1; + } + + k->get_config(vdev, vdev->config); + + val = lduw_le_p(vdev->config + addr); + return val; +} + +uint32_t virtio_config_modern_readl(VirtIODevice *vdev, uint32_t addr) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint32_t val; + + if (addr + sizeof(val) > vdev->config_len) { + return (uint32_t)-1; + } + + k->get_config(vdev, vdev->config); + + val = ldl_le_p(vdev->config + addr); + return val; +} + +void virtio_config_modern_writeb(VirtIODevice *vdev, uint32_t addr, uint32_t data) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint8_t val = data; + + if (addr + sizeof(val) > vdev->config_len) { + return; + } + + stb_p(vdev->config + addr, val); + + if (k->set_config) { + k->set_config(vdev, vdev->config); + } +} + +void virtio_config_modern_writew(VirtIODevice *vdev, uint32_t addr, uint32_t data) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint16_t val = data; + + if (addr + sizeof(val) > vdev->config_len) { + return; + } + + stw_le_p(vdev->config + addr, val); + + if (k->set_config) { + k->set_config(vdev, vdev->config); + } +} + +void virtio_config_modern_writel(VirtIODevice *vdev, uint32_t addr, uint32_t data) +{ + VirtioDeviceClass *k = VIRTIO_DEVICE_GET_CLASS(vdev); + uint32_t val = data; + + if (addr + sizeof(val) > vdev->config_len) { + return; + } + + stl_le_p(vdev->config + addr, val); + + if (k->set_config) { + k->set_config(vdev, vdev->config); + } +} + void virtio_queue_set_addr(VirtIODevice *vdev, int n, hwaddr addr) { vdev->vq[n].vring.desc = addr; -- MST
Michael S. Tsirkin
2015-Mar-02 11:40 UTC
[PATCH 2/2] virtio-pci: switch to modern accessors for 1.0
virtio 1.0 config space is in LE format for all devices, use modern wrappers when accessed through the 1.0 BAR. Reported-by: Rusty Russell <rusty at rustcorp.com.au> Signed-off-by: Michael S. Tsirkin <mst at redhat.com> --- hw/virtio/virtio-pci.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c index 4c9a0b8..49ea7fc 100644 --- a/hw/virtio/virtio-pci.c +++ b/hw/virtio/virtio-pci.c @@ -1198,13 +1198,13 @@ static uint64_t virtio_pci_device_read(void *opaque, hwaddr addr, switch (size) { case 1: - val = virtio_config_readb(vdev, addr); + val = virtio_config_modern_readb(vdev, addr); break; case 2: - val = virtio_config_readw(vdev, addr); + val = virtio_config_modern_readw(vdev, addr); break; case 4: - val = virtio_config_readl(vdev, addr); + val = virtio_config_modern_readl(vdev, addr); break; } return val; @@ -1216,13 +1216,13 @@ static void virtio_pci_device_write(void *opaque, hwaddr addr, VirtIODevice *vdev = opaque; switch (size) { case 1: - virtio_config_writeb(vdev, addr, val); + virtio_config_modern_writeb(vdev, addr, val); break; case 2: - virtio_config_writew(vdev, addr, val); + virtio_config_modern_writew(vdev, addr, val); break; case 4: - virtio_config_writel(vdev, addr, val); + virtio_config_modern_writel(vdev, addr, val); break; } } -- MST
On Mon, 2 Mar 2015 12:40:25 +0100 "Michael S. Tsirkin" <mst at redhat.com> wrote:> virtio 1.0 defines config space as LE, > as opposed to pre-1.0 which was native endian. > > Add API for transports to execute word/dword accesses in > little endian format - will be useful for mmio > and pci (byte access is also wrapped, for completeness). > > For simplicity, we still keep config in host native > endian format, byteswap to LE on guest access. > > Signed-off-by: Michael S. Tsirkin <mst at redhat.com> > --- > include/hw/virtio/virtio.h | 6 +++ > hw/virtio/virtio.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 99 insertions(+)One could also imagine making the accessors dependant on whether the provided virtio device is standard compliant, but as mmio will probably register different MemoryRegionOps for v1.0 devices as well, this should work out nicer this way. Reviewed-by: Cornelia Huck <cornelia.huck at de.ibm.com>
Cornelia Huck
2015-Mar-02 11:56 UTC
[PATCH 2/2] virtio-pci: switch to modern accessors for 1.0
On Mon, 2 Mar 2015 12:40:28 +0100 "Michael S. Tsirkin" <mst at redhat.com> wrote:> virtio 1.0 config space is in LE format for all > devices, use modern wrappers when accessed through > the 1.0 BAR. > > Reported-by: Rusty Russell <rusty at rustcorp.com.au> > Signed-off-by: Michael S. Tsirkin <mst at redhat.com> > --- > hw/virtio/virtio-pci.c | 12 ++++++------ > 1 file changed, 6 insertions(+), 6 deletions(-)Not that I'm deeply familiar with pci :), but this looks good to me. (This is on top of your pci branch, btw?)
Rusty Russell
2015-Mar-04 00:36 UTC
[PATCH 2/2] virtio-pci: switch to modern accessors for 1.0
"Michael S. Tsirkin" <mst at redhat.com> writes:> virtio 1.0 config space is in LE format for all > devices, use modern wrappers when accessed through > the 1.0 BAR.Hmm, I'm not so sure about these patches. It's easy to miss the existence of the _modern variants, and they're 90% the same as the legacy variants. But as long as it's fixed... Thanks, Rusty. PS. rng, block, net and 9p virtio 1.0 seem to work OK on BE guests (LE host).
Seemingly Similar Threads
- [PATCH 1/2] virtio: add modern config accessors
- [PATCH 2/2] virtio-pci: switch to modern accessors for 1.0
- [PATCH 2/2] virtio-pci: switch to modern accessors for 1.0
- [PATCH RFC v6 13/20] virtio: allow to fail setting status
- [PATCH RFC v6 13/20] virtio: allow to fail setting status