mirror of
https://github.com/clearlinux/kvmtool.git
synced 2026-06-16 02:15:47 +00:00
kvm tools: Handle virtio/pci I/O space as little endian
It doesn't work on big endian hosts as is. Signed-off-by: David Daney <david.daney@cavium.com> Signed-off-by: Andreas Herrmann <andreas.herrmann@caviumnetworks.com> Signed-off-by: Pekka Enberg <penberg@kernel.org>
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
|
||||
#define PCI_BAR_OFFSET(b) (offsetof(struct pci_device_header, bar[b]))
|
||||
|
||||
static union pci_config_address pci_config_address;
|
||||
static u32 pci_config_address_bits;
|
||||
|
||||
/* This is within our PCI gap - in an unused area.
|
||||
* Note this is a PCI *bus address*, is used to assign BARs etc.!
|
||||
@@ -49,7 +49,7 @@ static void *pci_config_address_ptr(u16 port)
|
||||
void *base;
|
||||
|
||||
offset = port - PCI_CONFIG_ADDRESS;
|
||||
base = &pci_config_address;
|
||||
base = &pci_config_address_bits;
|
||||
|
||||
return base + offset;
|
||||
}
|
||||
@@ -79,6 +79,10 @@ static struct ioport_operations pci_config_address_ops = {
|
||||
|
||||
static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_number)
|
||||
{
|
||||
union pci_config_address pci_config_address;
|
||||
|
||||
pci_config_address.w = ioport__read32(&pci_config_address_bits);
|
||||
|
||||
if (pci_config_address.bus_number != bus_number)
|
||||
return false;
|
||||
|
||||
@@ -90,6 +94,9 @@ static bool pci_device_exists(u8 bus_number, u8 device_number, u8 function_numbe
|
||||
|
||||
static bool pci_config_data_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
|
||||
{
|
||||
union pci_config_address pci_config_address;
|
||||
|
||||
pci_config_address.w = ioport__read32(&pci_config_address_bits);
|
||||
/*
|
||||
* If someone accesses PCI configuration space offsets that are not
|
||||
* aligned to 4 bytes, it uses ioports to signify that.
|
||||
@@ -103,6 +110,9 @@ static bool pci_config_data_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16
|
||||
|
||||
static bool pci_config_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
|
||||
{
|
||||
union pci_config_address pci_config_address;
|
||||
|
||||
pci_config_address.w = ioport__read32(&pci_config_address_bits);
|
||||
/*
|
||||
* If someone accesses PCI configuration space offsets that are not
|
||||
* aligned to 4 bytes, it uses ioports to signify that.
|
||||
@@ -133,7 +143,7 @@ void pci__config_wr(struct kvm *kvm, union pci_config_address addr, void *data,
|
||||
void *p = device__find_dev(DEVICE_BUS_PCI, dev_num)->data;
|
||||
struct pci_device_header *hdr = p;
|
||||
u8 bar = (offset - PCI_BAR_OFFSET(0)) / (sizeof(u32));
|
||||
u32 sz = PCI_IO_SIZE;
|
||||
u32 sz = cpu_to_le32(PCI_IO_SIZE);
|
||||
|
||||
if (bar < 6 && hdr->bar_size[bar])
|
||||
sz = hdr->bar_size[bar];
|
||||
|
||||
+3
-3
@@ -385,9 +385,9 @@ int virtio_pci__init(struct kvm *kvm, void *dev, struct virtio_device *vdev,
|
||||
| PCI_BASE_ADDRESS_SPACE_MEMORY),
|
||||
.status = cpu_to_le16(PCI_STATUS_CAP_LIST),
|
||||
.capabilities = (void *)&vpci->pci_hdr.msix - (void *)&vpci->pci_hdr,
|
||||
.bar_size[0] = IOPORT_SIZE,
|
||||
.bar_size[1] = IOPORT_SIZE,
|
||||
.bar_size[2] = PCI_IO_SIZE * 2,
|
||||
.bar_size[0] = cpu_to_le32(IOPORT_SIZE),
|
||||
.bar_size[1] = cpu_to_le32(IOPORT_SIZE),
|
||||
.bar_size[2] = cpu_to_le32(PCI_IO_SIZE*2),
|
||||
};
|
||||
|
||||
vpci->dev_hdr = (struct device_header) {
|
||||
|
||||
Reference in New Issue
Block a user