1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21#include "qemu/osdep.h"
22#include "hw/pci/msi.h"
23#include "hw/xen/xen.h"
24#include "qemu/range.h"
25#include "qapi/error.h"
26
27
28#define PCI_MSI_ADDRESS_LO_MASK (~0x3)
29
30
31#define PCI_MSI_32_SIZEOF 0x0a
32#define PCI_MSI_64_SIZEOF 0x0e
33#define PCI_MSI_32M_SIZEOF 0x14
34#define PCI_MSI_64M_SIZEOF 0x18
35
36#define PCI_MSI_VECTORS_MAX 32
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52bool msi_nonbroken;
53
54
55static inline uint8_t msi_cap_sizeof(uint16_t flags)
56{
57 switch (flags & (PCI_MSI_FLAGS_MASKBIT | PCI_MSI_FLAGS_64BIT)) {
58 case PCI_MSI_FLAGS_MASKBIT | PCI_MSI_FLAGS_64BIT:
59 return PCI_MSI_64M_SIZEOF;
60 case PCI_MSI_FLAGS_64BIT:
61 return PCI_MSI_64_SIZEOF;
62 case PCI_MSI_FLAGS_MASKBIT:
63 return PCI_MSI_32M_SIZEOF;
64 case 0:
65 return PCI_MSI_32_SIZEOF;
66 default:
67 abort();
68 break;
69 }
70 return 0;
71}
72
73
74
75#ifdef MSI_DEBUG
76# define MSI_DPRINTF(fmt, ...) \
77 fprintf(stderr, "%s:%d " fmt, __func__, __LINE__, ## __VA_ARGS__)
78#else
79# define MSI_DPRINTF(fmt, ...) do { } while (0)
80#endif
81#define MSI_DEV_PRINTF(dev, fmt, ...) \
82 MSI_DPRINTF("%s:%x " fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
83
84static inline unsigned int msi_nr_vectors(uint16_t flags)
85{
86 return 1U <<
87 ((flags & PCI_MSI_FLAGS_QSIZE) >> ctz32(PCI_MSI_FLAGS_QSIZE));
88}
89
90static inline uint8_t msi_flags_off(const PCIDevice* dev)
91{
92 return dev->msi_cap + PCI_MSI_FLAGS;
93}
94
95static inline uint8_t msi_address_lo_off(const PCIDevice* dev)
96{
97 return dev->msi_cap + PCI_MSI_ADDRESS_LO;
98}
99
100static inline uint8_t msi_address_hi_off(const PCIDevice* dev)
101{
102 return dev->msi_cap + PCI_MSI_ADDRESS_HI;
103}
104
105static inline uint8_t msi_data_off(const PCIDevice* dev, bool msi64bit)
106{
107 return dev->msi_cap + (msi64bit ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32);
108}
109
110static inline uint8_t msi_mask_off(const PCIDevice* dev, bool msi64bit)
111{
112 return dev->msi_cap + (msi64bit ? PCI_MSI_MASK_64 : PCI_MSI_MASK_32);
113}
114
115static inline uint8_t msi_pending_off(const PCIDevice* dev, bool msi64bit)
116{
117 return dev->msi_cap + (msi64bit ? PCI_MSI_PENDING_64 : PCI_MSI_PENDING_32);
118}
119
120
121
122
123
124void msi_set_message(PCIDevice *dev, MSIMessage msg)
125{
126 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
127 bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
128
129 if (msi64bit) {
130 pci_set_quad(dev->config + msi_address_lo_off(dev), msg.address);
131 } else {
132 pci_set_long(dev->config + msi_address_lo_off(dev), msg.address);
133 }
134 pci_set_word(dev->config + msi_data_off(dev, msi64bit), msg.data);
135}
136
137static MSIMessage msi_prepare_message(PCIDevice *dev, unsigned int vector)
138{
139 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
140 bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
141 unsigned int nr_vectors = msi_nr_vectors(flags);
142 MSIMessage msg;
143
144 assert(vector < nr_vectors);
145
146 if (msi64bit) {
147 msg.address = pci_get_quad(dev->config + msi_address_lo_off(dev));
148 } else {
149 msg.address = pci_get_long(dev->config + msi_address_lo_off(dev));
150 }
151
152
153 msg.data = pci_get_word(dev->config + msi_data_off(dev, msi64bit));
154 if (nr_vectors > 1) {
155 msg.data &= ~(nr_vectors - 1);
156 msg.data |= vector;
157 }
158
159 return msg;
160}
161
162MSIMessage msi_get_message(PCIDevice *dev, unsigned int vector)
163{
164 return dev->msi_prepare_message(dev, vector);
165}
166
167bool msi_enabled(const PCIDevice *dev)
168{
169 return msi_present(dev) &&
170 (pci_get_word(dev->config + msi_flags_off(dev)) &
171 PCI_MSI_FLAGS_ENABLE);
172}
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190int msi_init(struct PCIDevice *dev, uint8_t offset,
191 unsigned int nr_vectors, bool msi64bit,
192 bool msi_per_vector_mask, Error **errp)
193{
194 unsigned int vectors_order;
195 uint16_t flags;
196 uint8_t cap_size;
197 int config_offset;
198
199 if (!msi_nonbroken) {
200 error_setg(errp, "MSI is not supported by interrupt controller");
201 return -ENOTSUP;
202 }
203
204 MSI_DEV_PRINTF(dev,
205 "init offset: 0x%"PRIx8" vector: %"PRId8
206 " 64bit %d mask %d\n",
207 offset, nr_vectors, msi64bit, msi_per_vector_mask);
208
209 assert(!(nr_vectors & (nr_vectors - 1)));
210 assert(nr_vectors > 0);
211 assert(nr_vectors <= PCI_MSI_VECTORS_MAX);
212
213 vectors_order = ctz32(nr_vectors);
214
215 flags = vectors_order << ctz32(PCI_MSI_FLAGS_QMASK);
216 if (msi64bit) {
217 flags |= PCI_MSI_FLAGS_64BIT;
218 }
219 if (msi_per_vector_mask) {
220 flags |= PCI_MSI_FLAGS_MASKBIT;
221 }
222
223 cap_size = msi_cap_sizeof(flags);
224 config_offset = pci_add_capability(dev, PCI_CAP_ID_MSI, offset,
225 cap_size, errp);
226 if (config_offset < 0) {
227 return config_offset;
228 }
229
230 dev->msi_cap = config_offset;
231 dev->cap_present |= QEMU_PCI_CAP_MSI;
232
233 pci_set_word(dev->config + msi_flags_off(dev), flags);
234 pci_set_word(dev->wmask + msi_flags_off(dev),
235 PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
236 pci_set_long(dev->wmask + msi_address_lo_off(dev),
237 PCI_MSI_ADDRESS_LO_MASK);
238 if (msi64bit) {
239 pci_set_long(dev->wmask + msi_address_hi_off(dev), 0xffffffff);
240 }
241 pci_set_word(dev->wmask + msi_data_off(dev, msi64bit), 0xffff);
242
243 if (msi_per_vector_mask) {
244
245 pci_set_long(dev->wmask + msi_mask_off(dev, msi64bit),
246 0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors));
247 }
248
249 dev->msi_prepare_message = msi_prepare_message;
250
251 return 0;
252}
253
254void msi_uninit(struct PCIDevice *dev)
255{
256 uint16_t flags;
257 uint8_t cap_size;
258
259 if (!msi_present(dev)) {
260 return;
261 }
262 flags = pci_get_word(dev->config + msi_flags_off(dev));
263 cap_size = msi_cap_sizeof(flags);
264 pci_del_capability(dev, PCI_CAP_ID_MSI, cap_size);
265 dev->cap_present &= ~QEMU_PCI_CAP_MSI;
266 dev->msi_prepare_message = NULL;
267
268 MSI_DEV_PRINTF(dev, "uninit\n");
269}
270
271void msi_reset(PCIDevice *dev)
272{
273 uint16_t flags;
274 bool msi64bit;
275
276 if (!msi_present(dev)) {
277 return;
278 }
279
280 flags = pci_get_word(dev->config + msi_flags_off(dev));
281 flags &= ~(PCI_MSI_FLAGS_QSIZE | PCI_MSI_FLAGS_ENABLE);
282 msi64bit = flags & PCI_MSI_FLAGS_64BIT;
283
284 pci_set_word(dev->config + msi_flags_off(dev), flags);
285 pci_set_long(dev->config + msi_address_lo_off(dev), 0);
286 if (msi64bit) {
287 pci_set_long(dev->config + msi_address_hi_off(dev), 0);
288 }
289 pci_set_word(dev->config + msi_data_off(dev, msi64bit), 0);
290 if (flags & PCI_MSI_FLAGS_MASKBIT) {
291 pci_set_long(dev->config + msi_mask_off(dev, msi64bit), 0);
292 pci_set_long(dev->config + msi_pending_off(dev, msi64bit), 0);
293 }
294 MSI_DEV_PRINTF(dev, "reset\n");
295}
296
297bool msi_is_masked(const PCIDevice *dev, unsigned int vector)
298{
299 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
300 uint32_t mask, data;
301 bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
302 assert(vector < PCI_MSI_VECTORS_MAX);
303
304 if (!(flags & PCI_MSI_FLAGS_MASKBIT)) {
305 return false;
306 }
307
308 data = pci_get_word(dev->config + msi_data_off(dev, msi64bit));
309 if (xen_is_pirq_msi(data)) {
310 return false;
311 }
312
313 mask = pci_get_long(dev->config +
314 msi_mask_off(dev, flags & PCI_MSI_FLAGS_64BIT));
315 return mask & (1U << vector);
316}
317
318void msi_set_mask(PCIDevice *dev, int vector, bool mask, Error **errp)
319{
320 ERRP_GUARD();
321 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
322 bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
323 uint32_t irq_state, vector_mask, pending;
324
325 if (vector >= PCI_MSI_VECTORS_MAX) {
326 error_setg(errp, "msi: vector %d not allocated. max vector is %d",
327 vector, (PCI_MSI_VECTORS_MAX - 1));
328 return;
329 }
330
331 vector_mask = (1U << vector);
332
333 irq_state = pci_get_long(dev->config + msi_mask_off(dev, msi64bit));
334
335 if (mask) {
336 irq_state |= vector_mask;
337 } else {
338 irq_state &= ~vector_mask;
339 }
340
341 pci_set_long(dev->config + msi_mask_off(dev, msi64bit), irq_state);
342
343 pending = pci_get_long(dev->config + msi_pending_off(dev, msi64bit));
344 if (!mask && (pending & vector_mask)) {
345 pending &= ~vector_mask;
346 pci_set_long(dev->config + msi_pending_off(dev, msi64bit), pending);
347 msi_notify(dev, vector);
348 }
349}
350
351void msi_notify(PCIDevice *dev, unsigned int vector)
352{
353 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
354 bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
355 unsigned int nr_vectors = msi_nr_vectors(flags);
356 MSIMessage msg;
357
358 assert(vector < nr_vectors);
359 if (msi_is_masked(dev, vector)) {
360 assert(flags & PCI_MSI_FLAGS_MASKBIT);
361 pci_long_test_and_set_mask(
362 dev->config + msi_pending_off(dev, msi64bit), 1U << vector);
363 MSI_DEV_PRINTF(dev, "pending vector 0x%x\n", vector);
364 return;
365 }
366
367 msg = msi_get_message(dev, vector);
368
369 MSI_DEV_PRINTF(dev,
370 "notify vector 0x%x"
371 " address: 0x%"PRIx64" data: 0x%"PRIx32"\n",
372 vector, msg.address, msg.data);
373 msi_send_message(dev, msg);
374}
375
376void msi_send_message(PCIDevice *dev, MSIMessage msg)
377{
378 dev->msi_trigger(dev, msg);
379}
380
381
382void msi_write_config(PCIDevice *dev, uint32_t addr, uint32_t val, int len)
383{
384 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
385 bool msi64bit = flags & PCI_MSI_FLAGS_64BIT;
386 bool msi_per_vector_mask = flags & PCI_MSI_FLAGS_MASKBIT;
387 unsigned int nr_vectors;
388 uint8_t log_num_vecs;
389 uint8_t log_max_vecs;
390 unsigned int vector;
391 uint32_t pending;
392
393 if (!msi_present(dev) ||
394 !ranges_overlap(addr, len, dev->msi_cap, msi_cap_sizeof(flags))) {
395 return;
396 }
397
398#ifdef MSI_DEBUG
399 MSI_DEV_PRINTF(dev, "addr 0x%"PRIx32" val 0x%"PRIx32" len %d\n",
400 addr, val, len);
401 MSI_DEV_PRINTF(dev, "ctrl: 0x%"PRIx16" address: 0x%"PRIx32,
402 flags,
403 pci_get_long(dev->config + msi_address_lo_off(dev)));
404 if (msi64bit) {
405 fprintf(stderr, " address-hi: 0x%"PRIx32,
406 pci_get_long(dev->config + msi_address_hi_off(dev)));
407 }
408 fprintf(stderr, " data: 0x%"PRIx16,
409 pci_get_word(dev->config + msi_data_off(dev, msi64bit)));
410 if (flags & PCI_MSI_FLAGS_MASKBIT) {
411 fprintf(stderr, " mask 0x%"PRIx32" pending 0x%"PRIx32,
412 pci_get_long(dev->config + msi_mask_off(dev, msi64bit)),
413 pci_get_long(dev->config + msi_pending_off(dev, msi64bit)));
414 }
415 fprintf(stderr, "\n");
416#endif
417
418 if (!(flags & PCI_MSI_FLAGS_ENABLE)) {
419 return;
420 }
421
422
423
424
425
426
427
428
429
430
431
432
433 pci_device_deassert_intx(dev);
434
435
436
437
438
439
440 log_num_vecs =
441 (flags & PCI_MSI_FLAGS_QSIZE) >> ctz32(PCI_MSI_FLAGS_QSIZE);
442 log_max_vecs =
443 (flags & PCI_MSI_FLAGS_QMASK) >> ctz32(PCI_MSI_FLAGS_QMASK);
444 if (log_num_vecs > log_max_vecs) {
445 flags &= ~PCI_MSI_FLAGS_QSIZE;
446 flags |= log_max_vecs << ctz32(PCI_MSI_FLAGS_QSIZE);
447 pci_set_word(dev->config + msi_flags_off(dev), flags);
448 }
449
450 if (!msi_per_vector_mask) {
451
452
453 return;
454 }
455
456 nr_vectors = msi_nr_vectors(flags);
457
458
459 pending = pci_get_long(dev->config + msi_pending_off(dev, msi64bit));
460 pending &= 0xffffffff >> (PCI_MSI_VECTORS_MAX - nr_vectors);
461 pci_set_long(dev->config + msi_pending_off(dev, msi64bit), pending);
462
463
464 for (vector = 0; vector < nr_vectors; ++vector) {
465 if (msi_is_masked(dev, vector) || !(pending & (1U << vector))) {
466 continue;
467 }
468
469 pci_long_test_and_clear_mask(
470 dev->config + msi_pending_off(dev, msi64bit), 1U << vector);
471 msi_notify(dev, vector);
472 }
473}
474
475unsigned int msi_nr_vectors_allocated(const PCIDevice *dev)
476{
477 uint16_t flags = pci_get_word(dev->config + msi_flags_off(dev));
478 return msi_nr_vectors(flags);
479}
480