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 mmio32_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
->mmio32_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
->mmio32_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
->mmio32_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
->mmio32_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
->mmio32_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
->mmio32_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_BASE (1ULL << 45)
240 #define SPAPR_PCI_MMIO32_WIN_SIZE 0x80000000 /* 2 GiB */
241 #define SPAPR_PCI_IO_WIN_SIZE 0x10000
243 QPCIBus
*qpci_init_spapr(QGuestAllocator
*alloc
)
247 ret
= g_malloc(sizeof(*ret
));
251 ret
->bus
.io_readb
= qpci_spapr_io_readb
;
252 ret
->bus
.io_readw
= qpci_spapr_io_readw
;
253 ret
->bus
.io_readl
= qpci_spapr_io_readl
;
255 ret
->bus
.io_writeb
= qpci_spapr_io_writeb
;
256 ret
->bus
.io_writew
= qpci_spapr_io_writew
;
257 ret
->bus
.io_writel
= qpci_spapr_io_writel
;
259 ret
->bus
.config_readb
= qpci_spapr_config_readb
;
260 ret
->bus
.config_readw
= qpci_spapr_config_readw
;
261 ret
->bus
.config_readl
= qpci_spapr_config_readl
;
263 ret
->bus
.config_writeb
= qpci_spapr_config_writeb
;
264 ret
->bus
.config_writew
= qpci_spapr_config_writew
;
265 ret
->bus
.config_writel
= qpci_spapr_config_writel
;
267 ret
->bus
.iomap
= qpci_spapr_iomap
;
268 ret
->bus
.iounmap
= qpci_spapr_iounmap
;
270 /* FIXME: We assume the default location of the PHB for now.
271 * Ideally we'd parse the device tree deposited in the guest to
272 * get the window locations */
273 ret
->buid
= 0x800000020000000ULL
;
275 ret
->pio_cpu_base
= SPAPR_PCI_BASE
;
276 ret
->pio
.pci_base
= 0;
277 ret
->pio
.size
= SPAPR_PCI_IO_WIN_SIZE
;
279 /* 32-bit portion of the MMIO window is at PCI address 2..4 GiB */
280 ret
->mmio32_cpu_base
= SPAPR_PCI_BASE
+ SPAPR_PCI_MMIO32_WIN_SIZE
;
281 ret
->mmio32
.pci_base
= 0x80000000; /* 2 GiB */
282 ret
->mmio32
.size
= SPAPR_PCI_MMIO32_WIN_SIZE
;
284 ret
->pci_hole_start
= 0xC0000000;
286 ret
->mmio32
.pci_base
+ ret
->mmio32
.size
- ret
->pci_hole_start
;
287 ret
->pci_hole_alloc
= 0;
289 ret
->pci_iohole_start
= 0xc000;
290 ret
->pci_iohole_size
=
291 ret
->pio
.pci_base
+ ret
->pio
.size
- ret
->pci_iohole_start
;
292 ret
->pci_iohole_alloc
= 0;
297 void qpci_free_spapr(QPCIBus
*bus
)
299 QPCIBusSPAPR
*s
= container_of(bus
, QPCIBusSPAPR
, bus
);