To implement passthrough dGPU prime in guest, virtio-gpu need to check
p2pdma_distance of two GPUs. This adds a new command for guest to pass
virtual pci notations of two pci devices to host and send xen privcmd to
calculate physical p2pdma_distance.
Signed-off-by: Julia Zhang <julia.zhang@amd.com>
---
hw/display/virtio-gpu-virgl.c | 47 +++++++++++++++++++++
hw/i386/xen/xen-hvm.c | 6 +++
include/hw/virtio/virtio-gpu-bswap.h | 12 ++++++
include/hw/xen/xen.h | 3 ++
include/standard-headers/linux/virtio_gpu.h | 19 +++++++++
5 files changed, 87 insertions(+)
diff --git a/hw/display/virtio-gpu-virgl.c b/hw/display/virtio-gpu-virgl.c
index 07faeb1834..eb9b193ade 100644
--- a/hw/display/virtio-gpu-virgl.c
+++ b/hw/display/virtio-gpu-virgl.c
@@ -16,6 +16,12 @@
#include "qemu/iov.h"
#include "trace.h"
#include "hw/virtio/virtio.h"
+#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
+#include "hw/virtio/virtio-pci.h"
+#include "hw/virtio/virtio-bus.h"
+#include "hw/xen/xen.h"
+
#include "hw/virtio/virtio-gpu.h"
#include "hw/virtio/virtio-gpu-bswap.h"
#include "hw/virtio/virtio-gpu-pixman.h"
@@ -188,6 +194,44 @@ virtio_gpu_virgl_unmap_resource_blob(VirtIOGPU *g,
return 0;
}
+
+static void virgl_cmd_p2pdma_distance(VirtIOGPU *g,
+ struct virtio_gpu_ctrl_command *cmd)
+{
+ struct virtio_gpu_device_p2pdma_distance cmd_p;
+ struct virtio_gpu_resp_distance resp;
+ PCIDevice *client = NULL, *provider = NULL;
+ int ret;
+
+ VIRTIO_GPU_FILL_CMD(cmd_p);
+ virtio_gpu_p2pdma_distance_bswap(&cmd_p);
+
+ ret = pci_qdev_get_device(cmd_p.provider_bus, cmd_p.provider_slot, cmd_p.provider_func, &provider);
+
+ if (ret) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: virgl get physical device error: %s\n",
+ __func__, strerror(-ret));
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return;
+ }
+
+ ret = pci_qdev_get_device(cmd_p.client_bus, cmd_p.client_slot, cmd_p.client_func, &client);
+ if (ret) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: virgl get physical device error: %s\n",
+ __func__, strerror(-ret));
+ cmd->error = VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER;
+ return;
+ }
+
+ int distance = xen_p2pdma_distance(provider->hostaddr.bus, provider->hostaddr.slot,
+ provider->hostaddr.function,client->hostaddr.bus,
+ client->hostaddr.slot, client->hostaddr.function);
+
+ memset(&resp, 0, sizeof(resp));
+ resp.hdr.type = VIRTIO_GPU_RESP_OK_P2PDMA_DISTANCE;
+ resp.distance = distance;
+ virtio_gpu_ctrl_response(g, cmd, &resp.hdr, sizeof(resp));
+}
#endif
static void virgl_cmd_create_resource_2d(VirtIOGPU *g,
@@ -913,6 +957,9 @@ void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
case VIRTIO_GPU_CMD_SUBMIT_3D:
virgl_cmd_submit_3d(g, cmd);
break;
+ case VIRTIO_GPU_CMD_P2PDMA_DISTANCE:
+ virgl_cmd_p2pdma_distance(g, cmd);
+ break;
case VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D:
virgl_cmd_transfer_to_host_2d(g, cmd);
break;
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index d3df488c48..c8dd27dad7 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -604,6 +604,12 @@ static bool xen_check_stubdomain(struct xs_handle *xsh)
return is_stubdom;
}
+int xen_p2pdma_distance(uint32_t bus, uint32_t slot, uint32_t func,
+ uint32_t c_bus, uint32_t c_slot, uint32_t c_func)
+{
+ return xc_physdev_p2pdma_distance(xen_xc, bus, slot, func, c_bus, c_slot, c_func);
+}
+
void xen_hvm_init_pc(PCMachineState *pcms, MemoryRegion **ram_memory)
{
MachineState *ms = MACHINE(pcms);
diff --git a/include/hw/virtio/virtio-gpu-bswap.h b/include/hw/virtio/virtio-gpu-bswap.h
index dd1975e2d4..b5c0c0adcd 100644
--- a/include/hw/virtio/virtio-gpu-bswap.h
+++ b/include/hw/virtio/virtio-gpu-bswap.h
@@ -78,6 +78,18 @@ virtio_gpu_map_blob_bswap(struct virtio_gpu_resource_map_blob *mblob)
le64_to_cpus(&mblob->offset);
}
+static inline void
+virtio_gpu_p2pdma_distance_bswap(struct virtio_gpu_device_p2pdma_distance *p2p_dist)
+{
+ virtio_gpu_ctrl_hdr_bswap(&p2p_dist->hdr);
+ le32_to_cpus(&p2p_dist->provider_bus);
+ le32_to_cpus(&p2p_dist->provider_slot);
+ le32_to_cpus(&p2p_dist->provider_func);
+ le32_to_cpus(&p2p_dist->client_bus);
+ le32_to_cpus(&p2p_dist->client_bus);
+ le32_to_cpus(&p2p_dist->client_bus);
+}
+
static inline void
virtio_gpu_unmap_blob_bswap(struct virtio_gpu_resource_unmap_blob *ublob)
{
diff --git a/include/hw/xen/xen.h b/include/hw/xen/xen.h
index ecb89ecfc1..fe1d628327 100644
--- a/include/hw/xen/xen.h
+++ b/include/hw/xen/xen.h
@@ -48,4 +48,7 @@ qemu_irq *xen_interrupt_controller_init(void);
void xen_register_framebuffer(struct MemoryRegion *mr);
+int xen_p2pdma_distance(uint32_t bus, uint32_t slot, uint32_t func,
+ uint32_t c_bus, uint32_t c_slot, uint32_t c_func);
+
#endif /* QEMU_HW_XEN_H */
diff --git a/include/standard-headers/linux/virtio_gpu.h b/include/standard-headers/linux/virtio_gpu.h
index 6459fdb9fb..2e55dcc2fe 100644
--- a/include/standard-headers/linux/virtio_gpu.h
+++ b/include/standard-headers/linux/virtio_gpu.h
@@ -95,6 +95,7 @@ enum virtio_gpu_ctrl_type {
VIRTIO_GPU_CMD_SUBMIT_3D,
VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB,
VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB,
+ VIRTIO_GPU_CMD_P2PDMA_DISTANCE,
/* cursor commands */
VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300,
@@ -108,6 +109,7 @@ enum virtio_gpu_ctrl_type {
VIRTIO_GPU_RESP_OK_EDID,
VIRTIO_GPU_RESP_OK_RESOURCE_UUID,
VIRTIO_GPU_RESP_OK_MAP_INFO,
+ VIRTIO_GPU_RESP_OK_P2PDMA_DISTANCE,
/* error responses */
VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200,
@@ -429,6 +431,23 @@ struct virtio_gpu_set_scanout_blob {
uint32_t offsets[4];
};
+/* VIRTIO_GPU_CMD_P2PDMA_DISTANCE */
+struct virtio_gpu_device_p2pdma_distance {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 provider_bus;
+ __le32 provider_slot;
+ __le32 provider_func;
+ __le32 client_bus;
+ __le32 client_slot;
+ __le32 client_func;
+};
+
+/* VIRTIO_GPU_RESP_DISTANCE */
+struct virtio_gpu_resp_distance {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 distance;
+};
+
/* VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB */
struct virtio_gpu_resource_map_blob {
struct virtio_gpu_ctrl_hdr hdr;
--
2.34.1
On Sat, Dec 07, 2024 at 06:55:40PM +0800, Julia Zhang wrote: > diff --git a/include/standard-headers/linux/virtio_gpu.h b/include/standard-headers/linux/virtio_gpu.h > index 6459fdb9fb..2e55dcc2fe 100644 > --- a/include/standard-headers/linux/virtio_gpu.h > +++ b/include/standard-headers/linux/virtio_gpu.h > @@ -95,6 +95,7 @@ enum virtio_gpu_ctrl_type { > VIRTIO_GPU_CMD_SUBMIT_3D, > VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB, > VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB, > + VIRTIO_GPU_CMD_P2PDMA_DISTANCE, > > /* cursor commands */ > VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300, > @@ -108,6 +109,7 @@ enum virtio_gpu_ctrl_type { > VIRTIO_GPU_RESP_OK_EDID, > VIRTIO_GPU_RESP_OK_RESOURCE_UUID, > VIRTIO_GPU_RESP_OK_MAP_INFO, > + VIRTIO_GPU_RESP_OK_P2PDMA_DISTANCE, > > /* error responses */ > VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200, > @@ -429,6 +431,23 @@ struct virtio_gpu_set_scanout_blob { > uint32_t offsets[4]; > }; > > +/* VIRTIO_GPU_CMD_P2PDMA_DISTANCE */ > +struct virtio_gpu_device_p2pdma_distance { > + struct virtio_gpu_ctrl_hdr hdr; > + __le32 provider_bus; > + __le32 provider_slot; > + __le32 provider_func; > + __le32 client_bus; > + __le32 client_slot; > + __le32 client_func; > +}; > + > +/* VIRTIO_GPU_RESP_DISTANCE */ > +struct virtio_gpu_resp_distance { > + struct virtio_gpu_ctrl_hdr hdr; > + __le32 distance; > +}; > + > /* VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB */ > struct virtio_gpu_resource_map_blob { > struct virtio_gpu_ctrl_hdr hdr; > -- > 2.34.1 This is not how we change this header. you need a spec patch, an UAPI change to be accepted into linux. -- MST
© 2016 - 2025 Red Hat, Inc.