1 /*
2 * Copyright © 2019 Google LLC
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
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <limits.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "drm-shim/drm_shim.h"
28 #include "drm-uapi/msm_drm.h"
29 #include <sys/ioctl.h>
30
31 #include "util/u_math.h"
32
33 bool drm_shim_driver_prefers_first_render_node = true;
34
35 struct msm_device_info {
36 uint32_t gpu_id;
37 uint32_t chip_id;
38 uint32_t gmem_size;
39 };
40
41 static const struct msm_device_info *device_info;
42
43 static int
msm_ioctl_noop(int fd,unsigned long request,void * arg)44 msm_ioctl_noop(int fd, unsigned long request, void *arg)
45 {
46 return 0;
47 }
48
49 static int
msm_ioctl_gem_new(int fd,unsigned long request,void * arg)50 msm_ioctl_gem_new(int fd, unsigned long request, void *arg)
51 {
52 struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
53 struct drm_msm_gem_new *create = arg;
54 size_t size = ALIGN(create->size, 4096);
55
56 if (!size)
57 return -EINVAL;
58
59 struct shim_bo *bo = calloc(1, sizeof(*bo));
60 int ret;
61
62 ret = drm_shim_bo_init(bo, size);
63 if (ret) {
64 free(bo);
65 return ret;
66 }
67
68 create->handle = drm_shim_bo_get_handle(shim_fd, bo);
69
70 drm_shim_bo_put(bo);
71
72 return 0;
73 }
74
75 static int
msm_ioctl_gem_info(int fd,unsigned long request,void * arg)76 msm_ioctl_gem_info(int fd, unsigned long request, void *arg)
77 {
78 struct shim_fd *shim_fd = drm_shim_fd_lookup(fd);
79 struct drm_msm_gem_info *args = arg;
80 struct shim_bo *bo = drm_shim_bo_lookup(shim_fd, args->handle);
81
82 if (!bo)
83 return -ENOENT;
84
85 switch (args->info) {
86 case MSM_INFO_GET_OFFSET:
87 args->value = drm_shim_bo_get_mmap_offset(shim_fd, bo);
88 break;
89 case MSM_INFO_GET_IOVA:
90 args->value = bo->mem_addr;
91 break;
92 case MSM_INFO_SET_IOVA:
93 case MSM_INFO_SET_NAME:
94 break;
95 default:
96 fprintf(stderr, "Unknown DRM_IOCTL_MSM_GEM_INFO %d\n", args->info);
97 drm_shim_bo_put(bo);
98 return -1;
99 }
100
101 drm_shim_bo_put(bo);
102
103 return 0;
104 }
105
106 static int
msm_ioctl_get_param(int fd,unsigned long request,void * arg)107 msm_ioctl_get_param(int fd, unsigned long request, void *arg)
108 {
109 struct drm_msm_param *gp = arg;
110
111 switch (gp->param) {
112 case MSM_PARAM_GPU_ID:
113 gp->value = device_info->gpu_id;
114 return 0;
115 case MSM_PARAM_GMEM_SIZE:
116 gp->value = device_info->gmem_size;
117 return 0;
118 case MSM_PARAM_GMEM_BASE:
119 gp->value = 0x100000;
120 return 0;
121 case MSM_PARAM_CHIP_ID:
122 gp->value = device_info->chip_id;
123 return 0;
124 case MSM_PARAM_NR_RINGS:
125 gp->value = 1;
126 return 0;
127 case MSM_PARAM_MAX_FREQ:
128 gp->value = 1000000;
129 return 0;
130 case MSM_PARAM_TIMESTAMP:
131 gp->value = 0;
132 return 0;
133 case MSM_PARAM_PP_PGTABLE:
134 gp->value = 1;
135 return 0;
136 case MSM_PARAM_FAULTS:
137 case MSM_PARAM_SUSPENDS:
138 gp->value = 0;
139 return 0;
140 case MSM_PARAM_VA_START:
141 case MSM_PARAM_VA_SIZE:
142 gp->value = 0x100000000ULL;
143 return 0;
144 default:
145 fprintf(stderr, "Unknown DRM_IOCTL_MSM_GET_PARAM %d\n", gp->param);
146 return -1;
147 }
148 }
149
150 static int
msm_ioctl_gem_madvise(int fd,unsigned long request,void * arg)151 msm_ioctl_gem_madvise(int fd, unsigned long request, void *arg)
152 {
153 struct drm_msm_gem_madvise *args = arg;
154
155 args->retained = true;
156
157 return 0;
158 }
159
160 static ioctl_fn_t driver_ioctls[] = {
161 [DRM_MSM_GET_PARAM] = msm_ioctl_get_param,
162 [DRM_MSM_SET_PARAM] = msm_ioctl_noop,
163 [DRM_MSM_GEM_NEW] = msm_ioctl_gem_new,
164 [DRM_MSM_GEM_INFO] = msm_ioctl_gem_info,
165 [DRM_MSM_GEM_CPU_PREP] = msm_ioctl_noop,
166 [DRM_MSM_GEM_CPU_FINI] = msm_ioctl_noop,
167 [DRM_MSM_GEM_SUBMIT] = msm_ioctl_noop,
168 [DRM_MSM_WAIT_FENCE] = msm_ioctl_noop,
169 [DRM_MSM_GEM_MADVISE] = msm_ioctl_gem_madvise,
170 [DRM_MSM_SUBMITQUEUE_NEW] = msm_ioctl_noop,
171 [DRM_MSM_SUBMITQUEUE_CLOSE] = msm_ioctl_noop,
172 [DRM_MSM_SUBMITQUEUE_QUERY] = msm_ioctl_noop,
173 };
174
175 #define CHIPID(maj, min, rev, pat) \
176 ((maj << 24) | (min << 16) | (rev << 8) | (pat))
177
178 static const struct msm_device_info device_infos[] = {
179 {
180 /* First entry is default */
181 .gpu_id = 630,
182 .chip_id = CHIPID(6, 3, 0, 0xff),
183 .gmem_size = 1024 * 1024,
184 },
185 {
186 .gpu_id = 200,
187 .chip_id = CHIPID(2, 0, 0, 0),
188 .gmem_size = 256 * 1024,
189 },
190 {
191 .gpu_id = 201,
192 .chip_id = CHIPID(2, 0, 0, 1),
193 .gmem_size = 128 * 1024,
194 },
195 {
196 .gpu_id = 220,
197 .chip_id = CHIPID(2, 2, 0, 0xff),
198 .gmem_size = 512 * 1024,
199 },
200 {
201 .gpu_id = 305,
202 .chip_id = CHIPID(3, 0, 5, 0xff),
203 .gmem_size = 256 * 1024,
204 },
205 {
206 .gpu_id = 307,
207 .chip_id = CHIPID(3, 0, 6, 0),
208 .gmem_size = 128 * 1024,
209 },
210 {
211 .gpu_id = 320,
212 .chip_id = CHIPID(3, 2, 0xff, 0xff),
213 .gmem_size = 512 * 1024,
214 },
215 {
216 .gpu_id = 330,
217 .chip_id = CHIPID(3, 3, 0, 0xff),
218 .gmem_size = 1024 * 1024,
219 },
220 {
221 .gpu_id = 420,
222 .chip_id = CHIPID(4, 2, 0, 0xff),
223 .gmem_size = 1536 * 1024,
224 },
225 {
226 .gpu_id = 430,
227 .chip_id = CHIPID(4, 3, 0, 0xff),
228 .gmem_size = 1536 * 1024,
229 },
230 {
231 .gpu_id = 510,
232 .chip_id = CHIPID(5, 1, 0, 0xff),
233 .gmem_size = 256 * 1024,
234 },
235 {
236 .gpu_id = 530,
237 .chip_id = CHIPID(5, 3, 0, 2),
238 .gmem_size = 1024 * 1024,
239 },
240 {
241 .gpu_id = 540,
242 .chip_id = CHIPID(5, 4, 0, 2),
243 .gmem_size = 1024 * 1024,
244 },
245 {
246 .gpu_id = 618,
247 .chip_id = CHIPID(6, 1, 8, 0xff),
248 .gmem_size = 512 * 1024,
249 },
250 {
251 .gpu_id = 630,
252 .chip_id = CHIPID(6, 3, 0, 0xff),
253 .gmem_size = 1024 * 1024,
254 },
255 {
256 .gpu_id = 660,
257 .chip_id = CHIPID(6, 6, 0, 0xff),
258 .gmem_size = 1024 * 1024 + 512 * 1024,
259 },
260 };
261
262 static void
msm_driver_get_device_info(void)263 msm_driver_get_device_info(void)
264 {
265 const char *env = getenv("FD_GPU_ID");
266
267 if (!env) {
268 device_info = &device_infos[0];
269 return;
270 }
271
272 int gpu_id = atoi(env);
273 for (int i = 0; i < ARRAY_SIZE(device_infos); i++) {
274 if (device_infos[i].gpu_id == gpu_id) {
275 device_info = &device_infos[i];
276 return;
277 }
278 }
279
280 fprintf(stderr, "FD_GPU_ID unrecognized, shim supports %d",
281 device_infos[0].gpu_id);
282 for (int i = 1; i < ARRAY_SIZE(device_infos); i++)
283 fprintf(stderr, ", %d", device_infos[i].gpu_id);
284 fprintf(stderr, "\n");
285 abort();
286 }
287
288 void
drm_shim_driver_init(void)289 drm_shim_driver_init(void)
290 {
291 shim_device.bus_type = DRM_BUS_PLATFORM;
292 shim_device.driver_name = "msm";
293 shim_device.driver_ioctls = driver_ioctls;
294 shim_device.driver_ioctl_count = ARRAY_SIZE(driver_ioctls);
295
296 /* msm uses the DRM version to expose features, instead of getparam. */
297 shim_device.version_major = 1;
298 shim_device.version_minor = 9;
299 shim_device.version_patchlevel = 0;
300
301 msm_driver_get_device_info();
302
303 drm_shim_override_file("OF_FULLNAME=/rdb/msm\n"
304 "OF_COMPATIBLE_N=1\n"
305 "OF_COMPATIBLE_0=qcom,adreno\n",
306 "/sys/dev/char/%d:%d/device/uevent", DRM_MAJOR,
307 render_node_minor);
308 }
309