• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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