void pcie_dev_ser_num_init(PCIDevice *dev, uint16_t offset, uint64_t ser_num) { static const int pci_dsn_ver = 1; static const int pci_dsn_cap = 4; pcie_add_capability(dev, PCI_EXT_CAP_ID_DSN, pci_dsn_ver, offset, PCI_EXT_CAP_DSN_SIZEOF); pci_set_quad(dev->config + offset + pci_dsn_cap, ser_num); }
void pcie_ats_init(PCIDevice *dev, uint16_t offset) { pcie_add_capability(dev, PCI_EXT_CAP_ID_ATS, 0x1, offset, PCI_EXT_CAP_ATS_SIZEOF); dev->exp.ats_cap = offset; /* Invalidate Queue Depth 0, Page Aligned Request 0 */ pci_set_word(dev->config + offset + PCI_ATS_CAP, 0); /* STU 0, Disabled by default */ pci_set_word(dev->config + offset + PCI_ATS_CTRL, 0); pci_set_word(dev->wmask + dev->exp.ats_cap + PCI_ATS_CTRL, 0x800f); }
/* ARI */ void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn) { pcie_add_capability(dev, PCI_EXT_CAP_ID_ARI, PCI_ARI_VER, offset, PCI_ARI_SIZEOF); pci_set_long(dev->config + offset + PCI_ARI_CAP, (nextfn & 0xff) << 8); }
int pcie_aer_init(PCIDevice *dev, uint16_t offset) { PCIExpressDevice *exp; pcie_add_capability(dev, PCI_EXT_CAP_ID_ERR, PCI_ERR_VER, offset, PCI_ERR_SIZEOF); exp = &dev->exp; exp->aer_cap = offset; /* log_max is property */ if (dev->exp.aer_log.log_max == PCIE_AER_LOG_MAX_UNSET) { dev->exp.aer_log.log_max = PCIE_AER_LOG_MAX_DEFAULT; } /* clip down the value to avoid unreasobale memory usage */ if (dev->exp.aer_log.log_max > PCIE_AER_LOG_MAX_LIMIT) { return -EINVAL; } dev->exp.aer_log.log = g_malloc0(sizeof dev->exp.aer_log.log[0] * dev->exp.aer_log.log_max); pci_set_long(dev->w1cmask + offset + PCI_ERR_UNCOR_STATUS, PCI_ERR_UNC_SUPPORTED); pci_set_long(dev->config + offset + PCI_ERR_UNCOR_SEVER, PCI_ERR_UNC_SEVERITY_DEFAULT); pci_set_long(dev->wmask + offset + PCI_ERR_UNCOR_SEVER, PCI_ERR_UNC_SUPPORTED); pci_long_test_and_set_mask(dev->w1cmask + offset + PCI_ERR_COR_STATUS, PCI_ERR_COR_SUPPORTED); pci_set_long(dev->config + offset + PCI_ERR_COR_MASK, PCI_ERR_COR_MASK_DEFAULT); pci_set_long(dev->wmask + offset + PCI_ERR_COR_MASK, PCI_ERR_COR_SUPPORTED); /* capabilities and control. multiple header logging is supported */ if (dev->exp.aer_log.log_max > 0) { pci_set_long(dev->config + offset + PCI_ERR_CAP, PCI_ERR_CAP_ECRC_GENC | PCI_ERR_CAP_ECRC_CHKC | PCI_ERR_CAP_MHRC); pci_set_long(dev->wmask + offset + PCI_ERR_CAP, PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE | PCI_ERR_CAP_MHRE); } else { pci_set_long(dev->config + offset + PCI_ERR_CAP, PCI_ERR_CAP_ECRC_GENC | PCI_ERR_CAP_ECRC_CHKC); pci_set_long(dev->wmask + offset + PCI_ERR_CAP, PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE); } switch (pcie_cap_get_type(dev)) { case PCI_EXP_TYPE_ROOT_PORT: /* this case will be set by pcie_aer_root_init() */ /* fallthrough */ case PCI_EXP_TYPE_DOWNSTREAM: case PCI_EXP_TYPE_UPSTREAM: pci_word_test_and_set_mask(dev->wmask + PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_SERR); pci_long_test_and_set_mask(dev->w1cmask + PCI_STATUS, PCI_SEC_STATUS_RCV_SYSTEM_ERROR); break; default: /* nothing */ break; } return 0; }
int pcie_aer_init(PCIDevice *dev, uint8_t cap_ver, uint16_t offset, uint16_t size, Error **errp) { pcie_add_capability(dev, PCI_EXT_CAP_ID_ERR, cap_ver, offset, size); dev->exp.aer_cap = offset; /* clip down the value to avoid unreasonable memory usage */ if (dev->exp.aer_log.log_max > PCIE_AER_LOG_MAX_LIMIT) { error_setg(errp, "Invalid aer_log_max %d. The max number of aer log " "is %d", dev->exp.aer_log.log_max, PCIE_AER_LOG_MAX_LIMIT); return -EINVAL; } dev->exp.aer_log.log = g_malloc0(sizeof dev->exp.aer_log.log[0] * dev->exp.aer_log.log_max); pci_set_long(dev->w1cmask + offset + PCI_ERR_UNCOR_STATUS, PCI_ERR_UNC_SUPPORTED); pci_set_long(dev->config + offset + PCI_ERR_UNCOR_SEVER, PCI_ERR_UNC_SEVERITY_DEFAULT); pci_set_long(dev->wmask + offset + PCI_ERR_UNCOR_SEVER, PCI_ERR_UNC_SUPPORTED); pci_long_test_and_set_mask(dev->w1cmask + offset + PCI_ERR_COR_STATUS, PCI_ERR_COR_SUPPORTED); pci_set_long(dev->config + offset + PCI_ERR_COR_MASK, PCI_ERR_COR_MASK_DEFAULT); pci_set_long(dev->wmask + offset + PCI_ERR_COR_MASK, PCI_ERR_COR_SUPPORTED); /* capabilities and control. multiple header logging is supported */ if (dev->exp.aer_log.log_max > 0) { pci_set_long(dev->config + offset + PCI_ERR_CAP, PCI_ERR_CAP_ECRC_GENC | PCI_ERR_CAP_ECRC_CHKC | PCI_ERR_CAP_MHRC); pci_set_long(dev->wmask + offset + PCI_ERR_CAP, PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE | PCI_ERR_CAP_MHRE); } else { pci_set_long(dev->config + offset + PCI_ERR_CAP, PCI_ERR_CAP_ECRC_GENC | PCI_ERR_CAP_ECRC_CHKC); pci_set_long(dev->wmask + offset + PCI_ERR_CAP, PCI_ERR_CAP_ECRC_GENE | PCI_ERR_CAP_ECRC_CHKE); } switch (pcie_cap_get_type(dev)) { case PCI_EXP_TYPE_ROOT_PORT: /* this case will be set by pcie_aer_root_init() */ /* fallthrough */ case PCI_EXP_TYPE_DOWNSTREAM: case PCI_EXP_TYPE_UPSTREAM: pci_word_test_and_set_mask(dev->wmask + PCI_BRIDGE_CONTROL, PCI_BRIDGE_CTL_SERR); pci_long_test_and_set_mask(dev->w1cmask + PCI_STATUS, PCI_SEC_STATUS_RCV_SYSTEM_ERROR); break; default: /* nothing */ break; } return 0; }