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