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