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