xref: /xnu-11215.1.10/tests/vm/vm_compressor.c (revision 8d741a5de7ff4191bf97d57b9f54c2f6d4a15585) !
1*8d741a5dSApple OSS Distributions /*
2*8d741a5dSApple OSS Distributions  * Created by Jarrad Cisco on 09/28/2022.
3*8d741a5dSApple OSS Distributions  * Copyright © 2022 Apple. All rights reserved.
4*8d741a5dSApple OSS Distributions  *
5*8d741a5dSApple OSS Distributions  * Functional tests for VM compressor/swap.
6*8d741a5dSApple OSS Distributions  */
7*8d741a5dSApple OSS Distributions #include <sys/sysctl.h>
8*8d741a5dSApple OSS Distributions #include <darwintest.h>
9*8d741a5dSApple OSS Distributions #include <darwintest_utils.h>
10*8d741a5dSApple OSS Distributions #include <TargetConditionals.h>
11*8d741a5dSApple OSS Distributions 
12*8d741a5dSApple OSS Distributions #include <mach/mach.h>
13*8d741a5dSApple OSS Distributions #include <mach/mach_host.h>    /* host_statistics */
14*8d741a5dSApple OSS Distributions #include <vm/vm_compressor_info.h>
15*8d741a5dSApple OSS Distributions 
16*8d741a5dSApple OSS Distributions T_GLOBAL_META(
17*8d741a5dSApple OSS Distributions 	T_META_NAMESPACE("xnu.vm"),
18*8d741a5dSApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
19*8d741a5dSApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("VM"),
20*8d741a5dSApple OSS Distributions 	T_META_ASROOT(NO),
21*8d741a5dSApple OSS Distributions 	T_META_RUN_CONCURRENTLY(true));
22*8d741a5dSApple OSS Distributions 
23*8d741a5dSApple OSS Distributions T_DECL(swap_enabled,
24*8d741a5dSApple OSS Distributions     "Check that Swap is successfully enabled",
25*8d741a5dSApple OSS Distributions     T_META_ENABLED(TARGET_OS_OSX), T_META_TAG_VM_PREFERRED)
26*8d741a5dSApple OSS Distributions {
27*8d741a5dSApple OSS Distributions 	int swap_enabled;
28*8d741a5dSApple OSS Distributions 	size_t len = sizeof(swap_enabled);
29*8d741a5dSApple OSS Distributions 	int rc = sysctlbyname("vm.swap_enabled", &swap_enabled, &len, NULL, 0);
30*8d741a5dSApple OSS Distributions 	T_QUIET; T_ASSERT_POSIX_SUCCESS(rc, "Failed to query sysctl `vm.swap_enabled`");
31*8d741a5dSApple OSS Distributions 	T_EXPECT_EQ(swap_enabled, 1, "Check that vm.swap_enabled is set");
32*8d741a5dSApple OSS Distributions }
33*8d741a5dSApple OSS Distributions 
34*8d741a5dSApple OSS Distributions 
35*8d741a5dSApple OSS Distributions T_DECL(host_statistics_q_lens, "Check that the compressor queue lens sysctl works",
36*8d741a5dSApple OSS Distributions     T_META_REQUIRES_SYSCTL_EQ("kern.development", 1))
37*8d741a5dSApple OSS Distributions {
38*8d741a5dSApple OSS Distributions 	struct vm_compressor_q_lens d;
39*8d741a5dSApple OSS Distributions 	mach_msg_type_number_t vm_qlen_count = VM_COMPRESSOR_Q_LENS_COUNT;
40*8d741a5dSApple OSS Distributions 	kern_return_t kr = host_statistics64(mach_host_self(), HOST_VM_COMPRESSOR_Q_LENS, (host_info64_t)&d, &vm_qlen_count);
41*8d741a5dSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "host_statistics64(HOST_VM_COMPRESSOR_Q_LENS)");
42*8d741a5dSApple OSS Distributions 	T_EXPECT_EQ(vm_qlen_count, (uint32_t)VM_COMPRESSOR_Q_LENS_COUNT, "check output is the expected length");
43*8d741a5dSApple OSS Distributions }
44*8d741a5dSApple OSS Distributions 
45*8d741a5dSApple OSS Distributions size_t read_big_sysctl(const int *mib, size_t mib_len, const char* name, char **buf);
46*8d741a5dSApple OSS Distributions 
47*8d741a5dSApple OSS Distributions size_t
read_big_sysctl(const int * mib,size_t mib_len,const char * name,char ** buf)48*8d741a5dSApple OSS Distributions read_big_sysctl(const int *mib, size_t mib_len, const char* name, char **buf)
49*8d741a5dSApple OSS Distributions {
50*8d741a5dSApple OSS Distributions 	size_t len = 0;
51*8d741a5dSApple OSS Distributions 	int rc = sysctl(mib, mib_len, NULL, &len, NULL, 0);
52*8d741a5dSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(rc, "query size of sysctl `%s`(%zu)", name, mib_len);
53*8d741a5dSApple OSS Distributions 	T_ASSERT_GT(len, (size_t)0, "sysctl got size 0");
54*8d741a5dSApple OSS Distributions 	len += 4096; /* allocate a bit extra in case the size changed between the two calls */
55*8d741a5dSApple OSS Distributions 	*buf = (char*)malloc(len);
56*8d741a5dSApple OSS Distributions 	T_ASSERT_NE_PTR((void*)*buf, NULL, "allocation for sysctl %zu", len);
57*8d741a5dSApple OSS Distributions 	rc = sysctl(mib, mib_len, *buf, &len, NULL, 0);
58*8d741a5dSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(rc, "query of sysctl `%s`", name);
59*8d741a5dSApple OSS Distributions 	return len;
60*8d741a5dSApple OSS Distributions }
61*8d741a5dSApple OSS Distributions 
62*8d741a5dSApple OSS Distributions size_t
get_sysctl_mib(const char * ctl_name,int * mib,size_t mib_sz)63*8d741a5dSApple OSS Distributions get_sysctl_mib(const char* ctl_name, int* mib, size_t mib_sz)
64*8d741a5dSApple OSS Distributions {
65*8d741a5dSApple OSS Distributions 	size_t mib_size = mib_sz;
66*8d741a5dSApple OSS Distributions 	int rc = sysctlnametomib(ctl_name, mib, &mib_size);
67*8d741a5dSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(rc, "query name mib `%s` got %zu", ctl_name, mib_size);
68*8d741a5dSApple OSS Distributions 	return mib_size;
69*8d741a5dSApple OSS Distributions }
70*8d741a5dSApple OSS Distributions 
71*8d741a5dSApple OSS Distributions T_DECL(sysctl_c_segments, "Check that the sysctl that dumps all the c_segments works correctly",
72*8d741a5dSApple OSS Distributions     T_META_REQUIRES_SYSCTL_EQ("kern.development", 1))
73*8d741a5dSApple OSS Distributions {
74*8d741a5dSApple OSS Distributions 	int mib[CTL_MAXNAME] = {0};
75*8d741a5dSApple OSS Distributions 	size_t mib_len = get_sysctl_mib("vm.compressor_segments", mib, CTL_MAXNAME);
76*8d741a5dSApple OSS Distributions 	char *buf = NULL;
77*8d741a5dSApple OSS Distributions 	size_t sz = read_big_sysctl(mib, mib_len, "vm.compressor_segments", &buf);
78*8d741a5dSApple OSS Distributions 
79*8d741a5dSApple OSS Distributions 	size_t offset = 0;
80*8d741a5dSApple OSS Distributions 	T_ASSERT_GE_ULONG(sz, sizeof(uint32_t), "got buffer shorter than the magic value");
81*8d741a5dSApple OSS Distributions 	uint32_t hdr_magic = *((uint32_t*)buf);
82*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ_UINT(hdr_magic, VM_C_SEGMENT_INFO_MAGIC, "match magic value");
83*8d741a5dSApple OSS Distributions 	offset += sizeof(uint32_t);
84*8d741a5dSApple OSS Distributions 	while (offset < sz) {
85*8d741a5dSApple OSS Distributions 		// read next c_segment
86*8d741a5dSApple OSS Distributions 		T_QUIET; T_ASSERT_LE(offset + sizeof(struct c_segment_info), sz, "unexpected offset for c_segment_info");
87*8d741a5dSApple OSS Distributions 		const struct c_segment_info* cseg = (const struct c_segment_info*)(buf + offset);
88*8d741a5dSApple OSS Distributions 		offset += sizeof(struct c_segment_info);
89*8d741a5dSApple OSS Distributions 		// read it's slots
90*8d741a5dSApple OSS Distributions 		T_QUIET; T_ASSERT_LE(offset + cseg->csi_slots_len * sizeof(struct c_slot_info), sz, "unexpected offset for c_slot_info");
91*8d741a5dSApple OSS Distributions 		offset += cseg->csi_slots_len * sizeof(struct c_slot_info);
92*8d741a5dSApple OSS Distributions 	}
93*8d741a5dSApple OSS Distributions }
94*8d741a5dSApple OSS Distributions 
95*8d741a5dSApple OSS Distributions T_DECL(sysctl_vm_object_dump, "Check that the sysctl that dumps the metadata of a vm_object works correctly",
96*8d741a5dSApple OSS Distributions     T_META_REQUIRES_SYSCTL_EQ("kern.development", 1))
97*8d741a5dSApple OSS Distributions {
98*8d741a5dSApple OSS Distributions 	int mib[CTL_MAXNAME] = {0};
99*8d741a5dSApple OSS Distributions 	size_t mib_len = get_sysctl_mib("vm.task_vm_objects_slotmap", mib, CTL_MAXNAME);
100*8d741a5dSApple OSS Distributions 	mib[mib_len++] = getpid();
101*8d741a5dSApple OSS Distributions 
102*8d741a5dSApple OSS Distributions 	char *buf = NULL;
103*8d741a5dSApple OSS Distributions 	size_t sz = read_big_sysctl(mib, mib_len, "vm.compressor_segments.<pid>", &buf);
104*8d741a5dSApple OSS Distributions 
105*8d741a5dSApple OSS Distributions 	size_t offset = 0;
106*8d741a5dSApple OSS Distributions 	T_ASSERT_GE_ULONG(sz, sizeof(uint32_t), "got buffer shorter than the magic value");
107*8d741a5dSApple OSS Distributions 	uint32_t hdr_magic = *((uint32_t*)buf);
108*8d741a5dSApple OSS Distributions 	T_ASSERT_EQ_UINT(hdr_magic, VM_MAP_ENTRY_INFO_MAGIC, "match magic value");
109*8d741a5dSApple OSS Distributions 	offset += sizeof(uint32_t);
110*8d741a5dSApple OSS Distributions 
111*8d741a5dSApple OSS Distributions 	T_ASSERT_LE(offset + sizeof(struct vm_map_info_hdr), sz, "vm_map_info_hdr size");
112*8d741a5dSApple OSS Distributions 	struct vm_map_info_hdr* hdr = (struct vm_map_info_hdr*)(buf + offset);
113*8d741a5dSApple OSS Distributions 	for (int i = 0; i < hdr->vmi_nentries; ++i) {
114*8d741a5dSApple OSS Distributions 		T_QUIET; T_ASSERT_LE(offset + sizeof(struct vm_map_entry_info), sz, "vm_map_entry_info size");
115*8d741a5dSApple OSS Distributions 		offset += sizeof(struct vm_map_entry_info);
116*8d741a5dSApple OSS Distributions 	}
117*8d741a5dSApple OSS Distributions }
118