@@ -490,6 +490,82 @@ rte_eal_pci_probe_one_driver(struct rte_pci_driver *dr, struct rte_pci_device *d
return 1;
}
+/* Read PCI config space. */
+int rte_eal_pci_read_config(const struct rte_pci_device *dev,
+ void *buf, size_t len, off_t offset)
+{
+ struct pci_io io = {
+ .pi_sel = {
+ .pc_domain = dev->addr.domain,
+ .pc_bus = dev->addr.bus,
+ .pc_dev = dev->addr.devid,
+ .pc_func = dev->addr.function,
+ },
+ .pi_reg = offset,
+ .pi_width = len;
+ };
+
+ if (len == 0 || len > sizeof(io.pi_data)) {
+ RTE_LOG(ERR, EAL, "%s(): invalid register length\n", __func__);
+ return -1;
+ }
+
+ fd = open("/dev/pci", O_RDONLY);
+ if (fd < 0) {
+ RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
+ return -1;
+ }
+
+ if (ioctl(fd, PCIOCREAD, &io) < 0) {
+ RTE_LOG(ERR, EAL, "%s(): error with ioctl on /dev/pci: %s\n",
+ __func__, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ memcpy(buf, io.pi_data, len);
+ return 0;
+}
+
+/* Write PCI config space. */
+int rte_eal_pci_write_config(const struct rte_pci_device *device,
+ const void *buf, size_t len, off_t offset)
+{
+ struct pci_io io = {
+ .pi_sel = {
+ .pc_domain = dev->addr.domain,
+ .pc_bus = dev->addr.bus,
+ .pc_dev = dev->addr.devid,
+ .pc_func = dev->addr.function,
+ },
+ .pi_reg = offset,
+ .pi_width = len;
+ };
+
+ if (len == 0 || len > sizeof(io.pi_data)) {
+ RTE_LOG(ERR, EAL, "%s(): invalid register length\n", __func__);
+ return -1;
+ }
+ memcpy(io.pi_data, buf, len);
+
+ fd = open("/dev/pci", O_RDONLY);
+ if (fd < 0) {
+ RTE_LOG(ERR, EAL, "%s(): error opening /dev/pci\n", __func__);
+ return -1;
+ }
+
+ if (ioctl(fd, PCIOCWRITE, &io) < 0) {
+ RTE_LOG(ERR, EAL, "%s(): error with ioctl on /dev/pci: %s\n",
+ __func__, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ close(fd);
+ return 0;
+}
+
/* Init the PCI EAL subsystem */
int
rte_eal_pci_init(void)
@@ -393,6 +393,35 @@ void rte_eal_pci_register(struct rte_pci_driver *driver);
*/
void rte_eal_pci_unregister(struct rte_pci_driver *driver);
+
+/**
+ * Read PCI config space.
+ *
+ * @param device
+ * A pointer to a rte_pci_device structure describing the device
+ * to use
+ * @param buf
+ * A data buffer where the bytes should be read into
+ * @param size
+ * The length of the data buffer.
+ */
+int rte_eal_pci_read_config(const struct rte_pci_device *device,
+ void *buf, size_t len, off_t offset);
+
+/**
+ * Write PCI config space.
+ *
+ * @param device
+ * A pointer to a rte_pci_device structure describing the device
+ * to use
+ * @param buf
+ * A data buffer containing the bytes should be written
+ * @param size
+ * The length of the data buffer.
+ */
+int rte_eal_pci_write_config(const struct rte_pci_device *device,
+ const void *buf, size_t len, off_t offset);
+
#ifdef __cplusplus
}
#endif
@@ -756,6 +756,56 @@ rte_eal_pci_close_one_driver(struct rte_pci_driver *dr __rte_unused,
}
#endif /* RTE_LIBRTE_EAL_HOTPLUG */
+/* Read PCI config space. */
+int rte_eal_pci_read_config(const struct rte_pci_device *device,
+ void *buf, size_t len, off_t offset)
+{
+ const struct rte_intr_handle *intr_handle = &device->intr_handle;
+
+ switch (intr_handle->type) {
+ case RTE_INTR_HANDLE_UIO:
+ case RTE_INTR_HANDLE_UIO_INTX:
+ return pci_uio_read_config(intr_handle, buf, len, offset);
+
+#ifdef RTE_EAL_VFIO
+ case RTE_INTR_HANDLE_VFIO_MSIX:
+ case RTE_INTR_HANDLE_VFIO_MSI:
+ case RTE_INTR_HANDLE_VFIO_LEGACY:
+ return pci_vfio_read_config(intr_handle, buf, len, offset);
+#endif
+ default:
+ RTE_LOG(ERR, EAL,
+ "Unknown handle type of fd %d\n",
+ intr_handle->fd);
+ return -1;
+ }
+}
+
+/* Write PCI config space. */
+int rte_eal_pci_write_config(const struct rte_pci_device *device,
+ const void *buf, size_t len, off_t offset)
+{
+ const struct rte_intr_handle *intr_handle = &device->intr_handle;
+
+ switch (intr_handle->type) {
+ case RTE_INTR_HANDLE_UIO:
+ case RTE_INTR_HANDLE_UIO_INTX:
+ return pci_uio_write_config(intr_handle, buf, len, offset);
+
+#ifdef RTE_EAL_VFIO
+ case RTE_INTR_HANDLE_VFIO_MSIX:
+ case RTE_INTR_HANDLE_VFIO_MSI:
+ case RTE_INTR_HANDLE_VFIO_LEGACY:
+ return pci_vfio_write_config(intr_handle, buf, len, offset);
+#endif
+ default:
+ RTE_LOG(ERR, EAL,
+ "Unknown handle type of fd %d\n",
+ intr_handle->fd);
+ return -1;
+ }
+}
+
/* Init the PCI EAL subsystem */
int
rte_eal_pci_init(void)
@@ -68,6 +68,11 @@ void *pci_find_max_end_va(void);
void *pci_map_resource(void *requested_addr, int fd, off_t offset,
size_t size, int additional_flags);
+int pci_uio_read_config(const struct rte_intr_handle *intr_handle,
+ void *buf, size_t len, off_t offs);
+int pci_uio_write_config(const struct rte_intr_handle *intr_handle,
+ const void *buf, size_t len, off_t offs);
+
/* map IGB_UIO resource prototype */
int pci_uio_map_resource(struct rte_pci_device *dev);
@@ -86,6 +91,12 @@ int pci_vfio_enable(void);
int pci_vfio_is_enabled(void);
int pci_vfio_mp_sync_setup(void);
+/* access config space */
+int pci_vfio_read_config(const struct rte_intr_handle *intr_handle,
+ void *buf, size_t len, off_t offs);
+int pci_vfio_write_config(const struct rte_intr_handle *intr_handle,
+ const void *buf, size_t len, off_t offs);
+
/* map VFIO resource prototype */
int pci_vfio_map_resource(struct rte_pci_device *dev);
int pci_vfio_get_group_fd(int iommu_group_fd);
@@ -58,6 +58,20 @@ EAL_REGISTER_TAILQ(rte_uio_tailq)
#define OFF_MAX ((uint64_t)(off_t)-1)
+int
+pci_uio_read_config(const struct rte_intr_handle *intr_handle,
+ void *buf, size_t len, off_t offset)
+{
+ return pread(intr_handle->uio_cfg_fd, buf, len, offset);
+}
+
+int
+pci_uio_write_config(const struct rte_intr_handle *intr_handle,
+ const void *buf, size_t len, off_t offset)
+{
+ return pwrite(intr_handle->uio_cfg_fd, buf, len, offset);
+}
+
static int
pci_uio_set_bus_master(int dev_fd)
{
@@ -77,6 +77,22 @@ EAL_REGISTER_TAILQ(rte_vfio_tailq)
/* per-process VFIO config */
static struct vfio_config vfio_cfg;
+int
+pci_vfio_read_config(const struct rte_intr_handle *intr_handle,
+ void *buf, size_t len, off_t offs)
+{
+ return pread64(intr_handle->vfio_dev_fd, buf, len,
+ VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + offs);
+}
+
+int
+pci_vfio_write_config(const struct rte_intr_handle *intr_handle,
+ const void *buf, size_t len, off_t offs)
+{
+ return pwrite64(intr_handle->vfio_dev_fd, buf, len,
+ VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) + offs);
+}
+
/* get PCI BAR number where MSI-X interrupts are */
static int
pci_vfio_get_msix_bar(int fd, int *msix_bar, uint32_t *msix_table_offset,