xref: /qemu/tests/qtest/libqos/pci-spapr.c (revision 8360544a6d3a54df1fce80f55ba4ad075a8ded54)
1 /*
2  * libqos PCI bindings for SPAPR
3  *
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.
6  */
7 
8 #include "qemu/osdep.h"
9 #include "libqtest.h"
10 #include "libqos/pci-spapr.h"
11 #include "libqos/rtas.h"
12 
13 #include "hw/pci/pci_regs.h"
14 
15 #include "qemu-common.h"
16 #include "qemu/host-utils.h"
17 
18 
19 /* From include/hw/pci-host/spapr.h */
20 
21 typedef struct QPCIWindow {
22     uint64_t pci_base;    /* window address in PCI space */
23     uint64_t size;        /* window size */
24 } QPCIWindow;
25 
26 typedef struct QPCIBusSPAPR {
27     QPCIBus bus;
28     QGuestAllocator *alloc;
29 
30     uint64_t buid;
31 
32     uint64_t pio_cpu_base;
33     QPCIWindow pio;
34 
35     uint64_t mmio32_cpu_base;
36     QPCIWindow mmio32;
37 
38     uint64_t pci_hole_start;
39     uint64_t pci_hole_size;
40     uint64_t pci_hole_alloc;
41 
42     uint32_t pci_iohole_start;
43     uint32_t pci_iohole_size;
44     uint32_t pci_iohole_alloc;
45 } QPCIBusSPAPR;
46 
47 /*
48  * PCI devices are always little-endian
49  * SPAPR by default is big-endian
50  * so PCI accessors need to swap data endianness
51  */
52 
53 static uint8_t qpci_spapr_io_readb(QPCIBus *bus, void *addr)
54 {
55     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
56     uint64_t port = (uintptr_t)addr;
57     uint8_t v;
58     if (port < s->pio.size) {
59         v = readb(s->pio_cpu_base + port);
60     } else {
61         v = readb(s->mmio32_cpu_base + port);
62     }
63     return v;
64 }
65 
66 static uint16_t qpci_spapr_io_readw(QPCIBus *bus, void *addr)
67 {
68     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
69     uint64_t port = (uintptr_t)addr;
70     uint16_t v;
71     if (port < s->pio.size) {
72         v = readw(s->pio_cpu_base + port);
73     } else {
74         v = readw(s->mmio32_cpu_base + port);
75     }
76     return bswap16(v);
77 }
78 
79 static uint32_t qpci_spapr_io_readl(QPCIBus *bus, void *addr)
80 {
81     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
82     uint64_t port = (uintptr_t)addr;
83     uint32_t v;
84     if (port < s->pio.size) {
85         v = readl(s->pio_cpu_base + port);
86     } else {
87         v = readl(s->mmio32_cpu_base + port);
88     }
89     return bswap32(v);
90 }
91 
92 static void qpci_spapr_io_writeb(QPCIBus *bus, void *addr, uint8_t value)
93 {
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);
98     } else {
99         writeb(s->mmio32_cpu_base + port, value);
100     }
101 }
102 
103 static void qpci_spapr_io_writew(QPCIBus *bus, void *addr, uint16_t value)
104 {
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);
110     } else {
111         writew(s->mmio32_cpu_base + port, value);
112     }
113 }
114 
115 static void qpci_spapr_io_writel(QPCIBus *bus, void *addr, uint32_t value)
116 {
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);
122     } else {
123         writel(s->mmio32_cpu_base + port, value);
124     }
125 }
126 
127 static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
128 {
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);
132 }
133 
134 static uint16_t qpci_spapr_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
135 {
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);
139 }
140 
141 static uint32_t qpci_spapr_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
142 {
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);
146 }
147 
148 static void qpci_spapr_config_writeb(QPCIBus *bus, int devfn, uint8_t offset,
149                                      uint8_t value)
150 {
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);
154 }
155 
156 static void qpci_spapr_config_writew(QPCIBus *bus, int devfn, uint8_t offset,
157                                      uint16_t value)
158 {
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);
162 }
163 
164 static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset,
165                                      uint32_t value)
166 {
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);
170 }
171 
172 static void *qpci_spapr_iomap(QPCIBus *bus, QPCIDevice *dev, int barno,
173                               uint64_t *sizeptr)
174 {
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,
179     };
180     int bar_reg;
181     uint32_t addr;
182     uint64_t size;
183     uint32_t io_type;
184 
185     g_assert(barno >= 0 && barno <= 5);
186     bar_reg = bar_reg_map[barno];
187 
188     qpci_config_writel(dev, bar_reg, 0xFFFFFFFF);
189     addr = qpci_config_readl(dev, bar_reg);
190 
191     io_type = addr & PCI_BASE_ADDRESS_SPACE;
192     if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
193         addr &= PCI_BASE_ADDRESS_IO_MASK;
194     } else {
195         addr &= PCI_BASE_ADDRESS_MEM_MASK;
196     }
197 
198     size = (1ULL << ctzl(addr));
199     if (size == 0) {
200         return NULL;
201     }
202     if (sizeptr) {
203         *sizeptr = size;
204     }
205 
206     if (io_type == PCI_BASE_ADDRESS_SPACE_IO) {
207         uint16_t loc;
208 
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;
214 
215         qpci_config_writel(dev, bar_reg, loc | PCI_BASE_ADDRESS_SPACE_IO);
216 
217         return (void *)(unsigned long)loc;
218     } else {
219         uint64_t loc;
220 
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;
226 
227         qpci_config_writel(dev, bar_reg, loc);
228 
229         return (void *)(unsigned long)loc;
230     }
231 }
232 
233 static void qpci_spapr_iounmap(QPCIBus *bus, void *data)
234 {
235     /* FIXME */
236 }
237 
238 #define SPAPR_PCI_WINDOW_BASE        0x10000000000ULL
239 #define SPAPR_PCI_MMIO32_WIN_OFF     0xA0000000
240 #define SPAPR_PCI_MMIO32_WIN_SIZE    0x80000000 /* 2 GiB */
241 #define SPAPR_PCI_IO_WIN_OFF         0x80000000
242 #define SPAPR_PCI_IO_WIN_SIZE        0x10000
243 
244 QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
245 {
246     QPCIBusSPAPR *ret;
247 
248     ret = g_malloc(sizeof(*ret));
249 
250     ret->alloc = alloc;
251 
252     ret->bus.io_readb = qpci_spapr_io_readb;
253     ret->bus.io_readw = qpci_spapr_io_readw;
254     ret->bus.io_readl = qpci_spapr_io_readl;
255 
256     ret->bus.io_writeb = qpci_spapr_io_writeb;
257     ret->bus.io_writew = qpci_spapr_io_writew;
258     ret->bus.io_writel = qpci_spapr_io_writel;
259 
260     ret->bus.config_readb = qpci_spapr_config_readb;
261     ret->bus.config_readw = qpci_spapr_config_readw;
262     ret->bus.config_readl = qpci_spapr_config_readl;
263 
264     ret->bus.config_writeb = qpci_spapr_config_writeb;
265     ret->bus.config_writew = qpci_spapr_config_writew;
266     ret->bus.config_writel = qpci_spapr_config_writel;
267 
268     ret->bus.iomap = qpci_spapr_iomap;
269     ret->bus.iounmap = qpci_spapr_iounmap;
270 
271     /* FIXME: We assume the default location of the PHB for now.
272      * Ideally we'd parse the device tree deposited in the guest to
273      * get the window locations */
274     ret->buid = 0x800000020000000ULL;
275 
276     ret->pio_cpu_base = SPAPR_PCI_WINDOW_BASE + SPAPR_PCI_IO_WIN_OFF;
277     ret->pio.pci_base = 0;
278     ret->pio.size = SPAPR_PCI_IO_WIN_SIZE;
279 
280     /* 32-bit portion of the MMIO window is at PCI address 2..4 GiB */
281     ret->mmio32_cpu_base = SPAPR_PCI_WINDOW_BASE + SPAPR_PCI_MMIO32_WIN_OFF;
282     ret->mmio32.pci_base = 0x80000000; /* 2 GiB */
283     ret->mmio32.size = SPAPR_PCI_MMIO32_WIN_SIZE;
284 
285     ret->pci_hole_start = 0xC0000000;
286     ret->pci_hole_size =
287         ret->mmio32.pci_base + ret->mmio32.size - ret->pci_hole_start;
288     ret->pci_hole_alloc = 0;
289 
290     ret->pci_iohole_start = 0xc000;
291     ret->pci_iohole_size =
292         ret->pio.pci_base + ret->pio.size - ret->pci_iohole_start;
293     ret->pci_iohole_alloc = 0;
294 
295     return &ret->bus;
296 }
297 
298 void qpci_free_spapr(QPCIBus *bus)
299 {
300     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
301 
302     g_free(s);
303 }
304