From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:54105) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WzeI6-0003m5-Kk for qemu-devel@nongnu.org; Tue, 24 Jun 2014 23:54:42 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WzeHx-0000dF-6K for qemu-devel@nongnu.org; Tue, 24 Jun 2014 23:54:34 -0400 Received: from e23smtp02.au.ibm.com ([202.81.31.144]:55205) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WzeHw-0000ca-D3 for qemu-devel@nongnu.org; Tue, 24 Jun 2014 23:54:25 -0400 Received: from /spool/local by e23smtp02.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Wed, 25 Jun 2014 13:54:19 +1000 Received: from d23relay04.au.ibm.com (d23relay04.au.ibm.com [9.190.234.120]) by d23dlp02.au.ibm.com (Postfix) with ESMTP id 769352BB0055 for ; Wed, 25 Jun 2014 13:54:16 +1000 (EST) Received: from d23av02.au.ibm.com (d23av02.au.ibm.com [9.190.235.138]) by d23relay04.au.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id s5P3brtU37290202 for ; Wed, 25 Jun 2014 13:37:54 +1000 Received: from d23av02.au.ibm.com (localhost [127.0.0.1]) by d23av02.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id s5P3sFSg005472 for ; Wed, 25 Jun 2014 13:54:15 +1000 From: Alexey Kardashevskiy Date: Wed, 25 Jun 2014 13:54:11 +1000 Message-Id: <1403668451-18097-1-git-send-email-aik@ozlabs.ru> Subject: [Qemu-devel] [PATCH v2] vfio: Make BARs native endian List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Alexey Kardashevskiy , Alex Williamson , Nikunj A Dadhania Slow BAR access path is used when VFIO fails to mmap() BAR. Since this is just a transport between the guest and a device, there is no need to do endianness swapping. This changes BARs to use native endianness. Since non-ROM BARs were doing byte swapping, we need to remove it so does the patch. As the result, this eliminates cancelling byte swaps and there is no change in behavior for non-ROM BARs. ROM BARs were declared little endian too but byte swapping was not implemented for them so they never actually worked on big endian systems as there was no cancelling byte swap. This fixes endiannes for ROM BARs by declaring them native endian and only fixing access sizes as it is done for non-ROM BARs. Signed-off-by: Alexey Kardashevskiy --- Changes: v2: * removed "tcg" from commit log as tcg can mmap() BARs as well and do fast path --- hw/misc/vfio.c | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c index 7437c2e..3eb3c71 100644 --- a/hw/misc/vfio.c +++ b/hw/misc/vfio.c @@ -1052,10 +1052,10 @@ static void vfio_bar_write(void *opaque, hwaddr addr, buf.byte = data; break; case 2: - buf.word = cpu_to_le16(data); + buf.word = data; break; case 4: - buf.dword = cpu_to_le32(data); + buf.dword = data; break; default: hw_error("vfio: unsupported write size, %d bytes", size); @@ -1112,10 +1112,10 @@ static uint64_t vfio_bar_read(void *opaque, data = buf.byte; break; case 2: - data = le16_to_cpu(buf.word); + data = buf.word; break; case 4: - data = le32_to_cpu(buf.dword); + data = buf.dword; break; default: hw_error("vfio: unsupported read size, %d bytes", size); @@ -1142,7 +1142,7 @@ static uint64_t vfio_bar_read(void *opaque, static const MemoryRegionOps vfio_bar_ops = { .read = vfio_bar_read, .write = vfio_bar_write, - .endianness = DEVICE_LITTLE_ENDIAN, + .endianness = DEVICE_NATIVE_ENDIAN, }; static void vfio_pci_load_rom(VFIODevice *vdev) @@ -1204,21 +1204,42 @@ static void vfio_pci_load_rom(VFIODevice *vdev) static uint64_t vfio_rom_read(void *opaque, hwaddr addr, unsigned size) { VFIODevice *vdev = opaque; - uint64_t val = ((uint64_t)1 << (size * 8)) - 1; + union { + uint8_t byte; + uint16_t word; + uint32_t dword; + uint64_t qword; + } buf; + uint64_t data = 0; /* Load the ROM lazily when the guest tries to read it */ if (unlikely(!vdev->rom && !vdev->rom_read_failed)) { vfio_pci_load_rom(vdev); } - memcpy(&val, vdev->rom + addr, + memcpy(&buf, vdev->rom + addr, (addr < vdev->rom_size) ? MIN(size, vdev->rom_size - addr) : 0); + switch (size) { + case 1: + data = buf.byte; + break; + case 2: + data = buf.word; + break; + case 4: + data = buf.dword; + break; + default: + hw_error("vfio: unsupported read size, %d bytes", size); + break; + } + DPRINTF("%s(%04x:%02x:%02x.%x, 0x%"HWADDR_PRIx", 0x%x) = 0x%"PRIx64"\n", __func__, vdev->host.domain, vdev->host.bus, vdev->host.slot, - vdev->host.function, addr, size, val); + vdev->host.function, addr, size, data); - return val; + return data; } static void vfio_rom_write(void *opaque, hwaddr addr, @@ -1229,7 +1250,7 @@ static void vfio_rom_write(void *opaque, hwaddr addr, static const MemoryRegionOps vfio_rom_ops = { .read = vfio_rom_read, .write = vfio_rom_write, - .endianness = DEVICE_LITTLE_ENDIAN, + .endianness = DEVICE_NATIVE_ENDIAN, }; static bool vfio_blacklist_opt_rom(VFIODevice *vdev) -- 2.0.0