xref: /openbmc/qemu/hw/pci/msi.c (revision a23797ef)
1 /*
2  * msi.c
3  *
4  * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
5  *                    VA Linux Systems Japan K.K.
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11 
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16 
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, see <http://www.gnu.org/licenses/>.
19  */
20 
21 #include "hw/pci/msi.h"
22 #include "qemu/range.h"
23 
24 /* PCI_MSI_ADDRESS_LO */
25 #define PCI_MSI_ADDRESS_LO_MASK         (~0x3)
26 
27 /* If we get rid of cap allocator, we won't need those. */
28 #define PCI_MSI_32_SIZEOF       0x0a
29 #define PCI_MSI_64_SIZEOF       0x0e
30 #define PCI_MSI_32M_SIZEOF      0x14
31 #define PCI_MSI_64M_SIZEOF      0x18
32 
33 #define PCI_MSI_VECTORS_MAX     32
34 
35 /* Flag for interrupt controller to declare MSI/MSI-X support */
36 bool msi_supported;
37 
38 /* If we get rid of cap allocator, we won't need this. */
39 static inline uint8_t msi_cap_sizeof(uint16_t flags)
40 {
41     switch (flags & (PCI_MSI_FLAGS_MASKBIT | PCI_MSI_FLAGS_64BIT)) {
42     case PCI_MSI_FLAGS_MASKBIT | PCI_MSI_FLAGS_64BIT:
43         return PCI_MSI_64M_SIZEOF;
44     case PCI_MSI_FLAGS_64BIT:
45         return PCI_MSI_64_SIZEOF;
46     case PCI_MSI_FLAGS_MASKBIT:
47         return PCI_MSI_32M_SIZEOF;
48     case 0:
49         return PCI_MSI_32_SIZEOF;
50     default:
51         abort();
52         break;
53     }
54     return 0;
55 }
56 
57 //#define MSI_DEBUG
58 
59 #ifdef MSI_DEBUG
60 # define MSI_DPRINTF(fmt, ...)                                          \
61     fprintf(stderr, "%s:%d " fmt, __func__, __LINE__, ## __VA_ARGS__)
62 #else
63 # define MSI_DPRINTF(fmt, ...)  do { } while (0)
64 #endif
65 #define MSI_DEV_PRINTF(dev, fmt, ...)                                   \
66     MSI_DPRINTF("%s:%x " fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
67 
68 static inline unsigned int msi_nr_vectors(uint16_t flags)
69 {
70     return 1U <<
71         ((flags & PCI_MSI_FLAGS_QSIZE) >> ctz32(PCI_MSI_FLAGS_QSIZE));
72 }
73 
74 static inline uint8_t msi_flags_off(const PCIDevice* dev)
75 {
76     return dev->msi_cap + PCI_MSI_FLAGS;
77 }
78 
79 static inline uint8_t msi_address_lo_off(const PCIDevice* dev)
80 {
81     return dev->msi_cap + PCI_MSI_ADDRESS_LO;
82 }
83 
84 static inline uint8_t msi_address_hi_off(const PCIDevice* dev)
85 {
86     return dev->msi_cap + PCI_MSI_ADDRESS_HI;
87 }
88 
89 static inline uint8_t msi_data_off(const PCIDevice* dev, bool msi64bit)
90 {
91     return dev->msi_cap + (msi64bit ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32);
92 }
93 
94 static inline uint8_t msi_mask_off(const PCIDevice* dev, bool msi64bit)
95 {
96     return dev->msi_cap + (msi64bit ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32);
97 }
98 
99 static inline uint8_t msi_pending_off(const PCIDevice* dev, bool msi64bit)
100 {
101     return dev->msi_cap + (msi64bit ? PCI_MSI_PENDING_64 : PCI_MSI_PENDING_32);
102 }
103 
104 /*
105  * Special API for POWER to configure the vectors through
106  * a side channel. Should never be used by devices.
107  */
108 void msi_set_message(PCIDevice *dev, MSIMessage msg)
109 {
110     uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
111     bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
112 
113     if (msi64bit) {
114         pci_set_quad(dev->config + msi_address_lo_off(dev), msg.address);
115     } else {
116         pci_set_long(dev->config + msi_address_lo_off(dev), msg.address);
117     }
118     pci_set_word(dev->config + msi_data_off(dev, msi64bit), msg.data);
119 }
120 
121 MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector)
122 {
123     uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
124     bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
125     unsigned int nr_vectors = msi_nr_vectors(flags);
126     MSIMessage msg;
127 
128     assert(vector < nr_vectors);
129 
130     if (msi64bit) {
131         msg.address = pci_get_quad(dev->config + msi_address_lo_off(dev));
132     } else {
133         msg.address = pci_get_long(dev->config + msi_address_lo_off(dev));
134     }
135 
136     /* upper bit 31:16 is zero */
137     msg.data = pci_get_word(dev->config + msi_data_off(dev, msi64bit));
138     if (nr_vectors > 1) {
139         msg.data &= ~(nr_vectors - 1);
140         msg.data |= vector;
141     }
142 
143     return msg;
144 }
145 
146 bool msi_enabled(const PCIDevice *dev)
147 {
148     return msi_present(dev) &&
149         (pci_get_word(dev->config + msi_flags_off(dev)) &
150          PCI_MSI_FLAGS_ENABLE);
151 }
152 
153 int msi_init(struct PCIDevice *dev, uint8_t offset,
154              unsigned int nr_vectors, bool msi64bit, bool msi_per_vector_mask)
155 {
156     unsigned int vectors_order;
157     uint16_t flags;
158     uint8_t cap_size;
159     int config_offset;
160 
161     if (!msi_supported) {
162         return -ENOTSUP;
163     }
164 
165     MSI_DEV_PRINTF(dev,
166                    "init offset: 0x%"PRIx8" vector: %"PRId8
167                    " 64bit %d mask %d\n",
168                    offset, nr_vectors, msi64bit, msi_per_vector_mask);
169 
170     assert(!(nr_vectors & (nr_vectors - 1)));   /* power of 2 */
171     assert(nr_vectors > 0);
172     assert(nr_vectors <= PCI_MSI_VECTORS_MAX);
173     /* the nr of MSI vectors is up to 32 */
174     vectors_order = ctz32(nr_vectors);
175 
176     flags = vectors_order << ctz32(PCI_MSI_FLAGS_QMASK);
177     if (msi64bit) {
178         flags |= PCI_MSI_FLAGS_64BIT;
179     }
180     if (msi_per_vector_mask) {
181         flags |= PCI_MSI_FLAGS_MASKBIT;
182     }
183 
184     cap_size = msi_cap_sizeof(flags);
185     config_offset = pci_add_capability(dev, PCI_CAP_ID_MSI, offset, cap_size);
186     if (config_offset < 0) {
187         return config_offset;
188     }
189 
190     dev->msi_cap = config_offset;
191     dev->cap_present |= QEMU_PCI_CAP_MSI;
192 
193     pci_set_word(dev->config + msi_flags_off(dev), flags);
194     pci_set_word(dev->wmask + msi_flags_off(dev),
195                  PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
196     pci_set_long(dev->wmask + msi_address_lo_off(dev),
197                  PCI_MSI_ADDRESS_LO_MASK);
198     if (msi64bit) {
199         pci_set_long(dev->wmask + msi_address_hi_off(dev), 0xffffffff);
200     }
201     pci_set_word(dev->wmask + msi_data_off(dev, msi64bit), 0xffff);
202 
203     if (msi_per_vector_mask) {
204         /* Make mask bits 0 to nr_vectors - 1 writable. */
205         pci_set_long(dev->wmask + msi_mask_off(dev, msi64bit),
206                      0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors));
207     }
208     return config_offset;
209 }
210 
211 void msi_uninit(struct PCIDevice *dev)
212 {
213     uint16_t flags;
214     uint8_t cap_size;
215 
216     if (!msi_present(dev)) {
217         return;
218     }
219     flags = pci_get_word(dev->config + msi_flags_off(dev));
220     cap_size = msi_cap_sizeof(flags);
221     pci_del_capability(dev, PCI_CAP_ID_MSI, cap_size);
222     dev->cap_present &= ~QEMU_PCI_CAP_MSI;
223 
224     MSI_DEV_PRINTF(dev, "uninit\n");
225 }
226 
227 void msi_reset(PCIDevice *dev)
228 {
229     uint16_t flags;
230     bool msi64bit;
231 
232     if (!msi_present(dev)) {
233         return;
234     }
235 
236     flags = pci_get_word(dev->config + msi_flags_off(dev));
237     flags &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
238     msi64bit = flags & PCI_MSI_FLAGS_64BIT;
239 
240     pci_set_word(dev->config + msi_flags_off(dev), flags);
241     pci_set_long(dev->config + msi_address_lo_off(dev), 0);
242     if (msi64bit) {
243         pci_set_long(dev->config + msi_address_hi_off(dev), 0);
244     }
245     pci_set_word(dev->config + msi_data_off(dev, msi64bit), 0);
246     if (flags & PCI_MSI_FLAGS_MASKBIT) {
247         pci_set_long(dev->config + msi_mask_off(dev, msi64bit), 0);
248         pci_set_long(dev->config + msi_pending_off(dev, msi64bit), 0);
249     }
250     MSI_DEV_PRINTF(dev, "reset\n");
251 }
252 
253 static bool msi_is_masked(const PCIDevice *dev, unsigned int vector)
254 {
255     uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
256     uint32_t mask;
257     assert(vector < PCI_MSI_VECTORS_MAX);
258 
259     if (!(flags & PCI_MSI_FLAGS_MASKBIT)) {
260         return false;
261     }
262 
263     mask = pci_get_long(dev->config +
264                         msi_mask_off(dev, flags & PCI_MSI_FLAGS_64BIT));
265     return mask & (1U << vector);
266 }
267 
268 void msi_notify(PCIDevice *dev, unsigned int vector)
269 {
270     uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
271     bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
272     unsigned int nr_vectors = msi_nr_vectors(flags);
273     MSIMessage msg;
274 
275     assert(vector < nr_vectors);
276     if (msi_is_masked(dev, vector)) {
277         assert(flags & PCI_MSI_FLAGS_MASKBIT);
278         pci_long_test_and_set_mask(
279             dev->config + msi_pending_off(dev, msi64bit), 1U << vector);
280         MSI_DEV_PRINTF(dev, "pending vector 0x%x\n", vector);
281         return;
282     }
283 
284     msg = msi_get_message(dev, vector);
285 
286     MSI_DEV_PRINTF(dev,
287                    "notify vector 0x%x"
288                    " address: 0x%"PRIx64" data: 0x%"PRIx32"\n",
289                    vector, msg.address, msg.data);
290     msi_send_message(dev, msg);
291 }
292 
293 void msi_send_message(PCIDevice *dev, MSIMessage msg)
294 {
295     MemTxAttrs attrs = {};
296 
297     attrs.stream_id = (pci_bus_num(dev->bus) << 8) | dev->devfn;
298     address_space_stl_le(&dev->bus_master_as, msg.address, msg.data,
299                          attrs, NULL);
300 }
301 
302 /* Normally called by pci_default_write_config(). */
303 void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len)
304 {
305     uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
306     bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
307     bool msi_per_vector_mask = flags & PCI_MSI_FLAGS_MASKBIT;
308     unsigned int nr_vectors;
309     uint8_t log_num_vecs;
310     uint8_t log_max_vecs;
311     unsigned int vector;
312     uint32_t pending;
313 
314     if (!msi_present(dev) ||
315         !ranges_overlap(addr, len, dev->msi_cap, msi_cap_sizeof(flags))) {
316         return;
317     }
318 
319 #ifdef MSI_DEBUG
320     MSI_DEV_PRINTF(dev, "addr 0x%"PRIx32" val 0x%"PRIx32" len %d\n",
321                    addr, val, len);
322     MSI_DEV_PRINTF(dev, "ctrl: 0x%"PRIx16" address: 0x%"PRIx32,
323                    flags,
324                    pci_get_long(dev->config + msi_address_lo_off(dev)));
325     if (msi64bit) {
326         fprintf(stderr, " address-hi: 0x%"PRIx32,
327                 pci_get_long(dev->config + msi_address_hi_off(dev)));
328     }
329     fprintf(stderr, " data: 0x%"PRIx16,
330             pci_get_word(dev->config + msi_data_off(dev, msi64bit)));
331     if (flags & PCI_MSI_FLAGS_MASKBIT) {
332         fprintf(stderr, " mask 0x%"PRIx32" pending 0x%"PRIx32,
333                 pci_get_long(dev->config + msi_mask_off(dev, msi64bit)),
334                 pci_get_long(dev->config + msi_pending_off(dev, msi64bit)));
335     }
336     fprintf(stderr, "\n");
337 #endif
338 
339     if (!(flags & PCI_MSI_FLAGS_ENABLE)) {
340         return;
341     }
342 
343     /*
344      * Now MSI is enabled, clear INTx# interrupts.
345      * the driver is prohibited from writing enable bit to mask
346      * a service request. But the guest OS could do this.
347      * So we just discard the interrupts as moderate fallback.
348      *
349      * 6.8.3.3. Enabling Operation
350      *   While enabled for MSI or MSI-X operation, a function is prohibited
351      *   from using its INTx# pin (if implemented) to request
352      *   service (MSI, MSI-X, and INTx# are mutually exclusive).
353      */
354     pci_device_deassert_intx(dev);
355 
356     /*
357      * nr_vectors might be set bigger than capable. So clamp it.
358      * This is not legal by spec, so we can do anything we like,
359      * just don't crash the host
360      */
361     log_num_vecs =
362         (flags & PCI_MSI_FLAGS_QSIZE) >> ctz32(PCI_MSI_FLAGS_QSIZE);
363     log_max_vecs =
364         (flags & PCI_MSI_FLAGS_QMASK) >> ctz32(PCI_MSI_FLAGS_QMASK);
365     if (log_num_vecs > log_max_vecs) {
366         flags &= ~PCI_MSI_FLAGS_QSIZE;
367         flags |= log_max_vecs << ctz32(PCI_MSI_FLAGS_QSIZE);
368         pci_set_word(dev->config + msi_flags_off(dev), flags);
369     }
370 
371     if (!msi_per_vector_mask) {
372         /* if per vector masking isn't supported,
373            there is no pending interrupt. */
374         return;
375     }
376 
377     nr_vectors = msi_nr_vectors(flags);
378 
379     /* This will discard pending interrupts, if any. */
380     pending = pci_get_long(dev->config + msi_pending_off(dev, msi64bit));
381     pending &= 0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors);
382     pci_set_long(dev->config + msi_pending_off(dev, msi64bit), pending);
383 
384     /* deliver pending interrupts which are unmasked */
385     for (vector = 0; vector < nr_vectors; ++vector) {
386         if (msi_is_masked(dev, vector) || !(pending & (1U << vector))) {
387             continue;
388         }
389 
390         pci_long_test_and_clear_mask(
391             dev->config + msi_pending_off(dev, msi64bit), 1U << vector);
392         msi_notify(dev, vector);
393     }
394 }
395 
396 unsigned int msi_nr_vectors_allocated(const PCIDevice *dev)
397 {
398     uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
399     return msi_nr_vectors(flags);
400 }
401