• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Advanced Micro Devices, Inc.
3  *
4  * SPDX-License-Identifier: MIT
5  */
6 #ifndef AMDGPU_VIRTIO_PRIVATE_H
7 #define AMDGPU_VIRTIO_PRIVATE_H
8 
9 #include "drm-uapi/amdgpu_drm.h"
10 #include "drm-uapi/virtgpu_drm.h"
11 
12 #include "util/hash_table.h"
13 #include "util/simple_mtx.h"
14 
15 #include "amd_family.h"
16 
17 #include "virtio/vdrm/vdrm.h"
18 #include "virtio/virtio-gpu/drm_hw.h"
19 #include "amdgpu_virtio_proto.h"
20 #include "amdgpu_virtio.h"
21 
22 struct amdvgpu_host_blob;
23 struct amdvgpu_host_blob_allocator;
24 
25 /* Host context seqno handling.
26  * seqno are monotonically increasing integer, so we don't need
27  * to actually submit to know the value. This allows to not
28  * wait for the submission to go to the host (= no need to wait
29  * in the guest) and to know the seqno (= so we can take advantage
30  * of user fence).
31  */
32 struct amdvgpu_context {
33    uint32_t refcount;
34    uint32_t host_context_id;
35    uint64_t ring_next_seqno[];
36 };
37 
38 struct amdvgpu_device {
39    struct vdrm_device * vdev;
40 
41    /* List of existing devices */
42    int refcount;
43    struct amdvgpu_device *next;
44 
45    int fd;
46 
47    /* Table mapping kms handles to amdvgpu_bo instances.
48     * Used to maintain a 1-to-1 mapping between the 2.
49     */
50    simple_mtx_t handle_to_vbo_mutex;
51    struct hash_table *handle_to_vbo;
52 
53    /* Submission through virtio-gpu are ring based.
54     * Ring 0 is used for CPU jobs, then N rings are allocated: 1
55     * per IP type per instance (so if the GPU has 1 gfx queue and 2
56     * queues -> ring0 + 3 hw rings = 4 rings total).
57     */
58    uint32_t num_virtio_rings;
59    uint32_t virtio_ring_mapping[AMD_NUM_IP_TYPES];
60 
61    struct drm_amdgpu_info_device dev_info;
62 
63    /* Blob id are per drm_file identifiers of host blobs.
64     * Use a monotically increased integer to assign the blob id.
65     */
66    uint32_t next_blob_id;
67 
68    /* GPU VA management (allocation / release). */
69    amdgpu_va_manager_handle va_mgr;
70 
71    /* Debug option to make some protocol commands synchronous.
72     * If bit N is set, then the specific command will be sync.
73     */
74    int64_t sync_cmd;
75 
76    /* virtio-gpu uses a single context per drm_file and expects that
77     * any 2 jobs submitted to the same {context, ring} will execute in
78     * order.
79     * amdgpu on the other hand allows for multiple context per drm_file,
80     * so we either have to open multiple virtio-gpu drm_file to be able to
81     * have 1 virtio-gpu context per amdgpu-context or use a single amdgpu
82     * context.
83     * Using multiple drm_file might cause BO sharing issues so for now limit
84     * ourselves to a single amdgpu context. Each amdgpu_ctx object can schedule
85     * parallel work on 1 gfx, 2 sdma, 4 compute, 1 of each vcn queue.
86     */
87    simple_mtx_t contexts_mutex;
88    struct hash_table contexts;
89    bool allow_multiple_amdgpu_ctx;
90 };
91 
92 /* Refcounting helpers. Returns true when dst reaches 0. */
update_references(int * dst,int * src)93 static inline bool update_references(int *dst, int *src)
94 {
95    if (dst != src) {
96       /* bump src first */
97       if (src) {
98          assert(p_atomic_read(src) > 0);
99          p_atomic_inc(src);
100       }
101       if (dst) {
102          return p_atomic_dec_zero(dst);
103       }
104    }
105    return false;
106 }
107 
108 #define virtio_ioctl(fd, name, args) ({                              \
109       int ret = drmIoctl((fd), DRM_IOCTL_ ## name, (args));          \
110       ret;                                                           \
111       })
112 
113 struct amdvgpu_host_blob_creation_params {
114    struct drm_virtgpu_resource_create_blob args;
115    struct amdgpu_ccmd_gem_new_req req;
116 };
117 
118 struct amdvgpu_bo {
119    struct amdvgpu_device *dev;
120 
121    /* Importing the same kms handle must return the same
122     * amdvgpu_pointer, so we need a refcount.
123     */
124    int refcount;
125 
126    /* The size of the BO (might be smaller that the host
127     * bo' size).
128     */
129    unsigned size;
130 
131    /* The host blob backing this bo. */
132    struct amdvgpu_host_blob *host_blob;
133 };
134 
135 
136 uint32_t amdvgpu_get_resource_id(amdvgpu_bo_handle bo);
137 
138 /* There are 2 return-code:
139  *    - the virtio one, returned by vdrm_send_req
140  *    - the host one, which only makes sense for sync
141  *      requests.
142  */
143 static inline
vdrm_send_req_wrapper(amdvgpu_device_handle dev,struct vdrm_ccmd_req * req,struct amdgpu_ccmd_rsp * rsp,bool sync)144 int vdrm_send_req_wrapper(amdvgpu_device_handle dev,
145                           struct vdrm_ccmd_req *req,
146                           struct amdgpu_ccmd_rsp *rsp,
147                           bool sync) {
148    if (dev->sync_cmd & (1u << req->cmd))
149       sync = true;
150 
151    int r = vdrm_send_req(dev->vdev, req, sync);
152 
153    if (r)
154       return r;
155 
156    if (sync)
157       return rsp->ret;
158 
159    return 0;
160 }
161 #endif /* AMDGPU_VIRTIO_PRIVATE_H */
162