Bug Summary

File:dev/pci/drm/i915/gem/i915_gem_shmem.c
Warning:line 33, column 27
Value stored to 'i915' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name i915_gem_shmem.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/pci/drm/i915/gem/i915_gem_shmem.c
1/*
2 * SPDX-License-Identifier: MIT
3 *
4 * Copyright © 2014-2016 Intel Corporation
5 */
6
7#include <linux/pagevec.h>
8#include <linux/swap.h>
9
10#include "gem/i915_gem_region.h"
11#include "i915_drv.h"
12#include "i915_gemfs.h"
13#include "i915_gem_object.h"
14#include "i915_scatterlist.h"
15#include "i915_trace.h"
16
17/*
18 * Move pages to appropriate lru and release the pagevec, decrementing the
19 * ref count of those pages.
20 */
21static void check_release_pagevec(struct pagevec *pvec)
22{
23 STUB()do { printf("%s: stub\n", __func__); } while(0);
24#ifdef notyet
25 check_move_unevictable_pages(pvec);
26#endif
27 __pagevec_release(pvec);
28 cond_resched()do { if (({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_schedstate.spc_schedflags & 0x0002) yield
(); } while (0)
;
29}
30
31static int shmem_get_pages(struct drm_i915_gem_object *obj)
32{
33 struct drm_i915_privateinteldrm_softc *i915 = to_i915(obj->base.dev);
Value stored to 'i915' during its initialization is never read
34 struct intel_memory_region *mem = obj->mm.region;
35 const unsigned long page_count = obj->base.size / PAGE_SIZE(1 << 12);
36 unsigned long i;
37 struct address_space *mapping;
38 struct sg_table *st;
39 struct scatterlist *sg;
40 struct sgt_iter sgt_iter;
41 struct pglist plist;
42 struct vm_page *page;
43 unsigned long last_pfn = 0; /* suppress gcc warning */
44 unsigned int max_segment = i915_sg_segment_size();
45 unsigned int sg_page_sizes;
46 gfp_t noreclaim;
47 int ret;
48
49 /*
50 * Assert that the object is not currently in any GPU domain. As it
51 * wasn't in the GTT, there shouldn't be any way it could have been in
52 * a GPU cache
53 */
54 GEM_BUG_ON(obj->read_domains & I915_GEM_GPU_DOMAINS)((void)0);
55 GEM_BUG_ON(obj->write_domain & I915_GEM_GPU_DOMAINS)((void)0);
56
57 /*
58 * If there's no chance of allocating enough pages for the whole
59 * object, bail early.
60 */
61 if (obj->base.size > resource_size(&mem->region))
62 return -ENOMEM12;
63
64 st = kmalloc(sizeof(*st), GFP_KERNEL(0x0001 | 0x0004));
65 if (!st)
66 return -ENOMEM12;
67
68rebuild_st:
69 if (sg_alloc_table(st, page_count, GFP_KERNEL(0x0001 | 0x0004))) {
70 kfree(st);
71 return -ENOMEM12;
72 }
73
74#ifdef __linux__
75 /*
76 * Get the list of pages out of our struct file. They'll be pinned
77 * at this point until we release them.
78 *
79 * Fail silently without starting the shrinker
80 */
81 mapping = obj->base.filp->f_mapping;
82 mapping_set_unevictable(mapping);
83 noreclaim = mapping_gfp_constraint(mapping, ~__GFP_RECLAIM);
84 noreclaim |= __GFP_NORETRY0 | __GFP_NOWARN0;
85
86 sg = st->sgl;
87 st->nents = 0;
88 sg_page_sizes = 0;
89 for (i = 0; i < page_count; i++) {
90 const unsigned int shrink[] = {
91 I915_SHRINK_BOUND(1UL << (1)) | I915_SHRINK_UNBOUND(1UL << (0)),
92 0,
93 }, *s = shrink;
94 gfp_t gfp = noreclaim;
95
96 do {
97 cond_resched()do { if (({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0"
: "=r" (__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self
))); __ci;})->ci_schedstate.spc_schedflags & 0x0002) yield
(); } while (0)
;
98 page = shmem_read_mapping_page_gfp(mapping, i, gfp);
99 if (!IS_ERR(page))
100 break;
101
102 if (!*s) {
103 ret = PTR_ERR(page);
104 goto err_sg;
105 }
106
107 i915_gem_shrink(i915, 2 * page_count, NULL((void *)0), *s++);
108
109 /*
110 * We've tried hard to allocate the memory by reaping
111 * our own buffer, now let the real VM do its job and
112 * go down in flames if truly OOM.
113 *
114 * However, since graphics tend to be disposable,
115 * defer the oom here by reporting the ENOMEM back
116 * to userspace.
117 */
118 if (!*s) {
119 /* reclaim and warn, but no oom */
120 gfp = mapping_gfp_mask(mapping);
121
122 /*
123 * Our bo are always dirty and so we require
124 * kswapd to reclaim our pages (direct reclaim
125 * does not effectively begin pageout of our
126 * buffers on its own). However, direct reclaim
127 * only waits for kswapd when under allocation
128 * congestion. So as a result __GFP_RECLAIM is
129 * unreliable and fails to actually reclaim our
130 * dirty pages -- unless you try over and over
131 * again with !__GFP_NORETRY. However, we still
132 * want to fail this allocation rather than
133 * trigger the out-of-memory killer and for
134 * this we want __GFP_RETRY_MAYFAIL.
135 */
136 gfp |= __GFP_RETRY_MAYFAIL0;
137 }
138 } while (1);
139
140 if (!i ||
141 sg->length >= max_segment ||
142 page_to_pfn(page)(((page)->phys_addr) / (1 << 12)) != last_pfn + 1) {
143 if (i) {
144 sg_page_sizes |= sg->length;
145 sg = sg_next(sg);
146 }
147 st->nents++;
148 sg_set_page(sg, page, PAGE_SIZE(1 << 12), 0);
149 } else {
150 sg->length += PAGE_SIZE(1 << 12);
151 }
152 last_pfn = page_to_pfn(page)(((page)->phys_addr) / (1 << 12));
153
154 /* Check that the i965g/gm workaround works. */
155 GEM_BUG_ON(gfp & __GFP_DMA32 && last_pfn >= 0x00100000UL)((void)0);
156 }
157#else
158 sg = st->sgl;
159 st->nents = 0;
160 sg_page_sizes = 0;
161
162 TAILQ_INIT(&plist)do { (&plist)->tqh_first = ((void *)0); (&plist)->
tqh_last = &(&plist)->tqh_first; } while (0)
;
163 if (uvm_obj_wire(obj->base.uao, 0, obj->base.size, &plist)) {
164 sg_free_table(st);
165 kfree(st);
166 return -ENOMEM12;
167 }
168
169 i = 0;
170 TAILQ_FOREACH(page, &plist, pageq)for((page) = ((&plist)->tqh_first); (page) != ((void *
)0); (page) = ((page)->pageq.tqe_next))
{
171 if (i) {
172 sg_page_sizes |= sg->length;
173 sg = sg_next(sg);
174 }
175 st->nents++;
176 sg_set_page(sg, page, PAGE_SIZE(1 << 12), 0);
177 i++;
178 }
179#endif
180 if (sg) { /* loop terminated early; short sg table */
181 sg_page_sizes |= sg->length;
182 sg_mark_end(sg);
183 }
184
185 /* Trim unused sg entries to avoid wasting memory. */
186 i915_sg_trim(st);
187
188 ret = i915_gem_gtt_prepare_pages(obj, st);
189 if (ret) {
190 /*
191 * DMA remapping failed? One possible cause is that
192 * it could not reserve enough large entries, asking
193 * for PAGE_SIZE chunks instead may be helpful.
194 */
195 if (max_segment > PAGE_SIZE(1 << 12)) {
196#ifdef __linux__
197 for_each_sgt_page(page, sgt_iter, st)for ((sgt_iter) = __sgt_iter((st)->sgl, 0); ((page) = (sgt_iter
).pfn == 0 ? ((void *)0) : (PHYS_TO_VM_PAGE(((paddr_t)((sgt_iter
).pfn + ((sgt_iter).curr >> 12)) << 12)))); (((sgt_iter
).curr += (1 << 12)) >= (sgt_iter).max) ? (sgt_iter)
= __sgt_iter(__sg_next((sgt_iter).sgp), 0), 0 : 0)
198 put_page(page);
199#else
200 uvm_obj_unwire(obj->base.uao, 0, obj->base.size);
201#endif
202 sg_free_table(st);
203
204 max_segment = PAGE_SIZE(1 << 12);
205 goto rebuild_st;
206 } else {
207 dev_warn(&i915->drm.pdev->dev,printf("drm:pid%d:%s *WARNING* " "Failed to DMA remap %lu pages\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__ , page_count
)
208 "Failed to DMA remap %lu pages\n",printf("drm:pid%d:%s *WARNING* " "Failed to DMA remap %lu pages\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__ , page_count
)
209 page_count)printf("drm:pid%d:%s *WARNING* " "Failed to DMA remap %lu pages\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__ , page_count
)
;
210 goto err_pages;
211 }
212 }
213
214 if (i915_gem_object_needs_bit17_swizzle(obj))
215 i915_gem_object_do_bit_17_swizzle(obj, st);
216
217 __i915_gem_object_set_pages(obj, st, sg_page_sizes);
218
219 return 0;
220
221#ifdef __linux__
222err_sg:
223 sg_mark_end(sg);
224err_pages:
225 mapping_clear_unevictable(mapping);
226 if (sg != st->sgl) {
227 struct pagevec pvec;
228
229 pagevec_init(&pvec);
230 for_each_sgt_page(page, sgt_iter, st)for ((sgt_iter) = __sgt_iter((st)->sgl, 0); ((page) = (sgt_iter
).pfn == 0 ? ((void *)0) : (PHYS_TO_VM_PAGE(((paddr_t)((sgt_iter
).pfn + ((sgt_iter).curr >> 12)) << 12)))); (((sgt_iter
).curr += (1 << 12)) >= (sgt_iter).max) ? (sgt_iter)
= __sgt_iter(__sg_next((sgt_iter).sgp), 0), 0 : 0)
{
231 if (!pagevec_add(&pvec, page))
232 check_release_pagevec(&pvec);
233 }
234 if (pagevec_count(&pvec))
235 check_release_pagevec(&pvec);
236 }
237#else
238err_pages:
239 uvm_obj_unwire(obj->base.uao, 0, obj->base.size);
240#endif
241 sg_free_table(st);
242 kfree(st);
243
244 /*
245 * shmemfs first checks if there is enough memory to allocate the page
246 * and reports ENOSPC should there be insufficient, along with the usual
247 * ENOMEM for a genuine allocation failure.
248 *
249 * We use ENOSPC in our driver to mean that we have run out of aperture
250 * space and so want to translate the error from shmemfs back to our
251 * usual understanding of ENOMEM.
252 */
253 if (ret == -ENOSPC28)
254 ret = -ENOMEM12;
255
256 return ret;
257}
258
259static void
260shmem_truncate(struct drm_i915_gem_object *obj)
261{
262 /*
263 * Our goal here is to return as much of the memory as
264 * is possible back to the system as we are called from OOM.
265 * To do this we must instruct the shmfs to drop all of its
266 * backing pages, *now*.
267 */
268#ifdef __linux__
269 shmem_truncate_range(file_inode(obj->base.filp), 0, (loff_t)-1);
270#else
271 rw_enter(obj->base.uao->vmobjlock, RW_WRITE0x0001UL);
272 obj->base.uao->pgops->pgo_flush(obj->base.uao, 0, obj->base.size,
273 PGO_ALLPAGES0x010 | PGO_FREE0x008);
274 rw_exit(obj->base.uao->vmobjlock);
275#endif
276 obj->mm.madv = __I915_MADV_PURGED2;
277 obj->mm.pages = ERR_PTR(-EFAULT14);
278}
279
280static void
281shmem_writeback(struct drm_i915_gem_object *obj)
282{
283 STUB()do { printf("%s: stub\n", __func__); } while(0);
284#ifdef notyet
285 struct address_space *mapping;
286 struct writeback_control wbc = {
287 .sync_mode = WB_SYNC_NONE,
288 .nr_to_write = SWAP_CLUSTER_MAX,
289 .range_start = 0,
290 .range_end = LLONG_MAX0x7fffffffffffffffLL,
291 .for_reclaim = 1,
292 };
293 unsigned long i;
294
295 /*
296 * Leave mmapings intact (GTT will have been revoked on unbinding,
297 * leaving only CPU mmapings around) and add those pages to the LRU
298 * instead of invoking writeback so they are aged and paged out
299 * as normal.
300 */
301 mapping = obj->base.filp->f_mapping;
302
303 /* Begin writeback on each dirty page */
304 for (i = 0; i < obj->base.size >> PAGE_SHIFT12; i++) {
305 struct vm_page *page;
306
307 page = find_lock_page(mapping, i);
308 if (!page)
309 continue;
310
311 if (!page_mapped(page) && clear_page_dirty_for_io(page)) {
312 int ret;
313
314 SetPageReclaim(page);
315 ret = mapping->a_ops->writepage(page, &wbc);
316 if (!PageWriteback(page))
317 ClearPageReclaim(page);
318 if (!ret)
319 goto put;
320 }
321 unlock_page(page);
322put:
323 put_page(page);
324 }
325#endif
326}
327
328void
329__i915_gem_object_release_shmem(struct drm_i915_gem_object *obj,
330 struct sg_table *pages,
331 bool_Bool needs_clflush)
332{
333 GEM_BUG_ON(obj->mm.madv == __I915_MADV_PURGED)((void)0);
334
335 if (obj->mm.madv == I915_MADV_DONTNEED1)
336 obj->mm.dirty = false0;
337
338 if (needs_clflush &&
339 (obj->read_domains & I915_GEM_DOMAIN_CPU0x00000001) == 0 &&
340 !(obj->cache_coherent & I915_BO_CACHE_COHERENT_FOR_READ(1UL << (0))))
341 drm_clflush_sg(pages);
342
343 __start_cpu_write(obj);
344}
345
346static void
347shmem_put_pages(struct drm_i915_gem_object *obj, struct sg_table *pages)
348{
349 struct sgt_iter sgt_iter;
350 struct pagevec pvec;
351 struct vm_page *page;
352
353 __i915_gem_object_release_shmem(obj, pages, true1);
354
355 i915_gem_gtt_finish_pages(obj, pages);
356
357 if (i915_gem_object_needs_bit17_swizzle(obj))
358 i915_gem_object_save_bit_17_swizzle(obj, pages);
359
360#ifdef __linux__
361 mapping_clear_unevictable(file_inode(obj->base.filp)->i_mapping);
362#endif
363
364 pagevec_init(&pvec);
365 for_each_sgt_page(page, sgt_iter, pages)for ((sgt_iter) = __sgt_iter((pages)->sgl, 0); ((page) = (
sgt_iter).pfn == 0 ? ((void *)0) : (PHYS_TO_VM_PAGE(((paddr_t
)((sgt_iter).pfn + ((sgt_iter).curr >> 12)) << 12
)))); (((sgt_iter).curr += (1 << 12)) >= (sgt_iter).
max) ? (sgt_iter) = __sgt_iter(__sg_next((sgt_iter).sgp), 0),
0 : 0)
{
366 if (obj->mm.dirty)
367 set_page_dirty(page)x86_atomic_clearbits_u32(&page->pg_flags, 0x00000008);
368
369#ifdef __linux__
370 if (obj->mm.madv == I915_MADV_WILLNEED0)
371 mark_page_accessed(page);
372
373 if (!pagevec_add(&pvec, page))
374 check_release_pagevec(&pvec);
375#endif
376 }
377#ifdef __linux__
378 if (pagevec_count(&pvec))
379 check_release_pagevec(&pvec);
380#else
381 uvm_obj_unwire(obj->base.uao, 0, obj->base.size);
382#endif
383 obj->mm.dirty = false0;
384
385 sg_free_table(pages);
386 kfree(pages);
387}
388
389static int
390shmem_pwrite(struct drm_i915_gem_object *obj,
391 const struct drm_i915_gem_pwrite *arg)
392{
393#ifdef __linux__
394 struct address_space *mapping = obj->base.filp->f_mapping;
395#endif
396 char __user *user_data = u64_to_user_ptr(arg->data_ptr)((void *)(uintptr_t)(arg->data_ptr));
397 u64 remain, offset;
398 unsigned int pg;
399
400 /* Caller already validated user args */
401 GEM_BUG_ON(!access_ok(user_data, arg->size))((void)0);
402
403 /*
404 * Before we instantiate/pin the backing store for our use, we
405 * can prepopulate the shmemfs filp efficiently using a write into
406 * the pagecache. We avoid the penalty of instantiating all the
407 * pages, important if the user is just writing to a few and never
408 * uses the object on the GPU, and using a direct write into shmemfs
409 * allows it to avoid the cost of retrieving a page (either swapin
410 * or clearing-before-use) before it is overwritten.
411 */
412 if (i915_gem_object_has_pages(obj))
413 return -ENODEV19;
414
415 if (obj->mm.madv != I915_MADV_WILLNEED0)
416 return -EFAULT14;
417
418 /*
419 * Before the pages are instantiated the object is treated as being
420 * in the CPU domain. The pages will be clflushed as required before
421 * use, and we can freely write into the pages directly. If userspace
422 * races pwrite with any other operation; corruption will ensue -
423 * that is userspace's prerogative!
424 */
425
426 remain = arg->size;
427 offset = arg->offset;
428 pg = offset_in_page(offset)((vaddr_t)(offset) & ((1 << 12) - 1));
429
430 do {
431 unsigned int len, unwritten;
432 struct vm_page *page;
433 void *data, *vaddr;
434 int err;
435 char c;
436
437 len = PAGE_SIZE(1 << 12) - pg;
438 if (len > remain)
439 len = remain;
440
441 /* Prefault the user page to reduce potential recursion */
442 err = __get_user(c, user_data)-copyin((user_data), &((c)), sizeof((c)));
443 if (err)
444 return err;
445
446 err = __get_user(c, user_data + len - 1)-copyin((user_data + len - 1), &((c)), sizeof((c)));
447 if (err)
448 return err;
449
450#ifdef __linux__
451 err = pagecache_write_begin(obj->base.filp, mapping,
452 offset, len, 0,
453 &page, &data);
454 if (err < 0)
455 return err;
456#else
457 struct pglist plist;
458 TAILQ_INIT(&plist)do { (&plist)->tqh_first = ((void *)0); (&plist)->
tqh_last = &(&plist)->tqh_first; } while (0)
;
459 if (uvm_obj_wire(obj->base.uao, trunc_page(offset)((offset) & ~((1 << 12) - 1)),
460 trunc_page(offset)((offset) & ~((1 << 12) - 1)) + PAGE_SIZE(1 << 12), &plist)) {
461 err = -ENOMEM12;
462 return err;
463 }
464 page = TAILQ_FIRST(&plist)((&plist)->tqh_first);
465#endif
466
467 vaddr = kmap_atomic(page);
468 unwritten = __copy_from_user_inatomic(vaddr + pg,
469 user_data,
470 len);
471 kunmap_atomic(vaddr);
472
473#ifdef __linux__
474 err = pagecache_write_end(obj->base.filp, mapping,
475 offset, len, len - unwritten,
476 page, data);
477 if (err < 0)
478 return err;
479#else
480 uvm_obj_unwire(obj->base.uao, trunc_page(offset)((offset) & ~((1 << 12) - 1)),
481 trunc_page(offset)((offset) & ~((1 << 12) - 1)) + PAGE_SIZE(1 << 12));
482#endif
483
484 /* We don't handle -EFAULT, leave it to the caller to check */
485 if (unwritten)
486 return -ENODEV19;
487
488 remain -= len;
489 user_data += len;
490 offset += len;
491 pg = 0;
492 } while (remain);
493
494 return 0;
495}
496
497static void shmem_release(struct drm_i915_gem_object *obj)
498{
499 i915_gem_object_release_memory_region(obj);
500
501 fput(obj->base.filp);
502}
503
504const struct drm_i915_gem_object_ops i915_gem_shmem_ops = {
505 .name = "i915_gem_object_shmem",
506 .flags = I915_GEM_OBJECT_HAS_STRUCT_PAGE(1UL << (0)) |
507 I915_GEM_OBJECT_IS_SHRINKABLE(1UL << (2)),
508
509 .get_pages = shmem_get_pages,
510 .put_pages = shmem_put_pages,
511 .truncate = shmem_truncate,
512 .writeback = shmem_writeback,
513
514 .pwrite = shmem_pwrite,
515
516 .release = shmem_release,
517};
518
519#ifdef __linux__
520static int __create_shmem(struct drm_i915_privateinteldrm_softc *i915,
521 struct drm_gem_object *obj,
522 resource_size_t size)
523{
524 unsigned long flags = VM_NORESERVE;
525 struct file *filp;
526
527 drm_gem_private_object_init(&i915->drm, obj, size);
528
529 if (i915->mm.gemfs)
530 filp = shmem_file_setup_with_mnt(i915->mm.gemfs, "i915", size,
531 flags);
532 else
533 filp = shmem_file_setup("i915", size, flags);
534 if (IS_ERR(filp))
535 return PTR_ERR(filp);
536
537 obj->filp = filp;
538 return 0;
539}
540#endif
541
542static struct drm_i915_gem_object *
543create_shmem(struct intel_memory_region *mem,
544 resource_size_t size,
545 unsigned int flags)
546{
547 static struct lock_class_key lock_class;
548 struct drm_i915_privateinteldrm_softc *i915 = mem->i915;
549 struct drm_i915_gem_object *obj;
550 struct address_space *mapping;
551 unsigned int cache_level;
552 gfp_t mask;
553 int ret;
554
555 obj = i915_gem_object_alloc();
556 if (!obj)
557 return ERR_PTR(-ENOMEM12);
558
559#ifdef __linux__
560 ret = __create_shmem(i915, &obj->base, size);
561#else
562 ret = drm_gem_object_init(&i915->drm, &obj->base, size);
563#endif
564 if (ret)
565 goto fail;
566
567 mask = GFP_HIGHUSER0 | __GFP_RECLAIMABLE0;
568 if (IS_I965GM(i915)IS_PLATFORM(i915, INTEL_I965GM) || IS_I965G(i915)IS_PLATFORM(i915, INTEL_I965G)) {
569 /* 965gm cannot relocate objects above 4GiB. */
570 mask &= ~__GFP_HIGHMEM0;
571 mask |= __GFP_DMA320x00010000;
572 }
573
574#ifdef __linux__
575 mapping = obj->base.filp->f_mapping;
576 mapping_set_gfp_mask(mapping, mask);
577 GEM_BUG_ON(!(mapping_gfp_mask(mapping) & __GFP_RECLAIM))((void)0);
578#endif
579
580 i915_gem_object_init(obj, &i915_gem_shmem_ops, &lock_class);
581
582 obj->write_domain = I915_GEM_DOMAIN_CPU0x00000001;
583 obj->read_domains = I915_GEM_DOMAIN_CPU0x00000001;
584
585 if (HAS_LLC(i915)((&(i915)->__info)->has_llc))
586 /* On some devices, we can have the GPU use the LLC (the CPU
587 * cache) for about a 10% performance improvement
588 * compared to uncached. Graphics requests other than
589 * display scanout are coherent with the CPU in
590 * accessing this cache. This means in this mode we
591 * don't need to clflush on the CPU side, and on the
592 * GPU side we only need to flush internal caches to
593 * get data visible to the CPU.
594 *
595 * However, we maintain the display planes as UC, and so
596 * need to rebind when first used as such.
597 */
598 cache_level = I915_CACHE_LLC;
599 else
600 cache_level = I915_CACHE_NONE;
601
602 i915_gem_object_set_cache_coherency(obj, cache_level);
603
604 i915_gem_object_init_memory_region(obj, mem, 0);
605
606 return obj;
607
608fail:
609 i915_gem_object_free(obj);
610 return ERR_PTR(ret);
611}
612
613struct drm_i915_gem_object *
614i915_gem_object_create_shmem(struct drm_i915_privateinteldrm_softc *i915,
615 resource_size_t size)
616{
617 return i915_gem_object_create_region(i915->mm.regions[INTEL_REGION_SMEM],
618 size, 0);
619}
620
621/* Allocate a new GEM object and fill it with the supplied data */
622struct drm_i915_gem_object *
623i915_gem_object_create_shmem_from_data(struct drm_i915_privateinteldrm_softc *dev_priv,
624 const void *data, resource_size_t size)
625{
626 STUB()do { printf("%s: stub\n", __func__); } while(0);
627 return NULL((void *)0);
628#ifdef notyet
629 struct drm_i915_gem_object *obj;
630 struct file *file;
631 resource_size_t offset;
632 int err;
633
634 obj = i915_gem_object_create_shmem(dev_priv, round_up(size, PAGE_SIZE)((((size) + (((1 << 12)) - 1)) / ((1 << 12))) * (
(1 << 12)))
);
635 if (IS_ERR(obj))
636 return obj;
637
638 GEM_BUG_ON(obj->write_domain != I915_GEM_DOMAIN_CPU)((void)0);
639
640 file = obj->base.filp;
641 offset = 0;
642 do {
643 unsigned int len = min_t(typeof(size), size, PAGE_SIZE)({ typeof(size) __min_a = (size); typeof(size) __min_b = ((1 <<
12)); __min_a < __min_b ? __min_a : __min_b; })
;
644 struct vm_page *page;
645 void *pgdata, *vaddr;
646
647 err = pagecache_write_begin(file, file->f_mapping,
648 offset, len, 0,
649 &page, &pgdata);
650 if (err < 0)
651 goto fail;
652
653 vaddr = kmap(page);
654 memcpy(vaddr, data, len)__builtin_memcpy((vaddr), (data), (len));
655 kunmap(page);
656
657 err = pagecache_write_end(file, file->f_mapping,
658 offset, len, len,
659 page, pgdata);
660 if (err < 0)
661 goto fail;
662
663 size -= len;
664 data += len;
665 offset += len;
666 } while (size);
667
668 return obj;
669
670fail:
671 i915_gem_object_put(obj);
672 return ERR_PTR(err);
673#endif
674}
675
676static int init_shmem(struct intel_memory_region *mem)
677{
678 int err;
679
680 err = i915_gemfs_init(mem->i915);
681 if (err) {
682 DRM_NOTE("Unable to create a private tmpfs mount, hugepage support will be disabled(%d).\n",printk("\0015" "[" "drm" "] " "Unable to create a private tmpfs mount, hugepage support will be disabled(%d).\n"
, err)
683 err)printk("\0015" "[" "drm" "] " "Unable to create a private tmpfs mount, hugepage support will be disabled(%d).\n"
, err)
;
684 }
685
686 intel_memory_region_set_name(mem, "system");
687
688 return 0; /* Don't error, we can simply fallback to the kernel mnt */
689}
690
691static void release_shmem(struct intel_memory_region *mem)
692{
693 i915_gemfs_fini(mem->i915);
694}
695
696static const struct intel_memory_region_ops shmem_region_ops = {
697 .init = init_shmem,
698 .release = release_shmem,
699 .create_object = create_shmem,
700};
701
702struct intel_memory_region *i915_gem_shmem_setup(struct drm_i915_privateinteldrm_softc *i915)
703{
704 return intel_memory_region_create(i915, 0,
705 totalram_pages() << PAGE_SHIFT12,
706 PAGE_SIZE(1 << 12), 0,
707 &shmem_region_ops);
708}