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