[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 3/3] virtio-gpu: add a new command to get p2pdma_distance
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@xxxxxxx> --- 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |