From fe084f0b03a11a67a5ad57d03651b529b3d8db0c Mon Sep 17 00:00:00 2001 From: X512 Date: Mon, 17 Oct 2022 02:08:44 +0900 Subject: [PATCH] virtio_mmio: fix config space access using 1,2,4-byte memory access MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I596da650be81a596efcbe7e3abecf2a4da3a8459 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5747 Reviewed-by: Jérôme Duval Tested-by: Commit checker robot --- .../busses/virtio/virtio_mmio/virtio_mmio.cpp | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/add-ons/kernel/busses/virtio/virtio_mmio/virtio_mmio.cpp b/src/add-ons/kernel/busses/virtio/virtio_mmio/virtio_mmio.cpp index a3a0bd1099..f065851c2f 100644 --- a/src/add-ons/kernel/busses/virtio/virtio_mmio/virtio_mmio.cpp +++ b/src/add-ons/kernel/busses/virtio/virtio_mmio/virtio_mmio.cpp @@ -409,9 +409,26 @@ virtio_device_read_device_config(virtio_device cookie, uint8 offset, { TRACE("virtio_device_read_device_config(%p, %d, %" B_PRIuSIZE ")\n", cookie, offset, bufferSize); - VirtioDevice* dev = (VirtioDevice*)cookie; - memcpy(buffer, (void*)(dev->fRegs->config + offset), bufferSize); + + // TODO: check ARM support, ARM seems support only 32 bit aligned MMIO access. + vuint8* src = &dev->fRegs->config[offset]; + uint8* dst = (uint8*)buffer; + while (bufferSize > 0) { + uint8 size = 4; + if (bufferSize == 1) { + size = 1; + *dst = *src; + } else if (bufferSize <= 3) { + size = 2; + *(uint16*)dst = *(vuint16*)src; + } else + *(uint32*)dst = *(vuint32*)src; + + dst += size; + bufferSize -= size; + src += size; + } return B_OK; } @@ -424,7 +441,26 @@ virtio_device_write_device_config(virtio_device cookie, uint8 offset, TRACE("virtio_device_write_device_config(%p, %d, %" B_PRIuSIZE ")\n", cookie, offset, bufferSize); VirtioDevice* dev = (VirtioDevice*)cookie; - memcpy((void*)(dev->fRegs->config + offset), buffer, bufferSize); + + // See virtio_device_read_device_config + uint8* src = (uint8*)buffer; + vuint8* dst = &dev->fRegs->config[offset]; + while (bufferSize > 0) { + uint8 size = 4; + if (bufferSize == 1) { + size = 1; + *dst = *src; + } else if (bufferSize <= 3) { + size = 2; + *(vuint16*)dst = *(uint16*)src; + } else + *(vuint32*)dst = *(uint32*)src; + + dst += size; + bufferSize -= size; + src += size; + } + return B_OK; }