1*c54f35caSApple OSS Distributions #include "mach_vm_tests.h"
2*c54f35caSApple OSS Distributions
3*c54f35caSApple OSS Distributions T_GLOBAL_META(
4*c54f35caSApple OSS Distributions T_META_NAMESPACE("xnu.vm"),
5*c54f35caSApple OSS Distributions T_META_RADAR_COMPONENT_NAME("xnu"),
6*c54f35caSApple OSS Distributions T_META_RADAR_COMPONENT_VERSION("VM"));
7*c54f35caSApple OSS Distributions
8*c54f35caSApple OSS Distributions extern char **environ;
9*c54f35caSApple OSS Distributions
10*c54f35caSApple OSS Distributions static void
11*c54f35caSApple OSS Distributions spawn_process(char *action, char *serviceName, char *extraArg,
12*c54f35caSApple OSS Distributions mach_port_t *server_Port, pid_t *serverPid, boolean_t use4k);
13*c54f35caSApple OSS Distributions
14*c54f35caSApple OSS Distributions static void mach_client(void);
15*c54f35caSApple OSS Distributions
16*c54f35caSApple OSS Distributions mach_port_t serverPort;
17*c54f35caSApple OSS Distributions static pid_t serverPid;
18*c54f35caSApple OSS Distributions
19*c54f35caSApple OSS Distributions boolean_t debug = TRUE;
20*c54f35caSApple OSS Distributions
21*c54f35caSApple OSS Distributions void
spawn_process(char * action,char * serviceName,char * extraArg,mach_port_t * server_Port,pid_t * server_Pid,boolean_t use4k)22*c54f35caSApple OSS Distributions spawn_process(char *action, char *serviceName, char *extraArg,
23*c54f35caSApple OSS Distributions mach_port_t *server_Port, pid_t *server_Pid, boolean_t use4k)
24*c54f35caSApple OSS Distributions {
25*c54f35caSApple OSS Distributions char buffer[PATH_MAX];
26*c54f35caSApple OSS Distributions char *argv[10] = {0};
27*c54f35caSApple OSS Distributions int arg_index = 0;
28*c54f35caSApple OSS Distributions pid_t pid = -1;
29*c54f35caSApple OSS Distributions int r = proc_pidpath(getpid(), buffer, sizeof(buffer));
30*c54f35caSApple OSS Distributions T_ASSERT_NE(r, -1, "proc_pidpath");
31*c54f35caSApple OSS Distributions r = (int)strlcat(buffer, "_server", sizeof(buffer));
32*c54f35caSApple OSS Distributions T_ASSERT_LT(r, (int)sizeof(buffer), "strlcat");
33*c54f35caSApple OSS Distributions
34*c54f35caSApple OSS Distributions if (use4k) {
35*c54f35caSApple OSS Distributions int supported = 0;
36*c54f35caSApple OSS Distributions size_t supported_size = sizeof(supported);
37*c54f35caSApple OSS Distributions
38*c54f35caSApple OSS Distributions r = sysctlbyname("debug.vm_mixed_pagesize_supported", &supported, &supported_size, NULL, 0);
39*c54f35caSApple OSS Distributions if (r == 0 && supported) {
40*c54f35caSApple OSS Distributions T_LOG("Using %s to spawn process with 4k", VM_SPAWN_TOOL);
41*c54f35caSApple OSS Distributions argv[arg_index++] = VM_SPAWN_TOOL;
42*c54f35caSApple OSS Distributions } else {
43*c54f35caSApple OSS Distributions /*
44*c54f35caSApple OSS Distributions * We didnt find debug.vm.mixed_page.supported OR its set to 0.
45*c54f35caSApple OSS Distributions * Skip the test.
46*c54f35caSApple OSS Distributions */
47*c54f35caSApple OSS Distributions T_SKIP("Hardware doesn't support 4K pages, skipping test...");
48*c54f35caSApple OSS Distributions exit(0);
49*c54f35caSApple OSS Distributions }
50*c54f35caSApple OSS Distributions }
51*c54f35caSApple OSS Distributions argv[arg_index++] = (char *)&buffer[0];
52*c54f35caSApple OSS Distributions argv[arg_index++] = (char *)action;
53*c54f35caSApple OSS Distributions argv[arg_index++] = (char *)serviceName;
54*c54f35caSApple OSS Distributions argv[arg_index++] = (char *)extraArg;
55*c54f35caSApple OSS Distributions argv[arg_index++] = NULL;
56*c54f35caSApple OSS Distributions
57*c54f35caSApple OSS Distributions printf("posix_spawn with argv: ");
58*c54f35caSApple OSS Distributions for (r = 0; r <= arg_index; r++) {
59*c54f35caSApple OSS Distributions printf("%s ", argv[r]);
60*c54f35caSApple OSS Distributions }
61*c54f35caSApple OSS Distributions printf("\n");
62*c54f35caSApple OSS Distributions
63*c54f35caSApple OSS Distributions T_LOG("Spawning %s process(%s) with service name %s at %s\n", action, buffer, serviceName, buffer);
64*c54f35caSApple OSS Distributions
65*c54f35caSApple OSS Distributions
66*c54f35caSApple OSS Distributions posix_spawn_file_actions_t actions;
67*c54f35caSApple OSS Distributions posix_spawn_file_actions_init(&actions);
68*c54f35caSApple OSS Distributions
69*c54f35caSApple OSS Distributions if (use4k) {
70*c54f35caSApple OSS Distributions T_ASSERT_POSIX_ZERO(posix_spawn(&pid, VM_SPAWN_TOOL, &actions, NULL, argv, environ), "spawn %s", serviceName);
71*c54f35caSApple OSS Distributions } else {
72*c54f35caSApple OSS Distributions T_ASSERT_POSIX_ZERO(posix_spawn(&pid, buffer, &actions, NULL, argv, environ), "spawn %s", serviceName);
73*c54f35caSApple OSS Distributions }
74*c54f35caSApple OSS Distributions posix_spawn_file_actions_destroy(&actions);
75*c54f35caSApple OSS Distributions
76*c54f35caSApple OSS Distributions kern_return_t ret;
77*c54f35caSApple OSS Distributions mach_port_t servicePort;
78*c54f35caSApple OSS Distributions int attempts = 0;
79*c54f35caSApple OSS Distributions const int kMaxAttempts = 10;
80*c54f35caSApple OSS Distributions do {
81*c54f35caSApple OSS Distributions sleep(1);
82*c54f35caSApple OSS Distributions ret = bootstrap_look_up(bootstrap_port, serviceName, &servicePort);
83*c54f35caSApple OSS Distributions attempts++;
84*c54f35caSApple OSS Distributions } while (ret == BOOTSTRAP_UNKNOWN_SERVICE && attempts < kMaxAttempts);
85*c54f35caSApple OSS Distributions
86*c54f35caSApple OSS Distributions if (ret != KERN_SUCCESS) {
87*c54f35caSApple OSS Distributions printf("ERROR: Failed bootstrap lookup for process with mach service name '%s': (%d) %s\n", serviceName, ret, mach_error_string(ret));
88*c54f35caSApple OSS Distributions if (pid > 0) {
89*c54f35caSApple OSS Distributions kill(pid, SIGKILL);
90*c54f35caSApple OSS Distributions }
91*c54f35caSApple OSS Distributions T_FAIL("Failed bootstrap lookup for process with mach service");
92*c54f35caSApple OSS Distributions }
93*c54f35caSApple OSS Distributions
94*c54f35caSApple OSS Distributions *server_Port = servicePort;
95*c54f35caSApple OSS Distributions *server_Pid = pid;
96*c54f35caSApple OSS Distributions T_LOG("Server pid=%d port 0x%x", pid, servicePort);
97*c54f35caSApple OSS Distributions }
98*c54f35caSApple OSS Distributions
99*c54f35caSApple OSS Distributions void
mach_client()100*c54f35caSApple OSS Distributions mach_client()
101*c54f35caSApple OSS Distributions {
102*c54f35caSApple OSS Distributions mach_port_t replyPort;
103*c54f35caSApple OSS Distributions T_ASSERT_POSIX_ZERO(mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &replyPort), "create recieve port");
104*c54f35caSApple OSS Distributions T_ASSERT_POSIX_ZERO(mach_port_insert_right(mach_task_self(), replyPort, replyPort, MACH_MSG_TYPE_MAKE_SEND), "insert send port");
105*c54f35caSApple OSS Distributions
106*c54f35caSApple OSS Distributions ipc_message_t message;
107*c54f35caSApple OSS Distributions bzero(&message, sizeof(message));
108*c54f35caSApple OSS Distributions message.header.msgh_id = 1;
109*c54f35caSApple OSS Distributions
110*c54f35caSApple OSS Distributions message.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_COPY_SEND);
111*c54f35caSApple OSS Distributions message.header.msgh_remote_port = serverPort;
112*c54f35caSApple OSS Distributions message.header.msgh_local_port = replyPort;
113*c54f35caSApple OSS Distributions message.header.msgh_size = sizeof(message);
114*c54f35caSApple OSS Distributions
115*c54f35caSApple OSS Distributions /* reply creation is not necessary in this case.
116*c54f35caSApple OSS Distributions * mach_msg_size_t replySize = sizeof(ipc_message_t) + sizeof(mach_msg_trailer_t) + 64;
117*c54f35caSApple OSS Distributions * ipc_message_t *reply = calloc(1, replySize);
118*c54f35caSApple OSS Distributions */
119*c54f35caSApple OSS Distributions T_LOG("sending message to %d of size %u", message.header.msgh_remote_port, message.header.msgh_size);
120*c54f35caSApple OSS Distributions kern_return_t ret = mach_msg(&message.header, MACH_SEND_MSG, message.header.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
121*c54f35caSApple OSS Distributions T_ASSERT_MACH_SUCCESS(ret, "mach_msg to serverProcess");
122*c54f35caSApple OSS Distributions mach_vm_client(replyPort);
123*c54f35caSApple OSS Distributions T_LOG("Sending SIGKILL to server(%d)", serverPid);
124*c54f35caSApple OSS Distributions kill(serverPid, SIGKILL);
125*c54f35caSApple OSS Distributions }
126*c54f35caSApple OSS Distributions
127*c54f35caSApple OSS Distributions T_DECL(memory_share_tests,
128*c54f35caSApple OSS Distributions "test vm memory sharing between client and server process with different process PAGE_SIZE",
129*c54f35caSApple OSS Distributions T_META_ASROOT(true))
130*c54f35caSApple OSS Distributions {
131*c54f35caSApple OSS Distributions boolean_t use4k = FALSE;
132*c54f35caSApple OSS Distributions char serviceName[64];
133*c54f35caSApple OSS Distributions
134*c54f35caSApple OSS Distributions struct sigaction action = {
135*c54f35caSApple OSS Distributions .sa_handler = SIG_IGN,
136*c54f35caSApple OSS Distributions .sa_flags = SA_NOCLDWAIT
137*c54f35caSApple OSS Distributions };
138*c54f35caSApple OSS Distributions sigaction(SIGCHLD, &action, NULL);
139*c54f35caSApple OSS Distributions
140*c54f35caSApple OSS Distributions if (getenv("USE4K")) {
141*c54f35caSApple OSS Distributions use4k = TRUE;
142*c54f35caSApple OSS Distributions }
143*c54f35caSApple OSS Distributions
144*c54f35caSApple OSS Distributions if (getenv("QUIET")) {
145*c54f35caSApple OSS Distributions debug = FALSE;
146*c54f35caSApple OSS Distributions }
147*c54f35caSApple OSS Distributions
148*c54f35caSApple OSS Distributions T_LOG("running with use4k=%d debug=%d", use4k, (int)debug);
149*c54f35caSApple OSS Distributions
150*c54f35caSApple OSS Distributions strcpy(serviceName, MACH_VM_TEST_SERVICE_NAME);
151*c54f35caSApple OSS Distributions
152*c54f35caSApple OSS Distributions spawn_process("machserver", serviceName, NULL, &serverPort, &serverPid, use4k);
153*c54f35caSApple OSS Distributions mach_client();
154*c54f35caSApple OSS Distributions }
155*c54f35caSApple OSS Distributions
156*c54f35caSApple OSS Distributions /*
157*c54f35caSApple OSS Distributions * This posix spawn attribute used in the 4K test should only be valid on apple
158*c54f35caSApple OSS Distributions * silicon macs. But we've had issues in the past where it would accidently
159*c54f35caSApple OSS Distributions * trigger incorrect behavior on other platforms.
160*c54f35caSApple OSS Distributions * So we run the test on all platforms to catch issues like that.
161*c54f35caSApple OSS Distributions * On all non apple silcon mac platforms, this test should be identical to
162*c54f35caSApple OSS Distributions * running without the 4K flag.
163*c54f35caSApple OSS Distributions */
164*c54f35caSApple OSS Distributions T_DECL_REF(memory_share_tests_4k, memory_share_tests, "vm memory sharing with 4k processes",
165*c54f35caSApple OSS Distributions T_META_ENVVAR("USE4K=YES"),
166*c54f35caSApple OSS Distributions T_META_ASROOT(true)
167*c54f35caSApple OSS Distributions );
168