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