1*a325d9c4SApple OSS Distributions #include <darwintest.h>
2*a325d9c4SApple OSS Distributions #include <darwintest_utils.h>
3*a325d9c4SApple OSS Distributions
4*a325d9c4SApple OSS Distributions #include <mach/mach.h>
5*a325d9c4SApple OSS Distributions #include <sys/mman.h>
6*a325d9c4SApple OSS Distributions
7*a325d9c4SApple OSS Distributions #undef __abortlike
8*a325d9c4SApple OSS Distributions #define __abortlike
9*a325d9c4SApple OSS Distributions #define panic(fmt, ...) ({ T_FAIL(fmt, __VA_ARGS__); abort(); })
10*a325d9c4SApple OSS Distributions
11*a325d9c4SApple OSS Distributions #define __security_const_late
12*a325d9c4SApple OSS Distributions #define ZALLOC_TEST 1
13*a325d9c4SApple OSS Distributions #include "../osfmk/kern/zalloc.c"
14*a325d9c4SApple OSS Distributions
15*a325d9c4SApple OSS Distributions #define ZBA_TEST_SIZE (1ul << 20)
16*a325d9c4SApple OSS Distributions
17*a325d9c4SApple OSS Distributions static void
zba_populate_any(vm_address_t addr,vm_size_t size)18*a325d9c4SApple OSS Distributions zba_populate_any(vm_address_t addr, vm_size_t size)
19*a325d9c4SApple OSS Distributions {
20*a325d9c4SApple OSS Distributions int rc = mprotect((void *)addr, size, PROT_READ | PROT_WRITE);
21*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, "mprotect");
22*a325d9c4SApple OSS Distributions }
23*a325d9c4SApple OSS Distributions
24*a325d9c4SApple OSS Distributions static void
zba_populate_nope(vm_address_t addr,vm_size_t size)25*a325d9c4SApple OSS Distributions zba_populate_nope(vm_address_t addr, vm_size_t size)
26*a325d9c4SApple OSS Distributions {
27*a325d9c4SApple OSS Distributions #pragma unused(addr, size)
28*a325d9c4SApple OSS Distributions T_FAIL("Trying to extend the storage");
29*a325d9c4SApple OSS Distributions T_END;
30*a325d9c4SApple OSS Distributions }
31*a325d9c4SApple OSS Distributions
32*a325d9c4SApple OSS Distributions static void
zba_test_allow_extension(void)33*a325d9c4SApple OSS Distributions zba_test_allow_extension(void)
34*a325d9c4SApple OSS Distributions {
35*a325d9c4SApple OSS Distributions zba_test_info.zbats_populate = zba_populate_any;
36*a325d9c4SApple OSS Distributions }
37*a325d9c4SApple OSS Distributions
38*a325d9c4SApple OSS Distributions static void
zba_test_disallow_extension(void)39*a325d9c4SApple OSS Distributions zba_test_disallow_extension(void)
40*a325d9c4SApple OSS Distributions {
41*a325d9c4SApple OSS Distributions zba_test_info.zbats_populate = zba_populate_nope;
42*a325d9c4SApple OSS Distributions }
43*a325d9c4SApple OSS Distributions
44*a325d9c4SApple OSS Distributions static void
zba_test_setup(void)45*a325d9c4SApple OSS Distributions zba_test_setup(void)
46*a325d9c4SApple OSS Distributions {
47*a325d9c4SApple OSS Distributions kern_return_t kr;
48*a325d9c4SApple OSS Distributions int rc;
49*a325d9c4SApple OSS Distributions
50*a325d9c4SApple OSS Distributions kr = vm_allocate(mach_task_self(), &zba_test_info.zbats_base,
51*a325d9c4SApple OSS Distributions ZBA_TEST_SIZE + ZBA_CHUNK_SIZE, VM_FLAGS_ANYWHERE);
52*a325d9c4SApple OSS Distributions T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
53*a325d9c4SApple OSS Distributions
54*a325d9c4SApple OSS Distributions zba_test_info.zbats_base = roundup(zba_test_info.zbats_base,
55*a325d9c4SApple OSS Distributions ZBA_CHUNK_SIZE);
56*a325d9c4SApple OSS Distributions
57*a325d9c4SApple OSS Distributions rc = mprotect(zba_base_header(), ZBA_TEST_SIZE, PROT_NONE);
58*a325d9c4SApple OSS Distributions T_ASSERT_POSIX_SUCCESS(rc, "mprotect");
59*a325d9c4SApple OSS Distributions
60*a325d9c4SApple OSS Distributions T_LOG("SETUP allocator with base at %p", zba_base_header());
61*a325d9c4SApple OSS Distributions
62*a325d9c4SApple OSS Distributions zba_test_allow_extension();
63*a325d9c4SApple OSS Distributions zba_populate(0);
64*a325d9c4SApple OSS Distributions zba_init_chunk(0);
65*a325d9c4SApple OSS Distributions }
66*a325d9c4SApple OSS Distributions
67*a325d9c4SApple OSS Distributions T_DECL(zone_buddy_allocator_encodings, "test the buddy allocator formulas")
68*a325d9c4SApple OSS Distributions {
69*a325d9c4SApple OSS Distributions uint8_t bits[sizeof(zba_base_header()->zbah_bits)] = { };
70*a325d9c4SApple OSS Distributions
71*a325d9c4SApple OSS Distributions for (uint32_t o = ZBA_MAX_ORDER + 1; o-- > 0;) {
72*a325d9c4SApple OSS Distributions for (vm_address_t pos = 0; pos < ZBA_CHUNK_SIZE; pos += ZBA_GRANULE << o) {
73*a325d9c4SApple OSS Distributions struct zone_bits_chain *zbc;
74*a325d9c4SApple OSS Distributions size_t node = zba_node(pos, o);
75*a325d9c4SApple OSS Distributions
76*a325d9c4SApple OSS Distributions zbc = zba_chain_for_node(NULL, node, o);
77*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_EQ(pos, (vm_offset_t)zbc,
78*a325d9c4SApple OSS Distributions "zba_node / zba_chain_for_node is reversible (pos: %lx, node %zd)",
79*a325d9c4SApple OSS Distributions pos, node);
80*a325d9c4SApple OSS Distributions
81*a325d9c4SApple OSS Distributions
82*a325d9c4SApple OSS Distributions if (o == 0) {
83*a325d9c4SApple OSS Distributions // leaf nodes aren't represented in the bitmap
84*a325d9c4SApple OSS Distributions continue;
85*a325d9c4SApple OSS Distributions }
86*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_LT(node, 8 * sizeof(bits), "fits in bitfield: %zd", pos);
87*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_EQ(0, bits[node / 8] & (1 << (node % 8)), "never seen");
88*a325d9c4SApple OSS Distributions bits[node / 8] ^= 1 << (node % 8);
89*a325d9c4SApple OSS Distributions }
90*a325d9c4SApple OSS Distributions }
91*a325d9c4SApple OSS Distributions
92*a325d9c4SApple OSS Distributions T_PASS("zba_node, zba_chain_for_node look sane");
93*a325d9c4SApple OSS Distributions }
94*a325d9c4SApple OSS Distributions
95*a325d9c4SApple OSS Distributions T_DECL(zone_buddy_allocator, "test the zone bits setup")
96*a325d9c4SApple OSS Distributions {
97*a325d9c4SApple OSS Distributions vm_address_t base, pos;
98*a325d9c4SApple OSS Distributions
99*a325d9c4SApple OSS Distributions zba_test_setup();
100*a325d9c4SApple OSS Distributions
101*a325d9c4SApple OSS Distributions zba_test_disallow_extension();
102*a325d9c4SApple OSS Distributions
103*a325d9c4SApple OSS Distributions base = (vm_address_t)zba_slot_base();
104*a325d9c4SApple OSS Distributions for (pos = zba_chunk_header_size(0); pos < ZBA_CHUNK_SIZE; pos += ZBA_GRANULE) {
105*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_EQ(base + pos, zba_alloc(0), "alloc");
106*a325d9c4SApple OSS Distributions *(uint64_t *)(base + pos) = ~0ull;
107*a325d9c4SApple OSS Distributions }
108*a325d9c4SApple OSS Distributions for (pos = zba_chunk_header_size(0); pos < ZBA_CHUNK_SIZE; pos += ZBA_GRANULE) {
109*a325d9c4SApple OSS Distributions zba_free(base + pos, 0);
110*a325d9c4SApple OSS Distributions }
111*a325d9c4SApple OSS Distributions
112*a325d9c4SApple OSS Distributions for (pos = zba_chunk_header_size(0); pos < ZBA_CHUNK_SIZE; pos += ZBA_GRANULE) {
113*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_EQ(base + pos, zba_alloc(0), "alloc");
114*a325d9c4SApple OSS Distributions *(uint64_t *)(base + pos) = ~0ull;
115*a325d9c4SApple OSS Distributions }
116*a325d9c4SApple OSS Distributions zba_test_allow_extension();
117*a325d9c4SApple OSS Distributions
118*a325d9c4SApple OSS Distributions base += ZBA_CHUNK_SIZE;
119*a325d9c4SApple OSS Distributions for (pos = zba_chunk_header_size(1); pos < ZBA_CHUNK_SIZE; pos += ZBA_GRANULE) {
120*a325d9c4SApple OSS Distributions T_QUIET; T_ASSERT_EQ(base + pos, zba_alloc(0), "alloc");
121*a325d9c4SApple OSS Distributions *(uint64_t *)(base + pos) = ~0ull;
122*a325d9c4SApple OSS Distributions }
123*a325d9c4SApple OSS Distributions
124*a325d9c4SApple OSS Distributions for (pos = zba_chunk_header_size(1); pos < ZBA_CHUNK_SIZE; pos += ZBA_GRANULE) {
125*a325d9c4SApple OSS Distributions zba_free(base + pos, 0);
126*a325d9c4SApple OSS Distributions }
127*a325d9c4SApple OSS Distributions base -= ZBA_CHUNK_SIZE;
128*a325d9c4SApple OSS Distributions for (pos = zba_chunk_header_size(0); pos < ZBA_CHUNK_SIZE; pos += ZBA_GRANULE) {
129*a325d9c4SApple OSS Distributions zba_free(base + pos, 0);
130*a325d9c4SApple OSS Distributions }
131*a325d9c4SApple OSS Distributions }
132