xref: /aosp_15_r20/external/mesa3d/src/intel/common/i915/intel_gem.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright © 2022 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 
24 #include "i915/intel_gem.h"
25 
26 #include "common/intel_gem.h"
27 #include "i915/intel_engine.h"
28 
29 #include "drm-uapi/i915_drm.h"
30 
31 bool
i915_gem_create_context(int fd,uint32_t * context_id)32 i915_gem_create_context(int fd, uint32_t *context_id)
33 {
34    struct drm_i915_gem_context_create create = {};
35    if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create))
36       return false;
37    *context_id = create.ctx_id;
38    return true;
39 }
40 
41 bool
i915_gem_destroy_context(int fd,uint32_t context_id)42 i915_gem_destroy_context(int fd, uint32_t context_id)
43 {
44    struct drm_i915_gem_context_destroy destroy = {
45       .ctx_id = context_id,
46    };
47    return intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY, &destroy) == 0;
48 }
49 
50 bool
i915_gem_create_context_engines(int fd,enum intel_gem_create_context_flags flags,const struct intel_query_engine_info * info,int num_engines,enum intel_engine_class * engine_classes,uint32_t vm_id,uint32_t * context_id)51 i915_gem_create_context_engines(int fd,
52                                 enum intel_gem_create_context_flags flags,
53                                 const struct intel_query_engine_info *info,
54                                 int num_engines, enum intel_engine_class *engine_classes,
55                                 uint32_t vm_id,
56                                 uint32_t *context_id)
57 {
58    assert(info != NULL);
59    assert(num_engines <= 64);
60    I915_DEFINE_CONTEXT_PARAM_ENGINES(engines_param, 64);
61    engines_param.extensions = 0;
62 
63    /* For each type of intel_engine_class of interest, we keep track of
64     * the previous engine instance used.
65     */
66    int last_engine_idx[] = {
67       [INTEL_ENGINE_CLASS_RENDER] = -1,
68       [INTEL_ENGINE_CLASS_COPY] = -1,
69       [INTEL_ENGINE_CLASS_COMPUTE] = -1,
70       [INTEL_ENGINE_CLASS_VIDEO] = -1,
71    };
72 
73    int engine_counts[] = {
74       [INTEL_ENGINE_CLASS_RENDER] =
75          intel_engines_count(info, INTEL_ENGINE_CLASS_RENDER),
76       [INTEL_ENGINE_CLASS_COPY] =
77          intel_engines_count(info, INTEL_ENGINE_CLASS_COPY),
78       [INTEL_ENGINE_CLASS_COMPUTE] =
79          intel_engines_count(info, INTEL_ENGINE_CLASS_COMPUTE),
80       [INTEL_ENGINE_CLASS_VIDEO] =
81          intel_engines_count(info, INTEL_ENGINE_CLASS_VIDEO),
82    };
83 
84    /* For each queue, we look for the next instance that matches the class we
85     * need.
86     */
87    for (int i = 0; i < num_engines; i++) {
88       enum intel_engine_class engine_class = engine_classes[i];
89       assert(engine_class == INTEL_ENGINE_CLASS_RENDER ||
90              engine_class == INTEL_ENGINE_CLASS_COPY ||
91              engine_class == INTEL_ENGINE_CLASS_COMPUTE ||
92              engine_class == INTEL_ENGINE_CLASS_VIDEO);
93       if (engine_counts[engine_class] <= 0)
94          return false;
95 
96       /* Run through the engines reported by the kernel looking for the next
97        * matching instance. We loop in case we want to create multiple
98        * contexts on an engine instance.
99        */
100       int engine_instance = -1;
101       for (int i = 0; i < info->num_engines; i++) {
102          int *idx = &last_engine_idx[engine_class];
103          if (++(*idx) >= info->num_engines)
104             *idx = 0;
105          if (info->engines[*idx].engine_class == engine_class) {
106             engine_instance = info->engines[*idx].engine_instance;
107             break;
108          }
109       }
110       if (engine_instance < 0)
111          return false;
112 
113       engines_param.engines[i].engine_class = intel_engine_class_to_i915(engine_class);
114       engines_param.engines[i].engine_instance = engine_instance;
115    }
116 
117    uint32_t size = sizeof(engines_param.extensions);
118    size += sizeof(engines_param.engines[0]) * num_engines;
119    struct drm_i915_gem_context_create_ext_setparam set_engines = {
120       .param = {
121          .param = I915_CONTEXT_PARAM_ENGINES,
122          .value = (uintptr_t)&engines_param,
123          .size = size,
124       }
125    };
126    struct drm_i915_gem_context_create_ext_setparam protected_param = {
127       .param = {
128          .param = I915_CONTEXT_PARAM_PROTECTED_CONTENT,
129          .value = flags & INTEL_GEM_CREATE_CONTEXT_EXT_PROTECTED_FLAG,
130       },
131    };
132    struct drm_i915_gem_context_create_ext_setparam recoverable_param = {
133       .param = {
134          .param = I915_CONTEXT_PARAM_RECOVERABLE,
135          .value = flags & INTEL_GEM_CREATE_CONTEXT_EXT_RECOVERABLE_FLAG,
136       },
137    };
138    struct drm_i915_gem_context_create_ext_setparam low_latency_param = {
139       .param = {
140          .param = I915_CONTEXT_PARAM_LOW_LATENCY,
141          .value = flags & INTEL_GEM_CREATE_CONTEXT_EXT_LOW_LATENCY_FLAG,
142       }
143    };
144    struct drm_i915_gem_context_create_ext create = {
145       .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
146    };
147    struct drm_i915_gem_context_create_ext_setparam vm_param = {
148       .param = {
149          .param = I915_CONTEXT_PARAM_VM,
150          .value = vm_id,
151       },
152    };
153 
154    intel_i915_gem_add_ext(&create.extensions,
155                           I915_CONTEXT_CREATE_EXT_SETPARAM,
156                           &set_engines.base);
157    intel_i915_gem_add_ext(&create.extensions,
158                           I915_CONTEXT_CREATE_EXT_SETPARAM,
159                           &recoverable_param.base);
160 
161    if (vm_id != 0) {
162       intel_i915_gem_add_ext(&create.extensions,
163                              I915_CONTEXT_CREATE_EXT_SETPARAM,
164                              &vm_param.base);
165    }
166 
167    if (flags & INTEL_GEM_CREATE_CONTEXT_EXT_PROTECTED_FLAG) {
168       intel_i915_gem_add_ext(&create.extensions,
169                              I915_CONTEXT_CREATE_EXT_SETPARAM,
170                              &protected_param.base);
171    }
172 
173    if (flags & INTEL_GEM_CREATE_CONTEXT_EXT_LOW_LATENCY_FLAG) {
174       intel_i915_gem_add_ext(&create.extensions,
175                              I915_CONTEXT_CREATE_EXT_SETPARAM,
176                              &low_latency_param.base);
177    }
178 
179    if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT, &create) == -1)
180       return false;
181 
182    *context_id = create.ctx_id;
183    return true;
184 }
185 
186 bool
i915_gem_set_context_param(int fd,uint32_t context,uint32_t param,uint64_t value)187 i915_gem_set_context_param(int fd, uint32_t context, uint32_t param,
188                            uint64_t value)
189 {
190    struct drm_i915_gem_context_param p = {
191       .ctx_id = context,
192       .param = param,
193       .value = value,
194    };
195    return intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &p) == 0;
196 }
197 
198 bool
i915_gem_get_context_param(int fd,uint32_t context,uint32_t param,uint64_t * value)199 i915_gem_get_context_param(int fd, uint32_t context, uint32_t param,
200                            uint64_t *value)
201 {
202    struct drm_i915_gem_context_param gp = {
203       .ctx_id = context,
204       .param = param,
205    };
206    if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &gp))
207       return false;
208    *value = gp.value;
209    return true;
210 }
211 
212 bool
i915_gem_read_render_timestamp(int fd,uint64_t * value)213 i915_gem_read_render_timestamp(int fd, uint64_t *value)
214 {
215    struct drm_i915_reg_read reg_read = {
216       .offset = RCS_TIMESTAMP | I915_REG_READ_8B_WA,
217    };
218 
219    int ret = intel_ioctl(fd, DRM_IOCTL_I915_REG_READ, &reg_read);
220    if (ret == 0)
221       *value = reg_read.val;
222    return ret == 0;
223 }
224 
225 bool
i915_gem_create_context_ext(int fd,enum intel_gem_create_context_flags flags,uint32_t * ctx_id)226 i915_gem_create_context_ext(int fd,
227                             enum intel_gem_create_context_flags flags,
228                             uint32_t *ctx_id)
229 {
230    struct drm_i915_gem_context_create_ext_setparam recoverable_param = {
231       .param = {
232          .param = I915_CONTEXT_PARAM_RECOVERABLE,
233          .value = flags & INTEL_GEM_CREATE_CONTEXT_EXT_RECOVERABLE_FLAG,
234       },
235    };
236    struct drm_i915_gem_context_create_ext_setparam protected_param = {
237       .param = {
238          .param = I915_CONTEXT_PARAM_PROTECTED_CONTENT,
239          .value = flags & INTEL_GEM_CREATE_CONTEXT_EXT_PROTECTED_FLAG,
240       },
241    };
242    struct drm_i915_gem_context_create_ext create = {
243       .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
244    };
245 
246    intel_i915_gem_add_ext(&create.extensions,
247                           I915_CONTEXT_CREATE_EXT_SETPARAM,
248                           &recoverable_param.base);
249    intel_i915_gem_add_ext(&create.extensions,
250                           I915_CONTEXT_CREATE_EXT_SETPARAM,
251                           &protected_param.base);
252 
253    if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT, &create))
254       return false;
255 
256    *ctx_id = create.ctx_id;
257    return true;
258 }
259 
260 bool
i915_gem_supports_protected_context(int fd)261 i915_gem_supports_protected_context(int fd)
262 {
263    int val = 0;
264    uint32_t ctx_id;
265    bool ret;
266 
267    errno = 0;
268    if (!i915_gem_get_param(fd, I915_PARAM_PXP_STATUS, &val)) {
269       if (errno == ENODEV)
270          return false;
271    } else {
272       return (val > 0);
273    }
274 
275    /* failed without ENODEV, so older kernels require a creation test */
276    ret = i915_gem_create_context_ext(fd,
277                                      INTEL_GEM_CREATE_CONTEXT_EXT_PROTECTED_FLAG,
278                                      &ctx_id);
279    if (!ret)
280       return ret;
281 
282    i915_gem_destroy_context(fd, ctx_id);
283    return ret;
284 }
285 
286 bool
i915_gem_get_param(int fd,uint32_t param,int * value)287 i915_gem_get_param(int fd, uint32_t param, int *value)
288 {
289    drm_i915_getparam_t gp = {
290       .param = param,
291       .value = value,
292    };
293    return intel_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) == 0;
294 }
295 
296 bool
i915_gem_can_render_on_fd(int fd)297 i915_gem_can_render_on_fd(int fd)
298 {
299    int val;
300    return intel_gem_get_param(fd, I915_PARAM_CHIPSET_ID, &val) && val > 0;
301 }
302