1*33de042dSApple OSS Distributions #include <darwintest.h>
2*33de042dSApple OSS Distributions #include <darwintest_utils.h>
3*33de042dSApple OSS Distributions
4*33de042dSApple OSS Distributions #include <mach/mach_error.h>
5*33de042dSApple OSS Distributions #include <mach/mach_init.h>
6*33de042dSApple OSS Distributions #include <mach/memory_entry.h>
7*33de042dSApple OSS Distributions #include <mach/mach_port.h>
8*33de042dSApple OSS Distributions #include <mach/mach_vm.h>
9*33de042dSApple OSS Distributions #include <mach/memory_entry.h>
10*33de042dSApple OSS Distributions #include <mach/task.h>
11*33de042dSApple OSS Distributions #include <mach/task_info.h>
12*33de042dSApple OSS Distributions #include <mach/vm_map.h>
13*33de042dSApple OSS Distributions
14*33de042dSApple OSS Distributions #include <sys/kern_memorystatus.h>
15*33de042dSApple OSS Distributions #include <sys/mman.h>
16*33de042dSApple OSS Distributions #include <sys/types.h>
17*33de042dSApple OSS Distributions #include <sys/sysctl.h>
18*33de042dSApple OSS Distributions
19*33de042dSApple OSS Distributions #include <TargetConditionals.h>
20*33de042dSApple OSS Distributions
21*33de042dSApple OSS Distributions #include <Kernel/kern/ledger.h>
22*33de042dSApple OSS Distributions extern int ledger(int cmd, caddr_t arg1, caddr_t arg2, caddr_t arg3);
23*33de042dSApple OSS Distributions
24*33de042dSApple OSS Distributions T_GLOBAL_META(T_META_RUN_CONCURRENTLY(true));
25*33de042dSApple OSS Distributions static boolean_t legacy_footprint = FALSE;
26*33de042dSApple OSS Distributions
27*33de042dSApple OSS Distributions #if LEGACY_FOOTPRINT_ENTITLED && defined(__arm64__)
28*33de042dSApple OSS Distributions #define TEST_VM_NAMESPACE "xnu.vm_legacy"
29*33de042dSApple OSS Distributions #else /* ENTITLED && __arm64__ */
30*33de042dSApple OSS Distributions #define TEST_VM_NAMESPACE "xnu.vm"
31*33de042dSApple OSS Distributions #endif /* ENTITLED && __arm64__ */
32*33de042dSApple OSS Distributions
33*33de042dSApple OSS Distributions T_GLOBAL_META(
34*33de042dSApple OSS Distributions T_META_NAMESPACE(TEST_VM_NAMESPACE),
35*33de042dSApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
36*33de042dSApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("VM"),
37*33de042dSApple OSS Distributions T_META_RUN_CONCURRENTLY(true));
38*33de042dSApple OSS Distributions
39*33de042dSApple OSS Distributions #define MEM_SIZE (100 * 1024 * 1024) /* 100 MB */
40*33de042dSApple OSS Distributions
41*33de042dSApple OSS Distributions static int64_t ledger_count = -1;
42*33de042dSApple OSS Distributions static int footprint_index = -1;
43*33de042dSApple OSS Distributions static int pagetable_index = -1;
44*33de042dSApple OSS Distributions static struct ledger_entry_info *lei = NULL;
45*33de042dSApple OSS Distributions
46*33de042dSApple OSS Distributions static void
ledger_init(void)47*33de042dSApple OSS Distributions ledger_init(void)
48*33de042dSApple OSS Distributions {
49*33de042dSApple OSS Distributions static int ledger_inited = 0;
50*33de042dSApple OSS Distributions struct ledger_info li;
51*33de042dSApple OSS Distributions struct ledger_template_info *templateInfo;
52*33de042dSApple OSS Distributions int64_t templateCnt;
53*33de042dSApple OSS Distributions int i;
54*33de042dSApple OSS Distributions
55*33de042dSApple OSS Distributions if (ledger_inited) {
56*33de042dSApple OSS Distributions return;
57*33de042dSApple OSS Distributions }
58*33de042dSApple OSS Distributions ledger_inited = 1;
59*33de042dSApple OSS Distributions
60*33de042dSApple OSS Distributions T_SETUPBEGIN;
61*33de042dSApple OSS Distributions
62*33de042dSApple OSS Distributions legacy_footprint = FALSE;
63*33de042dSApple OSS Distributions #if LEGACY_FOOTPRINT_ENTITLED
64*33de042dSApple OSS Distributions int legacy_footprint_entitlement_mode;
65*33de042dSApple OSS Distributions size_t oldlen;
66*33de042dSApple OSS Distributions int ret;
67*33de042dSApple OSS Distributions
68*33de042dSApple OSS Distributions T_QUIET;
69*33de042dSApple OSS Distributions T_WITH_ERRNO;
70*33de042dSApple OSS Distributions oldlen = sizeof(legacy_footprint_entitlement_mode);
71*33de042dSApple OSS Distributions ret = sysctlbyname("kern.legacy_footprint_entitlement_mode",
72*33de042dSApple OSS Distributions &legacy_footprint_entitlement_mode,
73*33de042dSApple OSS Distributions &oldlen,
74*33de042dSApple OSS Distributions NULL,
75*33de042dSApple OSS Distributions 0);
76*33de042dSApple OSS Distributions if (ret == 0 && legacy_footprint_entitlement_mode == 2) {
77*33de042dSApple OSS Distributions legacy_footprint = TRUE;
78*33de042dSApple OSS Distributions }
79*33de042dSApple OSS Distributions #endif /* LEGACY_FOOTPRINT_ENTITLED */
80*33de042dSApple OSS Distributions
81*33de042dSApple OSS Distributions T_QUIET;
82*33de042dSApple OSS Distributions T_WITH_ERRNO;
83*33de042dSApple OSS Distributions T_ASSERT_EQ(ledger(LEDGER_INFO,
84*33de042dSApple OSS Distributions (caddr_t)(uintptr_t)getpid(),
85*33de042dSApple OSS Distributions (caddr_t)&li,
86*33de042dSApple OSS Distributions NULL),
87*33de042dSApple OSS Distributions 0,
88*33de042dSApple OSS Distributions "ledger(LEDGER_INFO)");
89*33de042dSApple OSS Distributions
90*33de042dSApple OSS Distributions templateCnt = li.li_entries;
91*33de042dSApple OSS Distributions templateInfo = malloc((size_t)li.li_entries * sizeof(struct ledger_template_info));
92*33de042dSApple OSS Distributions T_QUIET;
93*33de042dSApple OSS Distributions T_WITH_ERRNO;
94*33de042dSApple OSS Distributions T_ASSERT_NE(templateInfo, NULL, "malloc()");
95*33de042dSApple OSS Distributions
96*33de042dSApple OSS Distributions ledger_count = li.li_entries;
97*33de042dSApple OSS Distributions footprint_index = -1;
98*33de042dSApple OSS Distributions pagetable_index = -1;
99*33de042dSApple OSS Distributions T_QUIET;
100*33de042dSApple OSS Distributions T_WITH_ERRNO;
101*33de042dSApple OSS Distributions T_ASSERT_GE(ledger(LEDGER_TEMPLATE_INFO,
102*33de042dSApple OSS Distributions (caddr_t)templateInfo,
103*33de042dSApple OSS Distributions (caddr_t)&templateCnt,
104*33de042dSApple OSS Distributions NULL),
105*33de042dSApple OSS Distributions 0,
106*33de042dSApple OSS Distributions "ledger(LEDGER_TEMPLATE_INFO)");
107*33de042dSApple OSS Distributions for (i = 0; i < templateCnt; i++) {
108*33de042dSApple OSS Distributions if (!strncmp(templateInfo[i].lti_name,
109*33de042dSApple OSS Distributions "phys_footprint",
110*33de042dSApple OSS Distributions strlen("phys_footprint"))) {
111*33de042dSApple OSS Distributions footprint_index = i;
112*33de042dSApple OSS Distributions } else if (!strncmp(templateInfo[i].lti_name,
113*33de042dSApple OSS Distributions "page_table",
114*33de042dSApple OSS Distributions strlen("page_table"))) {
115*33de042dSApple OSS Distributions pagetable_index = i;
116*33de042dSApple OSS Distributions }
117*33de042dSApple OSS Distributions }
118*33de042dSApple OSS Distributions free(templateInfo);
119*33de042dSApple OSS Distributions
120*33de042dSApple OSS Distributions lei = (struct ledger_entry_info *)
121*33de042dSApple OSS Distributions malloc((size_t)ledger_count * sizeof(*lei));
122*33de042dSApple OSS Distributions T_QUIET;
123*33de042dSApple OSS Distributions T_WITH_ERRNO;
124*33de042dSApple OSS Distributions T_ASSERT_NE(lei, NULL, "malloc(ledger_entry_info)");
125*33de042dSApple OSS Distributions
126*33de042dSApple OSS Distributions T_QUIET;
127*33de042dSApple OSS Distributions T_ASSERT_NE(footprint_index, -1, "no footprint_index");
128*33de042dSApple OSS Distributions T_QUIET;
129*33de042dSApple OSS Distributions T_ASSERT_NE(pagetable_index, -1, "no pagetable_index");
130*33de042dSApple OSS Distributions
131*33de042dSApple OSS Distributions T_SETUPEND;
132*33de042dSApple OSS Distributions }
133*33de042dSApple OSS Distributions
134*33de042dSApple OSS Distributions static void
get_ledger_info(uint64_t * phys_footprint,uint64_t * page_table)135*33de042dSApple OSS Distributions get_ledger_info(
136*33de042dSApple OSS Distributions uint64_t *phys_footprint,
137*33de042dSApple OSS Distributions uint64_t *page_table)
138*33de042dSApple OSS Distributions {
139*33de042dSApple OSS Distributions int64_t count;
140*33de042dSApple OSS Distributions
141*33de042dSApple OSS Distributions count = ledger_count;
142*33de042dSApple OSS Distributions T_QUIET;
143*33de042dSApple OSS Distributions T_WITH_ERRNO;
144*33de042dSApple OSS Distributions T_ASSERT_GE(ledger(LEDGER_ENTRY_INFO,
145*33de042dSApple OSS Distributions (caddr_t)(uintptr_t)getpid(),
146*33de042dSApple OSS Distributions (caddr_t)lei,
147*33de042dSApple OSS Distributions (caddr_t)&count),
148*33de042dSApple OSS Distributions 0,
149*33de042dSApple OSS Distributions "ledger(LEDGER_ENTRY_INFO)");
150*33de042dSApple OSS Distributions T_QUIET;
151*33de042dSApple OSS Distributions T_ASSERT_GT(count, (int64_t)footprint_index, "no entry for footprint");
152*33de042dSApple OSS Distributions T_QUIET;
153*33de042dSApple OSS Distributions T_ASSERT_GT(count, (int64_t)pagetable_index, "no entry for pagetable");
154*33de042dSApple OSS Distributions if (phys_footprint) {
155*33de042dSApple OSS Distributions *phys_footprint = (uint64_t)(lei[footprint_index].lei_balance);
156*33de042dSApple OSS Distributions }
157*33de042dSApple OSS Distributions if (page_table) {
158*33de042dSApple OSS Distributions *page_table = (uint64_t)(lei[pagetable_index].lei_balance);
159*33de042dSApple OSS Distributions }
160*33de042dSApple OSS Distributions }
161*33de042dSApple OSS Distributions
162*33de042dSApple OSS Distributions static mach_vm_address_t
pre_warm_with_tag(mach_vm_size_t vm_size,int tag)163*33de042dSApple OSS Distributions pre_warm_with_tag(
164*33de042dSApple OSS Distributions mach_vm_size_t vm_size,
165*33de042dSApple OSS Distributions int tag)
166*33de042dSApple OSS Distributions {
167*33de042dSApple OSS Distributions kern_return_t kr;
168*33de042dSApple OSS Distributions mach_vm_address_t vm_addr;
169*33de042dSApple OSS Distributions unsigned char BigBufOnStack[100 * 1024];
170*33de042dSApple OSS Distributions uint64_t footprint, page_table;
171*33de042dSApple OSS Distributions
172*33de042dSApple OSS Distributions /* make sure ledgers are ready to be queried */
173*33de042dSApple OSS Distributions ledger_init();
174*33de042dSApple OSS Distributions
175*33de042dSApple OSS Distributions T_SETUPBEGIN;
176*33de042dSApple OSS Distributions
177*33de042dSApple OSS Distributions /*
178*33de042dSApple OSS Distributions * Touch a few pages ahead on the stack, to make
179*33de042dSApple OSS Distributions * sure we don't see a footprint increase due to
180*33de042dSApple OSS Distributions * an extra stack page later.
181*33de042dSApple OSS Distributions */
182*33de042dSApple OSS Distributions memset(BigBufOnStack, 0xb, sizeof(BigBufOnStack));
183*33de042dSApple OSS Distributions T_QUIET;
184*33de042dSApple OSS Distributions T_EXPECT_EQ(BigBufOnStack[0], 0xb,
185*33de042dSApple OSS Distributions "BigBufOnStack[0] == 0x%x",
186*33de042dSApple OSS Distributions BigBufOnStack[0]);
187*33de042dSApple OSS Distributions T_QUIET;
188*33de042dSApple OSS Distributions T_EXPECT_EQ(BigBufOnStack[sizeof(BigBufOnStack) - 1], 0xb,
189*33de042dSApple OSS Distributions "BigBufOnStack[%lu] == 0x%x",
190*33de042dSApple OSS Distributions sizeof(BigBufOnStack),
191*33de042dSApple OSS Distributions BigBufOnStack[sizeof(BigBufOnStack) - 1]);
192*33de042dSApple OSS Distributions
193*33de042dSApple OSS Distributions /*
194*33de042dSApple OSS Distributions * Pre-allocate, touch and then release the same amount
195*33de042dSApple OSS Distributions * of memory we'll be allocating later during the test,
196*33de042dSApple OSS Distributions * to account for any memory overhead (page tables, global
197*33de042dSApple OSS Distributions * variables, ...). Supplied VM tag should ensure memory
198*33de042dSApple OSS Distributions * is allocated in the appropriate VM range.
199*33de042dSApple OSS Distributions */
200*33de042dSApple OSS Distributions vm_addr = 0;
201*33de042dSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(),
202*33de042dSApple OSS Distributions &vm_addr,
203*33de042dSApple OSS Distributions vm_size,
204*33de042dSApple OSS Distributions VM_FLAGS_ANYWHERE | VM_MAKE_TAG(tag));
205*33de042dSApple OSS Distributions T_QUIET;
206*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_allocate(%lld) error 0x%x (%s)",
207*33de042dSApple OSS Distributions vm_size, kr, mach_error_string(kr));
208*33de042dSApple OSS Distributions memset((char *)(uintptr_t)vm_addr, 'p', (size_t)vm_size);
209*33de042dSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(),
210*33de042dSApple OSS Distributions vm_addr,
211*33de042dSApple OSS Distributions vm_size);
212*33de042dSApple OSS Distributions T_QUIET;
213*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_deallocate() error 0x%x (%s)",
214*33de042dSApple OSS Distributions kr, mach_error_string(kr));
215*33de042dSApple OSS Distributions
216*33de042dSApple OSS Distributions /*
217*33de042dSApple OSS Distributions * Exercise the ledger code to make sure it's ready to run
218*33de042dSApple OSS Distributions * without any extra memory overhead later.
219*33de042dSApple OSS Distributions */
220*33de042dSApple OSS Distributions get_ledger_info(&footprint, &page_table);
221*33de042dSApple OSS Distributions
222*33de042dSApple OSS Distributions T_SETUPEND;
223*33de042dSApple OSS Distributions
224*33de042dSApple OSS Distributions /*
225*33de042dSApple OSS Distributions * Return the start of the virtual range we pre-warmed, so that the
226*33de042dSApple OSS Distributions * test can check that it's using the same range.
227*33de042dSApple OSS Distributions */
228*33de042dSApple OSS Distributions return vm_addr;
229*33de042dSApple OSS Distributions }
230*33de042dSApple OSS Distributions
231*33de042dSApple OSS Distributions static mach_vm_address_t
pre_warm(mach_vm_size_t vm_size)232*33de042dSApple OSS Distributions pre_warm(
233*33de042dSApple OSS Distributions mach_vm_size_t vm_size)
234*33de042dSApple OSS Distributions {
235*33de042dSApple OSS Distributions /*
236*33de042dSApple OSS Distributions * Default to not tagging pre_warm memory.
237*33de042dSApple OSS Distributions */
238*33de042dSApple OSS Distributions return pre_warm_with_tag(vm_size, 0);
239*33de042dSApple OSS Distributions }
240*33de042dSApple OSS Distributions
241*33de042dSApple OSS Distributions T_DECL(phys_footprint_anonymous,
242*33de042dSApple OSS Distributions "phys_footprint for anonymous memory",
243*33de042dSApple OSS Distributions T_META_LTEPHASE(LTE_POSTINIT), T_META_TAG_VM_PREFERRED)
244*33de042dSApple OSS Distributions {
245*33de042dSApple OSS Distributions uint64_t footprint_before, pagetable_before;
246*33de042dSApple OSS Distributions uint64_t footprint_after, pagetable_after;
247*33de042dSApple OSS Distributions uint64_t footprint_expected;
248*33de042dSApple OSS Distributions kern_return_t kr;
249*33de042dSApple OSS Distributions mach_vm_address_t pre_vm_addr, vm_addr;
250*33de042dSApple OSS Distributions mach_vm_size_t vm_size, dirty_size;
251*33de042dSApple OSS Distributions
252*33de042dSApple OSS Distributions /* pre-warm to account for page table expansion */
253*33de042dSApple OSS Distributions pre_vm_addr = pre_warm(MEM_SIZE);
254*33de042dSApple OSS Distributions
255*33de042dSApple OSS Distributions /* allocating virtual memory... */
256*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
257*33de042dSApple OSS Distributions vm_addr = 0;
258*33de042dSApple OSS Distributions vm_size = MEM_SIZE;
259*33de042dSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &vm_addr, vm_size,
260*33de042dSApple OSS Distributions VM_FLAGS_ANYWHERE);
261*33de042dSApple OSS Distributions T_QUIET;
262*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_allocate() error 0x%x (%s)",
263*33de042dSApple OSS Distributions kr, mach_error_string(kr));
264*33de042dSApple OSS Distributions T_QUIET;
265*33de042dSApple OSS Distributions T_EXPECT_EQ(vm_addr, pre_vm_addr, "pre-warm mishap");
266*33de042dSApple OSS Distributions /* ... should not change footprint */
267*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
268*33de042dSApple OSS Distributions footprint_expected = footprint_before;
269*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
270*33de042dSApple OSS Distributions T_LOG("virtual allocation does not change phys_footprint");
271*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
272*33de042dSApple OSS Distributions "virtual allocation of %lld bytes: "
273*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
274*33de042dSApple OSS Distributions vm_size, footprint_before, footprint_after,
275*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
276*33de042dSApple OSS Distributions
277*33de042dSApple OSS Distributions /* touching memory... */
278*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
279*33de042dSApple OSS Distributions dirty_size = vm_size / 2;
280*33de042dSApple OSS Distributions memset((char *)(uintptr_t)vm_addr, 'x', (size_t)dirty_size);
281*33de042dSApple OSS Distributions /* ... should increase footprint */
282*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
283*33de042dSApple OSS Distributions footprint_expected = footprint_before + dirty_size;
284*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
285*33de042dSApple OSS Distributions T_LOG("modifying anonymous memory increases phys_footprint");
286*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
287*33de042dSApple OSS Distributions "touched %lld bytes: "
288*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
289*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
290*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
291*33de042dSApple OSS Distributions
292*33de042dSApple OSS Distributions /* deallocating memory... */
293*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
294*33de042dSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), vm_addr, vm_size);
295*33de042dSApple OSS Distributions T_QUIET;
296*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_deallocate() error 0x%x (%s)",
297*33de042dSApple OSS Distributions kr, mach_error_string(kr));
298*33de042dSApple OSS Distributions /* ... should decrease footprint */
299*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
300*33de042dSApple OSS Distributions footprint_expected = footprint_before - dirty_size;
301*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
302*33de042dSApple OSS Distributions T_LOG("deallocating dirty anonymous memory decreases phys_footprint");
303*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
304*33de042dSApple OSS Distributions "deallocated %lld dirty bytes: "
305*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
306*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
307*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
308*33de042dSApple OSS Distributions }
309*33de042dSApple OSS Distributions
310*33de042dSApple OSS Distributions #define TEMP_FILE_TEMPLATE "/tmp/phys_footprint_data.XXXXXXXX"
311*33de042dSApple OSS Distributions #define TEMP_FILE_SIZE (1 * 1024 * 1024)
312*33de042dSApple OSS Distributions
313*33de042dSApple OSS Distributions T_DECL(phys_footprint_file,
314*33de042dSApple OSS Distributions "phys_footprint for mapped file",
315*33de042dSApple OSS Distributions T_META_LTEPHASE(LTE_POSTINIT), T_META_TAG_VM_PREFERRED)
316*33de042dSApple OSS Distributions {
317*33de042dSApple OSS Distributions uint64_t footprint_before, pagetable_before;
318*33de042dSApple OSS Distributions uint64_t footprint_after, pagetable_after;
319*33de042dSApple OSS Distributions uint64_t footprint_expected;
320*33de042dSApple OSS Distributions mach_vm_address_t pre_vm_addr;
321*33de042dSApple OSS Distributions int fd;
322*33de042dSApple OSS Distributions char *map_addr;
323*33de042dSApple OSS Distributions size_t map_size, dirty_size;
324*33de042dSApple OSS Distributions ssize_t nbytes;
325*33de042dSApple OSS Distributions char tmp_file_name[PATH_MAX] = TEMP_FILE_TEMPLATE;
326*33de042dSApple OSS Distributions char *buf;
327*33de042dSApple OSS Distributions size_t buf_size;
328*33de042dSApple OSS Distributions
329*33de042dSApple OSS Distributions T_SETUPBEGIN;
330*33de042dSApple OSS Distributions buf_size = TEMP_FILE_SIZE;
331*33de042dSApple OSS Distributions T_QUIET;
332*33de042dSApple OSS Distributions T_ASSERT_NOTNULL(buf = (char *)malloc(buf_size),
333*33de042dSApple OSS Distributions "allocate %zu-byte buffer", buf_size);
334*33de042dSApple OSS Distributions memset(buf, 'f', buf_size);
335*33de042dSApple OSS Distributions T_WITH_ERRNO;
336*33de042dSApple OSS Distributions T_QUIET;
337*33de042dSApple OSS Distributions T_ASSERT_NOTNULL(mktemp(tmp_file_name),
338*33de042dSApple OSS Distributions "create temporary file name");
339*33de042dSApple OSS Distributions T_WITH_ERRNO;
340*33de042dSApple OSS Distributions T_QUIET;
341*33de042dSApple OSS Distributions T_ASSERT_GE(fd = open(tmp_file_name, O_CREAT | O_RDWR),
342*33de042dSApple OSS Distributions 0,
343*33de042dSApple OSS Distributions "create temp file");
344*33de042dSApple OSS Distributions T_WITH_ERRNO;
345*33de042dSApple OSS Distributions T_QUIET;
346*33de042dSApple OSS Distributions T_ASSERT_EQ(nbytes = write(fd, buf, buf_size),
347*33de042dSApple OSS Distributions (ssize_t)buf_size,
348*33de042dSApple OSS Distributions "write %zu bytes", buf_size);
349*33de042dSApple OSS Distributions free(buf);
350*33de042dSApple OSS Distributions T_SETUPEND;
351*33de042dSApple OSS Distributions
352*33de042dSApple OSS Distributions /* pre-warm to account for page table expansion */
353*33de042dSApple OSS Distributions #if TARGET_OS_OSX
354*33de042dSApple OSS Distributions pre_vm_addr = pre_warm_with_tag(TEMP_FILE_SIZE, VM_MEMORY_MALLOC);
355*33de042dSApple OSS Distributions #else
356*33de042dSApple OSS Distributions pre_vm_addr = pre_warm_with_tag(TEMP_FILE_SIZE, VM_MEMORY_MALLOC_TINY);
357*33de042dSApple OSS Distributions #endif
358*33de042dSApple OSS Distributions
359*33de042dSApple OSS Distributions /* mapping a file does not impact footprint... */
360*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
361*33de042dSApple OSS Distributions map_size = TEMP_FILE_SIZE;
362*33de042dSApple OSS Distributions T_WITH_ERRNO;
363*33de042dSApple OSS Distributions T_QUIET;
364*33de042dSApple OSS Distributions T_ASSERT_NOTNULL(map_addr = (char *)mmap(NULL, map_size,
365*33de042dSApple OSS Distributions PROT_READ | PROT_WRITE,
366*33de042dSApple OSS Distributions MAP_FILE | MAP_SHARED, fd, 0),
367*33de042dSApple OSS Distributions "mmap()");
368*33de042dSApple OSS Distributions T_QUIET;
369*33de042dSApple OSS Distributions T_EXPECT_EQ((mach_vm_address_t)map_addr, pre_vm_addr,
370*33de042dSApple OSS Distributions "pre-warm mishap");
371*33de042dSApple OSS Distributions /* ... should not change footprint */
372*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
373*33de042dSApple OSS Distributions footprint_expected = footprint_before;
374*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
375*33de042dSApple OSS Distributions T_LOG("mapping file does not change phys_footprint");
376*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
377*33de042dSApple OSS Distributions "mapping file with %zu bytes: "
378*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
379*33de042dSApple OSS Distributions map_size, footprint_before, footprint_after,
380*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
381*33de042dSApple OSS Distributions
382*33de042dSApple OSS Distributions /* touching file-backed memory... */
383*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
384*33de042dSApple OSS Distributions dirty_size = map_size / 2;
385*33de042dSApple OSS Distributions memset(map_addr, 'F', dirty_size);
386*33de042dSApple OSS Distributions /* ... should not impact footprint */
387*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
388*33de042dSApple OSS Distributions footprint_expected = footprint_before;
389*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
390*33de042dSApple OSS Distributions T_LOG("modifying file-backed memory does not impact phys_footprint");
391*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
392*33de042dSApple OSS Distributions "touched %zu bytes: "
393*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
394*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
395*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
396*33de042dSApple OSS Distributions
397*33de042dSApple OSS Distributions /* deallocating file-backed memory... */
398*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
399*33de042dSApple OSS Distributions T_WITH_ERRNO;
400*33de042dSApple OSS Distributions T_QUIET;
401*33de042dSApple OSS Distributions T_ASSERT_EQ(munmap(map_addr, map_size),
402*33de042dSApple OSS Distributions 0,
403*33de042dSApple OSS Distributions "unmap file");
404*33de042dSApple OSS Distributions /* ... should not impact footprint */
405*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
406*33de042dSApple OSS Distributions footprint_expected = footprint_before;
407*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
408*33de042dSApple OSS Distributions T_LOG("unmapping file-backed memory does not impact phys_footprint");
409*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
410*33de042dSApple OSS Distributions "unmapped %zu dirty bytes: "
411*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
412*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
413*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
414*33de042dSApple OSS Distributions }
415*33de042dSApple OSS Distributions
416*33de042dSApple OSS Distributions T_DECL(phys_footprint_purgeable,
417*33de042dSApple OSS Distributions "phys_footprint for purgeable memory",
418*33de042dSApple OSS Distributions T_META_LTEPHASE(LTE_POSTINIT), T_META_TAG_VM_PREFERRED)
419*33de042dSApple OSS Distributions {
420*33de042dSApple OSS Distributions uint64_t footprint_before, pagetable_before;
421*33de042dSApple OSS Distributions uint64_t footprint_after, pagetable_after;
422*33de042dSApple OSS Distributions uint64_t footprint_expected;
423*33de042dSApple OSS Distributions kern_return_t kr;
424*33de042dSApple OSS Distributions mach_vm_address_t pre_vm_addr, vm_addr;
425*33de042dSApple OSS Distributions mach_vm_size_t vm_size, dirty_size;
426*33de042dSApple OSS Distributions int state;
427*33de042dSApple OSS Distributions
428*33de042dSApple OSS Distributions /* pre-warm to account for page table expansion */
429*33de042dSApple OSS Distributions pre_vm_addr = pre_warm(MEM_SIZE);
430*33de042dSApple OSS Distributions
431*33de042dSApple OSS Distributions /* allocating purgeable virtual memory... */
432*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
433*33de042dSApple OSS Distributions vm_addr = 0;
434*33de042dSApple OSS Distributions vm_size = MEM_SIZE;
435*33de042dSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &vm_addr, vm_size,
436*33de042dSApple OSS Distributions VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE);
437*33de042dSApple OSS Distributions T_QUIET;
438*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_allocate() error 0x%x (%s)",
439*33de042dSApple OSS Distributions kr, mach_error_string(kr));
440*33de042dSApple OSS Distributions T_QUIET;
441*33de042dSApple OSS Distributions T_EXPECT_EQ(vm_addr, pre_vm_addr, "pre-warm mishap");
442*33de042dSApple OSS Distributions /* ... should not change footprint */
443*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
444*33de042dSApple OSS Distributions footprint_expected = footprint_before;
445*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
446*33de042dSApple OSS Distributions T_LOG("purgeable virtual allocation does not change phys_footprint");
447*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
448*33de042dSApple OSS Distributions "purgeable virtual allocation of %lld bytes: "
449*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
450*33de042dSApple OSS Distributions vm_size, footprint_before, footprint_after,
451*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
452*33de042dSApple OSS Distributions
453*33de042dSApple OSS Distributions /* touching memory... */
454*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
455*33de042dSApple OSS Distributions dirty_size = vm_size / 2;
456*33de042dSApple OSS Distributions memset((char *)(uintptr_t)vm_addr, 'x', (size_t)dirty_size);
457*33de042dSApple OSS Distributions /* ... should increase footprint */
458*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
459*33de042dSApple OSS Distributions footprint_expected = footprint_before + dirty_size;
460*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
461*33de042dSApple OSS Distributions T_LOG("modifying anonymous memory increases phys_footprint");
462*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
463*33de042dSApple OSS Distributions "touched %lld bytes: "
464*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
465*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
466*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
467*33de042dSApple OSS Distributions
468*33de042dSApple OSS Distributions /* making it volatile... */
469*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
470*33de042dSApple OSS Distributions state = VM_PURGABLE_VOLATILE;
471*33de042dSApple OSS Distributions T_QUIET;
472*33de042dSApple OSS Distributions T_ASSERT_EQ(mach_vm_purgable_control(mach_task_self(),
473*33de042dSApple OSS Distributions vm_addr,
474*33de042dSApple OSS Distributions VM_PURGABLE_SET_STATE,
475*33de042dSApple OSS Distributions &state),
476*33de042dSApple OSS Distributions KERN_SUCCESS,
477*33de042dSApple OSS Distributions "vm_purgable_control(VOLATILE)");
478*33de042dSApple OSS Distributions T_QUIET;
479*33de042dSApple OSS Distributions T_ASSERT_EQ(state, VM_PURGABLE_NONVOLATILE,
480*33de042dSApple OSS Distributions "memory was non-volatile");
481*33de042dSApple OSS Distributions /* ... should decrease footprint */
482*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
483*33de042dSApple OSS Distributions footprint_expected = footprint_before - dirty_size;
484*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
485*33de042dSApple OSS Distributions T_LOG("making volatile decreases phys_footprint");
486*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
487*33de042dSApple OSS Distributions "made volatile %lld dirty bytes: "
488*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
489*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
490*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
491*33de042dSApple OSS Distributions
492*33de042dSApple OSS Distributions /* making it non-volatile... */
493*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
494*33de042dSApple OSS Distributions state = VM_PURGABLE_NONVOLATILE;
495*33de042dSApple OSS Distributions T_QUIET;
496*33de042dSApple OSS Distributions T_ASSERT_EQ(mach_vm_purgable_control(mach_task_self(),
497*33de042dSApple OSS Distributions vm_addr,
498*33de042dSApple OSS Distributions VM_PURGABLE_SET_STATE,
499*33de042dSApple OSS Distributions &state),
500*33de042dSApple OSS Distributions KERN_SUCCESS,
501*33de042dSApple OSS Distributions "vm_purgable_control(NONVOLATILE)");
502*33de042dSApple OSS Distributions T_QUIET;
503*33de042dSApple OSS Distributions T_ASSERT_EQ(state, VM_PURGABLE_VOLATILE,
504*33de042dSApple OSS Distributions "memory was volatile");
505*33de042dSApple OSS Distributions /* ... should increase footprint */
506*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
507*33de042dSApple OSS Distributions footprint_expected = footprint_before + dirty_size;
508*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
509*33de042dSApple OSS Distributions T_LOG("making non-volatile increases phys_footprint");
510*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
511*33de042dSApple OSS Distributions "made non-volatile %lld dirty bytes: "
512*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
513*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
514*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
515*33de042dSApple OSS Distributions
516*33de042dSApple OSS Distributions /* deallocating memory... */
517*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
518*33de042dSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), vm_addr, vm_size);
519*33de042dSApple OSS Distributions T_QUIET;
520*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_deallocate() error 0x%x (%s)",
521*33de042dSApple OSS Distributions kr, mach_error_string(kr));
522*33de042dSApple OSS Distributions /* ... should decrease footprint */
523*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
524*33de042dSApple OSS Distributions footprint_expected = footprint_before - dirty_size;
525*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
526*33de042dSApple OSS Distributions T_LOG("deallocating memory decreases phys_footprint");
527*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
528*33de042dSApple OSS Distributions "deallocated %lld dirty bytes: "
529*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
530*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
531*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
532*33de042dSApple OSS Distributions }
533*33de042dSApple OSS Distributions
534*33de042dSApple OSS Distributions T_DECL(phys_footprint_purgeable_ownership,
535*33de042dSApple OSS Distributions "phys_footprint for owned purgeable memory",
536*33de042dSApple OSS Distributions T_META_LTEPHASE(LTE_POSTINIT), T_META_TAG_VM_PREFERRED)
537*33de042dSApple OSS Distributions {
538*33de042dSApple OSS Distributions uint64_t footprint_before, pagetable_before;
539*33de042dSApple OSS Distributions uint64_t footprint_after, pagetable_after;
540*33de042dSApple OSS Distributions uint64_t footprint_expected;
541*33de042dSApple OSS Distributions kern_return_t kr;
542*33de042dSApple OSS Distributions mach_vm_address_t pre_vm_addr, vm_addr;
543*33de042dSApple OSS Distributions mach_vm_size_t vm_size, dirty_size, me_size;
544*33de042dSApple OSS Distributions int state;
545*33de042dSApple OSS Distributions mach_port_t me_port;
546*33de042dSApple OSS Distributions
547*33de042dSApple OSS Distributions /* pre-warm to account for page table expansion */
548*33de042dSApple OSS Distributions pre_vm_addr = pre_warm(MEM_SIZE);
549*33de042dSApple OSS Distributions
550*33de042dSApple OSS Distributions /* allocating purgeable virtual memory... */
551*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
552*33de042dSApple OSS Distributions vm_addr = 0;
553*33de042dSApple OSS Distributions vm_size = MEM_SIZE;
554*33de042dSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &vm_addr, vm_size,
555*33de042dSApple OSS Distributions VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE);
556*33de042dSApple OSS Distributions T_QUIET;
557*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_allocate() error 0x%x (%s)",
558*33de042dSApple OSS Distributions kr, mach_error_string(kr));
559*33de042dSApple OSS Distributions T_QUIET;
560*33de042dSApple OSS Distributions T_EXPECT_EQ(vm_addr, pre_vm_addr, "pre-warm mishap");
561*33de042dSApple OSS Distributions /* ... should not change footprint */
562*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
563*33de042dSApple OSS Distributions footprint_expected = footprint_before;
564*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
565*33de042dSApple OSS Distributions T_LOG("purgeable virtual allocation does not change phys_footprint");
566*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
567*33de042dSApple OSS Distributions "purgeable virtual allocation of %lld bytes: "
568*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
569*33de042dSApple OSS Distributions vm_size, footprint_before, footprint_after,
570*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
571*33de042dSApple OSS Distributions
572*33de042dSApple OSS Distributions /* touching memory... */
573*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
574*33de042dSApple OSS Distributions dirty_size = vm_size / 2;
575*33de042dSApple OSS Distributions memset((char *)(uintptr_t)vm_addr, 'x', (size_t)dirty_size);
576*33de042dSApple OSS Distributions /* ... should increase footprint */
577*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
578*33de042dSApple OSS Distributions footprint_expected = footprint_before + dirty_size;
579*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
580*33de042dSApple OSS Distributions T_LOG("modifying anonymous memory increases phys_footprint");
581*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
582*33de042dSApple OSS Distributions "touched %lld bytes: "
583*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
584*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
585*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
586*33de042dSApple OSS Distributions
587*33de042dSApple OSS Distributions /* making it volatile... */
588*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
589*33de042dSApple OSS Distributions state = VM_PURGABLE_VOLATILE;
590*33de042dSApple OSS Distributions T_QUIET;
591*33de042dSApple OSS Distributions T_ASSERT_EQ(mach_vm_purgable_control(mach_task_self(),
592*33de042dSApple OSS Distributions vm_addr,
593*33de042dSApple OSS Distributions VM_PURGABLE_SET_STATE,
594*33de042dSApple OSS Distributions &state),
595*33de042dSApple OSS Distributions KERN_SUCCESS,
596*33de042dSApple OSS Distributions "vm_purgable_control(VOLATILE)");
597*33de042dSApple OSS Distributions T_QUIET;
598*33de042dSApple OSS Distributions T_ASSERT_EQ(state, VM_PURGABLE_NONVOLATILE,
599*33de042dSApple OSS Distributions "memory was non-volatile");
600*33de042dSApple OSS Distributions /* ... should decrease footprint */
601*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
602*33de042dSApple OSS Distributions footprint_expected = footprint_before - dirty_size;
603*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
604*33de042dSApple OSS Distributions T_LOG("making volatile decreases phys_footprint");
605*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
606*33de042dSApple OSS Distributions "made volatile %lld dirty bytes: "
607*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
608*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
609*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
610*33de042dSApple OSS Distributions
611*33de042dSApple OSS Distributions /* making it non-volatile... */
612*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
613*33de042dSApple OSS Distributions state = VM_PURGABLE_NONVOLATILE;
614*33de042dSApple OSS Distributions T_QUIET;
615*33de042dSApple OSS Distributions T_ASSERT_EQ(mach_vm_purgable_control(mach_task_self(),
616*33de042dSApple OSS Distributions vm_addr,
617*33de042dSApple OSS Distributions VM_PURGABLE_SET_STATE,
618*33de042dSApple OSS Distributions &state),
619*33de042dSApple OSS Distributions KERN_SUCCESS,
620*33de042dSApple OSS Distributions "vm_purgable_control(NONVOLATILE)");
621*33de042dSApple OSS Distributions T_QUIET;
622*33de042dSApple OSS Distributions T_ASSERT_EQ(state, VM_PURGABLE_VOLATILE,
623*33de042dSApple OSS Distributions "memory was volatile");
624*33de042dSApple OSS Distributions /* ... should increase footprint */
625*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
626*33de042dSApple OSS Distributions footprint_expected = footprint_before + dirty_size;
627*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
628*33de042dSApple OSS Distributions T_LOG("making non-volatile increases phys_footprint");
629*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
630*33de042dSApple OSS Distributions "made non-volatile %lld dirty bytes: "
631*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
632*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
633*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
634*33de042dSApple OSS Distributions
635*33de042dSApple OSS Distributions /* making a memory entry... */
636*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
637*33de042dSApple OSS Distributions me_size = vm_size;
638*33de042dSApple OSS Distributions me_port = MACH_PORT_NULL;
639*33de042dSApple OSS Distributions kr = mach_make_memory_entry_64(mach_task_self(),
640*33de042dSApple OSS Distributions &me_size,
641*33de042dSApple OSS Distributions vm_addr,
642*33de042dSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
643*33de042dSApple OSS Distributions &me_port,
644*33de042dSApple OSS Distributions MACH_PORT_NULL);
645*33de042dSApple OSS Distributions T_QUIET;
646*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "make_memory_entry() error 0x%x (%s)",
647*33de042dSApple OSS Distributions kr, mach_error_string(kr));
648*33de042dSApple OSS Distributions T_QUIET;
649*33de042dSApple OSS Distributions T_EXPECT_EQ(me_size, vm_size, "memory entry size mismatch");
650*33de042dSApple OSS Distributions /* ... should not change footprint */
651*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
652*33de042dSApple OSS Distributions footprint_expected = footprint_before;
653*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
654*33de042dSApple OSS Distributions T_LOG("making a memory entry does not change phys_footprint");
655*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
656*33de042dSApple OSS Distributions "making a memory entry of %lld bytes: "
657*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
658*33de042dSApple OSS Distributions vm_size, footprint_before, footprint_after,
659*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
660*33de042dSApple OSS Distributions
661*33de042dSApple OSS Distributions /* deallocating memory while holding memory entry... */
662*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
663*33de042dSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), vm_addr, vm_size);
664*33de042dSApple OSS Distributions T_QUIET;
665*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_deallocate() error 0x%x (%s)",
666*33de042dSApple OSS Distributions kr, mach_error_string(kr));
667*33de042dSApple OSS Distributions /* ... should not change footprint */
668*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
669*33de042dSApple OSS Distributions footprint_expected = footprint_before;
670*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
671*33de042dSApple OSS Distributions T_LOG("deallocating owned memory while holding memory entry "
672*33de042dSApple OSS Distributions "does not change phys_footprint");
673*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
674*33de042dSApple OSS Distributions "deallocated %lld dirty bytes: "
675*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
676*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
677*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
678*33de042dSApple OSS Distributions
679*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
680*33de042dSApple OSS Distributions footprint_expected = footprint_before;
681*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
682*33de042dSApple OSS Distributions T_LOG("deallocating owned memory while holding memory entry "
683*33de042dSApple OSS Distributions "does not change phys_footprint");
684*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
685*33de042dSApple OSS Distributions "deallocated %lld dirty bytes: "
686*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
687*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
688*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
689*33de042dSApple OSS Distributions
690*33de042dSApple OSS Distributions /* changing ownership of memory entry (from self to self)... */
691*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
692*33de042dSApple OSS Distributions kr = mach_memory_entry_ownership(me_port,
693*33de042dSApple OSS Distributions #if VM_LEDGER_TAG_UNCHANGED
694*33de042dSApple OSS Distributions MACH_PORT_NULL, /* owner remains unchanged */
695*33de042dSApple OSS Distributions VM_LEDGER_TAG_UNCHANGED, /* ledger-tag remains unchanged */
696*33de042dSApple OSS Distributions #else /* VM_LEDGER_TAG_UNCHANGED */
697*33de042dSApple OSS Distributions mach_task_self(),
698*33de042dSApple OSS Distributions VM_LEDGER_TAG_DEFAULT,
699*33de042dSApple OSS Distributions #endif /* VM_LEDGER_TAG_UNCHANGED */
700*33de042dSApple OSS Distributions 0);
701*33de042dSApple OSS Distributions T_QUIET;
702*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS,
703*33de042dSApple OSS Distributions "mach_memory_entry_ownership() error 0x%x (%s)",
704*33de042dSApple OSS Distributions kr, mach_error_string(kr));
705*33de042dSApple OSS Distributions /* ... should not change footprint */
706*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
707*33de042dSApple OSS Distributions footprint_expected = footprint_before;
708*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
709*33de042dSApple OSS Distributions T_LOG("changing ownership from self to self "
710*33de042dSApple OSS Distributions "does not change phys_footprint");
711*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
712*33de042dSApple OSS Distributions "changed ownership of %lld dirty bytes: "
713*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
714*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
715*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
716*33de042dSApple OSS Distributions
717*33de042dSApple OSS Distributions /* releasing the memory entry... */
718*33de042dSApple OSS Distributions kr = mach_port_deallocate(mach_task_self(), me_port);
719*33de042dSApple OSS Distributions T_QUIET;
720*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "mach_port_deallocate() error 0x%x (%s)",
721*33de042dSApple OSS Distributions kr, mach_error_string(kr));
722*33de042dSApple OSS Distributions /* ... should decrease footprint */
723*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
724*33de042dSApple OSS Distributions footprint_expected = footprint_before - dirty_size;
725*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
726*33de042dSApple OSS Distributions T_LOG("releasing memory entry decreases phys_footprint");
727*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
728*33de042dSApple OSS Distributions "made volatile %lld dirty bytes: "
729*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
730*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
731*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
732*33de042dSApple OSS Distributions }
733*33de042dSApple OSS Distributions
734*33de042dSApple OSS Distributions #if VM_LEDGER_TAG_UNCHANGED
735*33de042dSApple OSS Distributions T_DECL(phys_footprint_multiple_purgeable_ownership,
736*33de042dSApple OSS Distributions "phys_footprint for owned purgeable memory (MAP_MEM_VM_SHARE)",
737*33de042dSApple OSS Distributions T_META_NAMESPACE(TEST_VM_NAMESPACE),
738*33de042dSApple OSS Distributions T_META_LTEPHASE(LTE_POSTINIT), T_META_TAG_VM_PREFERRED)
739*33de042dSApple OSS Distributions {
740*33de042dSApple OSS Distributions uint64_t footprint_before, pagetable_before;
741*33de042dSApple OSS Distributions uint64_t footprint_after, pagetable_after;
742*33de042dSApple OSS Distributions uint64_t footprint_expected;
743*33de042dSApple OSS Distributions kern_return_t kr;
744*33de042dSApple OSS Distributions mach_vm_address_t pre_vm_addr, vm_addr;
745*33de042dSApple OSS Distributions mach_vm_size_t vm_size, dirty_size, me_size;
746*33de042dSApple OSS Distributions int state;
747*33de042dSApple OSS Distributions mach_port_t me_port;
748*33de042dSApple OSS Distributions
749*33de042dSApple OSS Distributions /* pre-warm to account for page table expansion */
750*33de042dSApple OSS Distributions pre_vm_addr = pre_warm(MEM_SIZE);
751*33de042dSApple OSS Distributions
752*33de042dSApple OSS Distributions /* allocating purgeable virtual memory... */
753*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
754*33de042dSApple OSS Distributions vm_addr = 0;
755*33de042dSApple OSS Distributions vm_size = MEM_SIZE;
756*33de042dSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &vm_addr, vm_size,
757*33de042dSApple OSS Distributions VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE);
758*33de042dSApple OSS Distributions T_QUIET;
759*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_allocate() error 0x%x (%s)",
760*33de042dSApple OSS Distributions kr, mach_error_string(kr));
761*33de042dSApple OSS Distributions T_QUIET;
762*33de042dSApple OSS Distributions T_EXPECT_EQ(vm_addr, pre_vm_addr, "pre-warm mishap");
763*33de042dSApple OSS Distributions /* ... should not change footprint */
764*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
765*33de042dSApple OSS Distributions footprint_expected = footprint_before;
766*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
767*33de042dSApple OSS Distributions T_LOG("purgeable virtual allocation does not change phys_footprint");
768*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
769*33de042dSApple OSS Distributions "purgeable virtual allocation of %lld bytes: "
770*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
771*33de042dSApple OSS Distributions vm_size, footprint_before, footprint_after,
772*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
773*33de042dSApple OSS Distributions
774*33de042dSApple OSS Distributions /* touching memory... */
775*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
776*33de042dSApple OSS Distributions dirty_size = vm_size / 2;
777*33de042dSApple OSS Distributions memset((char *)(uintptr_t)vm_addr, 'x', (size_t)dirty_size);
778*33de042dSApple OSS Distributions /* ... should increase footprint */
779*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
780*33de042dSApple OSS Distributions footprint_expected = footprint_before + dirty_size;
781*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
782*33de042dSApple OSS Distributions T_LOG("modifying anonymous memory increases phys_footprint");
783*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
784*33de042dSApple OSS Distributions "touched %lld bytes: "
785*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
786*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
787*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
788*33de042dSApple OSS Distributions
789*33de042dSApple OSS Distributions /* making it volatile... */
790*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
791*33de042dSApple OSS Distributions state = VM_PURGABLE_VOLATILE;
792*33de042dSApple OSS Distributions T_QUIET;
793*33de042dSApple OSS Distributions T_ASSERT_EQ(mach_vm_purgable_control(mach_task_self(),
794*33de042dSApple OSS Distributions vm_addr,
795*33de042dSApple OSS Distributions VM_PURGABLE_SET_STATE,
796*33de042dSApple OSS Distributions &state),
797*33de042dSApple OSS Distributions KERN_SUCCESS,
798*33de042dSApple OSS Distributions "vm_purgable_control(VOLATILE)");
799*33de042dSApple OSS Distributions T_QUIET;
800*33de042dSApple OSS Distributions T_ASSERT_EQ(state, VM_PURGABLE_NONVOLATILE,
801*33de042dSApple OSS Distributions "memory was non-volatile");
802*33de042dSApple OSS Distributions /* ... should decrease footprint */
803*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
804*33de042dSApple OSS Distributions footprint_expected = footprint_before - dirty_size;
805*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
806*33de042dSApple OSS Distributions T_LOG("making volatile decreases phys_footprint");
807*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
808*33de042dSApple OSS Distributions "made volatile %lld dirty bytes: "
809*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
810*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
811*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
812*33de042dSApple OSS Distributions
813*33de042dSApple OSS Distributions /* making it non-volatile... */
814*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
815*33de042dSApple OSS Distributions state = VM_PURGABLE_NONVOLATILE;
816*33de042dSApple OSS Distributions T_QUIET;
817*33de042dSApple OSS Distributions T_ASSERT_EQ(mach_vm_purgable_control(mach_task_self(),
818*33de042dSApple OSS Distributions vm_addr,
819*33de042dSApple OSS Distributions VM_PURGABLE_SET_STATE,
820*33de042dSApple OSS Distributions &state),
821*33de042dSApple OSS Distributions KERN_SUCCESS,
822*33de042dSApple OSS Distributions "vm_purgable_control(NONVOLATILE)");
823*33de042dSApple OSS Distributions T_QUIET;
824*33de042dSApple OSS Distributions T_ASSERT_EQ(state, VM_PURGABLE_VOLATILE,
825*33de042dSApple OSS Distributions "memory was volatile");
826*33de042dSApple OSS Distributions /* ... should increase footprint */
827*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
828*33de042dSApple OSS Distributions footprint_expected = footprint_before + dirty_size;
829*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
830*33de042dSApple OSS Distributions T_LOG("making non-volatile increases phys_footprint");
831*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
832*33de042dSApple OSS Distributions "made non-volatile %lld dirty bytes: "
833*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
834*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
835*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
836*33de042dSApple OSS Distributions
837*33de042dSApple OSS Distributions /* making a memory entry... */
838*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
839*33de042dSApple OSS Distributions me_size = vm_size;
840*33de042dSApple OSS Distributions me_port = MACH_PORT_NULL;
841*33de042dSApple OSS Distributions kr = mach_make_memory_entry_64(mach_task_self(),
842*33de042dSApple OSS Distributions &me_size,
843*33de042dSApple OSS Distributions vm_addr,
844*33de042dSApple OSS Distributions MAP_MEM_VM_SHARE | VM_PROT_READ | VM_PROT_WRITE,
845*33de042dSApple OSS Distributions &me_port,
846*33de042dSApple OSS Distributions MACH_PORT_NULL);
847*33de042dSApple OSS Distributions T_QUIET;
848*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "make_memory_entry() error 0x%x (%s)",
849*33de042dSApple OSS Distributions kr, mach_error_string(kr));
850*33de042dSApple OSS Distributions T_QUIET;
851*33de042dSApple OSS Distributions T_EXPECT_EQ(me_size, vm_size, "memory entry size mismatch");
852*33de042dSApple OSS Distributions /* ... should not change footprint */
853*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
854*33de042dSApple OSS Distributions footprint_expected = footprint_before;
855*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
856*33de042dSApple OSS Distributions T_LOG("making a memory entry does not change phys_footprint");
857*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
858*33de042dSApple OSS Distributions "making a memory entry of %lld bytes: "
859*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
860*33de042dSApple OSS Distributions vm_size, footprint_before, footprint_after,
861*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
862*33de042dSApple OSS Distributions
863*33de042dSApple OSS Distributions /* deallocating memory while holding memory entry... */
864*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
865*33de042dSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), vm_addr, vm_size);
866*33de042dSApple OSS Distributions T_QUIET;
867*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_deallocate() error 0x%x (%s)",
868*33de042dSApple OSS Distributions kr, mach_error_string(kr));
869*33de042dSApple OSS Distributions /* ... should not change footprint */
870*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
871*33de042dSApple OSS Distributions footprint_expected = footprint_before;
872*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
873*33de042dSApple OSS Distributions T_LOG("deallocating owned memory while holding memory entry "
874*33de042dSApple OSS Distributions "does not change phys_footprint");
875*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
876*33de042dSApple OSS Distributions "deallocated %lld dirty bytes: "
877*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
878*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
879*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
880*33de042dSApple OSS Distributions
881*33de042dSApple OSS Distributions /* changing ownership of memory entry (from self to self)... */
882*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
883*33de042dSApple OSS Distributions kr = mach_memory_entry_ownership(me_port,
884*33de042dSApple OSS Distributions MACH_PORT_NULL, /* owner remains unchanged */
885*33de042dSApple OSS Distributions VM_LEDGER_TAG_UNCHANGED, /* ledger-tag remains unchanged */
886*33de042dSApple OSS Distributions 0);
887*33de042dSApple OSS Distributions T_QUIET;
888*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS,
889*33de042dSApple OSS Distributions "mach_memory_entry_ownership() error 0x%x (%s)",
890*33de042dSApple OSS Distributions kr, mach_error_string(kr));
891*33de042dSApple OSS Distributions /* ... should not change footprint */
892*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
893*33de042dSApple OSS Distributions footprint_expected = footprint_before;
894*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
895*33de042dSApple OSS Distributions T_LOG("changing ownership from self to self "
896*33de042dSApple OSS Distributions "does not change phys_footprint");
897*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
898*33de042dSApple OSS Distributions "changed ownership of %lld dirty bytes: "
899*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
900*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
901*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
902*33de042dSApple OSS Distributions
903*33de042dSApple OSS Distributions /* releasing the memory entry... */
904*33de042dSApple OSS Distributions kr = mach_port_deallocate(mach_task_self(), me_port);
905*33de042dSApple OSS Distributions T_QUIET;
906*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "mach_port_deallocate() error 0x%x (%s)",
907*33de042dSApple OSS Distributions kr, mach_error_string(kr));
908*33de042dSApple OSS Distributions /* ... should decrease footprint */
909*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
910*33de042dSApple OSS Distributions footprint_expected = footprint_before - dirty_size;
911*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
912*33de042dSApple OSS Distributions T_LOG("releasing memory entry decreases phys_footprint");
913*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
914*33de042dSApple OSS Distributions "made volatile %lld dirty bytes: "
915*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
916*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
917*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
918*33de042dSApple OSS Distributions }
919*33de042dSApple OSS Distributions #endif /* VM_LEDGER_TAG_UNCHANGED */
920*33de042dSApple OSS Distributions
921*33de042dSApple OSS Distributions #ifdef MAP_MEM_LEDGER_TAGGED
922*33de042dSApple OSS Distributions T_DECL(phys_footprint_ledger_purgeable_owned,
923*33de042dSApple OSS Distributions "phys_footprint for ledger-tagged purgeable memory ownership",
924*33de042dSApple OSS Distributions T_META_LTEPHASE(LTE_POSTINIT), T_META_TAG_VM_PREFERRED)
925*33de042dSApple OSS Distributions {
926*33de042dSApple OSS Distributions uint64_t footprint_before, pagetable_before;
927*33de042dSApple OSS Distributions uint64_t footprint_after, pagetable_after;
928*33de042dSApple OSS Distributions uint64_t footprint_expected;
929*33de042dSApple OSS Distributions kern_return_t kr;
930*33de042dSApple OSS Distributions mach_vm_address_t pre_vm_addr, vm_addr;
931*33de042dSApple OSS Distributions mach_vm_size_t vm_size, dirty_size, me_size;
932*33de042dSApple OSS Distributions int state;
933*33de042dSApple OSS Distributions mach_port_t me_port;
934*33de042dSApple OSS Distributions
935*33de042dSApple OSS Distributions /* pre-warm to account for page table expansion */
936*33de042dSApple OSS Distributions pre_vm_addr = pre_warm(MEM_SIZE);
937*33de042dSApple OSS Distributions
938*33de042dSApple OSS Distributions /* making a memory entry... */
939*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
940*33de042dSApple OSS Distributions vm_size = MEM_SIZE;
941*33de042dSApple OSS Distributions me_size = vm_size;
942*33de042dSApple OSS Distributions me_port = MACH_PORT_NULL;
943*33de042dSApple OSS Distributions kr = mach_make_memory_entry_64(mach_task_self(),
944*33de042dSApple OSS Distributions &me_size,
945*33de042dSApple OSS Distributions 0,
946*33de042dSApple OSS Distributions (MAP_MEM_NAMED_CREATE |
947*33de042dSApple OSS Distributions MAP_MEM_LEDGER_TAGGED |
948*33de042dSApple OSS Distributions MAP_MEM_PURGABLE |
949*33de042dSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE),
950*33de042dSApple OSS Distributions &me_port,
951*33de042dSApple OSS Distributions MACH_PORT_NULL);
952*33de042dSApple OSS Distributions T_QUIET;
953*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "make_memory_entry() error 0x%x (%s)",
954*33de042dSApple OSS Distributions kr, mach_error_string(kr));
955*33de042dSApple OSS Distributions T_QUIET;
956*33de042dSApple OSS Distributions T_EXPECT_EQ(me_size, vm_size, "memory entry size mismatch");
957*33de042dSApple OSS Distributions /* ... should not change footprint */
958*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
959*33de042dSApple OSS Distributions footprint_expected = footprint_before;
960*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
961*33de042dSApple OSS Distributions T_LOG("making a memory entry does not change phys_footprint");
962*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
963*33de042dSApple OSS Distributions "making a memory entry of %lld bytes: "
964*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
965*33de042dSApple OSS Distributions vm_size, footprint_before, footprint_after,
966*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
967*33de042dSApple OSS Distributions
968*33de042dSApple OSS Distributions /* mapping ledger-tagged virtual memory... */
969*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
970*33de042dSApple OSS Distributions vm_addr = 0;
971*33de042dSApple OSS Distributions kr = mach_vm_map(mach_task_self(), &vm_addr, vm_size,
972*33de042dSApple OSS Distributions 0, /* mask */
973*33de042dSApple OSS Distributions VM_FLAGS_ANYWHERE,
974*33de042dSApple OSS Distributions me_port,
975*33de042dSApple OSS Distributions 0, /* offset */
976*33de042dSApple OSS Distributions FALSE, /* copy */
977*33de042dSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
978*33de042dSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
979*33de042dSApple OSS Distributions VM_INHERIT_DEFAULT);
980*33de042dSApple OSS Distributions T_QUIET;
981*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_map() error 0x%x (%s)",
982*33de042dSApple OSS Distributions kr, mach_error_string(kr));
983*33de042dSApple OSS Distributions T_QUIET;
984*33de042dSApple OSS Distributions T_EXPECT_EQ(vm_addr, pre_vm_addr, "pre-warm mishap");
985*33de042dSApple OSS Distributions /* ... should not change footprint */
986*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
987*33de042dSApple OSS Distributions footprint_expected = footprint_before;
988*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
989*33de042dSApple OSS Distributions T_LOG("mapping ledger-tagged memory does not change phys_footprint");
990*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
991*33de042dSApple OSS Distributions "ledger-tagged mapping of %lld bytes: "
992*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
993*33de042dSApple OSS Distributions vm_size, footprint_before, footprint_after,
994*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
995*33de042dSApple OSS Distributions
996*33de042dSApple OSS Distributions /* touching memory... */
997*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
998*33de042dSApple OSS Distributions dirty_size = vm_size / 2;
999*33de042dSApple OSS Distributions memset((char *)(uintptr_t)vm_addr, 'x', (size_t)dirty_size);
1000*33de042dSApple OSS Distributions /* ... should increase footprint */
1001*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1002*33de042dSApple OSS Distributions footprint_expected = footprint_before + dirty_size;
1003*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1004*33de042dSApple OSS Distributions T_LOG("modifying ledger-tagged memory increases phys_footprint");
1005*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1006*33de042dSApple OSS Distributions "touched %lld bytes: "
1007*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1008*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
1009*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1010*33de042dSApple OSS Distributions
1011*33de042dSApple OSS Distributions /* making it volatile... */
1012*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1013*33de042dSApple OSS Distributions state = VM_PURGABLE_VOLATILE;
1014*33de042dSApple OSS Distributions T_QUIET;
1015*33de042dSApple OSS Distributions T_ASSERT_EQ(mach_vm_purgable_control(mach_task_self(),
1016*33de042dSApple OSS Distributions vm_addr,
1017*33de042dSApple OSS Distributions VM_PURGABLE_SET_STATE,
1018*33de042dSApple OSS Distributions &state),
1019*33de042dSApple OSS Distributions KERN_SUCCESS,
1020*33de042dSApple OSS Distributions "vm_purgable_control(VOLATILE)");
1021*33de042dSApple OSS Distributions T_QUIET;
1022*33de042dSApple OSS Distributions T_ASSERT_EQ(state, VM_PURGABLE_NONVOLATILE,
1023*33de042dSApple OSS Distributions "memory was non-volatile");
1024*33de042dSApple OSS Distributions /* ... should decrease footprint */
1025*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1026*33de042dSApple OSS Distributions footprint_expected = footprint_before - dirty_size;
1027*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1028*33de042dSApple OSS Distributions T_LOG("making volatile decreases phys_footprint");
1029*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1030*33de042dSApple OSS Distributions "made volatile %lld dirty bytes: "
1031*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1032*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
1033*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1034*33de042dSApple OSS Distributions
1035*33de042dSApple OSS Distributions /* making it non-volatile... */
1036*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1037*33de042dSApple OSS Distributions state = VM_PURGABLE_NONVOLATILE;
1038*33de042dSApple OSS Distributions T_QUIET;
1039*33de042dSApple OSS Distributions T_ASSERT_EQ(mach_vm_purgable_control(mach_task_self(),
1040*33de042dSApple OSS Distributions vm_addr,
1041*33de042dSApple OSS Distributions VM_PURGABLE_SET_STATE,
1042*33de042dSApple OSS Distributions &state),
1043*33de042dSApple OSS Distributions KERN_SUCCESS,
1044*33de042dSApple OSS Distributions "vm_purgable_control(NONVOLATILE)");
1045*33de042dSApple OSS Distributions T_QUIET;
1046*33de042dSApple OSS Distributions T_ASSERT_EQ(state, VM_PURGABLE_VOLATILE,
1047*33de042dSApple OSS Distributions "memory was volatile");
1048*33de042dSApple OSS Distributions /* ... should increase footprint */
1049*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1050*33de042dSApple OSS Distributions footprint_expected = footprint_before + dirty_size;
1051*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1052*33de042dSApple OSS Distributions T_LOG("making non-volatile increases phys_footprint");
1053*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1054*33de042dSApple OSS Distributions "made non-volatile %lld dirty bytes: "
1055*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1056*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
1057*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1058*33de042dSApple OSS Distributions
1059*33de042dSApple OSS Distributions /* deallocating memory while holding memory entry... */
1060*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1061*33de042dSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), vm_addr, vm_size);
1062*33de042dSApple OSS Distributions T_QUIET;
1063*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_deallocate() error 0x%x (%s)",
1064*33de042dSApple OSS Distributions kr, mach_error_string(kr));
1065*33de042dSApple OSS Distributions /* ... should not change footprint */
1066*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1067*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1068*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1069*33de042dSApple OSS Distributions T_LOG("deallocating owned memory while holding memory entry "
1070*33de042dSApple OSS Distributions "does not change phys_footprint");
1071*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1072*33de042dSApple OSS Distributions "deallocated %lld dirty bytes: "
1073*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1074*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
1075*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1076*33de042dSApple OSS Distributions
1077*33de042dSApple OSS Distributions /* releasing the memory entry... */
1078*33de042dSApple OSS Distributions kr = mach_port_deallocate(mach_task_self(), me_port);
1079*33de042dSApple OSS Distributions T_QUIET;
1080*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "mach_port_deallocate() error 0x%x (%s)",
1081*33de042dSApple OSS Distributions kr, mach_error_string(kr));
1082*33de042dSApple OSS Distributions /* ... should decrease footprint */
1083*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1084*33de042dSApple OSS Distributions footprint_expected = footprint_before - dirty_size;
1085*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1086*33de042dSApple OSS Distributions T_LOG("releasing memory entry decreases phys_footprint");
1087*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1088*33de042dSApple OSS Distributions "made volatile %lld dirty bytes: "
1089*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1090*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
1091*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1092*33de042dSApple OSS Distributions }
1093*33de042dSApple OSS Distributions
1094*33de042dSApple OSS Distributions T_DECL(phys_footprint_ledger_owned,
1095*33de042dSApple OSS Distributions "phys_footprint for ledger-tagged memory ownership",
1096*33de042dSApple OSS Distributions T_META_LTEPHASE(LTE_POSTINIT), T_META_TAG_VM_PREFERRED)
1097*33de042dSApple OSS Distributions {
1098*33de042dSApple OSS Distributions uint64_t footprint_before, pagetable_before;
1099*33de042dSApple OSS Distributions uint64_t footprint_after, pagetable_after;
1100*33de042dSApple OSS Distributions uint64_t footprint_expected;
1101*33de042dSApple OSS Distributions kern_return_t kr;
1102*33de042dSApple OSS Distributions mach_vm_address_t pre_vm_addr, vm_addr;
1103*33de042dSApple OSS Distributions mach_vm_size_t vm_size, dirty_size, me_size;
1104*33de042dSApple OSS Distributions mach_port_t me_port;
1105*33de042dSApple OSS Distributions
1106*33de042dSApple OSS Distributions /* pre-warm to account for page table expansion */
1107*33de042dSApple OSS Distributions pre_vm_addr = pre_warm(MEM_SIZE);
1108*33de042dSApple OSS Distributions
1109*33de042dSApple OSS Distributions /* making a memory entry... */
1110*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1111*33de042dSApple OSS Distributions vm_size = MEM_SIZE;
1112*33de042dSApple OSS Distributions me_size = vm_size;
1113*33de042dSApple OSS Distributions me_port = MACH_PORT_NULL;
1114*33de042dSApple OSS Distributions kr = mach_make_memory_entry_64(mach_task_self(),
1115*33de042dSApple OSS Distributions &me_size,
1116*33de042dSApple OSS Distributions 0,
1117*33de042dSApple OSS Distributions (MAP_MEM_NAMED_CREATE |
1118*33de042dSApple OSS Distributions MAP_MEM_LEDGER_TAGGED |
1119*33de042dSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE),
1120*33de042dSApple OSS Distributions &me_port,
1121*33de042dSApple OSS Distributions MACH_PORT_NULL);
1122*33de042dSApple OSS Distributions T_QUIET;
1123*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "make_memory_entry() error 0x%x (%s)",
1124*33de042dSApple OSS Distributions kr, mach_error_string(kr));
1125*33de042dSApple OSS Distributions T_QUIET;
1126*33de042dSApple OSS Distributions T_EXPECT_EQ(me_size, vm_size, "memory entry size mismatch");
1127*33de042dSApple OSS Distributions /* ... should not change footprint */
1128*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1129*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1130*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1131*33de042dSApple OSS Distributions T_LOG("making a memory entry does not change phys_footprint");
1132*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1133*33de042dSApple OSS Distributions "making a memory entry of %lld bytes: "
1134*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1135*33de042dSApple OSS Distributions vm_size, footprint_before, footprint_after,
1136*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1137*33de042dSApple OSS Distributions
1138*33de042dSApple OSS Distributions /* mapping ledger-tagged virtual memory... */
1139*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1140*33de042dSApple OSS Distributions vm_addr = 0;
1141*33de042dSApple OSS Distributions kr = mach_vm_map(mach_task_self(), &vm_addr, vm_size,
1142*33de042dSApple OSS Distributions 0, /* mask */
1143*33de042dSApple OSS Distributions VM_FLAGS_ANYWHERE,
1144*33de042dSApple OSS Distributions me_port,
1145*33de042dSApple OSS Distributions 0, /* offset */
1146*33de042dSApple OSS Distributions FALSE, /* copy */
1147*33de042dSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
1148*33de042dSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
1149*33de042dSApple OSS Distributions VM_INHERIT_DEFAULT);
1150*33de042dSApple OSS Distributions T_QUIET;
1151*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_map() error 0x%x (%s)",
1152*33de042dSApple OSS Distributions kr, mach_error_string(kr));
1153*33de042dSApple OSS Distributions T_QUIET;
1154*33de042dSApple OSS Distributions T_EXPECT_EQ(vm_addr, pre_vm_addr, "pre-warm mishap");
1155*33de042dSApple OSS Distributions /* ... should not change footprint */
1156*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1157*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1158*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1159*33de042dSApple OSS Distributions T_LOG("mapping ledger-tagged memory does not change phys_footprint");
1160*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1161*33de042dSApple OSS Distributions "ledger-tagged mapping of %lld bytes: "
1162*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1163*33de042dSApple OSS Distributions vm_size, footprint_before, footprint_after,
1164*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1165*33de042dSApple OSS Distributions
1166*33de042dSApple OSS Distributions /* touching memory... */
1167*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1168*33de042dSApple OSS Distributions dirty_size = vm_size / 2;
1169*33de042dSApple OSS Distributions memset((char *)(uintptr_t)vm_addr, 'x', (size_t)dirty_size);
1170*33de042dSApple OSS Distributions /* ... should increase footprint */
1171*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1172*33de042dSApple OSS Distributions footprint_expected = footprint_before + dirty_size;
1173*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1174*33de042dSApple OSS Distributions T_LOG("modifying ledger-tagged memory increases phys_footprint");
1175*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1176*33de042dSApple OSS Distributions "touched %lld bytes: "
1177*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1178*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
1179*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1180*33de042dSApple OSS Distributions
1181*33de042dSApple OSS Distributions /* deallocating memory while holding memory entry... */
1182*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1183*33de042dSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), vm_addr, vm_size);
1184*33de042dSApple OSS Distributions T_QUIET;
1185*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_deallocate() error 0x%x (%s)",
1186*33de042dSApple OSS Distributions kr, mach_error_string(kr));
1187*33de042dSApple OSS Distributions /* ... should not change footprint */
1188*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1189*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1190*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1191*33de042dSApple OSS Distributions T_LOG("deallocating owned memory while holding memory entry "
1192*33de042dSApple OSS Distributions "does not change phys_footprint");
1193*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1194*33de042dSApple OSS Distributions "deallocated %lld dirty bytes: "
1195*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1196*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
1197*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1198*33de042dSApple OSS Distributions
1199*33de042dSApple OSS Distributions /* releasing the memory entry... */
1200*33de042dSApple OSS Distributions kr = mach_port_deallocate(mach_task_self(), me_port);
1201*33de042dSApple OSS Distributions T_QUIET;
1202*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "mach_port_deallocate() error 0x%x (%s)",
1203*33de042dSApple OSS Distributions kr, mach_error_string(kr));
1204*33de042dSApple OSS Distributions /* ... should decrease footprint */
1205*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1206*33de042dSApple OSS Distributions footprint_expected = footprint_before - dirty_size;
1207*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1208*33de042dSApple OSS Distributions T_LOG("releasing memory entry decreases phys_footprint");
1209*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1210*33de042dSApple OSS Distributions "made volatile %lld dirty bytes: "
1211*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1212*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
1213*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1214*33de042dSApple OSS Distributions }
1215*33de042dSApple OSS Distributions
1216*33de042dSApple OSS Distributions T_DECL(phys_footprint_no_footprint_for_debug,
1217*33de042dSApple OSS Distributions "phys_footprint for no_footprint_for_debug",
1218*33de042dSApple OSS Distributions T_META_LTEPHASE(LTE_POSTINIT), T_META_TAG_VM_PREFERRED)
1219*33de042dSApple OSS Distributions {
1220*33de042dSApple OSS Distributions uint64_t footprint_before, pagetable_before;
1221*33de042dSApple OSS Distributions uint64_t footprint_after, pagetable_after;
1222*33de042dSApple OSS Distributions uint64_t footprint_expected;
1223*33de042dSApple OSS Distributions kern_return_t kr;
1224*33de042dSApple OSS Distributions mach_vm_address_t pre_vm_addr, vm_addr;
1225*33de042dSApple OSS Distributions mach_vm_size_t vm_size, dirty_size, me_size;
1226*33de042dSApple OSS Distributions mach_port_t me_port;
1227*33de042dSApple OSS Distributions int new_value, ret;
1228*33de042dSApple OSS Distributions
1229*33de042dSApple OSS Distributions /* pre-warm to account for page table expansion */
1230*33de042dSApple OSS Distributions pre_vm_addr = pre_warm(MEM_SIZE);
1231*33de042dSApple OSS Distributions
1232*33de042dSApple OSS Distributions /* making a memory entry... */
1233*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1234*33de042dSApple OSS Distributions vm_size = MEM_SIZE;
1235*33de042dSApple OSS Distributions me_size = vm_size;
1236*33de042dSApple OSS Distributions me_port = MACH_PORT_NULL;
1237*33de042dSApple OSS Distributions kr = mach_make_memory_entry_64(mach_task_self(),
1238*33de042dSApple OSS Distributions &me_size,
1239*33de042dSApple OSS Distributions 0,
1240*33de042dSApple OSS Distributions (MAP_MEM_NAMED_CREATE |
1241*33de042dSApple OSS Distributions MAP_MEM_LEDGER_TAGGED |
1242*33de042dSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE),
1243*33de042dSApple OSS Distributions &me_port,
1244*33de042dSApple OSS Distributions MACH_PORT_NULL);
1245*33de042dSApple OSS Distributions T_QUIET;
1246*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "make_memory_entry() error 0x%x (%s)",
1247*33de042dSApple OSS Distributions kr, mach_error_string(kr));
1248*33de042dSApple OSS Distributions T_QUIET;
1249*33de042dSApple OSS Distributions T_EXPECT_EQ(me_size, vm_size, "memory entry size mismatch");
1250*33de042dSApple OSS Distributions /* ... should not change footprint */
1251*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1252*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1253*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1254*33de042dSApple OSS Distributions T_LOG("making a memory entry does not change phys_footprint");
1255*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1256*33de042dSApple OSS Distributions "making a memory entry of %lld bytes: "
1257*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1258*33de042dSApple OSS Distributions vm_size, footprint_before, footprint_after,
1259*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1260*33de042dSApple OSS Distributions
1261*33de042dSApple OSS Distributions /* pretending to call from the kernel should fail */
1262*33de042dSApple OSS Distributions kr = mach_memory_entry_ownership(me_port,
1263*33de042dSApple OSS Distributions mach_task_self(),
1264*33de042dSApple OSS Distributions VM_LEDGER_TAG_DEFAULT,
1265*33de042dSApple OSS Distributions VM_LEDGER_FLAG_FROM_KERNEL);
1266*33de042dSApple OSS Distributions T_QUIET;
1267*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_INVALID_ARGUMENT,
1268*33de042dSApple OSS Distributions "mach_memory_entry_ownership(FROM_KERNEL) fails");
1269*33de042dSApple OSS Distributions
1270*33de042dSApple OSS Distributions /* trying to hide debug memory from footprint while not allowed */
1271*33de042dSApple OSS Distributions kr = mach_memory_entry_ownership(me_port,
1272*33de042dSApple OSS Distributions mach_task_self(),
1273*33de042dSApple OSS Distributions VM_LEDGER_TAG_DEFAULT,
1274*33de042dSApple OSS Distributions VM_LEDGER_FLAG_NO_FOOTPRINT_FOR_DEBUG);
1275*33de042dSApple OSS Distributions T_QUIET;
1276*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_NO_ACCESS,
1277*33de042dSApple OSS Distributions "mach_memory_entry_ownership(NO_FOOTPRINT_FOR_DEBUG) fails without sysctl");
1278*33de042dSApple OSS Distributions
1279*33de042dSApple OSS Distributions /* let's get permission to hide debug memory */
1280*33de042dSApple OSS Distributions new_value = 1;
1281*33de042dSApple OSS Distributions ret = sysctlbyname("vm.task_no_footprint_for_debug", NULL, NULL, &new_value, sizeof(new_value));
1282*33de042dSApple OSS Distributions if (ret == -1 && errno == ENOENT) {
1283*33de042dSApple OSS Distributions T_SKIP("sysctlbyname(vm.task_no_footprint_for_debug) ENOENT");
1284*33de042dSApple OSS Distributions }
1285*33de042dSApple OSS Distributions T_QUIET;
1286*33de042dSApple OSS Distributions T_ASSERT_POSIX_SUCCESS(ret, "sysctlbyname(vm.task_no_footprint_for_debug)");
1287*33de042dSApple OSS Distributions
1288*33de042dSApple OSS Distributions /* trying to hide debug memory from footprint while allowed */
1289*33de042dSApple OSS Distributions task_id_token_t token;
1290*33de042dSApple OSS Distributions kr = task_create_identity_token(mach_task_self(), &token);
1291*33de042dSApple OSS Distributions T_QUIET;
1292*33de042dSApple OSS Distributions T_ASSERT_EQ(kr, KERN_SUCCESS,
1293*33de042dSApple OSS Distributions "task_create_identity_token");
1294*33de042dSApple OSS Distributions
1295*33de042dSApple OSS Distributions kr = mach_memory_entry_ownership(me_port,
1296*33de042dSApple OSS Distributions token, /* this time also try calling it with id token */
1297*33de042dSApple OSS Distributions VM_LEDGER_TAG_DEFAULT,
1298*33de042dSApple OSS Distributions VM_LEDGER_FLAG_NO_FOOTPRINT_FOR_DEBUG);
1299*33de042dSApple OSS Distributions T_QUIET;
1300*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS,
1301*33de042dSApple OSS Distributions "mach_memory_entry_ownership(NO_FOOTPRINT_FOR_DEBUG) succeeds after sysctl");
1302*33de042dSApple OSS Distributions mach_port_deallocate(mach_task_self(), token);
1303*33de042dSApple OSS Distributions
1304*33de042dSApple OSS Distributions /* mapping ledger-tagged virtual memory... */
1305*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1306*33de042dSApple OSS Distributions vm_addr = 0;
1307*33de042dSApple OSS Distributions kr = mach_vm_map(mach_task_self(), &vm_addr, vm_size,
1308*33de042dSApple OSS Distributions 0, /* mask */
1309*33de042dSApple OSS Distributions VM_FLAGS_ANYWHERE,
1310*33de042dSApple OSS Distributions me_port,
1311*33de042dSApple OSS Distributions 0, /* offset */
1312*33de042dSApple OSS Distributions FALSE, /* copy */
1313*33de042dSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
1314*33de042dSApple OSS Distributions VM_PROT_READ | VM_PROT_WRITE,
1315*33de042dSApple OSS Distributions VM_INHERIT_DEFAULT);
1316*33de042dSApple OSS Distributions T_QUIET;
1317*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_map() error 0x%x (%s)",
1318*33de042dSApple OSS Distributions kr, mach_error_string(kr));
1319*33de042dSApple OSS Distributions T_QUIET;
1320*33de042dSApple OSS Distributions T_EXPECT_EQ(vm_addr, pre_vm_addr, "pre-warm mishap");
1321*33de042dSApple OSS Distributions /* ... should not change footprint */
1322*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1323*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1324*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1325*33de042dSApple OSS Distributions T_LOG("mapping ledger-tagged memory does not change phys_footprint");
1326*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1327*33de042dSApple OSS Distributions "ledger-tagged mapping of %lld bytes: "
1328*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1329*33de042dSApple OSS Distributions vm_size, footprint_before, footprint_after,
1330*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1331*33de042dSApple OSS Distributions
1332*33de042dSApple OSS Distributions /* touching memory... */
1333*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1334*33de042dSApple OSS Distributions dirty_size = vm_size / 2;
1335*33de042dSApple OSS Distributions memset((char *)(uintptr_t)vm_addr, 'x', (size_t)dirty_size);
1336*33de042dSApple OSS Distributions /* ... should not increase footprint */
1337*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1338*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1339*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1340*33de042dSApple OSS Distributions T_LOG("modifying no_footprint_for_debug memory does not increase phys_footprint");
1341*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1342*33de042dSApple OSS Distributions "touched %lld bytes: "
1343*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1344*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
1345*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1346*33de042dSApple OSS Distributions
1347*33de042dSApple OSS Distributions /* deallocating memory while holding memory entry... */
1348*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1349*33de042dSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), vm_addr, vm_size);
1350*33de042dSApple OSS Distributions T_QUIET;
1351*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_deallocate() error 0x%x (%s)",
1352*33de042dSApple OSS Distributions kr, mach_error_string(kr));
1353*33de042dSApple OSS Distributions /* ... should not change footprint */
1354*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1355*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1356*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1357*33de042dSApple OSS Distributions T_LOG("deallocating owned memory while holding memory entry "
1358*33de042dSApple OSS Distributions "does not change phys_footprint");
1359*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1360*33de042dSApple OSS Distributions "deallocated %lld dirty bytes: "
1361*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1362*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
1363*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1364*33de042dSApple OSS Distributions
1365*33de042dSApple OSS Distributions /* releasing the memory entry... */
1366*33de042dSApple OSS Distributions kr = mach_port_deallocate(mach_task_self(), me_port);
1367*33de042dSApple OSS Distributions T_QUIET;
1368*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "mach_port_deallocate() error 0x%x (%s)",
1369*33de042dSApple OSS Distributions kr, mach_error_string(kr));
1370*33de042dSApple OSS Distributions /* ... should not change footprint */
1371*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1372*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1373*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1374*33de042dSApple OSS Distributions T_LOG("releasing memory entry does not change phys_footprint");
1375*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1376*33de042dSApple OSS Distributions "made volatile %lld dirty bytes: "
1377*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1378*33de042dSApple OSS Distributions dirty_size, footprint_before, footprint_after,
1379*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1380*33de042dSApple OSS Distributions }
1381*33de042dSApple OSS Distributions #endif /* MAP_MEM_LEDGER_TAGGED */
1382*33de042dSApple OSS Distributions
1383*33de042dSApple OSS Distributions /* IOSurface code from: CoreImage/CoreImageTests/CIRender/SurfaceUtils.c */
1384*33de042dSApple OSS Distributions #include <CoreFoundation/CoreFoundation.h>
1385*33de042dSApple OSS Distributions #include <IOSurface/IOSurface.h>
1386*33de042dSApple OSS Distributions #include <IOSurface/IOSurfacePrivate.h>
1387*33de042dSApple OSS Distributions static size_t
bytes_per_element(uint32_t format)1388*33de042dSApple OSS Distributions bytes_per_element(uint32_t format)
1389*33de042dSApple OSS Distributions {
1390*33de042dSApple OSS Distributions size_t bpe = 0;
1391*33de042dSApple OSS Distributions switch (format) {
1392*33de042dSApple OSS Distributions case 32: // kCVPixelFormatType_32ARGB (ARGB8)
1393*33de042dSApple OSS Distributions bpe = 4;
1394*33de042dSApple OSS Distributions break;
1395*33de042dSApple OSS Distributions default:
1396*33de042dSApple OSS Distributions bpe = 0;
1397*33de042dSApple OSS Distributions break;
1398*33de042dSApple OSS Distributions }
1399*33de042dSApple OSS Distributions return bpe;
1400*33de042dSApple OSS Distributions }
1401*33de042dSApple OSS Distributions static size_t
bytes_per_pixel(uint32_t format)1402*33de042dSApple OSS Distributions bytes_per_pixel(uint32_t format)
1403*33de042dSApple OSS Distributions {
1404*33de042dSApple OSS Distributions size_t bpe = 0;
1405*33de042dSApple OSS Distributions switch (format) {
1406*33de042dSApple OSS Distributions case 32: // kCVPixelFormatType_32ARGB (ARGB8)
1407*33de042dSApple OSS Distributions bpe = 4;
1408*33de042dSApple OSS Distributions break;
1409*33de042dSApple OSS Distributions default:
1410*33de042dSApple OSS Distributions bpe = 0;
1411*33de042dSApple OSS Distributions break;
1412*33de042dSApple OSS Distributions }
1413*33de042dSApple OSS Distributions return bpe;
1414*33de042dSApple OSS Distributions }
1415*33de042dSApple OSS Distributions static inline size_t
roundSizeToMultiple(size_t size,size_t mult)1416*33de042dSApple OSS Distributions roundSizeToMultiple(size_t size, size_t mult)
1417*33de042dSApple OSS Distributions {
1418*33de042dSApple OSS Distributions return ((size + mult - 1) / mult) * mult;
1419*33de042dSApple OSS Distributions }
1420*33de042dSApple OSS Distributions static inline void
setIntValue(CFMutableDictionaryRef dict,const CFStringRef key,int value)1421*33de042dSApple OSS Distributions setIntValue(CFMutableDictionaryRef dict, const CFStringRef key, int value)
1422*33de042dSApple OSS Distributions {
1423*33de042dSApple OSS Distributions CFNumberRef number = CFNumberCreate(0, kCFNumberIntType, &value);
1424*33de042dSApple OSS Distributions CFDictionarySetValue(dict, key, number);
1425*33de042dSApple OSS Distributions CFRelease(number);
1426*33de042dSApple OSS Distributions }
1427*33de042dSApple OSS Distributions static inline void
setBoolValue(CFMutableDictionaryRef dict,const CFStringRef key,bool value)1428*33de042dSApple OSS Distributions setBoolValue(CFMutableDictionaryRef dict, const CFStringRef key, bool value)
1429*33de042dSApple OSS Distributions {
1430*33de042dSApple OSS Distributions CFDictionarySetValue(dict, key, value ? kCFBooleanTrue : kCFBooleanFalse);
1431*33de042dSApple OSS Distributions }
1432*33de042dSApple OSS Distributions typedef void (^SurfacePlaneBlock)(void *data, size_t planeIndex, size_t width, size_t height, size_t rowbytes);
1433*33de042dSApple OSS Distributions static IOReturn
SurfaceApplyPlaneBlock(IOSurfaceRef surface,SurfacePlaneBlock block)1434*33de042dSApple OSS Distributions SurfaceApplyPlaneBlock(IOSurfaceRef surface, SurfacePlaneBlock block)
1435*33de042dSApple OSS Distributions {
1436*33de042dSApple OSS Distributions if (surface == nil || block == nil) {
1437*33de042dSApple OSS Distributions return kIOReturnBadArgument;
1438*33de042dSApple OSS Distributions }
1439*33de042dSApple OSS Distributions
1440*33de042dSApple OSS Distributions IOReturn result = kIOReturnSuccess;
1441*33de042dSApple OSS Distributions size_t planeCount = IOSurfaceGetPlaneCount(surface);
1442*33de042dSApple OSS Distributions
1443*33de042dSApple OSS Distributions if (planeCount == 0) {
1444*33de042dSApple OSS Distributions result = IOSurfaceLock(surface, 0, NULL);
1445*33de042dSApple OSS Distributions if (result != kIOReturnSuccess) {
1446*33de042dSApple OSS Distributions return result;
1447*33de042dSApple OSS Distributions }
1448*33de042dSApple OSS Distributions
1449*33de042dSApple OSS Distributions void* base = IOSurfaceGetBaseAddress(surface);
1450*33de042dSApple OSS Distributions size_t rb = IOSurfaceGetBytesPerRow(surface);
1451*33de042dSApple OSS Distributions size_t w = IOSurfaceGetWidth(surface);
1452*33de042dSApple OSS Distributions size_t h = IOSurfaceGetHeight(surface);
1453*33de042dSApple OSS Distributions
1454*33de042dSApple OSS Distributions if (base && rb && w && h) {
1455*33de042dSApple OSS Distributions block(base, 0, w, h, rb);
1456*33de042dSApple OSS Distributions }
1457*33de042dSApple OSS Distributions
1458*33de042dSApple OSS Distributions IOSurfaceUnlock(surface, 0, NULL);
1459*33de042dSApple OSS Distributions } else if (planeCount == 2) {
1460*33de042dSApple OSS Distributions for (size_t i = 0; i < planeCount; i++) {
1461*33de042dSApple OSS Distributions result = IOSurfaceLock(surface, 0, NULL);
1462*33de042dSApple OSS Distributions if (result != kIOReturnSuccess) {
1463*33de042dSApple OSS Distributions return result;
1464*33de042dSApple OSS Distributions }
1465*33de042dSApple OSS Distributions
1466*33de042dSApple OSS Distributions void* base = IOSurfaceGetBaseAddressOfPlane(surface, i);
1467*33de042dSApple OSS Distributions size_t rb = IOSurfaceGetBytesPerRowOfPlane(surface, i);
1468*33de042dSApple OSS Distributions size_t w = IOSurfaceGetWidthOfPlane(surface, i);
1469*33de042dSApple OSS Distributions size_t h = IOSurfaceGetHeightOfPlane(surface, i);
1470*33de042dSApple OSS Distributions
1471*33de042dSApple OSS Distributions if (base && rb && w && h) {
1472*33de042dSApple OSS Distributions block(base, i, w, h, rb);
1473*33de042dSApple OSS Distributions }
1474*33de042dSApple OSS Distributions
1475*33de042dSApple OSS Distributions IOSurfaceUnlock(surface, 0, NULL);
1476*33de042dSApple OSS Distributions }
1477*33de042dSApple OSS Distributions }
1478*33de042dSApple OSS Distributions return result;
1479*33de042dSApple OSS Distributions }
1480*33de042dSApple OSS Distributions static void
ClearSurface(IOSurfaceRef surface)1481*33de042dSApple OSS Distributions ClearSurface(IOSurfaceRef surface)
1482*33de042dSApple OSS Distributions {
1483*33de042dSApple OSS Distributions const int zero = 0;
1484*33de042dSApple OSS Distributions (void) SurfaceApplyPlaneBlock(surface, ^(void *p, size_t i, __unused size_t w, size_t h, size_t rb)
1485*33de042dSApple OSS Distributions {
1486*33de042dSApple OSS Distributions if (i == 0) {
1487*33de042dSApple OSS Distributions memset(p, zero, rb * h);
1488*33de042dSApple OSS Distributions } else {
1489*33de042dSApple OSS Distributions memset(p, 128, rb * h);
1490*33de042dSApple OSS Distributions }
1491*33de042dSApple OSS Distributions });
1492*33de042dSApple OSS Distributions }
1493*33de042dSApple OSS Distributions static size_t
SurfaceGetMemorySize(IOSurfaceRef surface)1494*33de042dSApple OSS Distributions SurfaceGetMemorySize(IOSurfaceRef surface)
1495*33de042dSApple OSS Distributions {
1496*33de042dSApple OSS Distributions size_t planeCount = IOSurfaceGetPlaneCount(surface);
1497*33de042dSApple OSS Distributions
1498*33de042dSApple OSS Distributions if (planeCount == 0) {
1499*33de042dSApple OSS Distributions size_t rb = IOSurfaceGetBytesPerRow(surface);
1500*33de042dSApple OSS Distributions size_t h = IOSurfaceGetHeight(surface);
1501*33de042dSApple OSS Distributions return rb * h;
1502*33de042dSApple OSS Distributions } else if (planeCount == 2) {
1503*33de042dSApple OSS Distributions size_t rb0 = IOSurfaceGetBytesPerRowOfPlane(surface, 0);
1504*33de042dSApple OSS Distributions size_t h0 = IOSurfaceGetHeightOfPlane(surface, 0);
1505*33de042dSApple OSS Distributions size_t rb1 = IOSurfaceGetBytesPerRowOfPlane(surface, 1);
1506*33de042dSApple OSS Distributions size_t h1 = IOSurfaceGetHeightOfPlane(surface, 1);
1507*33de042dSApple OSS Distributions return rb0 * h0 + rb1 * h1;
1508*33de042dSApple OSS Distributions }
1509*33de042dSApple OSS Distributions return 0;
1510*33de042dSApple OSS Distributions }
1511*33de042dSApple OSS Distributions static IOSurfaceRef
CreateSurface(uint32_t pixelsWide,uint32_t pixelsHigh,uint32_t rowBytesAlignment,uint32_t fmt,bool purgeable,bool clear)1512*33de042dSApple OSS Distributions CreateSurface(uint32_t pixelsWide, uint32_t pixelsHigh, uint32_t rowBytesAlignment, uint32_t fmt, bool purgeable, bool clear)
1513*33de042dSApple OSS Distributions {
1514*33de042dSApple OSS Distributions IOSurfaceRef surface = nil;
1515*33de042dSApple OSS Distributions
1516*33de042dSApple OSS Distributions if (pixelsWide < 1 || pixelsHigh < 1 || fmt == 0) {
1517*33de042dSApple OSS Distributions return nil;
1518*33de042dSApple OSS Distributions }
1519*33de042dSApple OSS Distributions
1520*33de042dSApple OSS Distributions size_t bpp = bytes_per_pixel(fmt);
1521*33de042dSApple OSS Distributions size_t bpe = bytes_per_element(fmt);
1522*33de042dSApple OSS Distributions if (bpp == 0 || bpe == 0) {
1523*33de042dSApple OSS Distributions return nil;
1524*33de042dSApple OSS Distributions }
1525*33de042dSApple OSS Distributions
1526*33de042dSApple OSS Distributions size_t rowbytes = pixelsWide * bpp;
1527*33de042dSApple OSS Distributions if (rowBytesAlignment == 0) {
1528*33de042dSApple OSS Distributions rowBytesAlignment = 16;
1529*33de042dSApple OSS Distributions }
1530*33de042dSApple OSS Distributions rowbytes = roundSizeToMultiple(rowbytes, rowBytesAlignment);
1531*33de042dSApple OSS Distributions
1532*33de042dSApple OSS Distributions CFMutableDictionaryRef props = CFDictionaryCreateMutable(0, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
1533*33de042dSApple OSS Distributions setIntValue(props, kIOSurfaceBytesPerRow, (int)rowbytes);
1534*33de042dSApple OSS Distributions setIntValue(props, kIOSurfaceWidth, (int)pixelsWide);
1535*33de042dSApple OSS Distributions setIntValue(props, kIOSurfaceHeight, (int)pixelsHigh);
1536*33de042dSApple OSS Distributions setIntValue(props, kIOSurfacePixelFormat, (int)fmt);
1537*33de042dSApple OSS Distributions #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
1538*33de042dSApple OSS Distributions setBoolValue(props, kIOSurfaceNonPurgeable, !purgeable);
1539*33de042dSApple OSS Distributions #else /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
1540*33de042dSApple OSS Distributions (void)purgeable;
1541*33de042dSApple OSS Distributions #endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
1542*33de042dSApple OSS Distributions {
1543*33de042dSApple OSS Distributions if (bpe != bpp) { // i.e. a 422 format such as 'yuvf' etc.
1544*33de042dSApple OSS Distributions setIntValue(props, kIOSurfaceElementWidth, 2);
1545*33de042dSApple OSS Distributions setIntValue(props, kIOSurfaceElementHeight, 1);
1546*33de042dSApple OSS Distributions }
1547*33de042dSApple OSS Distributions setIntValue(props, kIOSurfaceBytesPerElement, (int)bpe);
1548*33de042dSApple OSS Distributions }
1549*33de042dSApple OSS Distributions
1550*33de042dSApple OSS Distributions surface = IOSurfaceCreate(props);
1551*33de042dSApple OSS Distributions
1552*33de042dSApple OSS Distributions if (clear) {
1553*33de042dSApple OSS Distributions ClearSurface(surface);
1554*33de042dSApple OSS Distributions }
1555*33de042dSApple OSS Distributions
1556*33de042dSApple OSS Distributions CFRelease(props);
1557*33de042dSApple OSS Distributions return surface;
1558*33de042dSApple OSS Distributions }
1559*33de042dSApple OSS Distributions T_DECL(phys_footprint_purgeable_iokit,
1560*33de042dSApple OSS Distributions "phys_footprint for purgeable IOKit memory",
1561*33de042dSApple OSS Distributions T_META_LTEPHASE(LTE_POSTINIT), T_META_TAG_VM_PREFERRED)
1562*33de042dSApple OSS Distributions {
1563*33de042dSApple OSS Distributions uint64_t footprint_before, pagetable_before;
1564*33de042dSApple OSS Distributions uint64_t footprint_after, pagetable_after;
1565*33de042dSApple OSS Distributions uint64_t footprint_expected, footprint_delta_slop;
1566*33de042dSApple OSS Distributions int64_t footprint_delta;
1567*33de042dSApple OSS Distributions IOSurfaceRef surface;
1568*33de042dSApple OSS Distributions uint32_t old_state;
1569*33de042dSApple OSS Distributions uint64_t surface_size;
1570*33de042dSApple OSS Distributions
1571*33de042dSApple OSS Distributions T_SETUPBEGIN;
1572*33de042dSApple OSS Distributions footprint_delta_slop = 8 * vm_kernel_page_size;
1573*33de042dSApple OSS Distributions ledger_init();
1574*33de042dSApple OSS Distributions surface = CreateSurface(1024, 1024, 0, 32, true, true);
1575*33de042dSApple OSS Distributions IOSurfaceSetPurgeable(surface, kIOSurfacePurgeableVolatile, &old_state);
1576*33de042dSApple OSS Distributions IOSurfaceSetPurgeable(surface, kIOSurfacePurgeableNonVolatile, &old_state);
1577*33de042dSApple OSS Distributions CFRelease(surface);
1578*33de042dSApple OSS Distributions T_SETUPEND;
1579*33de042dSApple OSS Distributions
1580*33de042dSApple OSS Distributions surface_size = 1024 * 1024 * 4;
1581*33de042dSApple OSS Distributions
1582*33de042dSApple OSS Distributions /* create IOsurface: footprint grows */
1583*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1584*33de042dSApple OSS Distributions surface = CreateSurface(1024, 1024, 0, 32, true, true);
1585*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1586*33de042dSApple OSS Distributions if (legacy_footprint) {
1587*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1588*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1589*33de042dSApple OSS Distributions footprint_delta = (int64_t)(footprint_after - footprint_expected);
1590*33de042dSApple OSS Distributions T_LOG("LEGACY FOOTPRINT: creating purgeable IOSurface: no footprint impact");
1591*33de042dSApple OSS Distributions T_EXPECT_LE((uint64_t)llabs(footprint_delta), footprint_delta_slop,
1592*33de042dSApple OSS Distributions "create purgeable IOSurface %lld bytes: "
1593*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1594*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1595*33de042dSApple OSS Distributions footprint_expected, footprint_delta);
1596*33de042dSApple OSS Distributions } else {
1597*33de042dSApple OSS Distributions footprint_expected = footprint_before + surface_size;
1598*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1599*33de042dSApple OSS Distributions footprint_delta = (int64_t)(footprint_after - footprint_expected);
1600*33de042dSApple OSS Distributions T_LOG("creating purgeable IOSurface increases phys_footprint");
1601*33de042dSApple OSS Distributions T_EXPECT_LE((uint64_t)llabs(footprint_delta), footprint_delta_slop,
1602*33de042dSApple OSS Distributions "create purgeable IOSurface %lld bytes: "
1603*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1604*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1605*33de042dSApple OSS Distributions footprint_expected, footprint_delta);
1606*33de042dSApple OSS Distributions }
1607*33de042dSApple OSS Distributions
1608*33de042dSApple OSS Distributions /* make IOSurface volatile: footprint shrinks */
1609*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1610*33de042dSApple OSS Distributions IOSurfaceSetPurgeable(surface, kIOSurfacePurgeableVolatile, &old_state);
1611*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1612*33de042dSApple OSS Distributions if (legacy_footprint) {
1613*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1614*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1615*33de042dSApple OSS Distributions T_LOG("LEGACY FOOTPRINT: volatile IOSurface: no footprint impact");
1616*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1617*33de042dSApple OSS Distributions "volatile IOSurface %lld bytes: "
1618*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1619*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1620*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1621*33de042dSApple OSS Distributions } else {
1622*33de042dSApple OSS Distributions footprint_expected = footprint_before - surface_size;
1623*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1624*33de042dSApple OSS Distributions T_LOG("making IOSurface volatile decreases phys_footprint");
1625*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1626*33de042dSApple OSS Distributions "made volatile %lld bytes: "
1627*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1628*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1629*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1630*33de042dSApple OSS Distributions }
1631*33de042dSApple OSS Distributions
1632*33de042dSApple OSS Distributions /* make IOSurface non-volatile: footprint grows */
1633*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1634*33de042dSApple OSS Distributions IOSurfaceSetPurgeable(surface, kIOSurfacePurgeableNonVolatile, &old_state);
1635*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1636*33de042dSApple OSS Distributions if (legacy_footprint) {
1637*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1638*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1639*33de042dSApple OSS Distributions T_LOG("LEGACY FOOTPRINT: non-volatile IOSurface: no footprint impact");
1640*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1641*33de042dSApple OSS Distributions "non-volatile IOSurface %lld bytes: "
1642*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1643*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1644*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1645*33de042dSApple OSS Distributions } else {
1646*33de042dSApple OSS Distributions footprint_expected = footprint_before + surface_size;
1647*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1648*33de042dSApple OSS Distributions T_LOG("making IOSurface non-volatile increases phys_footprint");
1649*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1650*33de042dSApple OSS Distributions "made non-volatile %lld bytes: "
1651*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1652*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1653*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1654*33de042dSApple OSS Distributions }
1655*33de042dSApple OSS Distributions
1656*33de042dSApple OSS Distributions /* accessing IOSurface re-mapping: no footprint impact */
1657*33de042dSApple OSS Distributions
1658*33de042dSApple OSS Distributions /* deallocating IOSurface re-mapping: no footprint impact */
1659*33de042dSApple OSS Distributions
1660*33de042dSApple OSS Distributions /* release IOSurface: footprint shrinks */
1661*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1662*33de042dSApple OSS Distributions CFRelease(surface);
1663*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1664*33de042dSApple OSS Distributions if (legacy_footprint) {
1665*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1666*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1667*33de042dSApple OSS Distributions T_LOG("LEGACY FOOTPRINT: release IOSurface: no footprint impact");
1668*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1669*33de042dSApple OSS Distributions "releasing IOSurface %lld bytes: "
1670*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1671*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1672*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1673*33de042dSApple OSS Distributions } else {
1674*33de042dSApple OSS Distributions footprint_expected = footprint_before - surface_size;
1675*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1676*33de042dSApple OSS Distributions T_LOG("releasing IOSurface decreases phys_footprint");
1677*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1678*33de042dSApple OSS Distributions "released IOSurface %lld bytes: "
1679*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1680*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1681*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1682*33de042dSApple OSS Distributions }
1683*33de042dSApple OSS Distributions }
1684*33de042dSApple OSS Distributions
1685*33de042dSApple OSS Distributions #if (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR)
1686*33de042dSApple OSS Distributions T_DECL(phys_footprint_nonpurgeable_iokit,
1687*33de042dSApple OSS Distributions "phys_footprint for non-purgeable IOKit memory",
1688*33de042dSApple OSS Distributions T_META_LTEPHASE(LTE_POSTINIT), T_META_TAG_VM_PREFERRED)
1689*33de042dSApple OSS Distributions {
1690*33de042dSApple OSS Distributions uint64_t footprint_before, pagetable_before;
1691*33de042dSApple OSS Distributions uint64_t footprint_after, pagetable_after;
1692*33de042dSApple OSS Distributions uint64_t footprint_expected, footprint_delta_slop;
1693*33de042dSApple OSS Distributions int64_t footprint_delta;
1694*33de042dSApple OSS Distributions IOSurfaceRef surface;
1695*33de042dSApple OSS Distributions uint64_t surface_size;
1696*33de042dSApple OSS Distributions void *map_base;
1697*33de042dSApple OSS Distributions size_t map_size;
1698*33de042dSApple OSS Distributions mach_vm_address_t remap_addr;
1699*33de042dSApple OSS Distributions kern_return_t kr;
1700*33de042dSApple OSS Distributions vm_prot_t cur_prot, max_prot;
1701*33de042dSApple OSS Distributions uint32_t old_state;
1702*33de042dSApple OSS Distributions
1703*33de042dSApple OSS Distributions
1704*33de042dSApple OSS Distributions T_SETUPBEGIN;
1705*33de042dSApple OSS Distributions ledger_init();
1706*33de042dSApple OSS Distributions surface = CreateSurface(1024, 1024, 0, 32, false, true);
1707*33de042dSApple OSS Distributions CFRelease(surface);
1708*33de042dSApple OSS Distributions footprint_delta_slop = 8 * vm_kernel_page_size;
1709*33de042dSApple OSS Distributions T_SETUPEND;
1710*33de042dSApple OSS Distributions
1711*33de042dSApple OSS Distributions surface_size = 1024 * 1024 * 4;
1712*33de042dSApple OSS Distributions
1713*33de042dSApple OSS Distributions /* create IOsurface: footprint grows */
1714*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1715*33de042dSApple OSS Distributions surface = CreateSurface(1024, 1024, 0, 32, false, true);
1716*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1717*33de042dSApple OSS Distributions footprint_expected = footprint_before + surface_size;
1718*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1719*33de042dSApple OSS Distributions footprint_delta = (int64_t)(footprint_after - footprint_expected);
1720*33de042dSApple OSS Distributions T_LOG("creating non-purgeable IOSurface increases phys_footprint");
1721*33de042dSApple OSS Distributions T_EXPECT_LE((uint64_t)llabs(footprint_delta), footprint_delta_slop,
1722*33de042dSApple OSS Distributions "create non-purgeable IOSurface %lld bytes: "
1723*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1724*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1725*33de042dSApple OSS Distributions footprint_expected, footprint_delta);
1726*33de042dSApple OSS Distributions
1727*33de042dSApple OSS Distributions /* make IOSurface volatile: fail and no footprint impact */
1728*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1729*33de042dSApple OSS Distributions IOSurfaceSetPurgeable(surface, kIOSurfacePurgeableVolatile, &old_state);
1730*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1731*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1732*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1733*33de042dSApple OSS Distributions T_LOG("making non-purgeable IOSurface volatile: no footprint impact");
1734*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1735*33de042dSApple OSS Distributions "made volatile %lld non-purgeable bytes: "
1736*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1737*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1738*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1739*33de042dSApple OSS Distributions
1740*33de042dSApple OSS Distributions /* re-mapping IOSurface: no footprint impact */
1741*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1742*33de042dSApple OSS Distributions map_base = IOSurfaceGetBaseAddress(surface);
1743*33de042dSApple OSS Distributions map_size = SurfaceGetMemorySize(surface);
1744*33de042dSApple OSS Distributions // T_EXPECT_EQ(map_size, surface_size, "map_size %lld surface_size %lld",
1745*33de042dSApple OSS Distributions // map_size, surface_size);
1746*33de042dSApple OSS Distributions remap_addr = 0;
1747*33de042dSApple OSS Distributions kr = mach_vm_remap(mach_task_self(),
1748*33de042dSApple OSS Distributions &remap_addr,
1749*33de042dSApple OSS Distributions (mach_vm_size_t)surface_size,
1750*33de042dSApple OSS Distributions 0,
1751*33de042dSApple OSS Distributions VM_FLAGS_ANYWHERE,
1752*33de042dSApple OSS Distributions mach_task_self(),
1753*33de042dSApple OSS Distributions (mach_vm_address_t)map_base,
1754*33de042dSApple OSS Distributions FALSE, /* copy */
1755*33de042dSApple OSS Distributions &cur_prot,
1756*33de042dSApple OSS Distributions &max_prot,
1757*33de042dSApple OSS Distributions VM_INHERIT_DEFAULT);
1758*33de042dSApple OSS Distributions T_QUIET;
1759*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_remap() error 0x%x (%s)",
1760*33de042dSApple OSS Distributions kr, mach_error_string(kr));
1761*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1762*33de042dSApple OSS Distributions footprint_expected = footprint_before;
1763*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1764*33de042dSApple OSS Distributions T_LOG("re-mapping IOSurface does not impact phys_footprint");
1765*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1766*33de042dSApple OSS Distributions "remapping IOSurface %lld bytes: "
1767*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1768*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1769*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1770*33de042dSApple OSS Distributions
1771*33de042dSApple OSS Distributions /* accessing IOSurface re-mapping: footprint grows */
1772*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1773*33de042dSApple OSS Distributions memset((char *)(uintptr_t)remap_addr, 'p', (size_t)surface_size);
1774*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1775*33de042dSApple OSS Distributions footprint_expected = footprint_before + surface_size;
1776*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1777*33de042dSApple OSS Distributions T_LOG("accessing re-mapped IOSurface grows phys_footprint");
1778*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1779*33de042dSApple OSS Distributions "accessing remapped IOSurface %lld bytes: "
1780*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1781*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1782*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1783*33de042dSApple OSS Distributions
1784*33de042dSApple OSS Distributions /* deallocating IOSurface re-mapping: footprint shrinks */
1785*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1786*33de042dSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(),
1787*33de042dSApple OSS Distributions remap_addr,
1788*33de042dSApple OSS Distributions (mach_vm_size_t)surface_size);
1789*33de042dSApple OSS Distributions T_QUIET;
1790*33de042dSApple OSS Distributions T_EXPECT_EQ(kr, KERN_SUCCESS, "vm_deallocate() error 0x%x (%s)",
1791*33de042dSApple OSS Distributions kr, mach_error_string(kr));
1792*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1793*33de042dSApple OSS Distributions footprint_expected = footprint_before - surface_size;
1794*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1795*33de042dSApple OSS Distributions T_LOG("deallocating re-mapping of IOSurface shrinks phys_footprint");
1796*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1797*33de042dSApple OSS Distributions "deallocating remapped IOSurface %lld bytes: "
1798*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1799*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1800*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1801*33de042dSApple OSS Distributions
1802*33de042dSApple OSS Distributions /* release IOSurface: footprint shrinks */
1803*33de042dSApple OSS Distributions get_ledger_info(&footprint_before, &pagetable_before);
1804*33de042dSApple OSS Distributions CFRelease(surface);
1805*33de042dSApple OSS Distributions get_ledger_info(&footprint_after, &pagetable_after);
1806*33de042dSApple OSS Distributions footprint_expected = footprint_before - surface_size;
1807*33de042dSApple OSS Distributions footprint_expected += (pagetable_after - pagetable_before);
1808*33de042dSApple OSS Distributions T_LOG("releasing IOSurface decreases phys_footprint");
1809*33de042dSApple OSS Distributions T_EXPECT_EQ(footprint_after, footprint_expected,
1810*33de042dSApple OSS Distributions "released IOSurface %lld bytes: "
1811*33de042dSApple OSS Distributions "footprint %lld -> %lld expected %lld delta %lld",
1812*33de042dSApple OSS Distributions surface_size, footprint_before, footprint_after,
1813*33de042dSApple OSS Distributions footprint_expected, footprint_after - footprint_expected);
1814*33de042dSApple OSS Distributions }
1815*33de042dSApple OSS Distributions #endif /* (TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR) */
1816*33de042dSApple OSS Distributions
1817*33de042dSApple OSS Distributions #if 0
1818*33de042dSApple OSS Distributions #if LEGACY_FOOTPRINT_ENTITLED && defined(__arm64__)
1819*33de042dSApple OSS Distributions T_DECL(legacy_footprint_entitled_set_and_query,
1820*33de042dSApple OSS Distributions "legacy footprint entitled is sticky with memlimit set properties and can be queried",
1821*33de042dSApple OSS Distributions T_META_BOOTARGS_SET("legacy_footprint_entitlement_mode=3"), T_META_TAG_VM_PREFERRED)
1822*33de042dSApple OSS Distributions {
1823*33de042dSApple OSS Distributions int ret;
1824*33de042dSApple OSS Distributions int32_t max_task_pmem = 0, legacy_footprint_bonus_mb = 0;
1825*33de042dSApple OSS Distributions size_t size_max_task_pmem = sizeof(max_task_pmem);
1826*33de042dSApple OSS Distributions size_t size_legacy_footprint_bonus_mb = sizeof(legacy_footprint_bonus_mb);
1827*33de042dSApple OSS Distributions memorystatus_memlimit_properties2_t mmprops;
1828*33de042dSApple OSS Distributions
1829*33de042dSApple OSS Distributions /* Get the default limit */
1830*33de042dSApple OSS Distributions ret = sysctlbyname("kern.max_task_pmem", &max_task_pmem, &size_max_task_pmem, NULL, 0);
1831*33de042dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "call sysctlbyname to get max task physical memory.");
1832*33de042dSApple OSS Distributions
1833*33de042dSApple OSS Distributions ret = sysctlbyname("kern.legacy_footprint_bonus_mb", &legacy_footprint_bonus_mb,
1834*33de042dSApple OSS Distributions &size_legacy_footprint_bonus_mb, NULL, 0);
1835*33de042dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "call sysctlbyname to get the bonus value.");
1836*33de042dSApple OSS Distributions
1837*33de042dSApple OSS Distributions mmprops.v1.memlimit_active = -1;
1838*33de042dSApple OSS Distributions mmprops.v1.memlimit_inactive = -1;
1839*33de042dSApple OSS Distributions ret = memorystatus_control(MEMORYSTATUS_CMD_SET_MEMLIMIT_PROPERTIES, getpid(), 0, &mmprops.v1, sizeof(mmprops.v1));
1840*33de042dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control");
1841*33de042dSApple OSS Distributions
1842*33de042dSApple OSS Distributions /* Check our memlimt */
1843*33de042dSApple OSS Distributions ret = memorystatus_control(MEMORYSTATUS_CMD_GET_MEMLIMIT_PROPERTIES, getpid(), 0, &mmprops, sizeof(mmprops));
1844*33de042dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control");
1845*33de042dSApple OSS Distributions
1846*33de042dSApple OSS Distributions T_QUIET; T_ASSERT_EQ(mmprops.v1.memlimit_active, max_task_pmem + legacy_footprint_bonus_mb, "active limit");
1847*33de042dSApple OSS Distributions T_QUIET; T_ASSERT_EQ(mmprops.v1.memlimit_inactive, max_task_pmem + legacy_footprint_bonus_mb, "inactive limit");
1848*33de042dSApple OSS Distributions
1849*33de042dSApple OSS Distributions /* Verify MEMORYSTATUS_CMD_CONVERT_MEMLIMIT_MB */
1850*33de042dSApple OSS Distributions ret = memorystatus_control(MEMORYSTATUS_CMD_CONVERT_MEMLIMIT_MB, getpid(), (uint32_t) -1, NULL, 0);
1851*33de042dSApple OSS Distributions T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "memorystatus_control");
1852*33de042dSApple OSS Distributions T_QUIET; T_ASSERT_EQ(ret, max_task_pmem + legacy_footprint_bonus_mb, "got bonus adjustment");
1853*33de042dSApple OSS Distributions }
1854*33de042dSApple OSS Distributions #endif /* LEGACY_FOOTPRINT_ENTITLED && defined(__arm64__) */
1855*33de042dSApple OSS Distributions #endif
1856