]> Git Repo - linux.git/blob - drivers/gpu/drm/bochs/bochs_fbdev.c
bpf: prevent out of bounds speculation on pointer arithmetic
[linux.git] / drivers / gpu / drm / bochs / bochs_fbdev.c
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  */
7
8 #include "bochs.h"
9 #include <drm/drm_gem_framebuffer_helper.h>
10
11 /* ---------------------------------------------------------------------- */
12
13 static int bochsfb_mmap(struct fb_info *info,
14                         struct vm_area_struct *vma)
15 {
16         struct drm_fb_helper *fb_helper = info->par;
17         struct bochs_bo *bo = gem_to_bochs_bo(fb_helper->fb->obj[0]);
18
19         return ttm_fbdev_mmap(vma, &bo->bo);
20 }
21
22 static struct fb_ops bochsfb_ops = {
23         .owner = THIS_MODULE,
24         DRM_FB_HELPER_DEFAULT_OPS,
25         .fb_fillrect = drm_fb_helper_cfb_fillrect,
26         .fb_copyarea = drm_fb_helper_cfb_copyarea,
27         .fb_imageblit = drm_fb_helper_cfb_imageblit,
28         .fb_mmap = bochsfb_mmap,
29 };
30
31 static int bochsfb_create_object(struct bochs_device *bochs,
32                                  const struct drm_mode_fb_cmd2 *mode_cmd,
33                                  struct drm_gem_object **gobj_p)
34 {
35         struct drm_device *dev = bochs->dev;
36         struct drm_gem_object *gobj;
37         u32 size;
38         int ret = 0;
39
40         size = mode_cmd->pitches[0] * mode_cmd->height;
41         ret = bochs_gem_create(dev, size, true, &gobj);
42         if (ret)
43                 return ret;
44
45         *gobj_p = gobj;
46         return ret;
47 }
48
49 static int bochsfb_create(struct drm_fb_helper *helper,
50                           struct drm_fb_helper_surface_size *sizes)
51 {
52         struct bochs_device *bochs =
53                 container_of(helper, struct bochs_device, fb.helper);
54         struct fb_info *info;
55         struct drm_framebuffer *fb;
56         struct drm_mode_fb_cmd2 mode_cmd;
57         struct drm_gem_object *gobj = NULL;
58         struct bochs_bo *bo = NULL;
59         int size, ret;
60
61         if (sizes->surface_bpp != 32)
62                 return -EINVAL;
63
64         mode_cmd.width = sizes->surface_width;
65         mode_cmd.height = sizes->surface_height;
66         mode_cmd.pitches[0] = sizes->surface_width * 4;
67         mode_cmd.pixel_format = DRM_FORMAT_HOST_XRGB8888;
68         size = mode_cmd.pitches[0] * mode_cmd.height;
69
70         /* alloc, pin & map bo */
71         ret = bochsfb_create_object(bochs, &mode_cmd, &gobj);
72         if (ret) {
73                 DRM_ERROR("failed to create fbcon backing object %d\n", ret);
74                 return ret;
75         }
76
77         bo = gem_to_bochs_bo(gobj);
78
79         ret = ttm_bo_reserve(&bo->bo, true, false, NULL);
80         if (ret)
81                 return ret;
82
83         ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
84         if (ret) {
85                 DRM_ERROR("failed to pin fbcon\n");
86                 ttm_bo_unreserve(&bo->bo);
87                 return ret;
88         }
89
90         ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages,
91                           &bo->kmap);
92         if (ret) {
93                 DRM_ERROR("failed to kmap fbcon\n");
94                 ttm_bo_unreserve(&bo->bo);
95                 return ret;
96         }
97
98         ttm_bo_unreserve(&bo->bo);
99
100         /* init fb device */
101         info = drm_fb_helper_alloc_fbi(helper);
102         if (IS_ERR(info)) {
103                 DRM_ERROR("Failed to allocate fbi: %ld\n", PTR_ERR(info));
104                 return PTR_ERR(info);
105         }
106
107         info->par = &bochs->fb.helper;
108
109         fb = drm_gem_fbdev_fb_create(bochs->dev, sizes, 0, gobj, NULL);
110         if (IS_ERR(fb)) {
111                 DRM_ERROR("Failed to create framebuffer: %ld\n", PTR_ERR(fb));
112                 return PTR_ERR(fb);
113         }
114
115         /* setup helper */
116         bochs->fb.helper.fb = fb;
117
118         strcpy(info->fix.id, "bochsdrmfb");
119
120         info->fbops = &bochsfb_ops;
121
122         drm_fb_helper_fill_fix(info, fb->pitches[0], fb->format->depth);
123         drm_fb_helper_fill_var(info, &bochs->fb.helper, sizes->fb_width,
124                                sizes->fb_height);
125
126         info->screen_base = bo->kmap.virtual;
127         info->screen_size = size;
128
129         drm_vma_offset_remove(&bo->bo.bdev->vma_manager, &bo->bo.vma_node);
130         info->fix.smem_start = 0;
131         info->fix.smem_len = size;
132         return 0;
133 }
134
135 static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
136         .fb_probe = bochsfb_create,
137 };
138
139 static struct drm_framebuffer *
140 bochs_gem_fb_create(struct drm_device *dev, struct drm_file *file,
141                     const struct drm_mode_fb_cmd2 *mode_cmd)
142 {
143         if (mode_cmd->pixel_format != DRM_FORMAT_XRGB8888 &&
144             mode_cmd->pixel_format != DRM_FORMAT_BGRX8888)
145                 return ERR_PTR(-EINVAL);
146
147         return drm_gem_fb_create(dev, file, mode_cmd);
148 }
149
150 const struct drm_mode_config_funcs bochs_mode_funcs = {
151         .fb_create = bochs_gem_fb_create,
152 };
153
154 int bochs_fbdev_init(struct bochs_device *bochs)
155 {
156         return drm_fb_helper_fbdev_setup(bochs->dev, &bochs->fb.helper,
157                                          &bochs_fb_helper_funcs, 32, 1);
158 }
159
160 void bochs_fbdev_fini(struct bochs_device *bochs)
161 {
162         drm_fb_helper_fbdev_teardown(bochs->dev);
163 }
This page took 0.044271 seconds and 4 git commands to generate.