binder_alloc_kunit.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Test cases for binder allocator code.
  4. *
  5. * Copyright 2025 Google LLC.
  6. * Author: Tiffany Yang <ynaffit@google.com>
  7. */
  8. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  9. #include <kunit/test.h>
  10. #include <linux/anon_inodes.h>
  11. #include <linux/err.h>
  12. #include <linux/file.h>
  13. #include <linux/fs.h>
  14. #include <linux/mm.h>
  15. #include <linux/mman.h>
  16. #include <linux/seq_buf.h>
  17. #include <linux/sizes.h>
  18. #include "../binder_alloc.h"
  19. #include "../binder_internal.h"
  20. MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
  21. #define BINDER_MMAP_SIZE SZ_128K
  22. #define BUFFER_NUM 5
  23. #define BUFFER_MIN_SIZE (PAGE_SIZE / 8)
  24. #define FREESEQ_BUFLEN ((3 * BUFFER_NUM) + 1)
  25. #define ALIGN_TYPE_STRLEN (12)
  26. #define ALIGNMENTS_BUFLEN (((ALIGN_TYPE_STRLEN + 6) * BUFFER_NUM) + 1)
  27. #define PRINT_ALL_CASES (0)
  28. /* 5^5 alignment combinations * 2 places to share pages * 5! free sequences */
  29. #define TOTAL_EXHAUSTIVE_CASES (3125 * 2 * 120)
  30. /**
  31. * enum buf_end_align_type - Page alignment of a buffer
  32. * end with regard to the end of the previous buffer.
  33. *
  34. * In the pictures below, buf2 refers to the buffer we
  35. * are aligning. buf1 refers to previous buffer by addr.
  36. * Symbol [ means the start of a buffer, ] means the end
  37. * of a buffer, and | means page boundaries.
  38. */
  39. enum buf_end_align_type {
  40. /**
  41. * @SAME_PAGE_UNALIGNED: The end of this buffer is on
  42. * the same page as the end of the previous buffer and
  43. * is not page aligned. Examples:
  44. * buf1 ][ buf2 ][ ...
  45. * buf1 ]|[ buf2 ][ ...
  46. */
  47. SAME_PAGE_UNALIGNED = 0,
  48. /**
  49. * @SAME_PAGE_ALIGNED: When the end of the previous buffer
  50. * is not page aligned, the end of this buffer is on the
  51. * same page as the end of the previous buffer and is page
  52. * aligned. When the previous buffer is page aligned, the
  53. * end of this buffer is aligned to the next page boundary.
  54. * Examples:
  55. * buf1 ][ buf2 ]| ...
  56. * buf1 ]|[ buf2 ]| ...
  57. */
  58. SAME_PAGE_ALIGNED,
  59. /**
  60. * @NEXT_PAGE_UNALIGNED: The end of this buffer is on
  61. * the page next to the end of the previous buffer and
  62. * is not page aligned. Examples:
  63. * buf1 ][ buf2 | buf2 ][ ...
  64. * buf1 ]|[ buf2 | buf2 ][ ...
  65. */
  66. NEXT_PAGE_UNALIGNED,
  67. /**
  68. * @NEXT_PAGE_ALIGNED: The end of this buffer is on
  69. * the page next to the end of the previous buffer and
  70. * is page aligned. Examples:
  71. * buf1 ][ buf2 | buf2 ]| ...
  72. * buf1 ]|[ buf2 | buf2 ]| ...
  73. */
  74. NEXT_PAGE_ALIGNED,
  75. /**
  76. * @NEXT_NEXT_UNALIGNED: The end of this buffer is on
  77. * the page that follows the page after the end of the
  78. * previous buffer and is not page aligned. Examples:
  79. * buf1 ][ buf2 | buf2 | buf2 ][ ...
  80. * buf1 ]|[ buf2 | buf2 | buf2 ][ ...
  81. */
  82. NEXT_NEXT_UNALIGNED,
  83. /**
  84. * @LOOP_END: The number of enum values in &buf_end_align_type.
  85. * It is used for controlling loop termination.
  86. */
  87. LOOP_END,
  88. };
  89. static const char *const buf_end_align_type_strs[LOOP_END] = {
  90. [SAME_PAGE_UNALIGNED] = "SP_UNALIGNED",
  91. [SAME_PAGE_ALIGNED] = " SP_ALIGNED ",
  92. [NEXT_PAGE_UNALIGNED] = "NP_UNALIGNED",
  93. [NEXT_PAGE_ALIGNED] = " NP_ALIGNED ",
  94. [NEXT_NEXT_UNALIGNED] = "NN_UNALIGNED",
  95. };
  96. struct binder_alloc_test_case_info {
  97. char alignments[ALIGNMENTS_BUFLEN];
  98. struct seq_buf alignments_sb;
  99. size_t *buffer_sizes;
  100. int *free_sequence;
  101. bool front_pages;
  102. };
  103. static void stringify_free_seq(struct kunit *test, int *seq, struct seq_buf *sb)
  104. {
  105. int i;
  106. for (i = 0; i < BUFFER_NUM; i++)
  107. seq_buf_printf(sb, "[%d]", seq[i]);
  108. KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(sb));
  109. }
  110. static void stringify_alignments(struct kunit *test, int *alignments,
  111. struct seq_buf *sb)
  112. {
  113. int i;
  114. for (i = 0; i < BUFFER_NUM; i++)
  115. seq_buf_printf(sb, "[ %d:%s ]", i,
  116. buf_end_align_type_strs[alignments[i]]);
  117. KUNIT_EXPECT_FALSE(test, seq_buf_has_overflowed(sb));
  118. }
  119. static bool check_buffer_pages_allocated(struct kunit *test,
  120. struct binder_alloc *alloc,
  121. struct binder_buffer *buffer,
  122. size_t size)
  123. {
  124. unsigned long page_addr;
  125. unsigned long end;
  126. int page_index;
  127. end = PAGE_ALIGN(buffer->user_data + size);
  128. page_addr = buffer->user_data;
  129. for (; page_addr < end; page_addr += PAGE_SIZE) {
  130. page_index = (page_addr - alloc->vm_start) / PAGE_SIZE;
  131. if (!alloc->pages[page_index] ||
  132. !list_empty(page_to_lru(alloc->pages[page_index]))) {
  133. kunit_err(test, "expect alloc but is %s at page index %d\n",
  134. alloc->pages[page_index] ?
  135. "lru" : "free", page_index);
  136. return false;
  137. }
  138. }
  139. return true;
  140. }
  141. static unsigned long binder_alloc_test_alloc_buf(struct kunit *test,
  142. struct binder_alloc *alloc,
  143. struct binder_buffer *buffers[],
  144. size_t *sizes, int *seq)
  145. {
  146. unsigned long failures = 0;
  147. int i;
  148. for (i = 0; i < BUFFER_NUM; i++) {
  149. buffers[i] = binder_alloc_new_buf(alloc, sizes[i], 0, 0, 0);
  150. if (IS_ERR(buffers[i]) ||
  151. !check_buffer_pages_allocated(test, alloc, buffers[i], sizes[i]))
  152. failures++;
  153. }
  154. return failures;
  155. }
  156. static unsigned long binder_alloc_test_free_buf(struct kunit *test,
  157. struct binder_alloc *alloc,
  158. struct binder_buffer *buffers[],
  159. size_t *sizes, int *seq, size_t end)
  160. {
  161. unsigned long failures = 0;
  162. int i;
  163. for (i = 0; i < BUFFER_NUM; i++)
  164. binder_alloc_free_buf(alloc, buffers[seq[i]]);
  165. for (i = 0; i <= (end - 1) / PAGE_SIZE; i++) {
  166. if (list_empty(page_to_lru(alloc->pages[i]))) {
  167. kunit_err(test, "expect lru but is %s at page index %d\n",
  168. alloc->pages[i] ? "alloc" : "free", i);
  169. failures++;
  170. }
  171. }
  172. return failures;
  173. }
  174. static unsigned long binder_alloc_test_free_page(struct kunit *test,
  175. struct binder_alloc *alloc)
  176. {
  177. unsigned long failures = 0;
  178. unsigned long count;
  179. int i;
  180. while ((count = list_lru_count(alloc->freelist))) {
  181. list_lru_walk(alloc->freelist, binder_alloc_free_page,
  182. NULL, count);
  183. }
  184. for (i = 0; i < (alloc->buffer_size / PAGE_SIZE); i++) {
  185. if (alloc->pages[i]) {
  186. kunit_err(test, "expect free but is %s at page index %d\n",
  187. list_empty(page_to_lru(alloc->pages[i])) ?
  188. "alloc" : "lru", i);
  189. failures++;
  190. }
  191. }
  192. return failures;
  193. }
  194. /* Executes one full test run for the given test case. */
  195. static bool binder_alloc_test_alloc_free(struct kunit *test,
  196. struct binder_alloc *alloc,
  197. struct binder_alloc_test_case_info *tc,
  198. size_t end)
  199. {
  200. unsigned long pages = PAGE_ALIGN(end) / PAGE_SIZE;
  201. struct binder_buffer *buffers[BUFFER_NUM];
  202. unsigned long failures;
  203. bool failed = false;
  204. failures = binder_alloc_test_alloc_buf(test, alloc, buffers,
  205. tc->buffer_sizes,
  206. tc->free_sequence);
  207. failed = failed || failures;
  208. KUNIT_EXPECT_EQ_MSG(test, failures, 0,
  209. "Initial allocation failed: %lu/%u buffers with errors",
  210. failures, BUFFER_NUM);
  211. failures = binder_alloc_test_free_buf(test, alloc, buffers,
  212. tc->buffer_sizes,
  213. tc->free_sequence, end);
  214. failed = failed || failures;
  215. KUNIT_EXPECT_EQ_MSG(test, failures, 0,
  216. "Initial buffers not freed correctly: %lu/%lu pages not on lru list",
  217. failures, pages);
  218. /* Allocate from lru. */
  219. failures = binder_alloc_test_alloc_buf(test, alloc, buffers,
  220. tc->buffer_sizes,
  221. tc->free_sequence);
  222. failed = failed || failures;
  223. KUNIT_EXPECT_EQ_MSG(test, failures, 0,
  224. "Reallocation failed: %lu/%u buffers with errors",
  225. failures, BUFFER_NUM);
  226. failures = list_lru_count(alloc->freelist);
  227. failed = failed || failures;
  228. KUNIT_EXPECT_EQ_MSG(test, failures, 0,
  229. "lru list should be empty after reallocation but still has %lu pages",
  230. failures);
  231. failures = binder_alloc_test_free_buf(test, alloc, buffers,
  232. tc->buffer_sizes,
  233. tc->free_sequence, end);
  234. failed = failed || failures;
  235. KUNIT_EXPECT_EQ_MSG(test, failures, 0,
  236. "Reallocated buffers not freed correctly: %lu/%lu pages not on lru list",
  237. failures, pages);
  238. failures = binder_alloc_test_free_page(test, alloc);
  239. failed = failed || failures;
  240. KUNIT_EXPECT_EQ_MSG(test, failures, 0,
  241. "Failed to clean up allocated pages: %lu/%lu pages still installed",
  242. failures, (alloc->buffer_size / PAGE_SIZE));
  243. return failed;
  244. }
  245. static bool is_dup(int *seq, int index, int val)
  246. {
  247. int i;
  248. for (i = 0; i < index; i++) {
  249. if (seq[i] == val)
  250. return true;
  251. }
  252. return false;
  253. }
  254. /* Generate BUFFER_NUM factorial free orders. */
  255. static void permute_frees(struct kunit *test, struct binder_alloc *alloc,
  256. struct binder_alloc_test_case_info *tc,
  257. unsigned long *runs, unsigned long *failures,
  258. int index, size_t end)
  259. {
  260. bool case_failed;
  261. int i;
  262. if (index == BUFFER_NUM) {
  263. DECLARE_SEQ_BUF(freeseq_sb, FREESEQ_BUFLEN);
  264. case_failed = binder_alloc_test_alloc_free(test, alloc, tc, end);
  265. *runs += 1;
  266. *failures += case_failed;
  267. if (case_failed || PRINT_ALL_CASES) {
  268. stringify_free_seq(test, tc->free_sequence,
  269. &freeseq_sb);
  270. kunit_err(test, "case %lu: [%s] | %s - %s - %s", *runs,
  271. case_failed ? "FAILED" : "PASSED",
  272. tc->front_pages ? "front" : "back ",
  273. seq_buf_str(&tc->alignments_sb),
  274. seq_buf_str(&freeseq_sb));
  275. }
  276. return;
  277. }
  278. for (i = 0; i < BUFFER_NUM; i++) {
  279. if (is_dup(tc->free_sequence, index, i))
  280. continue;
  281. tc->free_sequence[index] = i;
  282. permute_frees(test, alloc, tc, runs, failures, index + 1, end);
  283. }
  284. }
  285. static void gen_buf_sizes(struct kunit *test,
  286. struct binder_alloc *alloc,
  287. struct binder_alloc_test_case_info *tc,
  288. size_t *end_offset, unsigned long *runs,
  289. unsigned long *failures)
  290. {
  291. size_t last_offset, offset = 0;
  292. size_t front_sizes[BUFFER_NUM];
  293. size_t back_sizes[BUFFER_NUM];
  294. int seq[BUFFER_NUM] = {0};
  295. int i;
  296. tc->free_sequence = seq;
  297. for (i = 0; i < BUFFER_NUM; i++) {
  298. last_offset = offset;
  299. offset = end_offset[i];
  300. front_sizes[i] = offset - last_offset;
  301. back_sizes[BUFFER_NUM - i - 1] = front_sizes[i];
  302. }
  303. back_sizes[0] += alloc->buffer_size - end_offset[BUFFER_NUM - 1];
  304. /*
  305. * Buffers share the first or last few pages.
  306. * Only BUFFER_NUM - 1 buffer sizes are adjustable since
  307. * we need one giant buffer before getting to the last page.
  308. */
  309. tc->front_pages = true;
  310. tc->buffer_sizes = front_sizes;
  311. permute_frees(test, alloc, tc, runs, failures, 0,
  312. end_offset[BUFFER_NUM - 1]);
  313. tc->front_pages = false;
  314. tc->buffer_sizes = back_sizes;
  315. permute_frees(test, alloc, tc, runs, failures, 0, alloc->buffer_size);
  316. }
  317. static void gen_buf_offsets(struct kunit *test, struct binder_alloc *alloc,
  318. size_t *end_offset, int *alignments,
  319. unsigned long *runs, unsigned long *failures,
  320. int index)
  321. {
  322. size_t end, prev;
  323. int align;
  324. if (index == BUFFER_NUM) {
  325. struct binder_alloc_test_case_info tc = {0};
  326. seq_buf_init(&tc.alignments_sb, tc.alignments,
  327. ALIGNMENTS_BUFLEN);
  328. stringify_alignments(test, alignments, &tc.alignments_sb);
  329. gen_buf_sizes(test, alloc, &tc, end_offset, runs, failures);
  330. return;
  331. }
  332. prev = index == 0 ? 0 : end_offset[index - 1];
  333. end = prev;
  334. BUILD_BUG_ON(BUFFER_MIN_SIZE * BUFFER_NUM >= PAGE_SIZE);
  335. for (align = SAME_PAGE_UNALIGNED; align < LOOP_END; align++) {
  336. if (align % 2)
  337. end = ALIGN(end, PAGE_SIZE);
  338. else
  339. end += BUFFER_MIN_SIZE;
  340. end_offset[index] = end;
  341. alignments[index] = align;
  342. gen_buf_offsets(test, alloc, end_offset, alignments, runs,
  343. failures, index + 1);
  344. }
  345. }
  346. struct binder_alloc_test {
  347. struct binder_alloc alloc;
  348. struct list_lru binder_test_freelist;
  349. struct file *filp;
  350. unsigned long mmap_uaddr;
  351. };
  352. static void binder_alloc_test_init_freelist(struct kunit *test)
  353. {
  354. struct binder_alloc_test *priv = test->priv;
  355. KUNIT_EXPECT_PTR_EQ(test, priv->alloc.freelist,
  356. &priv->binder_test_freelist);
  357. }
  358. static void binder_alloc_test_mmap(struct kunit *test)
  359. {
  360. struct binder_alloc_test *priv = test->priv;
  361. struct binder_alloc *alloc = &priv->alloc;
  362. struct binder_buffer *buf;
  363. struct rb_node *n;
  364. KUNIT_EXPECT_EQ(test, alloc->mapped, true);
  365. KUNIT_EXPECT_EQ(test, alloc->buffer_size, BINDER_MMAP_SIZE);
  366. n = rb_first(&alloc->allocated_buffers);
  367. KUNIT_EXPECT_PTR_EQ(test, n, NULL);
  368. n = rb_first(&alloc->free_buffers);
  369. buf = rb_entry(n, struct binder_buffer, rb_node);
  370. KUNIT_EXPECT_EQ(test, binder_alloc_buffer_size(alloc, buf),
  371. BINDER_MMAP_SIZE);
  372. KUNIT_EXPECT_TRUE(test, list_is_last(&buf->entry, &alloc->buffers));
  373. }
  374. /**
  375. * binder_alloc_exhaustive_test() - Exhaustively test alloc and free of buffer pages.
  376. * @test: The test context object.
  377. *
  378. * Allocate BUFFER_NUM buffers to cover all page alignment cases,
  379. * then free them in all orders possible. Check that pages are
  380. * correctly allocated, put onto lru when buffers are freed, and
  381. * are freed when binder_alloc_free_page() is called.
  382. */
  383. static void binder_alloc_exhaustive_test(struct kunit *test)
  384. {
  385. struct binder_alloc_test *priv = test->priv;
  386. size_t end_offset[BUFFER_NUM];
  387. int alignments[BUFFER_NUM];
  388. unsigned long failures = 0;
  389. unsigned long runs = 0;
  390. gen_buf_offsets(test, &priv->alloc, end_offset, alignments, &runs,
  391. &failures, 0);
  392. KUNIT_EXPECT_EQ(test, runs, TOTAL_EXHAUSTIVE_CASES);
  393. KUNIT_EXPECT_EQ(test, failures, 0);
  394. }
  395. /* ===== End test cases ===== */
  396. static void binder_alloc_test_vma_close(struct vm_area_struct *vma)
  397. {
  398. struct binder_alloc *alloc = vma->vm_private_data;
  399. binder_alloc_vma_close(alloc);
  400. }
  401. static const struct vm_operations_struct binder_alloc_test_vm_ops = {
  402. .close = binder_alloc_test_vma_close,
  403. .fault = binder_vm_fault,
  404. };
  405. static int binder_alloc_test_mmap_handler(struct file *filp,
  406. struct vm_area_struct *vma)
  407. {
  408. struct binder_alloc *alloc = filp->private_data;
  409. vm_flags_mod(vma, VM_DONTCOPY | VM_MIXEDMAP, VM_MAYWRITE);
  410. vma->vm_ops = &binder_alloc_test_vm_ops;
  411. vma->vm_private_data = alloc;
  412. return binder_alloc_mmap_handler(alloc, vma);
  413. }
  414. static const struct file_operations binder_alloc_test_fops = {
  415. .mmap = binder_alloc_test_mmap_handler,
  416. };
  417. static int binder_alloc_test_init(struct kunit *test)
  418. {
  419. struct binder_alloc_test *priv;
  420. int ret;
  421. priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
  422. if (!priv)
  423. return -ENOMEM;
  424. test->priv = priv;
  425. ret = list_lru_init(&priv->binder_test_freelist);
  426. if (ret) {
  427. kunit_err(test, "Failed to initialize test freelist\n");
  428. return ret;
  429. }
  430. /* __binder_alloc_init requires mm to be attached */
  431. ret = kunit_attach_mm();
  432. if (ret) {
  433. kunit_err(test, "Failed to attach mm\n");
  434. return ret;
  435. }
  436. __binder_alloc_init(&priv->alloc, &priv->binder_test_freelist);
  437. priv->filp = anon_inode_getfile("binder_alloc_kunit",
  438. &binder_alloc_test_fops, &priv->alloc,
  439. O_RDWR | O_CLOEXEC);
  440. if (IS_ERR_OR_NULL(priv->filp)) {
  441. kunit_err(test, "Failed to open binder alloc test driver file\n");
  442. return priv->filp ? PTR_ERR(priv->filp) : -ENOMEM;
  443. }
  444. priv->mmap_uaddr = kunit_vm_mmap(test, priv->filp, 0, BINDER_MMAP_SIZE,
  445. PROT_READ, MAP_PRIVATE | MAP_NORESERVE,
  446. 0);
  447. if (!priv->mmap_uaddr) {
  448. kunit_err(test, "Could not map the test's transaction memory\n");
  449. return -ENOMEM;
  450. }
  451. return 0;
  452. }
  453. static void binder_alloc_test_exit(struct kunit *test)
  454. {
  455. struct binder_alloc_test *priv = test->priv;
  456. /* Close the backing file to make sure binder_alloc_vma_close runs */
  457. if (!IS_ERR_OR_NULL(priv->filp))
  458. fput(priv->filp);
  459. if (priv->alloc.mm)
  460. binder_alloc_deferred_release(&priv->alloc);
  461. /* Make sure freelist is empty */
  462. KUNIT_EXPECT_EQ(test, list_lru_count(&priv->binder_test_freelist), 0);
  463. list_lru_destroy(&priv->binder_test_freelist);
  464. }
  465. static struct kunit_case binder_alloc_test_cases[] = {
  466. KUNIT_CASE(binder_alloc_test_init_freelist),
  467. KUNIT_CASE(binder_alloc_test_mmap),
  468. KUNIT_CASE_SLOW(binder_alloc_exhaustive_test),
  469. {}
  470. };
  471. static struct kunit_suite binder_alloc_test_suite = {
  472. .name = "binder_alloc",
  473. .test_cases = binder_alloc_test_cases,
  474. .init = binder_alloc_test_init,
  475. .exit = binder_alloc_test_exit,
  476. };
  477. kunit_test_suite(binder_alloc_test_suite);
  478. MODULE_AUTHOR("Tiffany Yang <ynaffit@google.com>");
  479. MODULE_DESCRIPTION("Binder Alloc KUnit tests");
  480. MODULE_LICENSE("GPL");