vesa, pci-shmem and virtio-pci devices need to set up config space with
little-endian conversions (as config space is LE).  The pci_config_address
bitfield also needs to be reversed when building on BE systems.

Signed-off-by: Matt Evans <m...@ozlabs.org>
---
 tools/kvm/hw/pci-shmem.c       |   23 +++++++++++----------
 tools/kvm/hw/vesa.c            |   15 +++++++------
 tools/kvm/include/kvm/ioport.h |   11 +++++----
 tools/kvm/include/kvm/pci.h    |   24 +++++++++++++++++-----
 tools/kvm/pci.c                |    4 +-
 tools/kvm/virtio/pci.c         |   41 +++++++++++++++++++++------------------
 6 files changed, 68 insertions(+), 50 deletions(-)

diff --git a/tools/kvm/hw/pci-shmem.c b/tools/kvm/hw/pci-shmem.c
index 780a377..fd954c5 100644
--- a/tools/kvm/hw/pci-shmem.c
+++ b/tools/kvm/hw/pci-shmem.c
@@ -8,21 +8,22 @@
 #include "kvm/ioeventfd.h"
 
 #include <linux/kvm.h>
+#include <linux/byteorder.h>
 #include <sys/ioctl.h>
 #include <fcntl.h>
 #include <sys/mman.h>
 
 static struct pci_device_header pci_shmem_pci_device = {
-       .vendor_id      = PCI_VENDOR_ID_REDHAT_QUMRANET,
-       .device_id      = 0x1110,
+       .vendor_id      = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
+       .device_id      = cpu_to_le16(0x1110),
        .header_type    = PCI_HEADER_TYPE_NORMAL,
-       .class          = 0xFF0000,     /* misc pci device */
-       .status         = PCI_STATUS_CAP_LIST,
+       .class[2]       = 0xFF, /* misc pci device */
+       .status         = cpu_to_le16(PCI_STATUS_CAP_LIST),
        .capabilities   = (void *)&pci_shmem_pci_device.msix - (void 
*)&pci_shmem_pci_device,
        .msix.cap       = PCI_CAP_ID_MSIX,
-       .msix.ctrl      = 1,
-       .msix.table_offset = 1,         /* Use BAR 1 */
-       .msix.pba_offset = 0x1001,      /* Use BAR 1 */
+       .msix.ctrl      = cpu_to_le16(1),
+       .msix.table_offset = cpu_to_le32(1),            /* Use BAR 1 */
+       .msix.pba_offset = cpu_to_le32(0x1001),         /* Use BAR 1 */
 };
 
 /* registers for the Inter-VM shared memory device */
@@ -123,7 +124,7 @@ int pci_shmem__get_local_irqfd(struct kvm *kvm)
                if (fd < 0)
                        return fd;
 
-               if (pci_shmem_pci_device.msix.ctrl & PCI_MSIX_FLAGS_ENABLE) {
+               if (pci_shmem_pci_device.msix.ctrl & 
cpu_to_le16(PCI_MSIX_FLAGS_ENABLE)) {
                        gsi = irq__add_msix_route(kvm, &msix_table[0].msg);
                } else {
                        gsi = pci_shmem_pci_device.irq_line;
@@ -241,11 +242,11 @@ int pci_shmem__init(struct kvm *kvm)
         * 1 - MSI-X MMIO space
         * 2 - Shared memory block
         */
-       pci_shmem_pci_device.bar[0] = ivshmem_registers | 
PCI_BASE_ADDRESS_SPACE_IO;
+       pci_shmem_pci_device.bar[0] = cpu_to_le32(ivshmem_registers | 
PCI_BASE_ADDRESS_SPACE_IO);
        pci_shmem_pci_device.bar_size[0] = shmem_region->size;
-       pci_shmem_pci_device.bar[1] = msix_block | 
PCI_BASE_ADDRESS_SPACE_MEMORY;
+       pci_shmem_pci_device.bar[1] = cpu_to_le32(msix_block | 
PCI_BASE_ADDRESS_SPACE_MEMORY);
        pci_shmem_pci_device.bar_size[1] = 0x1010;
-       pci_shmem_pci_device.bar[2] = shmem_region->phys_addr | 
PCI_BASE_ADDRESS_SPACE_MEMORY;
+       pci_shmem_pci_device.bar[2] = cpu_to_le32(shmem_region->phys_addr | 
PCI_BASE_ADDRESS_SPACE_MEMORY);
        pci_shmem_pci_device.bar_size[2] = shmem_region->size;
 
        pci__register(&pci_shmem_pci_device, dev);
diff --git a/tools/kvm/hw/vesa.c b/tools/kvm/hw/vesa.c
index 22b1652..63f1082 100644
--- a/tools/kvm/hw/vesa.c
+++ b/tools/kvm/hw/vesa.c
@@ -8,6 +8,7 @@
 #include "kvm/irq.h"
 #include "kvm/kvm.h"
 #include "kvm/pci.h"
+#include <linux/byteorder.h>
 #include <sys/mman.h>
 
 #include <sys/types.h>
@@ -31,14 +32,14 @@ static struct ioport_operations vesa_io_ops = {
 };
 
 static struct pci_device_header vesa_pci_device = {
-       .vendor_id              = PCI_VENDOR_ID_REDHAT_QUMRANET,
-       .device_id              = PCI_DEVICE_ID_VESA,
+       .vendor_id              = cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
+       .device_id              = cpu_to_le16(PCI_DEVICE_ID_VESA),
        .header_type            = PCI_HEADER_TYPE_NORMAL,
        .revision_id            = 0,
-       .class                  = 0x030000,
-       .subsys_vendor_id       = PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
-       .subsys_id              = PCI_SUBSYSTEM_ID_VESA,
-       .bar[1]                 = VESA_MEM_ADDR | PCI_BASE_ADDRESS_SPACE_MEMORY,
+       .class[2]               = 0x03,
+       .subsys_vendor_id       = 
cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET),
+       .subsys_id              = cpu_to_le16(PCI_SUBSYSTEM_ID_VESA),
+       .bar[1]                 = cpu_to_le32(VESA_MEM_ADDR | 
PCI_BASE_ADDRESS_SPACE_MEMORY),
        .bar_size[1]            = VESA_MEM_SIZE,
 };
 
@@ -56,7 +57,7 @@ struct framebuffer *vesa__init(struct kvm *kvm)
        vesa_pci_device.irq_pin         = pin;
        vesa_pci_device.irq_line        = line;
        vesa_base_addr                  = ioport__register(IOPORT_EMPTY, 
&vesa_io_ops, IOPORT_SIZE, NULL);
-       vesa_pci_device.bar[0]          = vesa_base_addr | 
PCI_BASE_ADDRESS_SPACE_IO;
+       vesa_pci_device.bar[0]          = cpu_to_le32(vesa_base_addr | 
PCI_BASE_ADDRESS_SPACE_IO);
        pci__register(&vesa_pci_device, dev);
 
        mem = mmap(NULL, VESA_MEM_SIZE, PROT_RW, MAP_ANON_NORESERVE, -1, 0);
diff --git a/tools/kvm/include/kvm/ioport.h b/tools/kvm/include/kvm/ioport.h
index 61a70ec..09bf876 100644
--- a/tools/kvm/include/kvm/ioport.h
+++ b/tools/kvm/include/kvm/ioport.h
@@ -7,6 +7,7 @@
 #include <limits.h>
 #include <asm/types.h>
 #include <linux/types.h>
+#include <linux/byteorder.h>
 
 /* some ports we reserve for own use */
 #define IOPORT_DBG                     0xe0
@@ -36,15 +37,15 @@ static inline u8 ioport__read8(u8 *data)
 {
        return *data;
 }
-
+/* On BE platforms, PCI I/O is byteswapped, i.e. LE, so swap back. */
 static inline u16 ioport__read16(u16 *data)
 {
-       return *data;
+       return le16_to_cpu(*data);
 }
 
 static inline u32 ioport__read32(u32 *data)
 {
-       return *data;
+       return le32_to_cpu(*data);
 }
 
 static inline void ioport__write8(u8 *data, u8 value)
@@ -54,12 +55,12 @@ static inline void ioport__write8(u8 *data, u8 value)
 
 static inline void ioport__write16(u16 *data, u16 value)
 {
-       *data            = value;
+       *data            = cpu_to_le16(value);
 }
 
 static inline void ioport__write32(u32 *data, u32 value)
 {
-       *data            = value;
+       *data            = cpu_to_le32(value);
 }
 
 #endif /* KVM__IOPORT_H */
diff --git a/tools/kvm/include/kvm/pci.h b/tools/kvm/include/kvm/pci.h
index b578ad7..88e92dc 100644
--- a/tools/kvm/include/kvm/pci.h
+++ b/tools/kvm/include/kvm/pci.h
@@ -5,6 +5,7 @@
 #include <linux/kvm.h>
 #include <linux/pci_regs.h>
 #include <linux/msi.h>
+#include <endian.h>
 
 #define PCI_MAX_DEVICES                        256
 /*
@@ -17,7 +18,8 @@
 #define PCI_CONFIG_BUS_FORWARD 0xcfa
 #define PCI_IO_SIZE            0x100
 
-struct pci_config_address {
+union pci_config_address {
+#if __BYTE_ORDER == __LITTLE_ENDIAN
        unsigned        zeros           : 2;            /* 1  .. 0  */
        unsigned        register_number : 6;            /* 7  .. 2  */
        unsigned        function_number : 3;            /* 10 .. 8  */
@@ -25,6 +27,16 @@ struct pci_config_address {
        unsigned        bus_number      : 8;            /* 23 .. 16 */
        unsigned        reserved        : 7;            /* 30 .. 24 */
        unsigned        enable_bit      : 1;            /* 31       */
+#else
+       unsigned        enable_bit      : 1;            /* 31       */
+       unsigned        reserved        : 7;            /* 30 .. 24 */
+       unsigned        bus_number      : 8;            /* 23 .. 16 */
+       unsigned        device_number   : 5;            /* 15 .. 11 */
+       unsigned        function_number : 3;            /* 10 .. 8  */
+       unsigned        register_number : 6;            /* 7  .. 2  */
+       unsigned        zeros           : 2;            /* 1  .. 0  */
+#endif
+       u32 w;
 };
 
 struct msix_table {
@@ -45,8 +57,8 @@ struct pci_device_header {
        u16             device_id;
        u16             command;
        u16             status;
-       u16             revision_id             :  8;
-       u32             class                   : 24;
+       u8              revision_id;
+       u8              class[3];
        u8              cacheline_size;
        u8              latency_timer;
        u8              header_type;
@@ -56,8 +68,8 @@ struct pci_device_header {
        u16             subsys_vendor_id;
        u16             subsys_id;
        u32             exp_rom_bar;
-       u32             capabilities            :  8;
-       u32             reserved1               : 24;
+       u8              capabilities;
+       u8              reserved1[3];
        u32             reserved2;
        u8              irq_line;
        u8              irq_pin;
@@ -66,7 +78,7 @@ struct pci_device_header {
        struct msix_cap msix;
        u8              empty[136]; /* Rest of PCI config space */
        u32             bar_size[6];
-};
+} __attribute__((packed));
 
 void pci__init(void);
 void pci__register(struct pci_device_header *dev, u8 dev_num);
diff --git a/tools/kvm/pci.c b/tools/kvm/pci.c
index 920e13e..5bbcbc7 100644
--- a/tools/kvm/pci.c
+++ b/tools/kvm/pci.c
@@ -9,7 +9,7 @@
 
 static struct pci_device_header                *pci_devices[PCI_MAX_DEVICES];
 
-static struct pci_config_address       pci_config_address;
+static union pci_config_address                pci_config_address;
 
 /* This is within our PCI gap - in an unused area */
 static u32 io_space_blocks             = KVM_32BIT_GAP_START + 0x1000000;
@@ -105,7 +105,7 @@ static bool pci_config_data_out(struct ioport *ioport, 
struct kvm *kvm, u16 port
                         * When the kernel got the size it would write the 
address
                         * back.
                         */
-                       if (ioport__read32(p + offset)) {
+                       if (*(u32 *)(p + offset)) {
                                /* See if kernel tries to mask one of the BARs 
*/
                                if ((offset >= PCI_BAR_OFFSET(0)) &&
                                    (offset <= PCI_BAR_OFFSET(6)) &&
diff --git a/tools/kvm/virtio/pci.c b/tools/kvm/virtio/pci.c
index 0737ae7..0ae93fb 100644
--- a/tools/kvm/virtio/pci.c
+++ b/tools/kvm/virtio/pci.c
@@ -9,6 +9,7 @@
 #include "kvm/virtio-trans.h"
 
 #include <linux/virtio_pci.h>
+#include <linux/byteorder.h>
 #include <string.h>
 
 struct virtio_trans_ops *virtio_pci__get_trans_ops(void)
@@ -59,7 +60,7 @@ static int virtio_pci__init_ioeventfd(struct kvm *kvm, struct 
virtio_trans *vtra
 
 static inline bool virtio_pci__msix_enabled(struct virtio_pci *vpci)
 {
-       return vpci->pci_hdr.msix.ctrl & PCI_MSIX_FLAGS_ENABLE;
+       return vpci->pci_hdr.msix.ctrl & cpu_to_le16(PCI_MSIX_FLAGS_ENABLE);
 }
 
 static bool virtio_pci__specific_io_in(struct kvm *kvm, struct virtio_trans 
*vtrans, u16 port,
@@ -245,8 +246,8 @@ int virtio_pci__signal_vq(struct kvm *kvm, struct 
virtio_trans *vtrans, u32 vq)
        int tbl = vpci->vq_vector[vq];
 
        if (virtio_pci__msix_enabled(vpci)) {
-               if (vpci->pci_hdr.msix.ctrl & PCI_MSIX_FLAGS_MASKALL ||
-                       vpci->msix_table[tbl].ctrl & 
PCI_MSIX_ENTRY_CTRL_MASKBIT) {
+               if (vpci->pci_hdr.msix.ctrl & 
cpu_to_le16(PCI_MSIX_FLAGS_MASKALL) ||
+                   vpci->msix_table[tbl].ctrl & 
cpu_to_le16(PCI_MSIX_ENTRY_CTRL_MASKBIT)) {
 
                        vpci->msix_pba |= 1 << tbl;
                        return 0;
@@ -266,8 +267,8 @@ int virtio_pci__signal_config(struct kvm *kvm, struct 
virtio_trans *vtrans)
        int tbl = vpci->config_vector;
 
        if (virtio_pci__msix_enabled(vpci)) {
-               if (vpci->pci_hdr.msix.ctrl & PCI_MSIX_FLAGS_MASKALL ||
-                       vpci->msix_table[tbl].ctrl & 
PCI_MSIX_ENTRY_CTRL_MASKBIT) {
+               if (vpci->pci_hdr.msix.ctrl & 
cpu_to_le16(PCI_MSIX_FLAGS_MASKALL) ||
+                   vpci->msix_table[tbl].ctrl & 
cpu_to_le16(PCI_MSIX_ENTRY_CTRL_MASKBIT)) {
 
                        vpci->msix_pba |= 1 << tbl;
                        return 0;
@@ -297,19 +298,21 @@ int virtio_pci__init(struct kvm *kvm, struct virtio_trans 
*vtrans, void *dev,
        kvm__register_mmio(kvm, vpci->msix_pba_block, 0x100, callback_mmio_pba, 
vpci);
 
        vpci->pci_hdr = (struct pci_device_header) {
-               .vendor_id              = PCI_VENDOR_ID_REDHAT_QUMRANET,
-               .device_id              = device_id,
+               .vendor_id              = 
cpu_to_le16(PCI_VENDOR_ID_REDHAT_QUMRANET),
+               .device_id              = cpu_to_le16(device_id),
                .header_type            = PCI_HEADER_TYPE_NORMAL,
                .revision_id            = 0,
-               .class                  = class,
-               .subsys_vendor_id       = 
PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET,
-               .subsys_id              = subsys_id,
-               .bar[0]                 = vpci->base_addr | 
PCI_BASE_ADDRESS_SPACE_IO,
-               .bar[1]                 = vpci->msix_io_block | 
PCI_BASE_ADDRESS_SPACE_MEMORY
-                                       | PCI_BASE_ADDRESS_MEM_TYPE_64,
-               .bar[3]                 = vpci->msix_pba_block | 
PCI_BASE_ADDRESS_SPACE_MEMORY
-                                       | PCI_BASE_ADDRESS_MEM_TYPE_64,
-               .status                 = PCI_STATUS_CAP_LIST,
+               .class[0]               = class & 0xff,
+               .class[1]               = (class >> 8) & 0xff,
+               .class[2]               = (class >> 16) & 0xff,
+               .subsys_vendor_id       = 
cpu_to_le16(PCI_SUBSYSTEM_VENDOR_ID_REDHAT_QUMRANET),
+               .subsys_id              = cpu_to_le16(subsys_id),
+               .bar[0]                 = cpu_to_le32(vpci->base_addr | 
PCI_BASE_ADDRESS_SPACE_IO),
+               .bar[1]                 = cpu_to_le32(vpci->msix_io_block | 
PCI_BASE_ADDRESS_SPACE_MEMORY
+                                                     | 
PCI_BASE_ADDRESS_MEM_TYPE_64),
+               .bar[3]                 = cpu_to_le32(vpci->msix_pba_block | 
PCI_BASE_ADDRESS_SPACE_MEMORY
+                                                     | 
PCI_BASE_ADDRESS_MEM_TYPE_64),
+               .status                 = cpu_to_le16(PCI_STATUS_CAP_LIST),
                .capabilities           = (void *)&vpci->pci_hdr.msix - (void 
*)&vpci->pci_hdr,
        };
 
@@ -326,14 +329,14 @@ int virtio_pci__init(struct kvm *kvm, struct virtio_trans 
*vtrans, void *dev,
         * For example, a returned value of "00000000011"
         * indicates a table size of 4.
         */
-       vpci->pci_hdr.msix.ctrl = (VIRTIO_PCI_MAX_VQ + VIRTIO_PCI_MAX_CONFIG - 
1);
+       vpci->pci_hdr.msix.ctrl = cpu_to_le16(VIRTIO_PCI_MAX_VQ + 
VIRTIO_PCI_MAX_CONFIG - 1);
 
        /*
         * Both table and PBA could be mapped on the same BAR, but for now
         * we're not in short of BARs
         */
-       vpci->pci_hdr.msix.table_offset = 1; /* Use BAR 1 */
-       vpci->pci_hdr.msix.pba_offset = 3; /* Use BAR 3 */
+       vpci->pci_hdr.msix.table_offset = cpu_to_le32(1); /* Use BAR 1 */
+       vpci->pci_hdr.msix.pba_offset = cpu_to_le32(3); /* Use BAR 3 */
        vpci->config_vector = 0;
 
        if (irq__register_device(subsys_id, &ndev, &pin, &line) < 0)
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to