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"
13 #include "hw/pci/pci_regs.h"
15 #include "qemu-common.h"
16 #include "qemu/host-utils.h"
19 /* From include/hw/pci-host/spapr.h */
21 typedef struct QPCIWindow {
22 uint64_t pci_base; /* window address in PCI space */
23 uint64_t size; /* window size */
26 typedef struct QPCIBusSPAPR {
28 QGuestAllocator *alloc;
32 uint64_t pio_cpu_base;
35 uint64_t mmio_cpu_base;
38 uint64_t pci_hole_start;
39 uint64_t pci_hole_size;
40 uint64_t pci_hole_alloc;
42 uint32_t pci_iohole_start;
43 uint32_t pci_iohole_size;
44 uint32_t pci_iohole_alloc;
48 * PCI devices are always little-endian
49 * SPAPR by default is big-endian
50 * so PCI accessors need to swap data endianness
53 static uint8_t qpci_spapr_io_readb(QPCIBus *bus, void *addr)
55 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
56 uint64_t port = (uintptr_t)addr;
58 if (port < s->pio.size) {
59 v = readb(s->pio_cpu_base + port);
61 v = readb(s->mmio_cpu_base + port);
66 static uint16_t qpci_spapr_io_readw(QPCIBus *bus, void *addr)
68 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
69 uint64_t port = (uintptr_t)addr;
71 if (port < s->pio.size) {
72 v = readw(s->pio_cpu_base + port);
74 v = readw(s->mmio_cpu_base + port);
79 static uint32_t qpci_spapr_io_readl(QPCIBus *bus, void *addr)
81 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
82 uint64_t port = (uintptr_t)addr;
84 if (port < s->pio.size) {
85 v = readl(s->pio_cpu_base + port);
87 v = readl(s->mmio_cpu_base + port);
92 static void qpci_spapr_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
94 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
95 uint64_t port = (uintptr_t)addr;
96 if (port < s->pio.size) {
97 writeb(s->pio_cpu_base + port, value);
99 writeb(s->mmio_cpu_base + port, value);
103 static void qpci_spapr_io_writew(QPCIBus *bus, void *addr, uint16_t value)
105 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
106 uint64_t port = (uintptr_t)addr;
107 value = bswap16(value);
108 if (port < s->pio.size) {
109 writew(s->pio_cpu_base + port, value);
111 writew(s->mmio_cpu_base + port, value);
115 static void qpci_spapr_io_writel(QPCIBus *bus, void *addr, uint32_t value)
117 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
118 uint64_t port = (uintptr_t)addr;
119 value = bswap32(value);
120 if (port < s->pio.size) {
121 writel(s->pio_cpu_base + port, value);
123 writel(s->mmio_cpu_base + port, value);
127 static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
129 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
130 uint32_t config_addr = (devfn << 8) | offset;
131 return qrtas_ibm_read_pci_config(s->alloc, s->buid, config_addr, 1);
134 static uint16_t qpci_spapr_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
136 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
137 uint32_t config_addr = (devfn << 8) | offset;
138 return qrtas_ibm_read_pci_config(s->alloc, s->buid, config_addr, 2);
141 static uint32_t qpci_spapr_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
143 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
144 uint32_t config_addr = (devfn << 8) | offset;
145 return qrtas_ibm_read_pci_config(s->alloc, s->buid, config_addr, 4);
148 static void qpci_spapr_config_writeb(QPCIBus *bus, int devfn, uint8_t offset,
151 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
152 uint32_t config_addr = (devfn << 8) | offset;
153 qrtas_ibm_write_pci_config(s->alloc, s->buid, config_addr, 1, value);
156 static void qpci_spapr_config_writew(QPCIBus *bus, int devfn, uint8_t offset,
159 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
160 uint32_t config_addr = (devfn << 8) | offset;
161 qrtas_ibm_write_pci_config(s->alloc, s->buid, config_addr, 2, value);
164 static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset,
167 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
168 uint32_t config_addr = (devfn << 8) | offset;
169 qrtas_ibm_write_pci_config(s->alloc, s->buid, config_addr, 4, value);
172 static void *qpci_spapr_iomap(QPCIBus *bus, QPCIDevice *dev, int barno,
175 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
176 static const int bar_reg_map[] = {
177 PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_2,
178 PCI_BASE_ADDRESS_3, PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5,
185 g_assert(barno >= 0 && barno <= 5);
186 bar_reg = bar_reg_map[barno];
188 qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
189 addr = qpci_config_readl(dev, bar_reg);
191 io_type = addr & PCI_BASE_ADDRESS_SPACE;
192 if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
193 addr &= PCI_BASE_ADDRESS_IO_MASK;
195 addr &= PCI_BASE_ADDRESS_MEM_MASK;
198 size = (1ULL << ctzl(addr));
206 if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
209 g_assert(QEMU_ALIGN_UP(s->pci_iohole_alloc, size) + size
210 <= s->pci_iohole_size);
211 s->pci_iohole_alloc = QEMU_ALIGN_UP(s->pci_iohole_alloc, size);
212 loc = s->pci_iohole_start + s->pci_iohole_alloc;
213 s->pci_iohole_alloc += size;
215 qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
217 return (void *)(unsigned long)loc;
221 g_assert(QEMU_ALIGN_UP(s->pci_hole_alloc, size) + size
222 <= s->pci_hole_size);
223 s->pci_hole_alloc = QEMU_ALIGN_UP(s->pci_hole_alloc, size);
224 loc = s->pci_hole_start + s->pci_hole_alloc;
225 s->pci_hole_alloc += size;
227 qpci_config_writel(dev, bar_reg, loc);
229 return (void *)(unsigned long)loc;
233 static void qpci_spapr_iounmap(QPCIBus *bus, void *data)
238 #define SPAPR_PCI_MEM_WIN_BUS_OFFSET 0x80000000ULL
239 #define SPAPR_PCI_WINDOW_BASE 0x10000000000ULL
240 #define SPAPR_PCI_WINDOW_SPACING 0x1000000000ULL
241 #define SPAPR_PCI_MMIO_WIN_OFF 0xA0000000
242 #define SPAPR_PCI_MMIO_WIN_SIZE (SPAPR_PCI_WINDOW_SPACING - \
243 SPAPR_PCI_MEM_WIN_BUS_OFFSET)
244 #define SPAPR_PCI_IO_WIN_OFF 0x80000000
245 #define SPAPR_PCI_IO_WIN_SIZE 0x10000
247 QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
251 ret = g_malloc(sizeof(*ret));
255 ret->bus.io_readb = qpci_spapr_io_readb;
256 ret->bus.io_readw = qpci_spapr_io_readw;
257 ret->bus.io_readl = qpci_spapr_io_readl;
259 ret->bus.io_writeb = qpci_spapr_io_writeb;
260 ret->bus.io_writew = qpci_spapr_io_writew;
261 ret->bus.io_writel = qpci_spapr_io_writel;
263 ret->bus.config_readb = qpci_spapr_config_readb;
264 ret->bus.config_readw = qpci_spapr_config_readw;
265 ret->bus.config_readl = qpci_spapr_config_readl;
267 ret->bus.config_writeb = qpci_spapr_config_writeb;
268 ret->bus.config_writew = qpci_spapr_config_writew;
269 ret->bus.config_writel = qpci_spapr_config_writel;
271 ret->bus.iomap = qpci_spapr_iomap;
272 ret->bus.iounmap = qpci_spapr_iounmap;
274 /* FIXME: We assume the default location of the PHB for now.
275 * Ideally we'd parse the device tree deposited in the guest to
276 * get the window locations */
277 ret->buid = 0x800000020000000ULL;
279 ret->pio_cpu_base = SPAPR_PCI_WINDOW_BASE + SPAPR_PCI_IO_WIN_OFF;
280 ret->pio.pci_base = 0;
281 ret->pio.size = SPAPR_PCI_IO_WIN_SIZE;
283 ret->mmio_cpu_base = SPAPR_PCI_WINDOW_BASE + SPAPR_PCI_MMIO_WIN_OFF;
284 ret->mmio.pci_base = SPAPR_PCI_MEM_WIN_BUS_OFFSET;
285 ret->mmio.size = SPAPR_PCI_MMIO_WIN_SIZE;
287 ret->pci_hole_start = 0xC0000000;
288 ret->pci_hole_size = SPAPR_PCI_MMIO_WIN_SIZE;
289 ret->pci_hole_alloc = 0;
291 ret->pci_iohole_start = 0xc000;
292 ret->pci_iohole_size = SPAPR_PCI_IO_WIN_SIZE;
293 ret->pci_iohole_alloc = 0;
298 void qpci_free_spapr(QPCIBus *bus)
300 QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);