• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 create = {
139       .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
140    };
141    struct drm_i915_gem_context_create_ext_setparam vm_param = {
142       .param = {
143          .param = I915_CONTEXT_PARAM_VM,
144          .value = vm_id,
145       },
146    };
147 
148    intel_i915_gem_add_ext(&create.extensions,
149                           I915_CONTEXT_CREATE_EXT_SETPARAM,
150                           &set_engines.base);
151    intel_i915_gem_add_ext(&create.extensions,
152                           I915_CONTEXT_CREATE_EXT_SETPARAM,
153                           &recoverable_param.base);
154 
155    if (vm_id != 0) {
156       intel_i915_gem_add_ext(&create.extensions,
157                              I915_CONTEXT_CREATE_EXT_SETPARAM,
158                              &vm_param.base);
159    }
160 
161    if (flags & INTEL_GEM_CREATE_CONTEXT_EXT_PROTECTED_FLAG) {
162       intel_i915_gem_add_ext(&create.extensions,
163                              I915_CONTEXT_CREATE_EXT_SETPARAM,
164                              &protected_param.base);
165    }
166 
167    if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT, &create) == -1)
168       return false;
169 
170    *context_id = create.ctx_id;
171    return true;
172 }
173 
174 bool
i915_gem_set_context_param(int fd,uint32_t context,uint32_t param,uint64_t value)175 i915_gem_set_context_param(int fd, uint32_t context, uint32_t param,
176                            uint64_t value)
177 {
178    struct drm_i915_gem_context_param p = {
179       .ctx_id = context,
180       .param = param,
181       .value = value,
182    };
183    return intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_SETPARAM, &p) == 0;
184 }
185 
186 bool
i915_gem_get_context_param(int fd,uint32_t context,uint32_t param,uint64_t * value)187 i915_gem_get_context_param(int fd, uint32_t context, uint32_t param,
188                            uint64_t *value)
189 {
190    struct drm_i915_gem_context_param gp = {
191       .ctx_id = context,
192       .param = param,
193    };
194    if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_GETPARAM, &gp))
195       return false;
196    *value = gp.value;
197    return true;
198 }
199 
200 bool
i915_gem_read_render_timestamp(int fd,uint64_t * value)201 i915_gem_read_render_timestamp(int fd, uint64_t *value)
202 {
203    struct drm_i915_reg_read reg_read = {
204       .offset = RCS_TIMESTAMP | I915_REG_READ_8B_WA,
205    };
206 
207    int ret = intel_ioctl(fd, DRM_IOCTL_I915_REG_READ, &reg_read);
208    if (ret == 0)
209       *value = reg_read.val;
210    return ret == 0;
211 }
212 
213 bool
i915_gem_create_context_ext(int fd,enum intel_gem_create_context_flags flags,uint32_t * ctx_id)214 i915_gem_create_context_ext(int fd,
215                             enum intel_gem_create_context_flags flags,
216                             uint32_t *ctx_id)
217 {
218    struct drm_i915_gem_context_create_ext_setparam recoverable_param = {
219       .param = {
220          .param = I915_CONTEXT_PARAM_RECOVERABLE,
221          .value = flags & INTEL_GEM_CREATE_CONTEXT_EXT_RECOVERABLE_FLAG,
222       },
223    };
224    struct drm_i915_gem_context_create_ext_setparam protected_param = {
225       .param = {
226          .param = I915_CONTEXT_PARAM_PROTECTED_CONTENT,
227          .value = flags & INTEL_GEM_CREATE_CONTEXT_EXT_PROTECTED_FLAG,
228       },
229    };
230    struct drm_i915_gem_context_create_ext create = {
231       .flags = I915_CONTEXT_CREATE_FLAGS_USE_EXTENSIONS,
232    };
233 
234    intel_i915_gem_add_ext(&create.extensions,
235                           I915_CONTEXT_CREATE_EXT_SETPARAM,
236                           &recoverable_param.base);
237    intel_i915_gem_add_ext(&create.extensions,
238                           I915_CONTEXT_CREATE_EXT_SETPARAM,
239                           &protected_param.base);
240 
241    if (intel_ioctl(fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE_EXT, &create))
242       return false;
243 
244    *ctx_id = create.ctx_id;
245    return true;
246 }
247 
248 bool
i915_gem_supports_protected_context(int fd)249 i915_gem_supports_protected_context(int fd)
250 {
251    int val = 0;
252    uint32_t ctx_id;
253    bool ret;
254 
255    errno = 0;
256    if (!i915_gem_get_param(fd, I915_PARAM_PXP_STATUS, &val)) {
257       if (errno == ENODEV)
258          return false;
259    } else {
260       return (val > 0);
261    }
262 
263    /* failed without ENODEV, so older kernels require a creation test */
264    ret = i915_gem_create_context_ext(fd,
265                                      INTEL_GEM_CREATE_CONTEXT_EXT_PROTECTED_FLAG,
266                                      &ctx_id);
267    if (!ret)
268       return ret;
269 
270    i915_gem_destroy_context(fd, ctx_id);
271    return ret;
272 }
273 
274 bool
i915_gem_get_param(int fd,uint32_t param,int * value)275 i915_gem_get_param(int fd, uint32_t param, int *value)
276 {
277    drm_i915_getparam_t gp = {
278       .param = param,
279       .value = value,
280    };
281    return intel_ioctl(fd, DRM_IOCTL_I915_GETPARAM, &gp) == 0;
282 }
283 
284 bool
i915_gem_can_render_on_fd(int fd)285 i915_gem_can_render_on_fd(int fd)
286 {
287    int val;
288    return intel_gem_get_param(fd, I915_PARAM_CHIPSET_ID, &val) && val > 0;
289 }
290