brintos

brintos / linux-shallow public Read only

0
0
Text · 2.5 KiB · ae935df Raw
118 lines · c
1// SPDX-License-Identifier: GPL-2.02/*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>9 10struct kunit_vm_mmap_resource {11	unsigned long addr;12	size_t size;13};14 15/* vm_mmap() arguments */16struct 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;23};24 25/* Create and attach a new mm if it doesn't already exist. */26static int kunit_attach_mm(void)27{28	struct mm_struct *mm;29 30	if (current->mm)31		return 0;32 33	/* arch_pick_mmap_layout() is only sane with MMU systems. */34	if (!IS_ENABLED(CONFIG_MMU))35		return -EINVAL;36 37	mm = mm_alloc();38	if (!mm)39		return -ENOMEM;40 41	/* Define the task size. */42	mm->task_size = TASK_SIZE;43 44	/* Make sure we can allocate new VMAs. */45	arch_pick_mmap_layout(mm, &current->signal->rlim[RLIMIT_STACK]);46 47	/* Attach the mm. It will be cleaned up when the process dies. */48	kthread_use_mm(mm);49 50	return 0;51}52 53static int kunit_vm_mmap_init(struct kunit_resource *res, void *context)54{55	struct kunit_vm_mmap_params *p = context;56	struct kunit_vm_mmap_resource vres;57	int ret;58 59	ret = kunit_attach_mm();60	if (ret)61		return ret;62 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;71	}72 73	return 0;74}75 76static void kunit_vm_mmap_free(struct kunit_resource *res)77{78	struct kunit_vm_mmap_resource *vres = res->data;79 80	/*81	 * Since this is executed from the test monitoring process,82	 * the test's mm has already been torn down. We don't need83	 * to run vm_munmap(vres->addr, vres->size), only clean up84	 * the vres.85	 */86 87	kfree(vres);88	res->data = NULL;89}90 91unsigned 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)95{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,103	};104	struct kunit_vm_mmap_resource *vres;105 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;114}115EXPORT_SYMBOL_GPL(kunit_vm_mmap);116 117MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);118