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