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