ttm_memory.c revision 1.1.1.3 1 /* $NetBSD: ttm_memory.c,v 1.1.1.3 2021/12/18 20:15:53 riastradh Exp $ */
2
3 /* SPDX-License-Identifier: GPL-2.0 OR MIT */
4 /**************************************************************************
5 *
6 * Copyright (c) 2006-2009 VMware, Inc., Palo Alto, CA., USA
7 * All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation the rights to use, copy, modify, merge, publish,
13 * distribute, sub license, and/or sell copies of the Software, and to
14 * permit persons to whom the Software is furnished to do so, subject to
15 * the following conditions:
16 *
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial portions
19 * of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
24 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
25 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
26 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
27 * USE OR OTHER DEALINGS IN THE SOFTWARE.
28 *
29 **************************************************************************/
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: ttm_memory.c,v 1.1.1.3 2021/12/18 20:15:53 riastradh Exp $");
33
34 #define pr_fmt(fmt) "[TTM] " fmt
35
36 #include <drm/ttm/ttm_memory.h>
37 #include <drm/ttm/ttm_module.h>
38 #include <drm/ttm/ttm_page_alloc.h>
39 #include <linux/spinlock.h>
40 #include <linux/sched.h>
41 #include <linux/wait.h>
42 #include <linux/mm.h>
43 #include <linux/module.h>
44 #include <linux/slab.h>
45 #include <linux/swap.h>
46
47 #define TTM_MEMORY_ALLOC_RETRIES 4
48
49 struct ttm_mem_global ttm_mem_glob;
50 EXPORT_SYMBOL(ttm_mem_glob);
51
52 struct ttm_mem_zone {
53 struct kobject kobj;
54 struct ttm_mem_global *glob;
55 const char *name;
56 uint64_t zone_mem;
57 uint64_t emer_mem;
58 uint64_t max_mem;
59 uint64_t swap_limit;
60 uint64_t used_mem;
61 };
62
63 static struct attribute ttm_mem_sys = {
64 .name = "zone_memory",
65 .mode = S_IRUGO
66 };
67 static struct attribute ttm_mem_emer = {
68 .name = "emergency_memory",
69 .mode = S_IRUGO | S_IWUSR
70 };
71 static struct attribute ttm_mem_max = {
72 .name = "available_memory",
73 .mode = S_IRUGO | S_IWUSR
74 };
75 static struct attribute ttm_mem_swap = {
76 .name = "swap_limit",
77 .mode = S_IRUGO | S_IWUSR
78 };
79 static struct attribute ttm_mem_used = {
80 .name = "used_memory",
81 .mode = S_IRUGO
82 };
83
84 static void ttm_mem_zone_kobj_release(struct kobject *kobj)
85 {
86 struct ttm_mem_zone *zone =
87 container_of(kobj, struct ttm_mem_zone, kobj);
88
89 pr_info("Zone %7s: Used memory at exit: %llu KiB\n",
90 zone->name, (unsigned long long)zone->used_mem >> 10);
91 kfree(zone);
92 }
93
94 static ssize_t ttm_mem_zone_show(struct kobject *kobj,
95 struct attribute *attr,
96 char *buffer)
97 {
98 struct ttm_mem_zone *zone =
99 container_of(kobj, struct ttm_mem_zone, kobj);
100 uint64_t val = 0;
101
102 spin_lock(&zone->glob->lock);
103 if (attr == &ttm_mem_sys)
104 val = zone->zone_mem;
105 else if (attr == &ttm_mem_emer)
106 val = zone->emer_mem;
107 else if (attr == &ttm_mem_max)
108 val = zone->max_mem;
109 else if (attr == &ttm_mem_swap)
110 val = zone->swap_limit;
111 else if (attr == &ttm_mem_used)
112 val = zone->used_mem;
113 spin_unlock(&zone->glob->lock);
114
115 return snprintf(buffer, PAGE_SIZE, "%llu\n",
116 (unsigned long long) val >> 10);
117 }
118
119 static void ttm_check_swapping(struct ttm_mem_global *glob);
120
121 static ssize_t ttm_mem_zone_store(struct kobject *kobj,
122 struct attribute *attr,
123 const char *buffer,
124 size_t size)
125 {
126 struct ttm_mem_zone *zone =
127 container_of(kobj, struct ttm_mem_zone, kobj);
128 int chars;
129 unsigned long val;
130 uint64_t val64;
131
132 chars = sscanf(buffer, "%lu", &val);
133 if (chars == 0)
134 return size;
135
136 val64 = val;
137 val64 <<= 10;
138
139 spin_lock(&zone->glob->lock);
140 if (val64 > zone->zone_mem)
141 val64 = zone->zone_mem;
142 if (attr == &ttm_mem_emer) {
143 zone->emer_mem = val64;
144 if (zone->max_mem > val64)
145 zone->max_mem = val64;
146 } else if (attr == &ttm_mem_max) {
147 zone->max_mem = val64;
148 if (zone->emer_mem < val64)
149 zone->emer_mem = val64;
150 } else if (attr == &ttm_mem_swap)
151 zone->swap_limit = val64;
152 spin_unlock(&zone->glob->lock);
153
154 ttm_check_swapping(zone->glob);
155
156 return size;
157 }
158
159 static struct attribute *ttm_mem_zone_attrs[] = {
160 &ttm_mem_sys,
161 &ttm_mem_emer,
162 &ttm_mem_max,
163 &ttm_mem_swap,
164 &ttm_mem_used,
165 NULL
166 };
167
168 static const struct sysfs_ops ttm_mem_zone_ops = {
169 .show = &ttm_mem_zone_show,
170 .store = &ttm_mem_zone_store
171 };
172
173 static struct kobj_type ttm_mem_zone_kobj_type = {
174 .release = &ttm_mem_zone_kobj_release,
175 .sysfs_ops = &ttm_mem_zone_ops,
176 .default_attrs = ttm_mem_zone_attrs,
177 };
178
179 static struct attribute ttm_mem_global_lower_mem_limit = {
180 .name = "lower_mem_limit",
181 .mode = S_IRUGO | S_IWUSR
182 };
183
184 static ssize_t ttm_mem_global_show(struct kobject *kobj,
185 struct attribute *attr,
186 char *buffer)
187 {
188 struct ttm_mem_global *glob =
189 container_of(kobj, struct ttm_mem_global, kobj);
190 uint64_t val = 0;
191
192 spin_lock(&glob->lock);
193 val = glob->lower_mem_limit;
194 spin_unlock(&glob->lock);
195 /* convert from number of pages to KB */
196 val <<= (PAGE_SHIFT - 10);
197 return snprintf(buffer, PAGE_SIZE, "%llu\n",
198 (unsigned long long) val);
199 }
200
201 static ssize_t ttm_mem_global_store(struct kobject *kobj,
202 struct attribute *attr,
203 const char *buffer,
204 size_t size)
205 {
206 int chars;
207 uint64_t val64;
208 unsigned long val;
209 struct ttm_mem_global *glob =
210 container_of(kobj, struct ttm_mem_global, kobj);
211
212 chars = sscanf(buffer, "%lu", &val);
213 if (chars == 0)
214 return size;
215
216 val64 = val;
217 /* convert from KB to number of pages */
218 val64 >>= (PAGE_SHIFT - 10);
219
220 spin_lock(&glob->lock);
221 glob->lower_mem_limit = val64;
222 spin_unlock(&glob->lock);
223
224 return size;
225 }
226
227 static struct attribute *ttm_mem_global_attrs[] = {
228 &ttm_mem_global_lower_mem_limit,
229 NULL
230 };
231
232 static const struct sysfs_ops ttm_mem_global_ops = {
233 .show = &ttm_mem_global_show,
234 .store = &ttm_mem_global_store,
235 };
236
237 static struct kobj_type ttm_mem_glob_kobj_type = {
238 .sysfs_ops = &ttm_mem_global_ops,
239 .default_attrs = ttm_mem_global_attrs,
240 };
241
242 static bool ttm_zones_above_swap_target(struct ttm_mem_global *glob,
243 bool from_wq, uint64_t extra)
244 {
245 unsigned int i;
246 struct ttm_mem_zone *zone;
247 uint64_t target;
248
249 for (i = 0; i < glob->num_zones; ++i) {
250 zone = glob->zones[i];
251
252 if (from_wq)
253 target = zone->swap_limit;
254 else if (capable(CAP_SYS_ADMIN))
255 target = zone->emer_mem;
256 else
257 target = zone->max_mem;
258
259 target = (extra > target) ? 0ULL : target;
260
261 if (zone->used_mem > target)
262 return true;
263 }
264 return false;
265 }
266
267 /**
268 * At this point we only support a single shrink callback.
269 * Extend this if needed, perhaps using a linked list of callbacks.
270 * Note that this function is reentrant:
271 * many threads may try to swap out at any given time.
272 */
273
274 static void ttm_shrink(struct ttm_mem_global *glob, bool from_wq,
275 uint64_t extra, struct ttm_operation_ctx *ctx)
276 {
277 int ret;
278
279 spin_lock(&glob->lock);
280
281 while (ttm_zones_above_swap_target(glob, from_wq, extra)) {
282 spin_unlock(&glob->lock);
283 ret = ttm_bo_swapout(&ttm_bo_glob, ctx);
284 spin_lock(&glob->lock);
285 if (unlikely(ret != 0))
286 break;
287 }
288
289 spin_unlock(&glob->lock);
290 }
291
292 static void ttm_shrink_work(struct work_struct *work)
293 {
294 struct ttm_operation_ctx ctx = {
295 .interruptible = false,
296 .no_wait_gpu = false
297 };
298 struct ttm_mem_global *glob =
299 container_of(work, struct ttm_mem_global, work);
300
301 ttm_shrink(glob, true, 0ULL, &ctx);
302 }
303
304 static int ttm_mem_init_kernel_zone(struct ttm_mem_global *glob,
305 const struct sysinfo *si)
306 {
307 struct ttm_mem_zone *zone = kzalloc(sizeof(*zone), GFP_KERNEL);
308 uint64_t mem;
309 int ret;
310
311 if (unlikely(!zone))
312 return -ENOMEM;
313
314 mem = si->totalram - si->totalhigh;
315 mem *= si->mem_unit;
316
317 zone->name = "kernel";
318 zone->zone_mem = mem;
319 zone->max_mem = mem >> 1;
320 zone->emer_mem = (mem >> 1) + (mem >> 2);
321 zone->swap_limit = zone->max_mem - (mem >> 3);
322 zone->used_mem = 0;
323 zone->glob = glob;
324 glob->zone_kernel = zone;
325 ret = kobject_init_and_add(
326 &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, zone->name);
327 if (unlikely(ret != 0)) {
328 kobject_put(&zone->kobj);
329 return ret;
330 }
331 glob->zones[glob->num_zones++] = zone;
332 return 0;
333 }
334
335 #ifdef CONFIG_HIGHMEM
336 static int ttm_mem_init_highmem_zone(struct ttm_mem_global *glob,
337 const struct sysinfo *si)
338 {
339 struct ttm_mem_zone *zone;
340 uint64_t mem;
341 int ret;
342
343 if (si->totalhigh == 0)
344 return 0;
345
346 zone = kzalloc(sizeof(*zone), GFP_KERNEL);
347 if (unlikely(!zone))
348 return -ENOMEM;
349
350 mem = si->totalram;
351 mem *= si->mem_unit;
352
353 zone->name = "highmem";
354 zone->zone_mem = mem;
355 zone->max_mem = mem >> 1;
356 zone->emer_mem = (mem >> 1) + (mem >> 2);
357 zone->swap_limit = zone->max_mem - (mem >> 3);
358 zone->used_mem = 0;
359 zone->glob = glob;
360 glob->zone_highmem = zone;
361 ret = kobject_init_and_add(
362 &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, "%s",
363 zone->name);
364 if (unlikely(ret != 0)) {
365 kobject_put(&zone->kobj);
366 return ret;
367 }
368 glob->zones[glob->num_zones++] = zone;
369 return 0;
370 }
371 #else
372 static int ttm_mem_init_dma32_zone(struct ttm_mem_global *glob,
373 const struct sysinfo *si)
374 {
375 struct ttm_mem_zone *zone = kzalloc(sizeof(*zone), GFP_KERNEL);
376 uint64_t mem;
377 int ret;
378
379 if (unlikely(!zone))
380 return -ENOMEM;
381
382 mem = si->totalram;
383 mem *= si->mem_unit;
384
385 /**
386 * No special dma32 zone needed.
387 */
388
389 if (mem <= ((uint64_t) 1ULL << 32)) {
390 kfree(zone);
391 return 0;
392 }
393
394 /*
395 * Limit max dma32 memory to 4GB for now
396 * until we can figure out how big this
397 * zone really is.
398 */
399
400 mem = ((uint64_t) 1ULL << 32);
401 zone->name = "dma32";
402 zone->zone_mem = mem;
403 zone->max_mem = mem >> 1;
404 zone->emer_mem = (mem >> 1) + (mem >> 2);
405 zone->swap_limit = zone->max_mem - (mem >> 3);
406 zone->used_mem = 0;
407 zone->glob = glob;
408 glob->zone_dma32 = zone;
409 ret = kobject_init_and_add(
410 &zone->kobj, &ttm_mem_zone_kobj_type, &glob->kobj, zone->name);
411 if (unlikely(ret != 0)) {
412 kobject_put(&zone->kobj);
413 return ret;
414 }
415 glob->zones[glob->num_zones++] = zone;
416 return 0;
417 }
418 #endif
419
420 int ttm_mem_global_init(struct ttm_mem_global *glob)
421 {
422 struct sysinfo si;
423 int ret;
424 int i;
425 struct ttm_mem_zone *zone;
426
427 spin_lock_init(&glob->lock);
428 glob->swap_queue = create_singlethread_workqueue("ttm_swap");
429 INIT_WORK(&glob->work, ttm_shrink_work);
430 ret = kobject_init_and_add(
431 &glob->kobj, &ttm_mem_glob_kobj_type, ttm_get_kobj(), "memory_accounting");
432 if (unlikely(ret != 0)) {
433 kobject_put(&glob->kobj);
434 return ret;
435 }
436
437 si_meminfo(&si);
438
439 /* set it as 0 by default to keep original behavior of OOM */
440 glob->lower_mem_limit = 0;
441
442 ret = ttm_mem_init_kernel_zone(glob, &si);
443 if (unlikely(ret != 0))
444 goto out_no_zone;
445 #ifdef CONFIG_HIGHMEM
446 ret = ttm_mem_init_highmem_zone(glob, &si);
447 if (unlikely(ret != 0))
448 goto out_no_zone;
449 #else
450 ret = ttm_mem_init_dma32_zone(glob, &si);
451 if (unlikely(ret != 0))
452 goto out_no_zone;
453 #endif
454 for (i = 0; i < glob->num_zones; ++i) {
455 zone = glob->zones[i];
456 pr_info("Zone %7s: Available graphics memory: %llu KiB\n",
457 zone->name, (unsigned long long)zone->max_mem >> 10);
458 }
459 ttm_page_alloc_init(glob, glob->zone_kernel->max_mem/(2*PAGE_SIZE));
460 ttm_dma_page_alloc_init(glob, glob->zone_kernel->max_mem/(2*PAGE_SIZE));
461 return 0;
462 out_no_zone:
463 ttm_mem_global_release(glob);
464 return ret;
465 }
466
467 void ttm_mem_global_release(struct ttm_mem_global *glob)
468 {
469 struct ttm_mem_zone *zone;
470 unsigned int i;
471
472 /* let the page allocator first stop the shrink work. */
473 ttm_page_alloc_fini();
474 ttm_dma_page_alloc_fini();
475
476 flush_workqueue(glob->swap_queue);
477 destroy_workqueue(glob->swap_queue);
478 glob->swap_queue = NULL;
479 for (i = 0; i < glob->num_zones; ++i) {
480 zone = glob->zones[i];
481 kobject_del(&zone->kobj);
482 kobject_put(&zone->kobj);
483 }
484 kobject_del(&glob->kobj);
485 kobject_put(&glob->kobj);
486 memset(glob, 0, sizeof(*glob));
487 }
488
489 static void ttm_check_swapping(struct ttm_mem_global *glob)
490 {
491 bool needs_swapping = false;
492 unsigned int i;
493 struct ttm_mem_zone *zone;
494
495 spin_lock(&glob->lock);
496 for (i = 0; i < glob->num_zones; ++i) {
497 zone = glob->zones[i];
498 if (zone->used_mem > zone->swap_limit) {
499 needs_swapping = true;
500 break;
501 }
502 }
503
504 spin_unlock(&glob->lock);
505
506 if (unlikely(needs_swapping))
507 (void)queue_work(glob->swap_queue, &glob->work);
508
509 }
510
511 static void ttm_mem_global_free_zone(struct ttm_mem_global *glob,
512 struct ttm_mem_zone *single_zone,
513 uint64_t amount)
514 {
515 unsigned int i;
516 struct ttm_mem_zone *zone;
517
518 spin_lock(&glob->lock);
519 for (i = 0; i < glob->num_zones; ++i) {
520 zone = glob->zones[i];
521 if (single_zone && zone != single_zone)
522 continue;
523 zone->used_mem -= amount;
524 }
525 spin_unlock(&glob->lock);
526 }
527
528 void ttm_mem_global_free(struct ttm_mem_global *glob,
529 uint64_t amount)
530 {
531 return ttm_mem_global_free_zone(glob, glob->zone_kernel, amount);
532 }
533 EXPORT_SYMBOL(ttm_mem_global_free);
534
535 /*
536 * check if the available mem is under lower memory limit
537 *
538 * a. if no swap disk at all or free swap space is under swap_mem_limit
539 * but available system mem is bigger than sys_mem_limit, allow TTM
540 * allocation;
541 *
542 * b. if the available system mem is less than sys_mem_limit but free
543 * swap disk is bigger than swap_mem_limit, allow TTM allocation.
544 */
545 bool
546 ttm_check_under_lowerlimit(struct ttm_mem_global *glob,
547 uint64_t num_pages,
548 struct ttm_operation_ctx *ctx)
549 {
550 int64_t available;
551
552 if (ctx->flags & TTM_OPT_FLAG_FORCE_ALLOC)
553 return false;
554
555 available = get_nr_swap_pages() + si_mem_available();
556 available -= num_pages;
557 if (available < glob->lower_mem_limit)
558 return true;
559
560 return false;
561 }
562 EXPORT_SYMBOL(ttm_check_under_lowerlimit);
563
564 static int ttm_mem_global_reserve(struct ttm_mem_global *glob,
565 struct ttm_mem_zone *single_zone,
566 uint64_t amount, bool reserve)
567 {
568 uint64_t limit;
569 int ret = -ENOMEM;
570 unsigned int i;
571 struct ttm_mem_zone *zone;
572
573 spin_lock(&glob->lock);
574 for (i = 0; i < glob->num_zones; ++i) {
575 zone = glob->zones[i];
576 if (single_zone && zone != single_zone)
577 continue;
578
579 limit = (capable(CAP_SYS_ADMIN)) ?
580 zone->emer_mem : zone->max_mem;
581
582 if (zone->used_mem > limit)
583 goto out_unlock;
584 }
585
586 if (reserve) {
587 for (i = 0; i < glob->num_zones; ++i) {
588 zone = glob->zones[i];
589 if (single_zone && zone != single_zone)
590 continue;
591 zone->used_mem += amount;
592 }
593 }
594
595 ret = 0;
596 out_unlock:
597 spin_unlock(&glob->lock);
598 ttm_check_swapping(glob);
599
600 return ret;
601 }
602
603
604 static int ttm_mem_global_alloc_zone(struct ttm_mem_global *glob,
605 struct ttm_mem_zone *single_zone,
606 uint64_t memory,
607 struct ttm_operation_ctx *ctx)
608 {
609 int count = TTM_MEMORY_ALLOC_RETRIES;
610
611 while (unlikely(ttm_mem_global_reserve(glob,
612 single_zone,
613 memory, true)
614 != 0)) {
615 if (ctx->no_wait_gpu)
616 return -ENOMEM;
617 if (unlikely(count-- == 0))
618 return -ENOMEM;
619 ttm_shrink(glob, false, memory + (memory >> 2) + 16, ctx);
620 }
621
622 return 0;
623 }
624
625 int ttm_mem_global_alloc(struct ttm_mem_global *glob, uint64_t memory,
626 struct ttm_operation_ctx *ctx)
627 {
628 /**
629 * Normal allocations of kernel memory are registered in
630 * the kernel zone.
631 */
632
633 return ttm_mem_global_alloc_zone(glob, glob->zone_kernel, memory, ctx);
634 }
635 EXPORT_SYMBOL(ttm_mem_global_alloc);
636
637 int ttm_mem_global_alloc_page(struct ttm_mem_global *glob,
638 struct page *page, uint64_t size,
639 struct ttm_operation_ctx *ctx)
640 {
641 struct ttm_mem_zone *zone = NULL;
642
643 /**
644 * Page allocations may be registed in a single zone
645 * only if highmem or !dma32.
646 */
647
648 #ifdef CONFIG_HIGHMEM
649 if (PageHighMem(page) && glob->zone_highmem != NULL)
650 zone = glob->zone_highmem;
651 #else
652 if (glob->zone_dma32 && page_to_pfn(page) > 0x00100000UL)
653 zone = glob->zone_kernel;
654 #endif
655 return ttm_mem_global_alloc_zone(glob, zone, size, ctx);
656 }
657
658 void ttm_mem_global_free_page(struct ttm_mem_global *glob, struct page *page,
659 uint64_t size)
660 {
661 struct ttm_mem_zone *zone = NULL;
662
663 #ifdef CONFIG_HIGHMEM
664 if (PageHighMem(page) && glob->zone_highmem != NULL)
665 zone = glob->zone_highmem;
666 #else
667 if (glob->zone_dma32 && page_to_pfn(page) > 0x00100000UL)
668 zone = glob->zone_kernel;
669 #endif
670 ttm_mem_global_free_zone(glob, zone, size);
671 }
672
673 size_t ttm_round_pot(size_t size)
674 {
675 if ((size & (size - 1)) == 0)
676 return size;
677 else if (size > PAGE_SIZE)
678 return PAGE_ALIGN(size);
679 else {
680 size_t tmp_size = 4;
681
682 while (tmp_size < size)
683 tmp_size <<= 1;
684
685 return tmp_size;
686 }
687 return 0;
688 }
689 EXPORT_SYMBOL(ttm_round_pot);
690
691 uint64_t ttm_get_kernel_zone_memory_size(struct ttm_mem_global *glob)
692 {
693 return glob->zone_kernel->max_mem;
694 }
695 EXPORT_SYMBOL(ttm_get_kernel_zone_memory_size);
696