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