Merge tag 'clk-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
[linux.git] / lib / kunit / user_alloc.c
blob46951be018be27776f8369322fe8be0d63f376ca
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3 * KUnit userspace memory allocation resource management.
4 */
5 #include <kunit/resource.h>
6 #include <kunit/test.h>
7 #include <linux/kthread.h>
8 #include <linux/mm.h>
10 struct kunit_vm_mmap_resource {
11 unsigned long addr;
12 size_t size;
15 /* vm_mmap() arguments */
16 struct kunit_vm_mmap_params {
17 struct file *file;
18 unsigned long addr;
19 unsigned long len;
20 unsigned long prot;
21 unsigned long flag;
22 unsigned long offset;
25 /* Create and attach a new mm if it doesn't already exist. */
26 static int kunit_attach_mm(void)
28 struct mm_struct *mm;
30 if (current->mm)
31 return 0;
33 /* arch_pick_mmap_layout() is only sane with MMU systems. */
34 if (!IS_ENABLED(CONFIG_MMU))
35 return -EINVAL;
37 mm = mm_alloc();
38 if (!mm)
39 return -ENOMEM;
41 /* Define the task size. */
42 mm->task_size = TASK_SIZE;
44 /* Make sure we can allocate new VMAs. */
45 arch_pick_mmap_layout(mm, &current->signal->rlim[RLIMIT_STACK]);
47 /* Attach the mm. It will be cleaned up when the process dies. */
48 kthread_use_mm(mm);
50 return 0;
53 static int kunit_vm_mmap_init(struct kunit_resource *res, void *context)
55 struct kunit_vm_mmap_params *p = context;
56 struct kunit_vm_mmap_resource vres;
57 int ret;
59 ret = kunit_attach_mm();
60 if (ret)
61 return ret;
63 vres.size = p->len;
64 vres.addr = vm_mmap(p->file, p->addr, p->len, p->prot, p->flag, p->offset);
65 if (!vres.addr)
66 return -ENOMEM;
67 res->data = kmemdup(&vres, sizeof(vres), GFP_KERNEL);
68 if (!res->data) {
69 vm_munmap(vres.addr, vres.size);
70 return -ENOMEM;
73 return 0;
76 static void kunit_vm_mmap_free(struct kunit_resource *res)
78 struct kunit_vm_mmap_resource *vres = res->data;
81 * Since this is executed from the test monitoring process,
82 * the test's mm has already been torn down. We don't need
83 * to run vm_munmap(vres->addr, vres->size), only clean up
84 * the vres.
87 kfree(vres);
88 res->data = NULL;
91 unsigned long kunit_vm_mmap(struct kunit *test, struct file *file,
92 unsigned long addr, unsigned long len,
93 unsigned long prot, unsigned long flag,
94 unsigned long offset)
96 struct kunit_vm_mmap_params params = {
97 .file = file,
98 .addr = addr,
99 .len = len,
100 .prot = prot,
101 .flag = flag,
102 .offset = offset,
104 struct kunit_vm_mmap_resource *vres;
106 vres = kunit_alloc_resource(test,
107 kunit_vm_mmap_init,
108 kunit_vm_mmap_free,
109 GFP_KERNEL,
110 &params);
111 if (vres)
112 return vres->addr;
113 return 0;
115 EXPORT_SYMBOL_GPL(kunit_vm_mmap);
117 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");