1 | // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause |
2 | /* |
3 | * Copyright(c) 2015-2017 Intel Corporation. |
4 | */ |
5 | |
6 | #include <linux/mm.h> |
7 | #include <linux/sched/signal.h> |
8 | #include <linux/device.h> |
9 | #include <linux/module.h> |
10 | |
11 | #include "hfi.h" |
12 | |
13 | static unsigned long cache_size = 256; |
14 | module_param(cache_size, ulong, S_IRUGO | S_IWUSR); |
15 | MODULE_PARM_DESC(cache_size, "Send and receive side cache size limit (in MB)" ); |
16 | |
17 | /* |
18 | * Determine whether the caller can pin pages. |
19 | * |
20 | * This function should be used in the implementation of buffer caches. |
21 | * The cache implementation should call this function prior to attempting |
22 | * to pin buffer pages in order to determine whether they should do so. |
23 | * The function computes cache limits based on the configured ulimit and |
24 | * cache size. Use of this function is especially important for caches |
25 | * which are not limited in any other way (e.g. by HW resources) and, thus, |
26 | * could keeping caching buffers. |
27 | * |
28 | */ |
29 | bool hfi1_can_pin_pages(struct hfi1_devdata *dd, struct mm_struct *mm, |
30 | u32 nlocked, u32 npages) |
31 | { |
32 | unsigned long ulimit_pages; |
33 | unsigned long cache_limit_pages; |
34 | unsigned int usr_ctxts; |
35 | |
36 | /* |
37 | * Perform RLIMIT_MEMLOCK based checks unless CAP_IPC_LOCK is present. |
38 | */ |
39 | if (!capable(CAP_IPC_LOCK)) { |
40 | ulimit_pages = |
41 | DIV_ROUND_DOWN_ULL(rlimit(RLIMIT_MEMLOCK), PAGE_SIZE); |
42 | |
43 | /* |
44 | * Pinning these pages would exceed this process's locked memory |
45 | * limit. |
46 | */ |
47 | if (atomic64_read(v: &mm->pinned_vm) + npages > ulimit_pages) |
48 | return false; |
49 | |
50 | /* |
51 | * Only allow 1/4 of the user's RLIMIT_MEMLOCK to be used for HFI |
52 | * caches. This fraction is then equally distributed among all |
53 | * existing user contexts. Note that if RLIMIT_MEMLOCK is |
54 | * 'unlimited' (-1), the value of this limit will be > 2^42 pages |
55 | * (2^64 / 2^12 / 2^8 / 2^2). |
56 | * |
57 | * The effectiveness of this check may be reduced if I/O occurs on |
58 | * some user contexts before all user contexts are created. This |
59 | * check assumes that this process is the only one using this |
60 | * context (e.g., the corresponding fd was not passed to another |
61 | * process for concurrent access) as there is no per-context, |
62 | * per-process tracking of pinned pages. It also assumes that each |
63 | * user context has only one cache to limit. |
64 | */ |
65 | usr_ctxts = dd->num_rcv_contexts - dd->first_dyn_alloc_ctxt; |
66 | if (nlocked + npages > (ulimit_pages / usr_ctxts / 4)) |
67 | return false; |
68 | } |
69 | |
70 | /* |
71 | * Pinning these pages would exceed the size limit for this cache. |
72 | */ |
73 | cache_limit_pages = cache_size * (1024 * 1024) / PAGE_SIZE; |
74 | if (nlocked + npages > cache_limit_pages) |
75 | return false; |
76 | |
77 | return true; |
78 | } |
79 | |
80 | int hfi1_acquire_user_pages(struct mm_struct *mm, unsigned long vaddr, size_t npages, |
81 | bool writable, struct page **pages) |
82 | { |
83 | int ret; |
84 | unsigned int gup_flags = FOLL_LONGTERM | (writable ? FOLL_WRITE : 0); |
85 | |
86 | ret = pin_user_pages_fast(start: vaddr, nr_pages: npages, gup_flags, pages); |
87 | if (ret < 0) |
88 | return ret; |
89 | |
90 | atomic64_add(i: ret, v: &mm->pinned_vm); |
91 | |
92 | return ret; |
93 | } |
94 | |
95 | void hfi1_release_user_pages(struct mm_struct *mm, struct page **p, |
96 | size_t npages, bool dirty) |
97 | { |
98 | unpin_user_pages_dirty_lock(pages: p, npages, make_dirty: dirty); |
99 | |
100 | if (mm) { /* during close after signal, mm can be NULL */ |
101 | atomic64_sub(i: npages, v: &mm->pinned_vm); |
102 | } |
103 | } |
104 | |