hw/virtio: Rename virtio_device_find() -> qmp_find_virtio_device()
[qemu.git] / hw / pci / pcie_aer.c
blob9a19be44ae5a2222c69248ec1cb64ff8575c3998
1 /*
2 * pcie_aer.c
4 * Copyright (c) 2010 Isaku Yamahata <yamahata at valinux co jp>
5 * VA Linux Systems Japan K.K.
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.
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.
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/>.
21 #include "qemu/osdep.h"
22 #include "migration/vmstate.h"
23 #include "hw/pci/pci_bridge.h"
24 #include "hw/pci/pcie.h"
25 #include "hw/pci/msix.h"
26 #include "hw/pci/msi.h"
27 #include "hw/pci/pci_bus.h"
28 #include "hw/pci/pcie_regs.h"
29 #include "pci-internal.h"
31 //#define DEBUG_PCIE
32 #ifdef DEBUG_PCIE
33 # define PCIE_DPRINTF(fmt, ...) \
34 fprintf(stderr, "%s:%d " fmt, __func__, __LINE__, ## __VA_ARGS__)
35 #else
36 # define PCIE_DPRINTF(fmt, ...) do {} while (0)
37 #endif
38 #define PCIE_DEV_PRINTF(dev, fmt, ...) \
39 PCIE_DPRINTF("%s:%x "fmt, (dev)->name, (dev)->devfn, ## __VA_ARGS__)
41 #define PCI_ERR_SRC_COR_OFFS 0
42 #define PCI_ERR_SRC_UNCOR_OFFS 2
44 /* From 6.2.7 Error Listing and Rules. Table 6-2, 6-3 and 6-4 */
45 static uint32_t pcie_aer_uncor_default_severity(uint32_t status)
47 switch (status) {
48 case PCI_ERR_UNC_INTN:
49 case PCI_ERR_UNC_DLP:
50 case PCI_ERR_UNC_SDN:
51 case PCI_ERR_UNC_RX_OVER:
52 case PCI_ERR_UNC_FCP:
53 case PCI_ERR_UNC_MALF_TLP:
54 return PCI_ERR_ROOT_CMD_FATAL_EN;
55 case PCI_ERR_UNC_POISON_TLP:
56 case PCI_ERR_UNC_ECRC:
57 case PCI_ERR_UNC_UNSUP:
58 case PCI_ERR_UNC_COMP_TIME:
59 case PCI_ERR_UNC_COMP_ABORT:
60 case PCI_ERR_UNC_UNX_COMP:
61 case PCI_ERR_UNC_ACSV:
62 case PCI_ERR_UNC_MCBTLP:
63 case PCI_ERR_UNC_ATOP_EBLOCKED:
64 case PCI_ERR_UNC_TLP_PRF_BLOCKED:
65 return PCI_ERR_ROOT_CMD_NONFATAL_EN;
66 default:
67 abort();
68 break;
70 return PCI_ERR_ROOT_CMD_FATAL_EN;
73 static int aer_log_add_err(PCIEAERLog *aer_log, const PCIEAERErr *err)
75 if (aer_log->log_num == aer_log->log_max) {
76 return -1;
78 memcpy(&aer_log->log[aer_log->log_num], err, sizeof *err);
79 aer_log->log_num++;
80 return 0;
83 static void aer_log_del_err(PCIEAERLog *aer_log, PCIEAERErr *err)
85 assert(aer_log->log_num);
86 *err = aer_log->log[0];
87 aer_log->log_num--;
88 memmove(&aer_log->log[0], &aer_log->log[1],
89 aer_log->log_num * sizeof *err);
92 static void aer_log_clear_all_err(PCIEAERLog *aer_log)
94 aer_log->log_num = 0;
97 int pcie_aer_init(PCIDevice *dev, uint8_t cap_ver, uint16_t offset,
98 uint16_t size, Error **errp)
100 pcie_add_capability(dev, PCI_EXT_CAP_ID_ERR, cap_ver,
101 offset, size);
102 dev->exp.aer_cap = offset;
104 /* clip down the value to avoid unreasonable memory usage */
105 if (dev->exp.aer_log.log_max > PCIE_AER_LOG_MAX_LIMIT) {
106 error_setg(errp, "Invalid aer_log_max %d. The max number of aer log "
107 "is %d", dev->exp.aer_log.log_max, PCIE_AER_LOG_MAX_LIMIT);
108 return -EINVAL;
110 dev->exp.aer_log.log = g_malloc0(sizeof dev->exp.aer_log.log[0] *
111 dev->exp.aer_log.log_max);
113 pci_set_long(dev->w1cmask + offset + PCI_ERR_UNCOR_STATUS,
114 PCI_ERR_UNC_SUPPORTED);
116 pci_set_long(dev->config + offset + PCI_ERR_UNCOR_SEVER,
117 PCI_ERR_UNC_SEVERITY_DEFAULT);
118 pci_set_long(dev->wmask + offset + PCI_ERR_UNCOR_SEVER,
119 PCI_ERR_UNC_SUPPORTED);
121 pci_long_test_and_set_mask(dev->w1cmask + offset + PCI_ERR_COR_STATUS,
122 PCI_ERR_COR_SUPPORTED);
124 pci_set_long(dev->config + offset + PCI_ERR_COR_MASK,
125 PCI_ERR_COR_MASK_DEFAULT);
126 pci_set_long(dev->wmask + offset + PCI_ERR_COR_MASK,
127 PCI_ERR_COR_SUPPORTED);
129 /* capabilities and control. multiple header logging is supported */
130 if (dev->exp.aer_log.log_max > 0) {
131 pci_set_long(dev->config + offset + PCI_ERR_CAP,
132 PCI_ERR_CAP_ECRC_GENC | PCI_ERR_CAP_ECRC_CHKC |
133 PCI_ERR_CAP_MHRC);
134 pci_set_long(dev->wmask + offset + PCI_ERR_CAP,
135 PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE |
136 PCI_ERR_CAP_MHRE);
137 } else {
138 pci_set_long(dev->config + offset + PCI_ERR_CAP,
139 PCI_ERR_CAP_ECRC_GENC | PCI_ERR_CAP_ECRC_CHKC);
140 pci_set_long(dev->wmask + offset + PCI_ERR_CAP,
141 PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE);
144 switch (pcie_cap_get_type(dev)) {
145 case PCI_EXP_TYPE_ROOT_PORT:
146 /* this case will be set by pcie_aer_root_init() */
147 /* fallthrough */
148 case PCI_EXP_TYPE_DOWNSTREAM:
149 case PCI_EXP_TYPE_UPSTREAM:
150 pci_word_test_and_set_mask(dev->wmask + PCI_BRIDGE_CONTROL,
151 PCI_BRIDGE_CTL_SERR);
152 pci_long_test_and_set_mask(dev->w1cmask + PCI_STATUS,
153 PCI_SEC_STATUS_RCV_SYSTEM_ERROR);
154 break;
155 default:
156 /* nothing */
157 break;
159 return 0;
162 void pcie_aer_exit(PCIDevice *dev)
164 g_free(dev->exp.aer_log.log);
167 static void pcie_aer_update_uncor_status(PCIDevice *dev)
169 uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
170 PCIEAERLog *aer_log = &dev->exp.aer_log;
172 uint16_t i;
173 for (i = 0; i < aer_log->log_num; i++) {
174 pci_long_test_and_set_mask(aer_cap + PCI_ERR_UNCOR_STATUS,
175 dev->exp.aer_log.log[i].status);
180 * return value:
181 * true: error message needs to be sent up
182 * false: error message is masked
184 * 6.2.6 Error Message Control
185 * Figure 6-3
186 * all pci express devices part
188 static bool
189 pcie_aer_msg_alldev(PCIDevice *dev, const PCIEAERMsg *msg)
191 if (!(pcie_aer_msg_is_uncor(msg) &&
192 (pci_get_word(dev->config + PCI_COMMAND) & PCI_COMMAND_SERR))) {
193 return false;
196 /* Signaled System Error
198 * 7.5.1.1 Command register
199 * Bit 8 SERR# Enable
201 * When Set, this bit enables reporting of Non-fatal and Fatal
202 * errors detected by the Function to the Root Complex. Note that
203 * errors are reported if enabled either through this bit or through
204 * the PCI Express specific bits in the Device Control register (see
205 * Section 7.8.4).
207 pci_word_test_and_set_mask(dev->config + PCI_STATUS,
208 PCI_STATUS_SIG_SYSTEM_ERROR);
210 if (!(msg->severity &
211 pci_get_word(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCTL))) {
212 return false;
215 /* send up error message */
216 return true;
220 * return value:
221 * true: error message is sent up
222 * false: error message is masked
224 * 6.2.6 Error Message Control
225 * Figure 6-3
226 * virtual pci bridge part
228 static bool pcie_aer_msg_vbridge(PCIDevice *dev, const PCIEAERMsg *msg)
230 uint16_t bridge_control = pci_get_word(dev->config + PCI_BRIDGE_CONTROL);
232 if (pcie_aer_msg_is_uncor(msg)) {
233 /* Received System Error */
234 pci_word_test_and_set_mask(dev->config + PCI_SEC_STATUS,
235 PCI_SEC_STATUS_RCV_SYSTEM_ERROR);
238 if (!(bridge_control & PCI_BRIDGE_CTL_SERR)) {
239 return false;
241 return true;
244 void pcie_aer_root_set_vector(PCIDevice *dev, unsigned int vector)
246 uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
247 assert(vector < PCI_ERR_ROOT_IRQ_MAX);
248 pci_long_test_and_clear_mask(aer_cap + PCI_ERR_ROOT_STATUS,
249 PCI_ERR_ROOT_IRQ);
250 pci_long_test_and_set_mask(aer_cap + PCI_ERR_ROOT_STATUS,
251 vector << PCI_ERR_ROOT_IRQ_SHIFT);
254 static unsigned int pcie_aer_root_get_vector(PCIDevice *dev)
256 uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
257 uint32_t root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
258 return (root_status & PCI_ERR_ROOT_IRQ) >> PCI_ERR_ROOT_IRQ_SHIFT;
261 /* Given a status register, get corresponding bits in the command register */
262 static uint32_t pcie_aer_status_to_cmd(uint32_t status)
264 uint32_t cmd = 0;
265 if (status & PCI_ERR_ROOT_COR_RCV) {
266 cmd |= PCI_ERR_ROOT_CMD_COR_EN;
268 if (status & PCI_ERR_ROOT_NONFATAL_RCV) {
269 cmd |= PCI_ERR_ROOT_CMD_NONFATAL_EN;
271 if (status & PCI_ERR_ROOT_FATAL_RCV) {
272 cmd |= PCI_ERR_ROOT_CMD_FATAL_EN;
274 return cmd;
277 static void pcie_aer_root_notify(PCIDevice *dev)
279 if (msix_enabled(dev)) {
280 msix_notify(dev, pcie_aer_root_get_vector(dev));
281 } else if (msi_enabled(dev)) {
282 msi_notify(dev, pcie_aer_root_get_vector(dev));
283 } else if (pci_intx(dev) != -1) {
284 pci_irq_assert(dev);
289 * 6.2.6 Error Message Control
290 * Figure 6-3
291 * root port part
293 static void pcie_aer_msg_root_port(PCIDevice *dev, const PCIEAERMsg *msg)
295 uint16_t cmd;
296 uint8_t *aer_cap;
297 uint32_t root_cmd;
298 uint32_t root_status, prev_status;
300 cmd = pci_get_word(dev->config + PCI_COMMAND);
301 aer_cap = dev->config + dev->exp.aer_cap;
302 root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
303 prev_status = root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
305 if (cmd & PCI_COMMAND_SERR) {
306 /* System Error.
308 * The way to report System Error is platform specific and
309 * it isn't implemented in qemu right now.
310 * So just discard the error for now.
311 * OS which cares of aer would receive errors via
312 * native aer mechanims, so this wouldn't matter.
316 /* Error Message Received: Root Error Status register */
317 switch (msg->severity) {
318 case PCI_ERR_ROOT_CMD_COR_EN:
319 if (root_status & PCI_ERR_ROOT_COR_RCV) {
320 root_status |= PCI_ERR_ROOT_MULTI_COR_RCV;
321 } else {
322 pci_set_word(aer_cap + PCI_ERR_ROOT_ERR_SRC + PCI_ERR_SRC_COR_OFFS,
323 msg->source_id);
325 root_status |= PCI_ERR_ROOT_COR_RCV;
326 break;
327 case PCI_ERR_ROOT_CMD_NONFATAL_EN:
328 root_status |= PCI_ERR_ROOT_NONFATAL_RCV;
329 break;
330 case PCI_ERR_ROOT_CMD_FATAL_EN:
331 if (!(root_status & PCI_ERR_ROOT_UNCOR_RCV)) {
332 root_status |= PCI_ERR_ROOT_FIRST_FATAL;
334 root_status |= PCI_ERR_ROOT_FATAL_RCV;
335 break;
336 default:
337 abort();
338 break;
340 if (pcie_aer_msg_is_uncor(msg)) {
341 if (root_status & PCI_ERR_ROOT_UNCOR_RCV) {
342 root_status |= PCI_ERR_ROOT_MULTI_UNCOR_RCV;
343 } else {
344 pci_set_word(aer_cap + PCI_ERR_ROOT_ERR_SRC +
345 PCI_ERR_SRC_UNCOR_OFFS, msg->source_id);
347 root_status |= PCI_ERR_ROOT_UNCOR_RCV;
349 pci_set_long(aer_cap + PCI_ERR_ROOT_STATUS, root_status);
351 /* 6.2.4.1.2 Interrupt Generation */
352 /* All the above did was set some bits in the status register.
353 * Specifically these that match message severity.
354 * The below code relies on this fact. */
355 if (!(root_cmd & msg->severity) ||
356 (pcie_aer_status_to_cmd(prev_status) & root_cmd)) {
357 /* Condition is not being set or was already true so nothing to do. */
358 return;
361 pcie_aer_root_notify(dev);
365 * 6.2.6 Error Message Control Figure 6-3
367 * Walk up the bus tree from the device, propagate the error message.
369 static void pcie_aer_msg(PCIDevice *dev, const PCIEAERMsg *msg)
371 uint8_t type;
373 while (dev) {
374 if (!pci_is_express(dev)) {
375 /* just ignore it */
376 /* TODO: Shouldn't we set PCI_STATUS_SIG_SYSTEM_ERROR?
377 * Consider e.g. a PCI bridge above a PCI Express device. */
378 return;
381 type = pcie_cap_get_type(dev);
382 if ((type == PCI_EXP_TYPE_ROOT_PORT ||
383 type == PCI_EXP_TYPE_UPSTREAM ||
384 type == PCI_EXP_TYPE_DOWNSTREAM) &&
385 !pcie_aer_msg_vbridge(dev, msg)) {
386 return;
388 if (!pcie_aer_msg_alldev(dev, msg)) {
389 return;
391 if (type == PCI_EXP_TYPE_ROOT_PORT) {
392 pcie_aer_msg_root_port(dev, msg);
393 /* Root port can notify system itself,
394 or send the error message to root complex event collector. */
396 * if root port is associated with an event collector,
397 * return the root complex event collector here.
398 * For now root complex event collector isn't supported.
400 return;
402 dev = pci_bridge_get_device(pci_get_bus(dev));
406 static void pcie_aer_update_log(PCIDevice *dev, const PCIEAERErr *err)
408 uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
409 uint8_t first_bit = ctz32(err->status);
410 uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
411 int i;
413 assert(err->status);
414 assert(!(err->status & (err->status - 1)));
416 errcap &= ~(PCI_ERR_CAP_FEP_MASK | PCI_ERR_CAP_TLP);
417 errcap |= PCI_ERR_CAP_FEP(first_bit);
419 if (err->flags & PCIE_AER_ERR_HEADER_VALID) {
420 for (i = 0; i < ARRAY_SIZE(err->header); ++i) {
421 /* 7.10.8 Header Log Register */
422 uint8_t *header_log =
423 aer_cap + PCI_ERR_HEADER_LOG + i * sizeof err->header[0];
424 stl_be_p(header_log, err->header[i]);
426 } else {
427 assert(!(err->flags & PCIE_AER_ERR_TLP_PREFIX_PRESENT));
428 memset(aer_cap + PCI_ERR_HEADER_LOG, 0, PCI_ERR_HEADER_LOG_SIZE);
431 if ((err->flags & PCIE_AER_ERR_TLP_PREFIX_PRESENT) &&
432 (pci_get_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVCAP2) &
433 PCI_EXP_DEVCAP2_EETLPP)) {
434 for (i = 0; i < ARRAY_SIZE(err->prefix); ++i) {
435 /* 7.10.12 tlp prefix log register */
436 uint8_t *prefix_log =
437 aer_cap + PCI_ERR_TLP_PREFIX_LOG + i * sizeof err->prefix[0];
438 stl_be_p(prefix_log, err->prefix[i]);
440 errcap |= PCI_ERR_CAP_TLP;
441 } else {
442 memset(aer_cap + PCI_ERR_TLP_PREFIX_LOG, 0,
443 PCI_ERR_TLP_PREFIX_LOG_SIZE);
445 pci_set_long(aer_cap + PCI_ERR_CAP, errcap);
448 static void pcie_aer_clear_log(PCIDevice *dev)
450 uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
452 pci_long_test_and_clear_mask(aer_cap + PCI_ERR_CAP,
453 PCI_ERR_CAP_FEP_MASK | PCI_ERR_CAP_TLP);
455 memset(aer_cap + PCI_ERR_HEADER_LOG, 0, PCI_ERR_HEADER_LOG_SIZE);
456 memset(aer_cap + PCI_ERR_TLP_PREFIX_LOG, 0, PCI_ERR_TLP_PREFIX_LOG_SIZE);
459 static void pcie_aer_clear_error(PCIDevice *dev)
461 uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
462 uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
463 PCIEAERLog *aer_log = &dev->exp.aer_log;
464 PCIEAERErr err;
466 if (!(errcap & PCI_ERR_CAP_MHRE) || !aer_log->log_num) {
467 pcie_aer_clear_log(dev);
468 return;
472 * If more errors are queued, set corresponding bits in uncorrectable
473 * error status.
474 * We emulate uncorrectable error status register as W1CS.
475 * So set bit in uncorrectable error status here again for multiple
476 * error recording support.
478 * 6.2.4.2 Multiple Error Handling(Advanced Error Reporting Capability)
480 pcie_aer_update_uncor_status(dev);
482 aer_log_del_err(aer_log, &err);
483 pcie_aer_update_log(dev, &err);
486 static int pcie_aer_record_error(PCIDevice *dev,
487 const PCIEAERErr *err)
489 uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
490 uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
491 int fep = PCI_ERR_CAP_FEP(errcap);
493 assert(err->status);
494 assert(!(err->status & (err->status - 1)));
496 if (errcap & PCI_ERR_CAP_MHRE &&
497 (pci_get_long(aer_cap + PCI_ERR_UNCOR_STATUS) & (1U << fep))) {
498 /* Not first error. queue error */
499 if (aer_log_add_err(&dev->exp.aer_log, err) < 0) {
500 /* overflow */
501 return -1;
503 return 0;
506 pcie_aer_update_log(dev, err);
507 return 0;
510 typedef struct PCIEAERInject {
511 PCIDevice *dev;
512 uint8_t *aer_cap;
513 const PCIEAERErr *err;
514 uint16_t devctl;
515 uint16_t devsta;
516 uint32_t error_status;
517 bool unsupported_request;
518 bool log_overflow;
519 PCIEAERMsg msg;
520 } PCIEAERInject;
522 static bool pcie_aer_inject_cor_error(PCIEAERInject *inj,
523 uint32_t uncor_status,
524 bool is_advisory_nonfatal)
526 PCIDevice *dev = inj->dev;
528 inj->devsta |= PCI_EXP_DEVSTA_CED;
529 if (inj->unsupported_request) {
530 inj->devsta |= PCI_EXP_DEVSTA_URD;
532 pci_set_word(dev->config + dev->exp.exp_cap + PCI_EXP_DEVSTA, inj->devsta);
534 if (inj->aer_cap) {
535 uint32_t mask;
536 pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_COR_STATUS,
537 inj->error_status);
538 mask = pci_get_long(inj->aer_cap + PCI_ERR_COR_MASK);
539 if (mask & inj->error_status) {
540 return false;
542 if (is_advisory_nonfatal) {
543 uint32_t uncor_mask =
544 pci_get_long(inj->aer_cap + PCI_ERR_UNCOR_MASK);
545 if (!(uncor_mask & uncor_status)) {
546 inj->log_overflow = !!pcie_aer_record_error(dev, inj->err);
548 pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_UNCOR_STATUS,
549 uncor_status);
553 if (inj->unsupported_request && !(inj->devctl & PCI_EXP_DEVCTL_URRE)) {
554 return false;
556 if (!(inj->devctl & PCI_EXP_DEVCTL_CERE)) {
557 return false;
560 inj->msg.severity = PCI_ERR_ROOT_CMD_COR_EN;
561 return true;
564 static bool pcie_aer_inject_uncor_error(PCIEAERInject *inj, bool is_fatal)
566 PCIDevice *dev = inj->dev;
567 uint16_t cmd;
569 if (is_fatal) {
570 inj->devsta |= PCI_EXP_DEVSTA_FED;
571 } else {
572 inj->devsta |= PCI_EXP_DEVSTA_NFED;
574 if (inj->unsupported_request) {
575 inj->devsta |= PCI_EXP_DEVSTA_URD;
577 pci_set_long(dev->config + dev->exp.exp_cap + PCI_EXP_DEVSTA, inj->devsta);
579 if (inj->aer_cap) {
580 uint32_t mask = pci_get_long(inj->aer_cap + PCI_ERR_UNCOR_MASK);
581 if (mask & inj->error_status) {
582 pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_UNCOR_STATUS,
583 inj->error_status);
584 return false;
587 inj->log_overflow = !!pcie_aer_record_error(dev, inj->err);
588 pci_long_test_and_set_mask(inj->aer_cap + PCI_ERR_UNCOR_STATUS,
589 inj->error_status);
592 cmd = pci_get_word(dev->config + PCI_COMMAND);
593 if (inj->unsupported_request &&
594 !(inj->devctl & PCI_EXP_DEVCTL_URRE) && !(cmd & PCI_COMMAND_SERR)) {
595 return false;
597 if (is_fatal) {
598 if (!((cmd & PCI_COMMAND_SERR) ||
599 (inj->devctl & PCI_EXP_DEVCTL_FERE))) {
600 return false;
602 inj->msg.severity = PCI_ERR_ROOT_CMD_FATAL_EN;
603 } else {
604 if (!((cmd & PCI_COMMAND_SERR) ||
605 (inj->devctl & PCI_EXP_DEVCTL_NFERE))) {
606 return false;
608 inj->msg.severity = PCI_ERR_ROOT_CMD_NONFATAL_EN;
610 return true;
614 * non-Function specific error must be recorded in all functions.
615 * It is the responsibility of the caller of this function.
616 * It is also caller's responsibility to determine which function should
617 * report the error.
619 * 6.2.4 Error Logging
620 * 6.2.5 Sequence of Device Error Signaling and Logging Operations
621 * Figure 6-2: Flowchart Showing Sequence of Device Error Signaling and Logging
622 * Operations
624 int pcie_aer_inject_error(PCIDevice *dev, const PCIEAERErr *err)
626 uint8_t *aer_cap = NULL;
627 uint16_t devctl = 0;
628 uint16_t devsta = 0;
629 uint32_t error_status = err->status;
630 PCIEAERInject inj;
632 if (!pci_is_express(dev)) {
633 return -ENOSYS;
636 if (err->flags & PCIE_AER_ERR_IS_CORRECTABLE) {
637 error_status &= PCI_ERR_COR_SUPPORTED;
638 } else {
639 error_status &= PCI_ERR_UNC_SUPPORTED;
642 /* invalid status bit. one and only one bit must be set */
643 if (!error_status || (error_status & (error_status - 1))) {
644 return -EINVAL;
647 if (dev->exp.aer_cap) {
648 uint8_t *exp_cap = dev->config + dev->exp.exp_cap;
649 aer_cap = dev->config + dev->exp.aer_cap;
650 devctl = pci_get_long(exp_cap + PCI_EXP_DEVCTL);
651 devsta = pci_get_long(exp_cap + PCI_EXP_DEVSTA);
654 inj.dev = dev;
655 inj.aer_cap = aer_cap;
656 inj.err = err;
657 inj.devctl = devctl;
658 inj.devsta = devsta;
659 inj.error_status = error_status;
660 inj.unsupported_request = !(err->flags & PCIE_AER_ERR_IS_CORRECTABLE) &&
661 err->status == PCI_ERR_UNC_UNSUP;
662 inj.log_overflow = false;
664 if (err->flags & PCIE_AER_ERR_IS_CORRECTABLE) {
665 if (!pcie_aer_inject_cor_error(&inj, 0, false)) {
666 return 0;
668 } else {
669 bool is_fatal =
670 pcie_aer_uncor_default_severity(error_status) ==
671 PCI_ERR_ROOT_CMD_FATAL_EN;
672 if (aer_cap) {
673 is_fatal =
674 error_status & pci_get_long(aer_cap + PCI_ERR_UNCOR_SEVER);
676 if (!is_fatal && (err->flags & PCIE_AER_ERR_MAYBE_ADVISORY)) {
677 inj.error_status = PCI_ERR_COR_ADV_NONFATAL;
678 if (!pcie_aer_inject_cor_error(&inj, error_status, true)) {
679 return 0;
681 } else {
682 if (!pcie_aer_inject_uncor_error(&inj, is_fatal)) {
683 return 0;
688 /* send up error message */
689 inj.msg.source_id = err->source_id;
690 pcie_aer_msg(dev, &inj.msg);
692 if (inj.log_overflow) {
693 PCIEAERErr header_log_overflow = {
694 .status = PCI_ERR_COR_HL_OVERFLOW,
695 .flags = PCIE_AER_ERR_IS_CORRECTABLE,
697 int ret = pcie_aer_inject_error(dev, &header_log_overflow);
698 assert(!ret);
700 return 0;
703 void pcie_aer_write_config(PCIDevice *dev,
704 uint32_t addr, uint32_t val, int len)
706 uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
707 uint32_t errcap = pci_get_long(aer_cap + PCI_ERR_CAP);
708 uint32_t first_error = 1U << PCI_ERR_CAP_FEP(errcap);
709 uint32_t uncorsta = pci_get_long(aer_cap + PCI_ERR_UNCOR_STATUS);
711 /* uncorrectable error */
712 if (!(uncorsta & first_error)) {
713 /* the bit that corresponds to the first error is cleared */
714 pcie_aer_clear_error(dev);
715 } else if (errcap & PCI_ERR_CAP_MHRE) {
716 /* When PCI_ERR_CAP_MHRE is enabled and the first error isn't cleared
717 * nothing should happen. So we have to revert the modification to
718 * the register.
720 pcie_aer_update_uncor_status(dev);
721 } else {
722 /* capability & control
723 * PCI_ERR_CAP_MHRE might be cleared, so clear of header log.
725 aer_log_clear_all_err(&dev->exp.aer_log);
729 void pcie_aer_root_init(PCIDevice *dev)
731 uint16_t pos = dev->exp.aer_cap;
733 pci_set_long(dev->wmask + pos + PCI_ERR_ROOT_COMMAND,
734 PCI_ERR_ROOT_CMD_EN_MASK);
735 pci_set_long(dev->w1cmask + pos + PCI_ERR_ROOT_STATUS,
736 PCI_ERR_ROOT_STATUS_REPORT_MASK);
737 /* PCI_ERR_ROOT_IRQ is RO but devices change it using a
738 * device-specific method.
740 pci_set_long(dev->cmask + pos + PCI_ERR_ROOT_STATUS,
741 ~PCI_ERR_ROOT_IRQ);
744 void pcie_aer_root_reset(PCIDevice *dev)
746 uint8_t* aer_cap = dev->config + dev->exp.aer_cap;
748 pci_set_long(aer_cap + PCI_ERR_ROOT_COMMAND, 0);
751 * Advanced Error Interrupt Message Number in Root Error Status Register
752 * must be updated by chip dependent code because it's chip dependent
753 * which number is used.
757 void pcie_aer_root_write_config(PCIDevice *dev,
758 uint32_t addr, uint32_t val, int len,
759 uint32_t root_cmd_prev)
761 uint8_t *aer_cap = dev->config + dev->exp.aer_cap;
762 uint32_t root_status = pci_get_long(aer_cap + PCI_ERR_ROOT_STATUS);
763 uint32_t enabled_cmd = pcie_aer_status_to_cmd(root_status);
764 uint32_t root_cmd = pci_get_long(aer_cap + PCI_ERR_ROOT_COMMAND);
765 /* 6.2.4.1.2 Interrupt Generation */
766 if (!msix_enabled(dev) && !msi_enabled(dev)) {
767 if (pci_intx(dev) != -1) {
768 pci_set_irq(dev, !!(root_cmd & enabled_cmd));
770 return;
773 if ((root_cmd_prev & enabled_cmd) || !(root_cmd & enabled_cmd)) {
774 /* Send MSI on transition from false to true. */
775 return;
778 pcie_aer_root_notify(dev);
781 static const VMStateDescription vmstate_pcie_aer_err = {
782 .name = "PCIE_AER_ERROR",
783 .version_id = 1,
784 .minimum_version_id = 1,
785 .fields = (VMStateField[]) {
786 VMSTATE_UINT32(status, PCIEAERErr),
787 VMSTATE_UINT16(source_id, PCIEAERErr),
788 VMSTATE_UINT16(flags, PCIEAERErr),
789 VMSTATE_UINT32_ARRAY(header, PCIEAERErr, 4),
790 VMSTATE_UINT32_ARRAY(prefix, PCIEAERErr, 4),
791 VMSTATE_END_OF_LIST()
795 static bool pcie_aer_state_log_num_valid(void *opaque, int version_id)
797 PCIEAERLog *s = opaque;
799 return s->log_num <= s->log_max;
802 const VMStateDescription vmstate_pcie_aer_log = {
803 .name = "PCIE_AER_ERROR_LOG",
804 .version_id = 1,
805 .minimum_version_id = 1,
806 .fields = (VMStateField[]) {
807 VMSTATE_UINT16(log_num, PCIEAERLog),
808 VMSTATE_UINT16_EQUAL(log_max, PCIEAERLog, NULL),
809 VMSTATE_VALIDATE("log_num <= log_max", pcie_aer_state_log_num_valid),
810 VMSTATE_STRUCT_VARRAY_POINTER_UINT16(log, PCIEAERLog, log_num,
811 vmstate_pcie_aer_err, PCIEAERErr),
812 VMSTATE_END_OF_LIST()
816 typedef struct PCIEAERErrorName {
817 const char *name;
818 uint32_t val;
819 bool correctable;
820 } PCIEAERErrorName;
823 * AER error name -> value conversion table
824 * This naming scheme is same to linux aer-injection tool.
826 static const struct PCIEAERErrorName pcie_aer_error_list[] = {
828 .name = "DLP",
829 .val = PCI_ERR_UNC_DLP,
830 .correctable = false,
831 }, {
832 .name = "SDN",
833 .val = PCI_ERR_UNC_SDN,
834 .correctable = false,
835 }, {
836 .name = "POISON_TLP",
837 .val = PCI_ERR_UNC_POISON_TLP,
838 .correctable = false,
839 }, {
840 .name = "FCP",
841 .val = PCI_ERR_UNC_FCP,
842 .correctable = false,
843 }, {
844 .name = "COMP_TIME",
845 .val = PCI_ERR_UNC_COMP_TIME,
846 .correctable = false,
847 }, {
848 .name = "COMP_ABORT",
849 .val = PCI_ERR_UNC_COMP_ABORT,
850 .correctable = false,
851 }, {
852 .name = "UNX_COMP",
853 .val = PCI_ERR_UNC_UNX_COMP,
854 .correctable = false,
855 }, {
856 .name = "RX_OVER",
857 .val = PCI_ERR_UNC_RX_OVER,
858 .correctable = false,
859 }, {
860 .name = "MALF_TLP",
861 .val = PCI_ERR_UNC_MALF_TLP,
862 .correctable = false,
863 }, {
864 .name = "ECRC",
865 .val = PCI_ERR_UNC_ECRC,
866 .correctable = false,
867 }, {
868 .name = "UNSUP",
869 .val = PCI_ERR_UNC_UNSUP,
870 .correctable = false,
871 }, {
872 .name = "ACSV",
873 .val = PCI_ERR_UNC_ACSV,
874 .correctable = false,
875 }, {
876 .name = "INTN",
877 .val = PCI_ERR_UNC_INTN,
878 .correctable = false,
879 }, {
880 .name = "MCBTLP",
881 .val = PCI_ERR_UNC_MCBTLP,
882 .correctable = false,
883 }, {
884 .name = "ATOP_EBLOCKED",
885 .val = PCI_ERR_UNC_ATOP_EBLOCKED,
886 .correctable = false,
887 }, {
888 .name = "TLP_PRF_BLOCKED",
889 .val = PCI_ERR_UNC_TLP_PRF_BLOCKED,
890 .correctable = false,
891 }, {
892 .name = "RCVR",
893 .val = PCI_ERR_COR_RCVR,
894 .correctable = true,
895 }, {
896 .name = "BAD_TLP",
897 .val = PCI_ERR_COR_BAD_TLP,
898 .correctable = true,
899 }, {
900 .name = "BAD_DLLP",
901 .val = PCI_ERR_COR_BAD_DLLP,
902 .correctable = true,
903 }, {
904 .name = "REP_ROLL",
905 .val = PCI_ERR_COR_REP_ROLL,
906 .correctable = true,
907 }, {
908 .name = "REP_TIMER",
909 .val = PCI_ERR_COR_REP_TIMER,
910 .correctable = true,
911 }, {
912 .name = "ADV_NONFATAL",
913 .val = PCI_ERR_COR_ADV_NONFATAL,
914 .correctable = true,
915 }, {
916 .name = "INTERNAL",
917 .val = PCI_ERR_COR_INTERNAL,
918 .correctable = true,
919 }, {
920 .name = "HL_OVERFLOW",
921 .val = PCI_ERR_COR_HL_OVERFLOW,
922 .correctable = true,
926 int pcie_aer_parse_error_string(const char *error_name,
927 uint32_t *status, bool *correctable)
929 int i;
931 for (i = 0; i < ARRAY_SIZE(pcie_aer_error_list); i++) {
932 const PCIEAERErrorName *e = &pcie_aer_error_list[i];
933 if (strcmp(error_name, e->name)) {
934 continue;
937 *status = e->val;
938 *correctable = e->correctable;
939 return 0;
941 return -EINVAL;