1#include "mem/tests/test_internal.h"
2
3TEST_GROUP_DECLARE(folio, .intensity_desc = {
4 .curve = SCALE_PIECEWISE_LOG,
5 .unit = "iters",
6 });
7
8TEST_DECLARE_UNIT(folio, backpointers) {
9 for (uint8_t order = 0; order <= 3; order++) {
10 struct folio *f = folio_alloc(order);
11 TEST_ASSERT_NONNULL(f);
12 TEST_ASSERT_EQ(f->order, order);
13 TEST_ASSERT_EQ(folio_nr_pages(f), (1ul << order));
14 TEST_ASSERT(!folio_mapped(f));
15 TEST_ASSERT_EQ(atomic_load(&f->mapcount), 0);
16
17 for (size_t n = 0; n < folio_nr_pages(f); n++) {
18 struct page *p = folio_get_page(f, n);
19 TEST_ASSERT_PTR_EQ(folio_from_paddr(folio_get_paddr_for(f, n)), f);
20 TEST_ASSERT_PTR_EQ(folio_from_page(p), f);
21 TEST_ASSERT_EQ(page_get_folio_index(p), n);
22 TEST_ASSERT_EQ(page_is_folio_head(p), (n == 0));
23 }
24 }
25 return TEST_SUCCESS;
26}
27
28TEST_DECLARE_UNIT(folio, zero_copy, TEST_INTENSITY(16, 128, 1024)) {
29 size_t iters = ctx->intensity_val ? ctx->intensity_val : 128;
30 for (size_t iter = 0; iter < iters; iter++) {
31 struct folio *src = folio_alloc(1); /* 2 pages */
32 struct folio *dst = folio_alloc(1);
33 TEST_ASSERT_NONNULL(src);
34 TEST_ASSERT_NONNULL(dst);
35
36 for (size_t n = 0; n < folio_nr_pages(f: src); n++) {
37 uint8_t *s = (uint8_t *) folio_get_vaddr_for(f: src, n);
38 uint8_t *d = (uint8_t *) folio_get_vaddr_for(f: dst, n);
39 for (size_t b = 0; b < PAGE_SIZE; b++) {
40 s[b] = (uint8_t) (b + n * 7 + 1);
41 d[b] = 0xAB;
42 }
43 }
44
45 folio_zero(f: src);
46 for (size_t n = 0; n < folio_nr_pages(f: src); n++) {
47 uint8_t *s = (uint8_t *) folio_get_vaddr_for(f: src, n);
48 for (size_t b = 0; b < PAGE_SIZE; b++)
49 TEST_ASSERT_EQ(s[b], 0);
50 }
51
52 for (size_t n = 0; n < folio_nr_pages(f: src); n++) {
53 uint8_t *s = (uint8_t *) folio_get_vaddr_for(f: src, n);
54 for (size_t b = 0; b < PAGE_SIZE; b++)
55 s[b] = (uint8_t) (b * 3 + n + 5);
56 }
57 folio_copy(src, dst);
58 for (size_t n = 0; n < folio_nr_pages(f: dst); n++) {
59 uint8_t *s = (uint8_t *) folio_get_vaddr_for(f: src, n);
60 uint8_t *d = (uint8_t *) folio_get_vaddr_for(f: dst, n);
61 TEST_ASSERT_MEM_EQ(s, d, PAGE_SIZE);
62 }
63 }
64
65 return TEST_SUCCESS;
66}
67
68TEST_DECLARE_UNIT(folio, anon_tag_mapcount) {
69 struct folio *f = folio_alloc(0);
70 TEST_ASSERT_NONNULL(f);
71
72 TEST_ASSERT(!folio_is_anon(f));
73
74 struct anon_vma *av = anon_vma_alloc();
75 TEST_ASSERT_NONNULL(av);
76
77 folio_set_anon(f, av, index: 0xDEAD);
78 TEST_ASSERT(folio_is_anon(f));
79 TEST_ASSERT_PTR_EQ(folio_get_anon_vma(f), av);
80 TEST_ASSERT_EQ(((uintptr_t) f->mapping & ~FOLIO_TAG_BITS), (uintptr_t) av);
81 TEST_ASSERT_EQ(f->index, 0xDEAD);
82
83 TEST_ASSERT(!folio_mapped(f));
84 folio_mapcount_inc(f);
85 TEST_ASSERT(folio_mapped(f) && atomic_load(&f->mapcount) == 1);
86 folio_mapcount_inc(f);
87 TEST_ASSERT_EQ(atomic_load(&f->mapcount), 2);
88 TEST_ASSERT_EQ(folio_mapcount_dec(f), false);
89 TEST_ASSERT_EQ(folio_mapcount_dec(f), true);
90 TEST_ASSERT(!folio_mapped(f));
91
92 return TEST_SUCCESS;
93}
94