• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1--- b/tools/testing/selftests/vm/userfaultfd.c
2+++ b/tools/testing/selftests/vm/userfaultfd.c
3@@ -82,9 +82,11 @@
4 static char *huge_fd_off0;
5 static unsigned long long *count_verify;
6 static int uffd, uffd_flags, finished, *pipefd;
7+static volatile bool ready_for_fork;
8 static char *area_src, *area_src_alias, *area_dst, *area_dst_alias;
9 static char *zeropage;
10 pthread_attr_t attr;
11+pthread_key_t long_jmp_key;
12
13 /* pthread_mutex_t starts at page offset 0 */
14 #define area_mutex(___area, ___nr)					\
15@@ -139,8 +141,11 @@
16
17 static void anon_allocate_area(void **alloc_area)
18 {
19-	if (posix_memalign(alloc_area, page_size, nr_pages * page_size)) {
20-		fprintf(stderr, "out of memory\n");
21+	// We can't use posix_memalign due to pointer-tagging used in bionic.
22+	*alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
23+			   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
24+	if (*alloc_area == MAP_FAILED) {
25+		fprintf(stderr, "anon memory mmap failed\n");
26 		*alloc_area = NULL;
27 	}
28 }
29@@ -284,23 +289,11 @@
30 static void *locking_thread(void *arg)
31 {
32 	unsigned long cpu = (unsigned long) arg;
33-	struct random_data rand;
34 	unsigned long page_nr = *(&(page_nr)); /* uninitialized warning */
35-	int32_t rand_nr;
36 	unsigned long long count;
37-	char randstate[64];
38-	unsigned int seed;
39 	time_t start;
40
41-	if (bounces & BOUNCE_RANDOM) {
42-		seed = (unsigned int) time(NULL) - bounces;
43-		if (!(bounces & BOUNCE_RACINGFAULTS))
44-			seed += cpu;
45-		bzero(&rand, sizeof(rand));
46-		bzero(&randstate, sizeof(randstate));
47-		if (initstate_r(seed, randstate, sizeof(randstate), &rand))
48-			fprintf(stderr, "srandom_r error\n"), exit(1);
49-	} else {
50+	if (!(bounces & BOUNCE_RANDOM)) {
51 		page_nr = -bounces;
52 		if (!(bounces & BOUNCE_RACINGFAULTS))
53 			page_nr += cpu * nr_pages_per_cpu;
54@@ -308,13 +301,9 @@
55
56 	while (!finished) {
57 		if (bounces & BOUNCE_RANDOM) {
58-			if (random_r(&rand, &rand_nr))
59-				fprintf(stderr, "random_r 1 error\n"), exit(1);
60-			page_nr = rand_nr;
61-			if (sizeof(page_nr) > sizeof(rand_nr)) {
62-				if (random_r(&rand, &rand_nr))
63-					fprintf(stderr, "random_r 2 error\n"), exit(1);
64-				page_nr |= (((unsigned long) rand_nr) << 16) <<
65+			page_nr = random();
66+			if (sizeof(page_nr) > sizeof(uint32_t)) {
67+				page_nr |= (((unsigned long) random()) << 16) <<
68 					   16;
69 			}
70 		} else
71@@ -501,6 +490,9 @@
72 	pollfd[1].fd = pipefd[cpu*2];
73 	pollfd[1].events = POLLIN;
74
75+	// Notify the main thread that it can now fork.
76+	ready_for_fork = true;
77+
78 	for (;;) {
79 		ret = poll(pollfd, 2, -1);
80 		if (!ret)
81@@ -548,18 +540,31 @@
82
83 pthread_mutex_t uffd_read_mutex = PTHREAD_MUTEX_INITIALIZER;
84
85+static void sigusr1_handler(int signum, siginfo_t *siginfo, void *ptr)
86+{
87+	jmp_buf *env;
88+	env = pthread_getspecific(long_jmp_key);
89+	longjmp(*env, 1);
90+}
91+
92 static void *uffd_read_thread(void *arg)
93 {
94 	unsigned long *this_cpu_userfaults;
95 	struct uffd_msg msg;
96+	jmp_buf env;
97+	int setjmp_ret;
98+
99+	pthread_setspecific(long_jmp_key, &env);
100
101 	this_cpu_userfaults = (unsigned long *) arg;
102 	*this_cpu_userfaults = 0;
103
104 	pthread_mutex_unlock(&uffd_read_mutex);
105-	/* from here cancellation is ok */
106
107-	for (;;) {
108+	// One first return setjmp return 0. On second (fake) return from
109+	// longjmp() it returns the provided value, which will be 1 in our case.
110+	setjmp_ret = setjmp(env);
111+	while (!setjmp_ret) {
112 		if (uffd_read_msg(uffd, &msg))
113 			continue;
114 		(*this_cpu_userfaults) += uffd_handle_page_fault(&msg);
115@@ -608,6 +613,7 @@
116 				   background_thread, (void *)cpu))
117 			return 1;
118 	}
119+
120 	for (cpu = 0; cpu < nr_cpus; cpu++)
121 		if (pthread_join(background_threads[cpu], NULL))
122 			return 1;
123@@ -640,7 +646,7 @@
124 			if (pthread_join(uffd_threads[cpu], &_userfaults[cpu]))
125 				return 1;
126 		} else {
127-			if (pthread_cancel(uffd_threads[cpu]))
128+			if (pthread_kill(uffd_threads[cpu], SIGUSR1))
129 				return 1;
130 			if (pthread_join(uffd_threads[cpu], NULL))
131 				return 1;
132@@ -654,7 +660,7 @@
133 {
134 	struct uffdio_api uffdio_api;
135
136-	uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
137+	uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY);
138 	if (uffd < 0) {
139 		fprintf(stderr,
140 			"userfaultfd syscall not available in this kernel\n");
141@@ -914,6 +920,10 @@
142 	pid_t pid;
143 	char c;
144
145+	// All the syscalls below up to pthread_create will ensure that this
146+	// write is completed before, the uffd_thread sets it to true.
147+	ready_for_fork = false;
148+
149 	printf("testing events (fork, remap, remove): ");
150 	fflush(stdout);
151
152@@ -942,6 +952,11 @@
153 	if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, NULL))
154 		perror("uffd_poll_thread create"), exit(1);
155
156+	// Wait for the poll_thread to start executing before forking. This is
157+	// required to avoid a deadlock, which can happen if poll_thread doesn't
158+	// start getting executed by the time fork is invoked.
159+	while (!ready_for_fork);
160+
161 	pid = fork();
162 	if (pid < 0)
163 		perror("fork"), exit(1);
164@@ -974,6 +989,10 @@
165 	pid_t pid;
166 	char c;
167
168+	// All the syscalls below up to pthread_create will ensure that this
169+	// write is completed before, the uffd_thread sets it to true.
170+	ready_for_fork = false;
171+
172 	printf("testing signal delivery: ");
173 	fflush(stdout);
174
175@@ -1007,6 +1026,11 @@
176 	if (pthread_create(&uffd_mon, &attr, uffd_poll_thread, NULL))
177 		perror("uffd_poll_thread create"), exit(1);
178
179+	// Wait for the poll_thread to start executing before forking. This is
180+	// required to avoid a deadlock, which can happen if poll_thread doesn't
181+	// start getting executed by the time fork is invoked.
182+	while (!ready_for_fork);
183+
184 	pid = fork();
185 	if (pid < 0)
186 		perror("fork"), exit(1);
187@@ -1036,6 +1060,7 @@
188 	char *tmp_area;
189 	unsigned long nr;
190 	struct uffdio_register uffdio_register;
191+	struct sigaction act;
192 	unsigned long cpu;
193 	int err;
194 	unsigned long userfaults[nr_cpus];
195@@ -1094,6 +1119,17 @@
196 	pthread_attr_init(&attr);
197 	pthread_attr_setstacksize(&attr, 16*1024*1024);
198
199+	// For handling thread termination of read thread in the absense of
200+	// pthread_cancel().
201+	pthread_key_create(&long_jmp_key, NULL);
202+	memset(&act, 0, sizeof(act));
203+	act.sa_sigaction = sigusr1_handler;
204+	act.sa_flags = SA_SIGINFO;
205+	if (sigaction(SIGUSR1, &act, 0)) {
206+		perror("sigaction");
207+		return 1;
208+	}
209+
210 	err = 0;
211 	while (bounces--) {
212 		unsigned long expected_ioctls;
213@@ -1215,6 +1251,8 @@
214 		printf("\n");
215 	}
216
217+	pthread_key_delete(long_jmp_key);
218+
219 	if (err)
220 		return err;
221
222@@ -1291,6 +1329,9 @@
223
224 int main(int argc, char **argv)
225 {
226+	char randstate[64];
227+	unsigned int seed;
228+
229 	if (argc < 4)
230 		usage();
231
232@@ -1332,6 +1373,12 @@
233 	}
234 	printf("nr_pages: %lu, nr_pages_per_cpu: %lu\n",
235 	       nr_pages, nr_pages_per_cpu);
236+
237+	seed = (unsigned int) time(NULL);
238+	bzero(&randstate, sizeof(randstate));
239+	if (!initstate(seed, randstate, sizeof(randstate)))
240+		fprintf(stderr, "srandom_r error\n"), exit(1);
241+
242 	return userfaultfd_stress();
243 }
244
245--- a/tools/testing/selftests/vm/userfaultfd.c
246+++ b/tools/testing/selftests/vm/userfaultfd.c
247@@ -662,8 +662,13 @@ static int userfaultfd_open(int features)
248
249 	uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY);
250 	if (uffd < 0) {
251+		if (errno == ENOSYS) {
252+			fprintf(stderr,
253+				"userfaultfd syscall not available in this kernel\n");
254+			exit(KSFT_PASS);
255+		}
256 		fprintf(stderr,
257-			"userfaultfd syscall not available in this kernel\n");
258+			"userfaultfd syscall failed with errno: %d\n", errno);
259 		return 1;
260 	}
261 	uffd_flags = fcntl(uffd, F_GETFD, NULL);
262