1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Test cases for binder allocator code 4 */ 5 6 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 7 8 #include <kunit/test.h> 9 #include <linux/anon_inodes.h> 10 #include <linux/err.h> 11 #include <linux/file.h> 12 #include <linux/fs.h> 13 #include <linux/mm.h> 14 #include <linux/mman.h> 15 #include <linux/sizes.h> 16 17 #include "../binder_alloc.h" 18 #include "../binder_internal.h" 19 20 MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); 21 22 #define BINDER_MMAP_SIZE SZ_128K 23 24 struct binder_alloc_test { 25 struct binder_alloc alloc; 26 struct list_lru binder_test_freelist; 27 struct file *filp; 28 unsigned long mmap_uaddr; 29 }; 30 31 static void binder_alloc_test_init_freelist(struct kunit *test) 32 { 33 struct binder_alloc_test *priv = test->priv; 34 35 KUNIT_EXPECT_PTR_EQ(test, priv->alloc.freelist, 36 &priv->binder_test_freelist); 37 } 38 39 static void binder_alloc_test_mmap(struct kunit *test) 40 { 41 struct binder_alloc_test *priv = test->priv; 42 struct binder_alloc *alloc = &priv->alloc; 43 struct binder_buffer *buf; 44 struct rb_node *n; 45 46 KUNIT_EXPECT_EQ(test, alloc->mapped, true); 47 KUNIT_EXPECT_EQ(test, alloc->buffer_size, BINDER_MMAP_SIZE); 48 49 n = rb_first(&alloc->allocated_buffers); 50 KUNIT_EXPECT_PTR_EQ(test, n, NULL); 51 52 n = rb_first(&alloc->free_buffers); 53 buf = rb_entry(n, struct binder_buffer, rb_node); 54 KUNIT_EXPECT_EQ(test, binder_alloc_buffer_size(alloc, buf), 55 BINDER_MMAP_SIZE); 56 KUNIT_EXPECT_TRUE(test, list_is_last(&buf->entry, &alloc->buffers)); 57 } 58 59 /* ===== End test cases ===== */ 60 61 static void binder_alloc_test_vma_close(struct vm_area_struct *vma) 62 { 63 struct binder_alloc *alloc = vma->vm_private_data; 64 65 binder_alloc_vma_close(alloc); 66 } 67 68 static const struct vm_operations_struct binder_alloc_test_vm_ops = { 69 .close = binder_alloc_test_vma_close, 70 .fault = binder_vm_fault, 71 }; 72 73 static int binder_alloc_test_mmap_handler(struct file *filp, 74 struct vm_area_struct *vma) 75 { 76 struct binder_alloc *alloc = filp->private_data; 77 78 vm_flags_mod(vma, VM_DONTCOPY | VM_MIXEDMAP, VM_MAYWRITE); 79 80 vma->vm_ops = &binder_alloc_test_vm_ops; 81 vma->vm_private_data = alloc; 82 83 return binder_alloc_mmap_handler(alloc, vma); 84 } 85 86 static const struct file_operations binder_alloc_test_fops = { 87 .mmap = binder_alloc_test_mmap_handler, 88 }; 89 90 static int binder_alloc_test_init(struct kunit *test) 91 { 92 struct binder_alloc_test *priv; 93 int ret; 94 95 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); 96 if (!priv) 97 return -ENOMEM; 98 test->priv = priv; 99 100 ret = list_lru_init(&priv->binder_test_freelist); 101 if (ret) { 102 kunit_err(test, "Failed to initialize test freelist\n"); 103 return ret; 104 } 105 106 /* __binder_alloc_init requires mm to be attached */ 107 ret = kunit_attach_mm(); 108 if (ret) { 109 kunit_err(test, "Failed to attach mm\n"); 110 return ret; 111 } 112 __binder_alloc_init(&priv->alloc, &priv->binder_test_freelist); 113 114 priv->filp = anon_inode_getfile("binder_alloc_kunit", 115 &binder_alloc_test_fops, &priv->alloc, 116 O_RDWR | O_CLOEXEC); 117 if (IS_ERR_OR_NULL(priv->filp)) { 118 kunit_err(test, "Failed to open binder alloc test driver file\n"); 119 return priv->filp ? PTR_ERR(priv->filp) : -ENOMEM; 120 } 121 122 priv->mmap_uaddr = kunit_vm_mmap(test, priv->filp, 0, BINDER_MMAP_SIZE, 123 PROT_READ, MAP_PRIVATE | MAP_NORESERVE, 124 0); 125 if (!priv->mmap_uaddr) { 126 kunit_err(test, "Could not map the test's transaction memory\n"); 127 return -ENOMEM; 128 } 129 130 return 0; 131 } 132 133 static void binder_alloc_test_exit(struct kunit *test) 134 { 135 struct binder_alloc_test *priv = test->priv; 136 137 /* Close the backing file to make sure binder_alloc_vma_close runs */ 138 if (!IS_ERR_OR_NULL(priv->filp)) 139 fput(priv->filp); 140 141 if (priv->alloc.mm) 142 binder_alloc_deferred_release(&priv->alloc); 143 144 /* Make sure freelist is empty */ 145 KUNIT_EXPECT_EQ(test, list_lru_count(&priv->binder_test_freelist), 0); 146 list_lru_destroy(&priv->binder_test_freelist); 147 } 148 149 static struct kunit_case binder_alloc_test_cases[] = { 150 KUNIT_CASE(binder_alloc_test_init_freelist), 151 KUNIT_CASE(binder_alloc_test_mmap), 152 {} 153 }; 154 155 static struct kunit_suite binder_alloc_test_suite = { 156 .name = "binder_alloc", 157 .test_cases = binder_alloc_test_cases, 158 .init = binder_alloc_test_init, 159 .exit = binder_alloc_test_exit, 160 }; 161 162 kunit_test_suite(binder_alloc_test_suite); 163 164 MODULE_AUTHOR("Tiffany Yang <ynaffit@google.com>"); 165 MODULE_DESCRIPTION("Binder Alloc KUnit tests"); 166 MODULE_LICENSE("GPL"); 167