From patchwork Fri Dec 9 06:55:36 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matt Evans X-Patchwork-Id: 130302 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id A62701007D7 for ; Fri, 9 Dec 2011 17:54:46 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752320Ab1LIGyp (ORCPT ); Fri, 9 Dec 2011 01:54:45 -0500 Received: from ozlabs.org ([203.10.76.45]:42503 "EHLO ozlabs.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752315Ab1LIGyo (ORCPT ); Fri, 9 Dec 2011 01:54:44 -0500 Received: from [10.61.2.183] (ibmaus65.lnk.telstra.net [165.228.126.9]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPSA id 53BFC1007D6; Fri, 9 Dec 2011 17:54:43 +1100 (EST) Message-ID: <4EE1B0E8.3080808@ozlabs.org> Date: Fri, 09 Dec 2011 17:55:36 +1100 From: Matt Evans User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.23) Gecko/20110921 Thunderbird/3.1.15 MIME-Version: 1.0 To: kvm@vger.kernel.org, kvm-ppc@vger.kernel.org CC: penberg@kernel.org, asias.hejun@gmail.com, levinsasha928@gmail.com, gorcunov@gmail.com Subject: [PATCH V2 19/23] kvm tools: Endian-sanitise pci.h and PCI device setup References: In-Reply-To: Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org 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 --- 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 | 40 ++++++++++++++++++++++++++------------ tools/kvm/pci.c | 4 +- tools/kvm/virtio/pci.c | 41 +++++++++++++++++++++------------------ 6 files changed, 77 insertions(+), 57 deletions(-) -- To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html 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 +#include #include #include #include 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 #include #include @@ -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 #include #include +#include /* 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..21f93d0 100644 --- a/tools/kvm/include/kvm/pci.h +++ b/tools/kvm/include/kvm/pci.h @@ -5,6 +5,7 @@ #include #include #include +#include #define PCI_MAX_DEVICES 256 /* @@ -17,14 +18,27 @@ #define PCI_CONFIG_BUS_FORWARD 0xcfa #define PCI_IO_SIZE 0x100 -struct pci_config_address { - unsigned zeros : 2; /* 1 .. 0 */ - unsigned register_number : 6; /* 7 .. 2 */ - unsigned function_number : 3; /* 10 .. 8 */ - unsigned device_number : 5; /* 15 .. 11 */ - unsigned bus_number : 8; /* 23 .. 16 */ - unsigned reserved : 7; /* 30 .. 24 */ - unsigned enable_bit : 1; /* 31 */ +union pci_config_address { + struct { +#if __BYTE_ORDER == __LITTLE_ENDIAN + unsigned zeros : 2; /* 1 .. 0 */ + unsigned register_number : 6; /* 7 .. 2 */ + unsigned function_number : 3; /* 10 .. 8 */ + unsigned device_number : 5; /* 15 .. 11 */ + 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 +59,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 +70,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 +80,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 d9fc3a5..acb7d96 100644 --- a/tools/kvm/virtio/pci.c +++ b/tools/kvm/virtio/pci.c @@ -9,6 +9,7 @@ #include "kvm/virtio-trans.h" #include +#include #include 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, @@ -244,8 +245,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; @@ -265,8 +266,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; @@ -296,19 +297,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, }; @@ -325,14 +328,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)