[PATCH v2 06/12] virtio_pci: read the device memory buffer registers

Alexander Graf <[email protected]>
Newsgroups dev.linux.lists.virtualization,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
In preparation to support VIRTIO_F_DMB, read the two registers a device
uses to describe its Device Memory Buffer. Both are read-only le16
fields at the end of the common configuration structure. dmb_shm_id
names the VIRTIO_PCI_CAP_SHARED_MEMORY_CFG capability that
virtio_pci_find_shm_cap() has to find to map the region, and is valid
once the feature is negotiated. dmb_mem_type describes the memory the
region is made of: VIRTIO_DMB_MEM_TYPE_COHERENT means a write by either
side becomes visible to the other with no cache maintenance by the
driver. It is valid as soon as the device offers the feature, so a
driver that does not support the value it reads can decline the offer
instead of failing the device afterwards.

Add both fields, VIRTIO_PCI_COMMON_DMB_SHM_ID and
VIRTIO_PCI_COMMON_DMB_MEM_TYPE for the offsets check_offsets() asserts
them against, and vp_modern_get_dmb_shm_id() and
vp_modern_get_dmb_mem_type() to read them. vp_modern_probe() capped the
common cfg mapping at the end of admin_queue_num, exactly where
dmb_shm_id starts, so extend it to the end of dmb_mem_type.
vp_modern_map_capability() takes that as an upper bound, so a device with
a shorter common cfg maps what it has and mdev->common_len records how
much.

Link: https://lore.kernel.org/virtio-comment/[email protected]/
Assisted-by: Kiro:claude-opus-5 checkpatch sparse
Signed-off-by: Alexander Graf <[email protected]>
---
 drivers/virtio/virtio_pci_modern_dev.c | 47 +++++++++++++++++++++++++-
 include/linux/virtio_pci_modern.h      |  2 ++
 include/uapi/linux/virtio_pci.h        | 19 +++++++++++
 3 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c
index 413a8c353463..270c67fe58ff 100644
--- a/drivers/virtio/virtio_pci_modern_dev.c
+++ b/drivers/virtio/virtio_pci_modern_dev.c
@@ -211,6 +211,10 @@ static inline void check_offsets(void)
 		     offsetof(struct virtio_pci_modern_common_cfg, admin_queue_index));
 	BUILD_BUG_ON(VIRTIO_PCI_COMMON_ADM_Q_NUM !=
 		     offsetof(struct virtio_pci_modern_common_cfg, admin_queue_num));
+	BUILD_BUG_ON(VIRTIO_PCI_COMMON_DMB_SHM_ID !=
+		     offsetof(struct virtio_pci_modern_common_cfg, dmb_shm_id));
+	BUILD_BUG_ON(VIRTIO_PCI_COMMON_DMB_MEM_TYPE !=
+		     offsetof(struct virtio_pci_modern_common_cfg, dmb_mem_type));
 }
 
 /*
@@ -300,7 +304,7 @@ int vp_modern_probe(struct virtio_pci_modern_device *mdev)
 	mdev->common = vp_modern_map_capability(mdev, common,
 			      sizeof(struct virtio_pci_common_cfg), 4, 0,
 			      offsetofend(struct virtio_pci_modern_common_cfg,
-					  admin_queue_num),
+					  dmb_mem_type),
 			      &mdev->common_len, NULL);
 	if (!mdev->common)
 		goto err_map_common;
@@ -752,6 +756,47 @@ u16 vp_modern_avq_index(struct virtio_pci_modern_device *mdev)
 }
 EXPORT_SYMBOL_GPL(vp_modern_avq_index);
 
+/*
+ * vp_modern_get_dmb_shm_id - read the Device Memory Buffer shared memory id
+ * @mdev: the modern virtio-pci device
+ *
+ * The value identifies the VIRTIO_PCI_CAP_SHARED_MEMORY_CFG capability that
+ * describes the Device Memory Buffer region.  Only valid once VIRTIO_F_DMB
+ * has been negotiated, and the caller has to have established that the common
+ * configuration structure is long enough to hold the field.
+ *
+ * Returns the shared memory id.
+ */
+u16 vp_modern_get_dmb_shm_id(struct virtio_pci_modern_device *mdev)
+{
+	struct virtio_pci_modern_common_cfg __iomem *cfg;
+
+	cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common;
+	return vp_ioread16(&cfg->dmb_shm_id);
+}
+EXPORT_SYMBOL_GPL(vp_modern_get_dmb_shm_id);
+
+/*
+ * vp_modern_get_dmb_mem_type - read the Device Memory Buffer memory type
+ * @mdev: the modern virtio-pci device
+ *
+ * The value describes the memory the Device Memory Buffer region is made of.
+ * VIRTIO_DMB_MEM_TYPE_COHERENT means the region is cache coherent.  Valid
+ * whenever the device offers VIRTIO_F_DMB, and the caller has to have
+ * established that the common configuration structure is long enough to hold
+ * the field.
+ *
+ * Returns the memory type.
+ */
+u16 vp_modern_get_dmb_mem_type(struct virtio_pci_modern_device *mdev)
+{
+	struct virtio_pci_modern_common_cfg __iomem *cfg;
+
+	cfg = (struct virtio_pci_modern_common_cfg __iomem *)mdev->common;
+	return vp_ioread16(&cfg->dmb_mem_type);
+}
+EXPORT_SYMBOL_GPL(vp_modern_get_dmb_mem_type);
+
 MODULE_VERSION("0.1");
 MODULE_DESCRIPTION("Modern Virtio PCI Device");
 MODULE_AUTHOR("Jason Wang <[email protected]>");
diff --git a/include/linux/virtio_pci_modern.h b/include/linux/virtio_pci_modern.h
index 9a3f2fc53bd6..80643c895495 100644
--- a/include/linux/virtio_pci_modern.h
+++ b/include/linux/virtio_pci_modern.h
@@ -162,4 +162,6 @@ int vp_modern_get_queue_reset(struct virtio_pci_modern_device *mdev, u16 index);
 void vp_modern_set_queue_reset(struct virtio_pci_modern_device *mdev, u16 index);
 u16 vp_modern_avq_num(struct virtio_pci_modern_device *mdev);
 u16 vp_modern_avq_index(struct virtio_pci_modern_device *mdev);
+u16 vp_modern_get_dmb_shm_id(struct virtio_pci_modern_device *mdev);
+u16 vp_modern_get_dmb_mem_type(struct virtio_pci_modern_device *mdev);
 #endif
diff --git a/include/uapi/linux/virtio_pci.h b/include/uapi/linux/virtio_pci.h
index e732e3456e27..1bd2bb981dc9 100644
--- a/include/uapi/linux/virtio_pci.h
+++ b/include/uapi/linux/virtio_pci.h
@@ -193,6 +193,23 @@ struct virtio_pci_modern_common_cfg {
 
 	__le16 admin_queue_index;	/* read-only */
 	__le16 admin_queue_num;		/* read-only */
+
+	/*
+	 * Reports the shmid of the Device Memory Buffer region.  Valid once
+	 * VIRTIO_F_DMB has been negotiated.
+	 */
+	__le16 dmb_shm_id;		/* read-only */
+
+	/*
+	 * Reports the memory type of the Device Memory Buffer region.
+	 * VIRTIO_DMB_MEM_TYPE_COHERENT means the region is cache coherent: a
+	 * write by either side becomes visible to the other with no cache
+	 * maintenance by the driver.  Every other value is reserved, and a
+	 * driver must not accept VIRTIO_F_DMB unless the value is one it
+	 * supports.  Valid whenever the device offers VIRTIO_F_DMB, so that a
+	 * driver can read it before it accepts.
+	 */
+	__le16 dmb_mem_type;		/* read-only */
 };
 
 /* Fields in VIRTIO_PCI_CAP_PCI_CFG: */
@@ -235,6 +252,8 @@ struct virtio_pci_cfg_cap {
 #define VIRTIO_PCI_COMMON_Q_RESET	58
 #define VIRTIO_PCI_COMMON_ADM_Q_IDX	60
 #define VIRTIO_PCI_COMMON_ADM_Q_NUM	62
+#define VIRTIO_PCI_COMMON_DMB_SHM_ID	64
+#define VIRTIO_PCI_COMMON_DMB_MEM_TYPE	66
 
 #endif /* VIRTIO_PCI_NO_MODERN */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.