xref: /qemu/tests/qtest/libqos/pci-spapr.c (revision b8cc4d0231b97c3dd7930d91ab91657b5a105b78)
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 } QPCIBusSPAPR;
38 
39 /*
40  * PCI devices are always little-endian
41  * SPAPR by default is big-endian
42  * so PCI accessors need to swap data endianness
43  */
44 
45 static uint8_t qpci_spapr_pio_readb(QPCIBus *bus, uint32_t addr)
46 {
47     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
48     return readb(s->pio_cpu_base + addr);
49 }
50 
51 static uint8_t qpci_spapr_mmio32_readb(QPCIBus *bus, uint32_t addr)
52 {
53     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
54     return readb(s->mmio32_cpu_base + addr);
55 }
56 
57 static void qpci_spapr_pio_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
58 {
59     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
60     writeb(s->pio_cpu_base + addr, val);
61 }
62 
63 static void qpci_spapr_mmio32_writeb(QPCIBus *bus, uint32_t addr, uint8_t val)
64 {
65     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
66     writeb(s->mmio32_cpu_base + addr, val);
67 }
68 
69 static uint16_t qpci_spapr_pio_readw(QPCIBus *bus, uint32_t addr)
70 {
71     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
72     return bswap16(readw(s->pio_cpu_base + addr));
73 }
74 
75 static uint16_t qpci_spapr_mmio32_readw(QPCIBus *bus, uint32_t addr)
76 {
77     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
78     return bswap16(readw(s->mmio32_cpu_base + addr));
79 }
80 
81 static void qpci_spapr_pio_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
82 {
83     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
84     writew(s->pio_cpu_base + addr, bswap16(val));
85 }
86 
87 static void qpci_spapr_mmio32_writew(QPCIBus *bus, uint32_t addr, uint16_t val)
88 {
89     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
90     writew(s->mmio32_cpu_base + addr, bswap16(val));
91 }
92 
93 static uint32_t qpci_spapr_pio_readl(QPCIBus *bus, uint32_t addr)
94 {
95     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
96     return bswap32(readl(s->pio_cpu_base + addr));
97 }
98 
99 static uint32_t qpci_spapr_mmio32_readl(QPCIBus *bus, uint32_t addr)
100 {
101     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
102     return bswap32(readl(s->mmio32_cpu_base + addr));
103 }
104 
105 static void qpci_spapr_pio_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
106 {
107     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
108     writel(s->pio_cpu_base + addr, bswap32(val));
109 }
110 
111 static void qpci_spapr_mmio32_writel(QPCIBus *bus, uint32_t addr, uint32_t val)
112 {
113     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
114     writel(s->mmio32_cpu_base + addr, bswap32(val));
115 }
116 
117 static uint8_t qpci_spapr_config_readb(QPCIBus *bus, int devfn, uint8_t offset)
118 {
119     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
120     uint32_t config_addr = (devfn << 8) | offset;
121     return qrtas_ibm_read_pci_config(s->alloc, s->buid, config_addr, 1);
122 }
123 
124 static uint16_t qpci_spapr_config_readw(QPCIBus *bus, int devfn, uint8_t offset)
125 {
126     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
127     uint32_t config_addr = (devfn << 8) | offset;
128     return qrtas_ibm_read_pci_config(s->alloc, s->buid, config_addr, 2);
129 }
130 
131 static uint32_t qpci_spapr_config_readl(QPCIBus *bus, int devfn, uint8_t offset)
132 {
133     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
134     uint32_t config_addr = (devfn << 8) | offset;
135     return qrtas_ibm_read_pci_config(s->alloc, s->buid, config_addr, 4);
136 }
137 
138 static void qpci_spapr_config_writeb(QPCIBus *bus, int devfn, uint8_t offset,
139                                      uint8_t value)
140 {
141     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
142     uint32_t config_addr = (devfn << 8) | offset;
143     qrtas_ibm_write_pci_config(s->alloc, s->buid, config_addr, 1, value);
144 }
145 
146 static void qpci_spapr_config_writew(QPCIBus *bus, int devfn, uint8_t offset,
147                                      uint16_t value)
148 {
149     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
150     uint32_t config_addr = (devfn << 8) | offset;
151     qrtas_ibm_write_pci_config(s->alloc, s->buid, config_addr, 2, value);
152 }
153 
154 static void qpci_spapr_config_writel(QPCIBus *bus, int devfn, uint8_t offset,
155                                      uint32_t value)
156 {
157     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
158     uint32_t config_addr = (devfn << 8) | offset;
159     qrtas_ibm_write_pci_config(s->alloc, s->buid, config_addr, 4, value);
160 }
161 
162 #define SPAPR_PCI_BASE               (1ULL << 45)
163 
164 #define SPAPR_PCI_MMIO32_WIN_SIZE    0x80000000 /* 2 GiB */
165 #define SPAPR_PCI_IO_WIN_SIZE        0x10000
166 
167 QPCIBus *qpci_init_spapr(QGuestAllocator *alloc)
168 {
169     QPCIBusSPAPR *ret;
170 
171     ret = g_malloc(sizeof(*ret));
172 
173     ret->alloc = alloc;
174 
175     ret->bus.pio_readb = qpci_spapr_pio_readb;
176     ret->bus.pio_readw = qpci_spapr_pio_readw;
177     ret->bus.pio_readl = qpci_spapr_pio_readl;
178 
179     ret->bus.pio_writeb = qpci_spapr_pio_writeb;
180     ret->bus.pio_writew = qpci_spapr_pio_writew;
181     ret->bus.pio_writel = qpci_spapr_pio_writel;
182 
183     ret->bus.mmio_readb = qpci_spapr_mmio32_readb;
184     ret->bus.mmio_readw = qpci_spapr_mmio32_readw;
185     ret->bus.mmio_readl = qpci_spapr_mmio32_readl;
186 
187     ret->bus.mmio_writeb = qpci_spapr_mmio32_writeb;
188     ret->bus.mmio_writew = qpci_spapr_mmio32_writew;
189     ret->bus.mmio_writel = qpci_spapr_mmio32_writel;
190 
191     ret->bus.config_readb = qpci_spapr_config_readb;
192     ret->bus.config_readw = qpci_spapr_config_readw;
193     ret->bus.config_readl = qpci_spapr_config_readl;
194 
195     ret->bus.config_writeb = qpci_spapr_config_writeb;
196     ret->bus.config_writew = qpci_spapr_config_writew;
197     ret->bus.config_writel = qpci_spapr_config_writel;
198 
199     /* FIXME: We assume the default location of the PHB for now.
200      * Ideally we'd parse the device tree deposited in the guest to
201      * get the window locations */
202     ret->buid = 0x800000020000000ULL;
203 
204     ret->pio_cpu_base = SPAPR_PCI_BASE;
205     ret->pio.pci_base = 0;
206     ret->pio.size = SPAPR_PCI_IO_WIN_SIZE;
207 
208     /* 32-bit portion of the MMIO window is at PCI address 2..4 GiB */
209     ret->mmio32_cpu_base = SPAPR_PCI_BASE + SPAPR_PCI_MMIO32_WIN_SIZE;
210     ret->mmio32.pci_base = 0x80000000; /* 2 GiB */
211     ret->mmio32.size = SPAPR_PCI_MMIO32_WIN_SIZE;
212 
213     ret->bus.pio_alloc_ptr = 0xc000;
214     ret->bus.mmio_alloc_ptr = ret->mmio32.pci_base;
215     ret->bus.mmio_limit = ret->mmio32.pci_base + ret->mmio32.size;
216 
217     return &ret->bus;
218 }
219 
220 void qpci_free_spapr(QPCIBus *bus)
221 {
222     QPCIBusSPAPR *s = container_of(bus, QPCIBusSPAPR, bus);
223 
224     g_free(s);
225 }
226