2 * libqos PCI bindings for SPAPR
4 * This work is licensed under the terms of the GNU GPL, version 2 or later.
5 * See the COPYING file in the top-level directory.
8 #include "qemu/osdep.h"
10 #include "libqos/pci-spapr.h"
11 #include "libqos/rtas.h"
12 #include "libqos/qgraph.h"
14 #include "hw/pci/pci_regs.h"
16 #include "qemu/host-utils.h"
17 #include "qemu/module.h"
20 * PCI devices are always little-endian
21 * SPAPR by default is big-endian
22 * so PCI accessors need to swap data endianness
25 static uint8_t qpci_spapr_pio_readb(QPCIBus
*bus
, uint32_t addr
)
27 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
28 return qtest_readb(bus
->qts
, s
->pio_cpu_base
+ addr
);
31 static void qpci_spapr_pio_writeb(QPCIBus
*bus
, uint32_t addr
, uint8_t val
)
33 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
34 qtest_writeb(bus
->qts
, s
->pio_cpu_base
+ addr
, val
);
37 static uint16_t qpci_spapr_pio_readw(QPCIBus
*bus
, uint32_t addr
)
39 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
40 return bswap16(qtest_readw(bus
->qts
, s
->pio_cpu_base
+ addr
));
43 static void qpci_spapr_pio_writew(QPCIBus
*bus
, uint32_t addr
, uint16_t val
)
45 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
46 qtest_writew(bus
->qts
, s
->pio_cpu_base
+ addr
, bswap16(val
));
49 static uint32_t qpci_spapr_pio_readl(QPCIBus
*bus
, uint32_t addr
)
51 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
52 return bswap32(qtest_readl(bus
->qts
, s
->pio_cpu_base
+ addr
));
55 static void qpci_spapr_pio_writel(QPCIBus
*bus
, uint32_t addr
, uint32_t val
)
57 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
58 qtest_writel(bus
->qts
, s
->pio_cpu_base
+ addr
, bswap32(val
));
61 static uint64_t qpci_spapr_pio_readq(QPCIBus
*bus
, uint32_t addr
)
63 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
64 return bswap64(qtest_readq(bus
->qts
, s
->pio_cpu_base
+ addr
));
67 static void qpci_spapr_pio_writeq(QPCIBus
*bus
, uint32_t addr
, uint64_t val
)
69 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
70 qtest_writeq(bus
->qts
, s
->pio_cpu_base
+ addr
, bswap64(val
));
73 static void qpci_spapr_memread(QPCIBus
*bus
, uint32_t addr
,
74 void *buf
, size_t len
)
76 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
77 qtest_memread(bus
->qts
, s
->mmio32_cpu_base
+ addr
, buf
, len
);
80 static void qpci_spapr_memwrite(QPCIBus
*bus
, uint32_t addr
,
81 const void *buf
, size_t len
)
83 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
84 qtest_memwrite(bus
->qts
, s
->mmio32_cpu_base
+ addr
, buf
, len
);
87 static uint8_t qpci_spapr_config_readb(QPCIBus
*bus
, int devfn
, uint8_t offset
)
89 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
90 uint32_t config_addr
= (devfn
<< 8) | offset
;
91 return qrtas_ibm_read_pci_config(bus
->qts
, s
->alloc
, s
->buid
,
95 static uint16_t qpci_spapr_config_readw(QPCIBus
*bus
, int devfn
, uint8_t offset
)
97 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
98 uint32_t config_addr
= (devfn
<< 8) | offset
;
99 return qrtas_ibm_read_pci_config(bus
->qts
, s
->alloc
, s
->buid
,
103 static uint32_t qpci_spapr_config_readl(QPCIBus
*bus
, int devfn
, uint8_t offset
)
105 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
106 uint32_t config_addr
= (devfn
<< 8) | offset
;
107 return qrtas_ibm_read_pci_config(bus
->qts
, s
->alloc
, s
->buid
,
111 static void qpci_spapr_config_writeb(QPCIBus
*bus
, int devfn
, uint8_t offset
,
114 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
115 uint32_t config_addr
= (devfn
<< 8) | offset
;
116 qrtas_ibm_write_pci_config(bus
->qts
, s
->alloc
, s
->buid
,
117 config_addr
, 1, value
);
120 static void qpci_spapr_config_writew(QPCIBus
*bus
, int devfn
, uint8_t offset
,
123 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
124 uint32_t config_addr
= (devfn
<< 8) | offset
;
125 qrtas_ibm_write_pci_config(bus
->qts
, s
->alloc
, s
->buid
,
126 config_addr
, 2, value
);
129 static void qpci_spapr_config_writel(QPCIBus
*bus
, int devfn
, uint8_t offset
,
132 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);
133 uint32_t config_addr
= (devfn
<< 8) | offset
;
134 qrtas_ibm_write_pci_config(bus
->qts
, s
->alloc
, s
->buid
,
135 config_addr
, 4, value
);
138 #define SPAPR_PCI_BASE (1ULL << 45)
140 #define SPAPR_PCI_MMIO32_WIN_SIZE 0x80000000 /* 2 GiB */
141 #define SPAPR_PCI_IO_WIN_SIZE 0x10000
143 static void *qpci_spapr_get_driver(void *obj
, const char *interface
)
145 QPCIBusSPAPR
*qpci
= obj
;
146 if (!g_strcmp0(interface
, "pci-bus")) {
149 fprintf(stderr
, "%s not present in pci-bus-spapr", interface
);
150 g_assert_not_reached();
153 void qpci_init_spapr(QPCIBusSPAPR
*qpci
, QTestState
*qts
,
154 QGuestAllocator
*alloc
)
158 /* tests cannot use spapr, needs to be fixed first */
159 qpci
->bus
.has_buggy_msi
= true;
163 qpci
->bus
.pio_readb
= qpci_spapr_pio_readb
;
164 qpci
->bus
.pio_readw
= qpci_spapr_pio_readw
;
165 qpci
->bus
.pio_readl
= qpci_spapr_pio_readl
;
166 qpci
->bus
.pio_readq
= qpci_spapr_pio_readq
;
168 qpci
->bus
.pio_writeb
= qpci_spapr_pio_writeb
;
169 qpci
->bus
.pio_writew
= qpci_spapr_pio_writew
;
170 qpci
->bus
.pio_writel
= qpci_spapr_pio_writel
;
171 qpci
->bus
.pio_writeq
= qpci_spapr_pio_writeq
;
173 qpci
->bus
.memread
= qpci_spapr_memread
;
174 qpci
->bus
.memwrite
= qpci_spapr_memwrite
;
176 qpci
->bus
.config_readb
= qpci_spapr_config_readb
;
177 qpci
->bus
.config_readw
= qpci_spapr_config_readw
;
178 qpci
->bus
.config_readl
= qpci_spapr_config_readl
;
180 qpci
->bus
.config_writeb
= qpci_spapr_config_writeb
;
181 qpci
->bus
.config_writew
= qpci_spapr_config_writew
;
182 qpci
->bus
.config_writel
= qpci_spapr_config_writel
;
184 /* FIXME: We assume the default location of the PHB for now.
185 * Ideally we'd parse the device tree deposited in the guest to
186 * get the window locations */
187 qpci
->buid
= 0x800000020000000ULL
;
189 qpci
->pio_cpu_base
= SPAPR_PCI_BASE
;
190 qpci
->pio
.pci_base
= 0;
191 qpci
->pio
.size
= SPAPR_PCI_IO_WIN_SIZE
;
193 /* 32-bit portion of the MMIO window is at PCI address 2..4 GiB */
194 qpci
->mmio32_cpu_base
= SPAPR_PCI_BASE
;
195 qpci
->mmio32
.pci_base
= SPAPR_PCI_MMIO32_WIN_SIZE
;
196 qpci
->mmio32
.size
= SPAPR_PCI_MMIO32_WIN_SIZE
;
199 qpci
->bus
.pio_alloc_ptr
= 0xc000;
200 qpci
->bus
.mmio_alloc_ptr
= qpci
->mmio32
.pci_base
;
201 qpci
->bus
.mmio_limit
= qpci
->mmio32
.pci_base
+ qpci
->mmio32
.size
;
203 qpci
->obj
.get_driver
= qpci_spapr_get_driver
;
206 QPCIBus
*qpci_new_spapr(QTestState
*qts
, QGuestAllocator
*alloc
)
208 QPCIBusSPAPR
*qpci
= g_new0(QPCIBusSPAPR
, 1);
209 qpci_init_spapr(qpci
, qts
, alloc
);
214 void qpci_free_spapr(QPCIBus
*bus
)
221 s
= container_of(bus
, QPCIBusSPAPR
, bus
);
226 static void qpci_spapr_register_nodes(void)
228 qos_node_create_driver("pci-bus-spapr", NULL
);
229 qos_node_produces("pci-bus-spapr", "pci-bus");
232 libqos_init(qpci_spapr_register_nodes
);