xref: /aosp_15_r20/external/linux-kselftest/tools/testing/selftests/vm/hmm-tests.c (revision 053f45be4e351dfd5e965df293cd45b779f579ee)
1*053f45beSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0
2*053f45beSAndroid Build Coastguard Worker /*
3*053f45beSAndroid Build Coastguard Worker  * HMM stands for Heterogeneous Memory Management, it is a helper layer inside
4*053f45beSAndroid Build Coastguard Worker  * the linux kernel to help device drivers mirror a process address space in
5*053f45beSAndroid Build Coastguard Worker  * the device. This allows the device to use the same address space which
6*053f45beSAndroid Build Coastguard Worker  * makes communication and data exchange a lot easier.
7*053f45beSAndroid Build Coastguard Worker  *
8*053f45beSAndroid Build Coastguard Worker  * This framework's sole purpose is to exercise various code paths inside
9*053f45beSAndroid Build Coastguard Worker  * the kernel to make sure that HMM performs as expected and to flush out any
10*053f45beSAndroid Build Coastguard Worker  * bugs.
11*053f45beSAndroid Build Coastguard Worker  */
12*053f45beSAndroid Build Coastguard Worker 
13*053f45beSAndroid Build Coastguard Worker #include "../kselftest_harness.h"
14*053f45beSAndroid Build Coastguard Worker 
15*053f45beSAndroid Build Coastguard Worker #include <errno.h>
16*053f45beSAndroid Build Coastguard Worker #include <fcntl.h>
17*053f45beSAndroid Build Coastguard Worker #include <stdio.h>
18*053f45beSAndroid Build Coastguard Worker #include <stdlib.h>
19*053f45beSAndroid Build Coastguard Worker #include <stdint.h>
20*053f45beSAndroid Build Coastguard Worker #include <unistd.h>
21*053f45beSAndroid Build Coastguard Worker #include <strings.h>
22*053f45beSAndroid Build Coastguard Worker #include <time.h>
23*053f45beSAndroid Build Coastguard Worker #include <pthread.h>
24*053f45beSAndroid Build Coastguard Worker #include <sys/types.h>
25*053f45beSAndroid Build Coastguard Worker #include <sys/stat.h>
26*053f45beSAndroid Build Coastguard Worker #include <sys/mman.h>
27*053f45beSAndroid Build Coastguard Worker #include <sys/ioctl.h>
28*053f45beSAndroid Build Coastguard Worker 
29*053f45beSAndroid Build Coastguard Worker 
30*053f45beSAndroid Build Coastguard Worker /*
31*053f45beSAndroid Build Coastguard Worker  * This is a private UAPI to the kernel test module so it isn't exported
32*053f45beSAndroid Build Coastguard Worker  * in the usual include/uapi/... directory.
33*053f45beSAndroid Build Coastguard Worker  */
34*053f45beSAndroid Build Coastguard Worker #include <lib/test_hmm_uapi.h>
35*053f45beSAndroid Build Coastguard Worker #include <mm/gup_test.h>
36*053f45beSAndroid Build Coastguard Worker 
37*053f45beSAndroid Build Coastguard Worker struct hmm_buffer {
38*053f45beSAndroid Build Coastguard Worker 	void		*ptr;
39*053f45beSAndroid Build Coastguard Worker 	void		*mirror;
40*053f45beSAndroid Build Coastguard Worker 	unsigned long	size;
41*053f45beSAndroid Build Coastguard Worker 	int		fd;
42*053f45beSAndroid Build Coastguard Worker 	uint64_t	cpages;
43*053f45beSAndroid Build Coastguard Worker 	uint64_t	faults;
44*053f45beSAndroid Build Coastguard Worker };
45*053f45beSAndroid Build Coastguard Worker 
46*053f45beSAndroid Build Coastguard Worker enum {
47*053f45beSAndroid Build Coastguard Worker 	HMM_PRIVATE_DEVICE_ONE,
48*053f45beSAndroid Build Coastguard Worker 	HMM_PRIVATE_DEVICE_TWO,
49*053f45beSAndroid Build Coastguard Worker 	HMM_COHERENCE_DEVICE_ONE,
50*053f45beSAndroid Build Coastguard Worker 	HMM_COHERENCE_DEVICE_TWO,
51*053f45beSAndroid Build Coastguard Worker };
52*053f45beSAndroid Build Coastguard Worker 
53*053f45beSAndroid Build Coastguard Worker #define TWOMEG		(1 << 21)
54*053f45beSAndroid Build Coastguard Worker #define HMM_BUFFER_SIZE (1024 << 12)
55*053f45beSAndroid Build Coastguard Worker #define HMM_PATH_MAX    64
56*053f45beSAndroid Build Coastguard Worker #define NTIMES		10
57*053f45beSAndroid Build Coastguard Worker 
58*053f45beSAndroid Build Coastguard Worker #define ALIGN(x, a) (((x) + (a - 1)) & (~((a) - 1)))
59*053f45beSAndroid Build Coastguard Worker /* Just the flags we need, copied from mm.h: */
60*053f45beSAndroid Build Coastguard Worker #define FOLL_WRITE	0x01	/* check pte is writable */
61*053f45beSAndroid Build Coastguard Worker #define FOLL_LONGTERM   0x10000 /* mapping lifetime is indefinite */
62*053f45beSAndroid Build Coastguard Worker 
FIXTURE(hmm)63*053f45beSAndroid Build Coastguard Worker FIXTURE(hmm)
64*053f45beSAndroid Build Coastguard Worker {
65*053f45beSAndroid Build Coastguard Worker 	int		fd;
66*053f45beSAndroid Build Coastguard Worker 	unsigned int	page_size;
67*053f45beSAndroid Build Coastguard Worker 	unsigned int	page_shift;
68*053f45beSAndroid Build Coastguard Worker };
69*053f45beSAndroid Build Coastguard Worker 
FIXTURE_VARIANT(hmm)70*053f45beSAndroid Build Coastguard Worker FIXTURE_VARIANT(hmm)
71*053f45beSAndroid Build Coastguard Worker {
72*053f45beSAndroid Build Coastguard Worker 	int     device_number;
73*053f45beSAndroid Build Coastguard Worker };
74*053f45beSAndroid Build Coastguard Worker 
FIXTURE_VARIANT_ADD(hmm,hmm_device_private)75*053f45beSAndroid Build Coastguard Worker FIXTURE_VARIANT_ADD(hmm, hmm_device_private)
76*053f45beSAndroid Build Coastguard Worker {
77*053f45beSAndroid Build Coastguard Worker 	.device_number = HMM_PRIVATE_DEVICE_ONE,
78*053f45beSAndroid Build Coastguard Worker };
79*053f45beSAndroid Build Coastguard Worker 
FIXTURE_VARIANT_ADD(hmm,hmm_device_coherent)80*053f45beSAndroid Build Coastguard Worker FIXTURE_VARIANT_ADD(hmm, hmm_device_coherent)
81*053f45beSAndroid Build Coastguard Worker {
82*053f45beSAndroid Build Coastguard Worker 	.device_number = HMM_COHERENCE_DEVICE_ONE,
83*053f45beSAndroid Build Coastguard Worker };
84*053f45beSAndroid Build Coastguard Worker 
FIXTURE(hmm2)85*053f45beSAndroid Build Coastguard Worker FIXTURE(hmm2)
86*053f45beSAndroid Build Coastguard Worker {
87*053f45beSAndroid Build Coastguard Worker 	int		fd0;
88*053f45beSAndroid Build Coastguard Worker 	int		fd1;
89*053f45beSAndroid Build Coastguard Worker 	unsigned int	page_size;
90*053f45beSAndroid Build Coastguard Worker 	unsigned int	page_shift;
91*053f45beSAndroid Build Coastguard Worker };
92*053f45beSAndroid Build Coastguard Worker 
FIXTURE_VARIANT(hmm2)93*053f45beSAndroid Build Coastguard Worker FIXTURE_VARIANT(hmm2)
94*053f45beSAndroid Build Coastguard Worker {
95*053f45beSAndroid Build Coastguard Worker 	int     device_number0;
96*053f45beSAndroid Build Coastguard Worker 	int     device_number1;
97*053f45beSAndroid Build Coastguard Worker };
98*053f45beSAndroid Build Coastguard Worker 
FIXTURE_VARIANT_ADD(hmm2,hmm2_device_private)99*053f45beSAndroid Build Coastguard Worker FIXTURE_VARIANT_ADD(hmm2, hmm2_device_private)
100*053f45beSAndroid Build Coastguard Worker {
101*053f45beSAndroid Build Coastguard Worker 	.device_number0 = HMM_PRIVATE_DEVICE_ONE,
102*053f45beSAndroid Build Coastguard Worker 	.device_number1 = HMM_PRIVATE_DEVICE_TWO,
103*053f45beSAndroid Build Coastguard Worker };
104*053f45beSAndroid Build Coastguard Worker 
FIXTURE_VARIANT_ADD(hmm2,hmm2_device_coherent)105*053f45beSAndroid Build Coastguard Worker FIXTURE_VARIANT_ADD(hmm2, hmm2_device_coherent)
106*053f45beSAndroid Build Coastguard Worker {
107*053f45beSAndroid Build Coastguard Worker 	.device_number0 = HMM_COHERENCE_DEVICE_ONE,
108*053f45beSAndroid Build Coastguard Worker 	.device_number1 = HMM_COHERENCE_DEVICE_TWO,
109*053f45beSAndroid Build Coastguard Worker };
110*053f45beSAndroid Build Coastguard Worker 
hmm_open(int unit)111*053f45beSAndroid Build Coastguard Worker static int hmm_open(int unit)
112*053f45beSAndroid Build Coastguard Worker {
113*053f45beSAndroid Build Coastguard Worker 	char pathname[HMM_PATH_MAX];
114*053f45beSAndroid Build Coastguard Worker 	int fd;
115*053f45beSAndroid Build Coastguard Worker 
116*053f45beSAndroid Build Coastguard Worker 	snprintf(pathname, sizeof(pathname), "/dev/hmm_dmirror%d", unit);
117*053f45beSAndroid Build Coastguard Worker 	fd = open(pathname, O_RDWR, 0);
118*053f45beSAndroid Build Coastguard Worker 	if (fd < 0)
119*053f45beSAndroid Build Coastguard Worker 		fprintf(stderr, "could not open hmm dmirror driver (%s)\n",
120*053f45beSAndroid Build Coastguard Worker 			pathname);
121*053f45beSAndroid Build Coastguard Worker 	return fd;
122*053f45beSAndroid Build Coastguard Worker }
123*053f45beSAndroid Build Coastguard Worker 
hmm_is_coherent_type(int dev_num)124*053f45beSAndroid Build Coastguard Worker static bool hmm_is_coherent_type(int dev_num)
125*053f45beSAndroid Build Coastguard Worker {
126*053f45beSAndroid Build Coastguard Worker 	return (dev_num >= HMM_COHERENCE_DEVICE_ONE);
127*053f45beSAndroid Build Coastguard Worker }
128*053f45beSAndroid Build Coastguard Worker 
FIXTURE_SETUP(hmm)129*053f45beSAndroid Build Coastguard Worker FIXTURE_SETUP(hmm)
130*053f45beSAndroid Build Coastguard Worker {
131*053f45beSAndroid Build Coastguard Worker 	self->page_size = sysconf(_SC_PAGE_SIZE);
132*053f45beSAndroid Build Coastguard Worker 	self->page_shift = ffs(self->page_size) - 1;
133*053f45beSAndroid Build Coastguard Worker 
134*053f45beSAndroid Build Coastguard Worker 	self->fd = hmm_open(variant->device_number);
135*053f45beSAndroid Build Coastguard Worker 	if (self->fd < 0 && hmm_is_coherent_type(variant->device_number))
136*053f45beSAndroid Build Coastguard Worker 		SKIP(exit(0), "DEVICE_COHERENT not available");
137*053f45beSAndroid Build Coastguard Worker 	ASSERT_GE(self->fd, 0);
138*053f45beSAndroid Build Coastguard Worker }
139*053f45beSAndroid Build Coastguard Worker 
FIXTURE_SETUP(hmm2)140*053f45beSAndroid Build Coastguard Worker FIXTURE_SETUP(hmm2)
141*053f45beSAndroid Build Coastguard Worker {
142*053f45beSAndroid Build Coastguard Worker 	self->page_size = sysconf(_SC_PAGE_SIZE);
143*053f45beSAndroid Build Coastguard Worker 	self->page_shift = ffs(self->page_size) - 1;
144*053f45beSAndroid Build Coastguard Worker 
145*053f45beSAndroid Build Coastguard Worker 	self->fd0 = hmm_open(variant->device_number0);
146*053f45beSAndroid Build Coastguard Worker 	if (self->fd0 < 0 && hmm_is_coherent_type(variant->device_number0))
147*053f45beSAndroid Build Coastguard Worker 		SKIP(exit(0), "DEVICE_COHERENT not available");
148*053f45beSAndroid Build Coastguard Worker 	ASSERT_GE(self->fd0, 0);
149*053f45beSAndroid Build Coastguard Worker 	self->fd1 = hmm_open(variant->device_number1);
150*053f45beSAndroid Build Coastguard Worker 	ASSERT_GE(self->fd1, 0);
151*053f45beSAndroid Build Coastguard Worker }
152*053f45beSAndroid Build Coastguard Worker 
FIXTURE_TEARDOWN(hmm)153*053f45beSAndroid Build Coastguard Worker FIXTURE_TEARDOWN(hmm)
154*053f45beSAndroid Build Coastguard Worker {
155*053f45beSAndroid Build Coastguard Worker 	int ret = close(self->fd);
156*053f45beSAndroid Build Coastguard Worker 
157*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
158*053f45beSAndroid Build Coastguard Worker 	self->fd = -1;
159*053f45beSAndroid Build Coastguard Worker }
160*053f45beSAndroid Build Coastguard Worker 
FIXTURE_TEARDOWN(hmm2)161*053f45beSAndroid Build Coastguard Worker FIXTURE_TEARDOWN(hmm2)
162*053f45beSAndroid Build Coastguard Worker {
163*053f45beSAndroid Build Coastguard Worker 	int ret = close(self->fd0);
164*053f45beSAndroid Build Coastguard Worker 
165*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
166*053f45beSAndroid Build Coastguard Worker 	self->fd0 = -1;
167*053f45beSAndroid Build Coastguard Worker 
168*053f45beSAndroid Build Coastguard Worker 	ret = close(self->fd1);
169*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
170*053f45beSAndroid Build Coastguard Worker 	self->fd1 = -1;
171*053f45beSAndroid Build Coastguard Worker }
172*053f45beSAndroid Build Coastguard Worker 
hmm_dmirror_cmd(int fd,unsigned long request,struct hmm_buffer * buffer,unsigned long npages)173*053f45beSAndroid Build Coastguard Worker static int hmm_dmirror_cmd(int fd,
174*053f45beSAndroid Build Coastguard Worker 			   unsigned long request,
175*053f45beSAndroid Build Coastguard Worker 			   struct hmm_buffer *buffer,
176*053f45beSAndroid Build Coastguard Worker 			   unsigned long npages)
177*053f45beSAndroid Build Coastguard Worker {
178*053f45beSAndroid Build Coastguard Worker 	struct hmm_dmirror_cmd cmd;
179*053f45beSAndroid Build Coastguard Worker 	int ret;
180*053f45beSAndroid Build Coastguard Worker 
181*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device reading system memory. */
182*053f45beSAndroid Build Coastguard Worker 	cmd.addr = (__u64)buffer->ptr;
183*053f45beSAndroid Build Coastguard Worker 	cmd.ptr = (__u64)buffer->mirror;
184*053f45beSAndroid Build Coastguard Worker 	cmd.npages = npages;
185*053f45beSAndroid Build Coastguard Worker 
186*053f45beSAndroid Build Coastguard Worker 	for (;;) {
187*053f45beSAndroid Build Coastguard Worker 		ret = ioctl(fd, request, &cmd);
188*053f45beSAndroid Build Coastguard Worker 		if (ret == 0)
189*053f45beSAndroid Build Coastguard Worker 			break;
190*053f45beSAndroid Build Coastguard Worker 		if (errno == EINTR)
191*053f45beSAndroid Build Coastguard Worker 			continue;
192*053f45beSAndroid Build Coastguard Worker 		return -errno;
193*053f45beSAndroid Build Coastguard Worker 	}
194*053f45beSAndroid Build Coastguard Worker 	buffer->cpages = cmd.cpages;
195*053f45beSAndroid Build Coastguard Worker 	buffer->faults = cmd.faults;
196*053f45beSAndroid Build Coastguard Worker 
197*053f45beSAndroid Build Coastguard Worker 	return 0;
198*053f45beSAndroid Build Coastguard Worker }
199*053f45beSAndroid Build Coastguard Worker 
hmm_buffer_free(struct hmm_buffer * buffer)200*053f45beSAndroid Build Coastguard Worker static void hmm_buffer_free(struct hmm_buffer *buffer)
201*053f45beSAndroid Build Coastguard Worker {
202*053f45beSAndroid Build Coastguard Worker 	if (buffer == NULL)
203*053f45beSAndroid Build Coastguard Worker 		return;
204*053f45beSAndroid Build Coastguard Worker 
205*053f45beSAndroid Build Coastguard Worker 	if (buffer->ptr)
206*053f45beSAndroid Build Coastguard Worker 		munmap(buffer->ptr, buffer->size);
207*053f45beSAndroid Build Coastguard Worker 	free(buffer->mirror);
208*053f45beSAndroid Build Coastguard Worker 	free(buffer);
209*053f45beSAndroid Build Coastguard Worker }
210*053f45beSAndroid Build Coastguard Worker 
211*053f45beSAndroid Build Coastguard Worker /*
212*053f45beSAndroid Build Coastguard Worker  * Create a temporary file that will be deleted on close.
213*053f45beSAndroid Build Coastguard Worker  */
hmm_create_file(unsigned long size)214*053f45beSAndroid Build Coastguard Worker static int hmm_create_file(unsigned long size)
215*053f45beSAndroid Build Coastguard Worker {
216*053f45beSAndroid Build Coastguard Worker 	char path[HMM_PATH_MAX];
217*053f45beSAndroid Build Coastguard Worker 	int fd;
218*053f45beSAndroid Build Coastguard Worker 
219*053f45beSAndroid Build Coastguard Worker 	strcpy(path, "/tmp");
220*053f45beSAndroid Build Coastguard Worker 	fd = open(path, O_TMPFILE | O_EXCL | O_RDWR, 0600);
221*053f45beSAndroid Build Coastguard Worker 	if (fd >= 0) {
222*053f45beSAndroid Build Coastguard Worker 		int r;
223*053f45beSAndroid Build Coastguard Worker 
224*053f45beSAndroid Build Coastguard Worker 		do {
225*053f45beSAndroid Build Coastguard Worker 			r = ftruncate(fd, size);
226*053f45beSAndroid Build Coastguard Worker 		} while (r == -1 && errno == EINTR);
227*053f45beSAndroid Build Coastguard Worker 		if (!r)
228*053f45beSAndroid Build Coastguard Worker 			return fd;
229*053f45beSAndroid Build Coastguard Worker 		close(fd);
230*053f45beSAndroid Build Coastguard Worker 	}
231*053f45beSAndroid Build Coastguard Worker 	return -1;
232*053f45beSAndroid Build Coastguard Worker }
233*053f45beSAndroid Build Coastguard Worker 
234*053f45beSAndroid Build Coastguard Worker /*
235*053f45beSAndroid Build Coastguard Worker  * Return a random unsigned number.
236*053f45beSAndroid Build Coastguard Worker  */
hmm_random(void)237*053f45beSAndroid Build Coastguard Worker static unsigned int hmm_random(void)
238*053f45beSAndroid Build Coastguard Worker {
239*053f45beSAndroid Build Coastguard Worker 	static int fd = -1;
240*053f45beSAndroid Build Coastguard Worker 	unsigned int r;
241*053f45beSAndroid Build Coastguard Worker 
242*053f45beSAndroid Build Coastguard Worker 	if (fd < 0) {
243*053f45beSAndroid Build Coastguard Worker 		fd = open("/dev/urandom", O_RDONLY);
244*053f45beSAndroid Build Coastguard Worker 		if (fd < 0) {
245*053f45beSAndroid Build Coastguard Worker 			fprintf(stderr, "%s:%d failed to open /dev/urandom\n",
246*053f45beSAndroid Build Coastguard Worker 					__FILE__, __LINE__);
247*053f45beSAndroid Build Coastguard Worker 			return ~0U;
248*053f45beSAndroid Build Coastguard Worker 		}
249*053f45beSAndroid Build Coastguard Worker 	}
250*053f45beSAndroid Build Coastguard Worker 	read(fd, &r, sizeof(r));
251*053f45beSAndroid Build Coastguard Worker 	return r;
252*053f45beSAndroid Build Coastguard Worker }
253*053f45beSAndroid Build Coastguard Worker 
hmm_nanosleep(unsigned int n)254*053f45beSAndroid Build Coastguard Worker static void hmm_nanosleep(unsigned int n)
255*053f45beSAndroid Build Coastguard Worker {
256*053f45beSAndroid Build Coastguard Worker 	struct timespec t;
257*053f45beSAndroid Build Coastguard Worker 
258*053f45beSAndroid Build Coastguard Worker 	t.tv_sec = 0;
259*053f45beSAndroid Build Coastguard Worker 	t.tv_nsec = n;
260*053f45beSAndroid Build Coastguard Worker 	nanosleep(&t, NULL);
261*053f45beSAndroid Build Coastguard Worker }
262*053f45beSAndroid Build Coastguard Worker 
hmm_migrate_sys_to_dev(int fd,struct hmm_buffer * buffer,unsigned long npages)263*053f45beSAndroid Build Coastguard Worker static int hmm_migrate_sys_to_dev(int fd,
264*053f45beSAndroid Build Coastguard Worker 				   struct hmm_buffer *buffer,
265*053f45beSAndroid Build Coastguard Worker 				   unsigned long npages)
266*053f45beSAndroid Build Coastguard Worker {
267*053f45beSAndroid Build Coastguard Worker 	return hmm_dmirror_cmd(fd, HMM_DMIRROR_MIGRATE_TO_DEV, buffer, npages);
268*053f45beSAndroid Build Coastguard Worker }
269*053f45beSAndroid Build Coastguard Worker 
hmm_migrate_dev_to_sys(int fd,struct hmm_buffer * buffer,unsigned long npages)270*053f45beSAndroid Build Coastguard Worker static int hmm_migrate_dev_to_sys(int fd,
271*053f45beSAndroid Build Coastguard Worker 				   struct hmm_buffer *buffer,
272*053f45beSAndroid Build Coastguard Worker 				   unsigned long npages)
273*053f45beSAndroid Build Coastguard Worker {
274*053f45beSAndroid Build Coastguard Worker 	return hmm_dmirror_cmd(fd, HMM_DMIRROR_MIGRATE_TO_SYS, buffer, npages);
275*053f45beSAndroid Build Coastguard Worker }
276*053f45beSAndroid Build Coastguard Worker 
277*053f45beSAndroid Build Coastguard Worker /*
278*053f45beSAndroid Build Coastguard Worker  * Simple NULL test of device open/close.
279*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,open_close)280*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, open_close)
281*053f45beSAndroid Build Coastguard Worker {
282*053f45beSAndroid Build Coastguard Worker }
283*053f45beSAndroid Build Coastguard Worker 
284*053f45beSAndroid Build Coastguard Worker /*
285*053f45beSAndroid Build Coastguard Worker  * Read private anonymous memory.
286*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,anon_read)287*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, anon_read)
288*053f45beSAndroid Build Coastguard Worker {
289*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
290*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
291*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
292*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
293*053f45beSAndroid Build Coastguard Worker 	int *ptr;
294*053f45beSAndroid Build Coastguard Worker 	int ret;
295*053f45beSAndroid Build Coastguard Worker 	int val;
296*053f45beSAndroid Build Coastguard Worker 
297*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
298*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
299*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
300*053f45beSAndroid Build Coastguard Worker 
301*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
302*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
303*053f45beSAndroid Build Coastguard Worker 
304*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
305*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
306*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
307*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
308*053f45beSAndroid Build Coastguard Worker 
309*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
310*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
311*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
312*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
313*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
314*053f45beSAndroid Build Coastguard Worker 
315*053f45beSAndroid Build Coastguard Worker 	/*
316*053f45beSAndroid Build Coastguard Worker 	 * Initialize buffer in system memory but leave the first two pages
317*053f45beSAndroid Build Coastguard Worker 	 * zero (pte_none and pfn_zero).
318*053f45beSAndroid Build Coastguard Worker 	 */
319*053f45beSAndroid Build Coastguard Worker 	i = 2 * self->page_size / sizeof(*ptr);
320*053f45beSAndroid Build Coastguard Worker 	for (ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
321*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
322*053f45beSAndroid Build Coastguard Worker 
323*053f45beSAndroid Build Coastguard Worker 	/* Set buffer permission to read-only. */
324*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr, size, PROT_READ);
325*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
326*053f45beSAndroid Build Coastguard Worker 
327*053f45beSAndroid Build Coastguard Worker 	/* Populate the CPU page table with a special zero page. */
328*053f45beSAndroid Build Coastguard Worker 	val = *(int *)(buffer->ptr + self->page_size);
329*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(val, 0);
330*053f45beSAndroid Build Coastguard Worker 
331*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device reading system memory. */
332*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_READ, buffer, npages);
333*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
334*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
335*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
336*053f45beSAndroid Build Coastguard Worker 
337*053f45beSAndroid Build Coastguard Worker 	/* Check what the device read. */
338*053f45beSAndroid Build Coastguard Worker 	ptr = buffer->mirror;
339*053f45beSAndroid Build Coastguard Worker 	for (i = 0; i < 2 * self->page_size / sizeof(*ptr); ++i)
340*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], 0);
341*053f45beSAndroid Build Coastguard Worker 	for (; i < size / sizeof(*ptr); ++i)
342*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
343*053f45beSAndroid Build Coastguard Worker 
344*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
345*053f45beSAndroid Build Coastguard Worker }
346*053f45beSAndroid Build Coastguard Worker 
347*053f45beSAndroid Build Coastguard Worker /*
348*053f45beSAndroid Build Coastguard Worker  * Read private anonymous memory which has been protected with
349*053f45beSAndroid Build Coastguard Worker  * mprotect() PROT_NONE.
350*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,anon_read_prot)351*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, anon_read_prot)
352*053f45beSAndroid Build Coastguard Worker {
353*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
354*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
355*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
356*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
357*053f45beSAndroid Build Coastguard Worker 	int *ptr;
358*053f45beSAndroid Build Coastguard Worker 	int ret;
359*053f45beSAndroid Build Coastguard Worker 
360*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
361*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
362*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
363*053f45beSAndroid Build Coastguard Worker 
364*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
365*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
366*053f45beSAndroid Build Coastguard Worker 
367*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
368*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
369*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
370*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
371*053f45beSAndroid Build Coastguard Worker 
372*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
373*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
374*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
375*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
376*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
377*053f45beSAndroid Build Coastguard Worker 
378*053f45beSAndroid Build Coastguard Worker 	/* Initialize buffer in system memory. */
379*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
380*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
381*053f45beSAndroid Build Coastguard Worker 
382*053f45beSAndroid Build Coastguard Worker 	/* Initialize mirror buffer so we can verify it isn't written. */
383*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
384*053f45beSAndroid Build Coastguard Worker 		ptr[i] = -i;
385*053f45beSAndroid Build Coastguard Worker 
386*053f45beSAndroid Build Coastguard Worker 	/* Protect buffer from reading. */
387*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr, size, PROT_NONE);
388*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
389*053f45beSAndroid Build Coastguard Worker 
390*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device reading system memory. */
391*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_READ, buffer, npages);
392*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, -EFAULT);
393*053f45beSAndroid Build Coastguard Worker 
394*053f45beSAndroid Build Coastguard Worker 	/* Allow CPU to read the buffer so we can check it. */
395*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr, size, PROT_READ);
396*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
397*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
398*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
399*053f45beSAndroid Build Coastguard Worker 
400*053f45beSAndroid Build Coastguard Worker 	/* Check what the device read. */
401*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
402*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], -i);
403*053f45beSAndroid Build Coastguard Worker 
404*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
405*053f45beSAndroid Build Coastguard Worker }
406*053f45beSAndroid Build Coastguard Worker 
407*053f45beSAndroid Build Coastguard Worker /*
408*053f45beSAndroid Build Coastguard Worker  * Write private anonymous memory.
409*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,anon_write)410*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, anon_write)
411*053f45beSAndroid Build Coastguard Worker {
412*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
413*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
414*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
415*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
416*053f45beSAndroid Build Coastguard Worker 	int *ptr;
417*053f45beSAndroid Build Coastguard Worker 	int ret;
418*053f45beSAndroid Build Coastguard Worker 
419*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
420*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
421*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
422*053f45beSAndroid Build Coastguard Worker 
423*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
424*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
425*053f45beSAndroid Build Coastguard Worker 
426*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
427*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
428*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
429*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
430*053f45beSAndroid Build Coastguard Worker 
431*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
432*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
433*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
434*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
435*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
436*053f45beSAndroid Build Coastguard Worker 
437*053f45beSAndroid Build Coastguard Worker 	/* Initialize data that the device will write to buffer->ptr. */
438*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
439*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
440*053f45beSAndroid Build Coastguard Worker 
441*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device writing system memory. */
442*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_WRITE, buffer, npages);
443*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
444*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
445*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
446*053f45beSAndroid Build Coastguard Worker 
447*053f45beSAndroid Build Coastguard Worker 	/* Check what the device wrote. */
448*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
449*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
450*053f45beSAndroid Build Coastguard Worker 
451*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
452*053f45beSAndroid Build Coastguard Worker }
453*053f45beSAndroid Build Coastguard Worker 
454*053f45beSAndroid Build Coastguard Worker /*
455*053f45beSAndroid Build Coastguard Worker  * Write private anonymous memory which has been protected with
456*053f45beSAndroid Build Coastguard Worker  * mprotect() PROT_READ.
457*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,anon_write_prot)458*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, anon_write_prot)
459*053f45beSAndroid Build Coastguard Worker {
460*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
461*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
462*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
463*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
464*053f45beSAndroid Build Coastguard Worker 	int *ptr;
465*053f45beSAndroid Build Coastguard Worker 	int ret;
466*053f45beSAndroid Build Coastguard Worker 
467*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
468*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
469*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
470*053f45beSAndroid Build Coastguard Worker 
471*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
472*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
473*053f45beSAndroid Build Coastguard Worker 
474*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
475*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
476*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
477*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
478*053f45beSAndroid Build Coastguard Worker 
479*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
480*053f45beSAndroid Build Coastguard Worker 			   PROT_READ,
481*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
482*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
483*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
484*053f45beSAndroid Build Coastguard Worker 
485*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device reading a zero page of memory. */
486*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_READ, buffer, 1);
487*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
488*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, 1);
489*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
490*053f45beSAndroid Build Coastguard Worker 
491*053f45beSAndroid Build Coastguard Worker 	/* Initialize data that the device will write to buffer->ptr. */
492*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
493*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
494*053f45beSAndroid Build Coastguard Worker 
495*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device writing system memory. */
496*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_WRITE, buffer, npages);
497*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, -EPERM);
498*053f45beSAndroid Build Coastguard Worker 
499*053f45beSAndroid Build Coastguard Worker 	/* Check what the device wrote. */
500*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
501*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], 0);
502*053f45beSAndroid Build Coastguard Worker 
503*053f45beSAndroid Build Coastguard Worker 	/* Now allow writing and see that the zero page is replaced. */
504*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr, size, PROT_WRITE | PROT_READ);
505*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
506*053f45beSAndroid Build Coastguard Worker 
507*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device writing system memory. */
508*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_WRITE, buffer, npages);
509*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
510*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
511*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
512*053f45beSAndroid Build Coastguard Worker 
513*053f45beSAndroid Build Coastguard Worker 	/* Check what the device wrote. */
514*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
515*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
516*053f45beSAndroid Build Coastguard Worker 
517*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
518*053f45beSAndroid Build Coastguard Worker }
519*053f45beSAndroid Build Coastguard Worker 
520*053f45beSAndroid Build Coastguard Worker /*
521*053f45beSAndroid Build Coastguard Worker  * Check that a device writing an anonymous private mapping
522*053f45beSAndroid Build Coastguard Worker  * will copy-on-write if a child process inherits the mapping.
523*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,anon_write_child)524*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, anon_write_child)
525*053f45beSAndroid Build Coastguard Worker {
526*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
527*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
528*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
529*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
530*053f45beSAndroid Build Coastguard Worker 	int *ptr;
531*053f45beSAndroid Build Coastguard Worker 	pid_t pid;
532*053f45beSAndroid Build Coastguard Worker 	int child_fd;
533*053f45beSAndroid Build Coastguard Worker 	int ret;
534*053f45beSAndroid Build Coastguard Worker 
535*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
536*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
537*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
538*053f45beSAndroid Build Coastguard Worker 
539*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
540*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
541*053f45beSAndroid Build Coastguard Worker 
542*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
543*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
544*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
545*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
546*053f45beSAndroid Build Coastguard Worker 
547*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
548*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
549*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
550*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
551*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
552*053f45beSAndroid Build Coastguard Worker 
553*053f45beSAndroid Build Coastguard Worker 	/* Initialize buffer->ptr so we can tell if it is written. */
554*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
555*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
556*053f45beSAndroid Build Coastguard Worker 
557*053f45beSAndroid Build Coastguard Worker 	/* Initialize data that the device will write to buffer->ptr. */
558*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
559*053f45beSAndroid Build Coastguard Worker 		ptr[i] = -i;
560*053f45beSAndroid Build Coastguard Worker 
561*053f45beSAndroid Build Coastguard Worker 	pid = fork();
562*053f45beSAndroid Build Coastguard Worker 	if (pid == -1)
563*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(pid, 0);
564*053f45beSAndroid Build Coastguard Worker 	if (pid != 0) {
565*053f45beSAndroid Build Coastguard Worker 		waitpid(pid, &ret, 0);
566*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(WIFEXITED(ret), 1);
567*053f45beSAndroid Build Coastguard Worker 
568*053f45beSAndroid Build Coastguard Worker 		/* Check that the parent's buffer did not change. */
569*053f45beSAndroid Build Coastguard Worker 		for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
570*053f45beSAndroid Build Coastguard Worker 			ASSERT_EQ(ptr[i], i);
571*053f45beSAndroid Build Coastguard Worker 		return;
572*053f45beSAndroid Build Coastguard Worker 	}
573*053f45beSAndroid Build Coastguard Worker 
574*053f45beSAndroid Build Coastguard Worker 	/* Check that we see the parent's values. */
575*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
576*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
577*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
578*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], -i);
579*053f45beSAndroid Build Coastguard Worker 
580*053f45beSAndroid Build Coastguard Worker 	/* The child process needs its own mirror to its own mm. */
581*053f45beSAndroid Build Coastguard Worker 	child_fd = hmm_open(0);
582*053f45beSAndroid Build Coastguard Worker 	ASSERT_GE(child_fd, 0);
583*053f45beSAndroid Build Coastguard Worker 
584*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device writing system memory. */
585*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(child_fd, HMM_DMIRROR_WRITE, buffer, npages);
586*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
587*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
588*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
589*053f45beSAndroid Build Coastguard Worker 
590*053f45beSAndroid Build Coastguard Worker 	/* Check what the device wrote. */
591*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
592*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], -i);
593*053f45beSAndroid Build Coastguard Worker 
594*053f45beSAndroid Build Coastguard Worker 	close(child_fd);
595*053f45beSAndroid Build Coastguard Worker 	exit(0);
596*053f45beSAndroid Build Coastguard Worker }
597*053f45beSAndroid Build Coastguard Worker 
598*053f45beSAndroid Build Coastguard Worker /*
599*053f45beSAndroid Build Coastguard Worker  * Check that a device writing an anonymous shared mapping
600*053f45beSAndroid Build Coastguard Worker  * will not copy-on-write if a child process inherits the mapping.
601*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,anon_write_child_shared)602*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, anon_write_child_shared)
603*053f45beSAndroid Build Coastguard Worker {
604*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
605*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
606*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
607*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
608*053f45beSAndroid Build Coastguard Worker 	int *ptr;
609*053f45beSAndroid Build Coastguard Worker 	pid_t pid;
610*053f45beSAndroid Build Coastguard Worker 	int child_fd;
611*053f45beSAndroid Build Coastguard Worker 	int ret;
612*053f45beSAndroid Build Coastguard Worker 
613*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
614*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
615*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
616*053f45beSAndroid Build Coastguard Worker 
617*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
618*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
619*053f45beSAndroid Build Coastguard Worker 
620*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
621*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
622*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
623*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
624*053f45beSAndroid Build Coastguard Worker 
625*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
626*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
627*053f45beSAndroid Build Coastguard Worker 			   MAP_SHARED | MAP_ANONYMOUS,
628*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
629*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
630*053f45beSAndroid Build Coastguard Worker 
631*053f45beSAndroid Build Coastguard Worker 	/* Initialize buffer->ptr so we can tell if it is written. */
632*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
633*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
634*053f45beSAndroid Build Coastguard Worker 
635*053f45beSAndroid Build Coastguard Worker 	/* Initialize data that the device will write to buffer->ptr. */
636*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
637*053f45beSAndroid Build Coastguard Worker 		ptr[i] = -i;
638*053f45beSAndroid Build Coastguard Worker 
639*053f45beSAndroid Build Coastguard Worker 	pid = fork();
640*053f45beSAndroid Build Coastguard Worker 	if (pid == -1)
641*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(pid, 0);
642*053f45beSAndroid Build Coastguard Worker 	if (pid != 0) {
643*053f45beSAndroid Build Coastguard Worker 		waitpid(pid, &ret, 0);
644*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(WIFEXITED(ret), 1);
645*053f45beSAndroid Build Coastguard Worker 
646*053f45beSAndroid Build Coastguard Worker 		/* Check that the parent's buffer did change. */
647*053f45beSAndroid Build Coastguard Worker 		for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
648*053f45beSAndroid Build Coastguard Worker 			ASSERT_EQ(ptr[i], -i);
649*053f45beSAndroid Build Coastguard Worker 		return;
650*053f45beSAndroid Build Coastguard Worker 	}
651*053f45beSAndroid Build Coastguard Worker 
652*053f45beSAndroid Build Coastguard Worker 	/* Check that we see the parent's values. */
653*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
654*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
655*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
656*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], -i);
657*053f45beSAndroid Build Coastguard Worker 
658*053f45beSAndroid Build Coastguard Worker 	/* The child process needs its own mirror to its own mm. */
659*053f45beSAndroid Build Coastguard Worker 	child_fd = hmm_open(0);
660*053f45beSAndroid Build Coastguard Worker 	ASSERT_GE(child_fd, 0);
661*053f45beSAndroid Build Coastguard Worker 
662*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device writing system memory. */
663*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(child_fd, HMM_DMIRROR_WRITE, buffer, npages);
664*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
665*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
666*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
667*053f45beSAndroid Build Coastguard Worker 
668*053f45beSAndroid Build Coastguard Worker 	/* Check what the device wrote. */
669*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
670*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], -i);
671*053f45beSAndroid Build Coastguard Worker 
672*053f45beSAndroid Build Coastguard Worker 	close(child_fd);
673*053f45beSAndroid Build Coastguard Worker 	exit(0);
674*053f45beSAndroid Build Coastguard Worker }
675*053f45beSAndroid Build Coastguard Worker 
676*053f45beSAndroid Build Coastguard Worker /*
677*053f45beSAndroid Build Coastguard Worker  * Write private anonymous huge page.
678*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,anon_write_huge)679*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, anon_write_huge)
680*053f45beSAndroid Build Coastguard Worker {
681*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
682*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
683*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
684*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
685*053f45beSAndroid Build Coastguard Worker 	void *old_ptr;
686*053f45beSAndroid Build Coastguard Worker 	void *map;
687*053f45beSAndroid Build Coastguard Worker 	int *ptr;
688*053f45beSAndroid Build Coastguard Worker 	int ret;
689*053f45beSAndroid Build Coastguard Worker 
690*053f45beSAndroid Build Coastguard Worker 	size = 2 * TWOMEG;
691*053f45beSAndroid Build Coastguard Worker 
692*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
693*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
694*053f45beSAndroid Build Coastguard Worker 
695*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
696*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
697*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
698*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
699*053f45beSAndroid Build Coastguard Worker 
700*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
701*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
702*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
703*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
704*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
705*053f45beSAndroid Build Coastguard Worker 
706*053f45beSAndroid Build Coastguard Worker 	size = TWOMEG;
707*053f45beSAndroid Build Coastguard Worker 	npages = size >> self->page_shift;
708*053f45beSAndroid Build Coastguard Worker 	map = (void *)ALIGN((uintptr_t)buffer->ptr, size);
709*053f45beSAndroid Build Coastguard Worker 	ret = madvise(map, size, MADV_HUGEPAGE);
710*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
711*053f45beSAndroid Build Coastguard Worker 	old_ptr = buffer->ptr;
712*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = map;
713*053f45beSAndroid Build Coastguard Worker 
714*053f45beSAndroid Build Coastguard Worker 	/* Initialize data that the device will write to buffer->ptr. */
715*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
716*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
717*053f45beSAndroid Build Coastguard Worker 
718*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device writing system memory. */
719*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_WRITE, buffer, npages);
720*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
721*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
722*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
723*053f45beSAndroid Build Coastguard Worker 
724*053f45beSAndroid Build Coastguard Worker 	/* Check what the device wrote. */
725*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
726*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
727*053f45beSAndroid Build Coastguard Worker 
728*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = old_ptr;
729*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
730*053f45beSAndroid Build Coastguard Worker }
731*053f45beSAndroid Build Coastguard Worker 
732*053f45beSAndroid Build Coastguard Worker /*
733*053f45beSAndroid Build Coastguard Worker  * Read numeric data from raw and tagged kernel status files.  Used to read
734*053f45beSAndroid Build Coastguard Worker  * /proc and /sys data (without a tag) and from /proc/meminfo (with a tag).
735*053f45beSAndroid Build Coastguard Worker  */
file_read_ulong(char * file,const char * tag)736*053f45beSAndroid Build Coastguard Worker static long file_read_ulong(char *file, const char *tag)
737*053f45beSAndroid Build Coastguard Worker {
738*053f45beSAndroid Build Coastguard Worker 	int fd;
739*053f45beSAndroid Build Coastguard Worker 	char buf[2048];
740*053f45beSAndroid Build Coastguard Worker 	int len;
741*053f45beSAndroid Build Coastguard Worker 	char *p, *q;
742*053f45beSAndroid Build Coastguard Worker 	long val;
743*053f45beSAndroid Build Coastguard Worker 
744*053f45beSAndroid Build Coastguard Worker 	fd = open(file, O_RDONLY);
745*053f45beSAndroid Build Coastguard Worker 	if (fd < 0) {
746*053f45beSAndroid Build Coastguard Worker 		/* Error opening the file */
747*053f45beSAndroid Build Coastguard Worker 		return -1;
748*053f45beSAndroid Build Coastguard Worker 	}
749*053f45beSAndroid Build Coastguard Worker 
750*053f45beSAndroid Build Coastguard Worker 	len = read(fd, buf, sizeof(buf));
751*053f45beSAndroid Build Coastguard Worker 	close(fd);
752*053f45beSAndroid Build Coastguard Worker 	if (len < 0) {
753*053f45beSAndroid Build Coastguard Worker 		/* Error in reading the file */
754*053f45beSAndroid Build Coastguard Worker 		return -1;
755*053f45beSAndroid Build Coastguard Worker 	}
756*053f45beSAndroid Build Coastguard Worker 	if (len == sizeof(buf)) {
757*053f45beSAndroid Build Coastguard Worker 		/* Error file is too large */
758*053f45beSAndroid Build Coastguard Worker 		return -1;
759*053f45beSAndroid Build Coastguard Worker 	}
760*053f45beSAndroid Build Coastguard Worker 	buf[len] = '\0';
761*053f45beSAndroid Build Coastguard Worker 
762*053f45beSAndroid Build Coastguard Worker 	/* Search for a tag if provided */
763*053f45beSAndroid Build Coastguard Worker 	if (tag) {
764*053f45beSAndroid Build Coastguard Worker 		p = strstr(buf, tag);
765*053f45beSAndroid Build Coastguard Worker 		if (!p)
766*053f45beSAndroid Build Coastguard Worker 			return -1; /* looks like the line we want isn't there */
767*053f45beSAndroid Build Coastguard Worker 		p += strlen(tag);
768*053f45beSAndroid Build Coastguard Worker 	} else
769*053f45beSAndroid Build Coastguard Worker 		p = buf;
770*053f45beSAndroid Build Coastguard Worker 
771*053f45beSAndroid Build Coastguard Worker 	val = strtol(p, &q, 0);
772*053f45beSAndroid Build Coastguard Worker 	if (*q != ' ') {
773*053f45beSAndroid Build Coastguard Worker 		/* Error parsing the file */
774*053f45beSAndroid Build Coastguard Worker 		return -1;
775*053f45beSAndroid Build Coastguard Worker 	}
776*053f45beSAndroid Build Coastguard Worker 
777*053f45beSAndroid Build Coastguard Worker 	return val;
778*053f45beSAndroid Build Coastguard Worker }
779*053f45beSAndroid Build Coastguard Worker 
780*053f45beSAndroid Build Coastguard Worker /*
781*053f45beSAndroid Build Coastguard Worker  * Write huge TLBFS page.
782*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,anon_write_hugetlbfs)783*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, anon_write_hugetlbfs)
784*053f45beSAndroid Build Coastguard Worker {
785*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
786*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
787*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
788*053f45beSAndroid Build Coastguard Worker 	unsigned long default_hsize;
789*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
790*053f45beSAndroid Build Coastguard Worker 	int *ptr;
791*053f45beSAndroid Build Coastguard Worker 	int ret;
792*053f45beSAndroid Build Coastguard Worker 
793*053f45beSAndroid Build Coastguard Worker 	default_hsize = file_read_ulong("/proc/meminfo", "Hugepagesize:");
794*053f45beSAndroid Build Coastguard Worker 	if (default_hsize < 0 || default_hsize*1024 < default_hsize)
795*053f45beSAndroid Build Coastguard Worker 		SKIP(return, "Huge page size could not be determined");
796*053f45beSAndroid Build Coastguard Worker 	default_hsize = default_hsize*1024; /* KB to B */
797*053f45beSAndroid Build Coastguard Worker 
798*053f45beSAndroid Build Coastguard Worker 	size = ALIGN(TWOMEG, default_hsize);
799*053f45beSAndroid Build Coastguard Worker 	npages = size >> self->page_shift;
800*053f45beSAndroid Build Coastguard Worker 
801*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
802*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
803*053f45beSAndroid Build Coastguard Worker 
804*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
805*053f45beSAndroid Build Coastguard Worker 				   PROT_READ | PROT_WRITE,
806*053f45beSAndroid Build Coastguard Worker 				   MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
807*053f45beSAndroid Build Coastguard Worker 				   -1, 0);
808*053f45beSAndroid Build Coastguard Worker 	if (buffer->ptr == MAP_FAILED) {
809*053f45beSAndroid Build Coastguard Worker 		free(buffer);
810*053f45beSAndroid Build Coastguard Worker 		SKIP(return, "Huge page could not be allocated");
811*053f45beSAndroid Build Coastguard Worker 	}
812*053f45beSAndroid Build Coastguard Worker 
813*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
814*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
815*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
816*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
817*053f45beSAndroid Build Coastguard Worker 
818*053f45beSAndroid Build Coastguard Worker 	/* Initialize data that the device will write to buffer->ptr. */
819*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
820*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
821*053f45beSAndroid Build Coastguard Worker 
822*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device writing system memory. */
823*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_WRITE, buffer, npages);
824*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
825*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
826*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
827*053f45beSAndroid Build Coastguard Worker 
828*053f45beSAndroid Build Coastguard Worker 	/* Check what the device wrote. */
829*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
830*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
831*053f45beSAndroid Build Coastguard Worker 
832*053f45beSAndroid Build Coastguard Worker 	munmap(buffer->ptr, buffer->size);
833*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = NULL;
834*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
835*053f45beSAndroid Build Coastguard Worker }
836*053f45beSAndroid Build Coastguard Worker 
837*053f45beSAndroid Build Coastguard Worker /*
838*053f45beSAndroid Build Coastguard Worker  * Read mmap'ed file memory.
839*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,file_read)840*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, file_read)
841*053f45beSAndroid Build Coastguard Worker {
842*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
843*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
844*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
845*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
846*053f45beSAndroid Build Coastguard Worker 	int *ptr;
847*053f45beSAndroid Build Coastguard Worker 	int ret;
848*053f45beSAndroid Build Coastguard Worker 	int fd;
849*053f45beSAndroid Build Coastguard Worker 	ssize_t len;
850*053f45beSAndroid Build Coastguard Worker 
851*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
852*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
853*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
854*053f45beSAndroid Build Coastguard Worker 
855*053f45beSAndroid Build Coastguard Worker 	fd = hmm_create_file(size);
856*053f45beSAndroid Build Coastguard Worker 	ASSERT_GE(fd, 0);
857*053f45beSAndroid Build Coastguard Worker 
858*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
859*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
860*053f45beSAndroid Build Coastguard Worker 
861*053f45beSAndroid Build Coastguard Worker 	buffer->fd = fd;
862*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
863*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
864*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
865*053f45beSAndroid Build Coastguard Worker 
866*053f45beSAndroid Build Coastguard Worker 	/* Write initial contents of the file. */
867*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
868*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
869*053f45beSAndroid Build Coastguard Worker 	len = pwrite(fd, buffer->mirror, size, 0);
870*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(len, size);
871*053f45beSAndroid Build Coastguard Worker 	memset(buffer->mirror, 0, size);
872*053f45beSAndroid Build Coastguard Worker 
873*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
874*053f45beSAndroid Build Coastguard Worker 			   PROT_READ,
875*053f45beSAndroid Build Coastguard Worker 			   MAP_SHARED,
876*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
877*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
878*053f45beSAndroid Build Coastguard Worker 
879*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device reading system memory. */
880*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_READ, buffer, npages);
881*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
882*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
883*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
884*053f45beSAndroid Build Coastguard Worker 
885*053f45beSAndroid Build Coastguard Worker 	/* Check what the device read. */
886*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
887*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
888*053f45beSAndroid Build Coastguard Worker 
889*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
890*053f45beSAndroid Build Coastguard Worker }
891*053f45beSAndroid Build Coastguard Worker 
892*053f45beSAndroid Build Coastguard Worker /*
893*053f45beSAndroid Build Coastguard Worker  * Write mmap'ed file memory.
894*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,file_write)895*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, file_write)
896*053f45beSAndroid Build Coastguard Worker {
897*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
898*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
899*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
900*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
901*053f45beSAndroid Build Coastguard Worker 	int *ptr;
902*053f45beSAndroid Build Coastguard Worker 	int ret;
903*053f45beSAndroid Build Coastguard Worker 	int fd;
904*053f45beSAndroid Build Coastguard Worker 	ssize_t len;
905*053f45beSAndroid Build Coastguard Worker 
906*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
907*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
908*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
909*053f45beSAndroid Build Coastguard Worker 
910*053f45beSAndroid Build Coastguard Worker 	fd = hmm_create_file(size);
911*053f45beSAndroid Build Coastguard Worker 	ASSERT_GE(fd, 0);
912*053f45beSAndroid Build Coastguard Worker 
913*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
914*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
915*053f45beSAndroid Build Coastguard Worker 
916*053f45beSAndroid Build Coastguard Worker 	buffer->fd = fd;
917*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
918*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
919*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
920*053f45beSAndroid Build Coastguard Worker 
921*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
922*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
923*053f45beSAndroid Build Coastguard Worker 			   MAP_SHARED,
924*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
925*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
926*053f45beSAndroid Build Coastguard Worker 
927*053f45beSAndroid Build Coastguard Worker 	/* Initialize data that the device will write to buffer->ptr. */
928*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
929*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
930*053f45beSAndroid Build Coastguard Worker 
931*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device writing system memory. */
932*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_WRITE, buffer, npages);
933*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
934*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
935*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
936*053f45beSAndroid Build Coastguard Worker 
937*053f45beSAndroid Build Coastguard Worker 	/* Check what the device wrote. */
938*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
939*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
940*053f45beSAndroid Build Coastguard Worker 
941*053f45beSAndroid Build Coastguard Worker 	/* Check that the device also wrote the file. */
942*053f45beSAndroid Build Coastguard Worker 	len = pread(fd, buffer->mirror, size, 0);
943*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(len, size);
944*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
945*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
946*053f45beSAndroid Build Coastguard Worker 
947*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
948*053f45beSAndroid Build Coastguard Worker }
949*053f45beSAndroid Build Coastguard Worker 
950*053f45beSAndroid Build Coastguard Worker /*
951*053f45beSAndroid Build Coastguard Worker  * Migrate anonymous memory to device private memory.
952*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,migrate)953*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, migrate)
954*053f45beSAndroid Build Coastguard Worker {
955*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
956*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
957*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
958*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
959*053f45beSAndroid Build Coastguard Worker 	int *ptr;
960*053f45beSAndroid Build Coastguard Worker 	int ret;
961*053f45beSAndroid Build Coastguard Worker 
962*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
963*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
964*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
965*053f45beSAndroid Build Coastguard Worker 
966*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
967*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
968*053f45beSAndroid Build Coastguard Worker 
969*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
970*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
971*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
972*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
973*053f45beSAndroid Build Coastguard Worker 
974*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
975*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
976*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
977*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
978*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
979*053f45beSAndroid Build Coastguard Worker 
980*053f45beSAndroid Build Coastguard Worker 	/* Initialize buffer in system memory. */
981*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
982*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
983*053f45beSAndroid Build Coastguard Worker 
984*053f45beSAndroid Build Coastguard Worker 	/* Migrate memory to device. */
985*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
986*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
987*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
988*053f45beSAndroid Build Coastguard Worker 
989*053f45beSAndroid Build Coastguard Worker 	/* Check what the device read. */
990*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
991*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
992*053f45beSAndroid Build Coastguard Worker 
993*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
994*053f45beSAndroid Build Coastguard Worker }
995*053f45beSAndroid Build Coastguard Worker 
996*053f45beSAndroid Build Coastguard Worker /*
997*053f45beSAndroid Build Coastguard Worker  * Migrate anonymous memory to device private memory and fault some of it back
998*053f45beSAndroid Build Coastguard Worker  * to system memory, then try migrating the resulting mix of system and device
999*053f45beSAndroid Build Coastguard Worker  * private memory to the device.
1000*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,migrate_fault)1001*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, migrate_fault)
1002*053f45beSAndroid Build Coastguard Worker {
1003*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1004*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1005*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1006*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
1007*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1008*053f45beSAndroid Build Coastguard Worker 	int ret;
1009*053f45beSAndroid Build Coastguard Worker 
1010*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
1011*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
1012*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1013*053f45beSAndroid Build Coastguard Worker 
1014*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1015*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1016*053f45beSAndroid Build Coastguard Worker 
1017*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
1018*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
1019*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
1020*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
1021*053f45beSAndroid Build Coastguard Worker 
1022*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
1023*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
1024*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
1025*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
1026*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
1027*053f45beSAndroid Build Coastguard Worker 
1028*053f45beSAndroid Build Coastguard Worker 	/* Initialize buffer in system memory. */
1029*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1030*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
1031*053f45beSAndroid Build Coastguard Worker 
1032*053f45beSAndroid Build Coastguard Worker 	/* Migrate memory to device. */
1033*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
1034*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1035*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1036*053f45beSAndroid Build Coastguard Worker 
1037*053f45beSAndroid Build Coastguard Worker 	/* Check what the device read. */
1038*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
1039*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
1040*053f45beSAndroid Build Coastguard Worker 
1041*053f45beSAndroid Build Coastguard Worker 	/* Fault half the pages back to system memory and check them. */
1042*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / (2 * sizeof(*ptr)); ++i)
1043*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
1044*053f45beSAndroid Build Coastguard Worker 
1045*053f45beSAndroid Build Coastguard Worker 	/* Migrate memory to the device again. */
1046*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
1047*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1048*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1049*053f45beSAndroid Build Coastguard Worker 
1050*053f45beSAndroid Build Coastguard Worker 	/* Check what the device read. */
1051*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
1052*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
1053*053f45beSAndroid Build Coastguard Worker 
1054*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
1055*053f45beSAndroid Build Coastguard Worker }
1056*053f45beSAndroid Build Coastguard Worker 
TEST_F(hmm,migrate_release)1057*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, migrate_release)
1058*053f45beSAndroid Build Coastguard Worker {
1059*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1060*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1061*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1062*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
1063*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1064*053f45beSAndroid Build Coastguard Worker 	int ret;
1065*053f45beSAndroid Build Coastguard Worker 
1066*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
1067*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
1068*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1069*053f45beSAndroid Build Coastguard Worker 
1070*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1071*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1072*053f45beSAndroid Build Coastguard Worker 
1073*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
1074*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
1075*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
1076*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
1077*053f45beSAndroid Build Coastguard Worker 
1078*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size, PROT_READ | PROT_WRITE,
1079*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS, buffer->fd, 0);
1080*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
1081*053f45beSAndroid Build Coastguard Worker 
1082*053f45beSAndroid Build Coastguard Worker 	/* Initialize buffer in system memory. */
1083*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1084*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
1085*053f45beSAndroid Build Coastguard Worker 
1086*053f45beSAndroid Build Coastguard Worker 	/* Migrate memory to device. */
1087*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
1088*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1089*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1090*053f45beSAndroid Build Coastguard Worker 
1091*053f45beSAndroid Build Coastguard Worker 	/* Check what the device read. */
1092*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
1093*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
1094*053f45beSAndroid Build Coastguard Worker 
1095*053f45beSAndroid Build Coastguard Worker 	/* Release device memory. */
1096*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_RELEASE, buffer, npages);
1097*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1098*053f45beSAndroid Build Coastguard Worker 
1099*053f45beSAndroid Build Coastguard Worker 	/* Fault pages back to system memory and check them. */
1100*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / (2 * sizeof(*ptr)); ++i)
1101*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
1102*053f45beSAndroid Build Coastguard Worker 
1103*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
1104*053f45beSAndroid Build Coastguard Worker }
1105*053f45beSAndroid Build Coastguard Worker 
1106*053f45beSAndroid Build Coastguard Worker /*
1107*053f45beSAndroid Build Coastguard Worker  * Migrate anonymous shared memory to device private memory.
1108*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,migrate_shared)1109*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, migrate_shared)
1110*053f45beSAndroid Build Coastguard Worker {
1111*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1112*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1113*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1114*053f45beSAndroid Build Coastguard Worker 	int ret;
1115*053f45beSAndroid Build Coastguard Worker 
1116*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
1117*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
1118*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1119*053f45beSAndroid Build Coastguard Worker 
1120*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1121*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1122*053f45beSAndroid Build Coastguard Worker 
1123*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
1124*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
1125*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
1126*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
1127*053f45beSAndroid Build Coastguard Worker 
1128*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
1129*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
1130*053f45beSAndroid Build Coastguard Worker 			   MAP_SHARED | MAP_ANONYMOUS,
1131*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
1132*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
1133*053f45beSAndroid Build Coastguard Worker 
1134*053f45beSAndroid Build Coastguard Worker 	/* Migrate memory to device. */
1135*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
1136*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, -ENOENT);
1137*053f45beSAndroid Build Coastguard Worker 
1138*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
1139*053f45beSAndroid Build Coastguard Worker }
1140*053f45beSAndroid Build Coastguard Worker 
1141*053f45beSAndroid Build Coastguard Worker /*
1142*053f45beSAndroid Build Coastguard Worker  * Try to migrate various memory types to device private memory.
1143*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm2,migrate_mixed)1144*053f45beSAndroid Build Coastguard Worker TEST_F(hmm2, migrate_mixed)
1145*053f45beSAndroid Build Coastguard Worker {
1146*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1147*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1148*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1149*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1150*053f45beSAndroid Build Coastguard Worker 	unsigned char *p;
1151*053f45beSAndroid Build Coastguard Worker 	int ret;
1152*053f45beSAndroid Build Coastguard Worker 	int val;
1153*053f45beSAndroid Build Coastguard Worker 
1154*053f45beSAndroid Build Coastguard Worker 	npages = 6;
1155*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1156*053f45beSAndroid Build Coastguard Worker 
1157*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1158*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1159*053f45beSAndroid Build Coastguard Worker 
1160*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
1161*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
1162*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
1163*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
1164*053f45beSAndroid Build Coastguard Worker 
1165*053f45beSAndroid Build Coastguard Worker 	/* Reserve a range of addresses. */
1166*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
1167*053f45beSAndroid Build Coastguard Worker 			   PROT_NONE,
1168*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
1169*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
1170*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
1171*053f45beSAndroid Build Coastguard Worker 	p = buffer->ptr;
1172*053f45beSAndroid Build Coastguard Worker 
1173*053f45beSAndroid Build Coastguard Worker 	/* Migrating a protected area should be an error. */
1174*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd1, buffer, npages);
1175*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, -EINVAL);
1176*053f45beSAndroid Build Coastguard Worker 
1177*053f45beSAndroid Build Coastguard Worker 	/* Punch a hole after the first page address. */
1178*053f45beSAndroid Build Coastguard Worker 	ret = munmap(buffer->ptr + self->page_size, self->page_size);
1179*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1180*053f45beSAndroid Build Coastguard Worker 
1181*053f45beSAndroid Build Coastguard Worker 	/* We expect an error if the vma doesn't cover the range. */
1182*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd1, buffer, 3);
1183*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, -EINVAL);
1184*053f45beSAndroid Build Coastguard Worker 
1185*053f45beSAndroid Build Coastguard Worker 	/* Page 2 will be a read-only zero page. */
1186*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr + 2 * self->page_size, self->page_size,
1187*053f45beSAndroid Build Coastguard Worker 				PROT_READ);
1188*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1189*053f45beSAndroid Build Coastguard Worker 	ptr = (int *)(buffer->ptr + 2 * self->page_size);
1190*053f45beSAndroid Build Coastguard Worker 	val = *ptr + 3;
1191*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(val, 3);
1192*053f45beSAndroid Build Coastguard Worker 
1193*053f45beSAndroid Build Coastguard Worker 	/* Page 3 will be read-only. */
1194*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr + 3 * self->page_size, self->page_size,
1195*053f45beSAndroid Build Coastguard Worker 				PROT_READ | PROT_WRITE);
1196*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1197*053f45beSAndroid Build Coastguard Worker 	ptr = (int *)(buffer->ptr + 3 * self->page_size);
1198*053f45beSAndroid Build Coastguard Worker 	*ptr = val;
1199*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr + 3 * self->page_size, self->page_size,
1200*053f45beSAndroid Build Coastguard Worker 				PROT_READ);
1201*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1202*053f45beSAndroid Build Coastguard Worker 
1203*053f45beSAndroid Build Coastguard Worker 	/* Page 4-5 will be read-write. */
1204*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr + 4 * self->page_size, 2 * self->page_size,
1205*053f45beSAndroid Build Coastguard Worker 				PROT_READ | PROT_WRITE);
1206*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1207*053f45beSAndroid Build Coastguard Worker 	ptr = (int *)(buffer->ptr + 4 * self->page_size);
1208*053f45beSAndroid Build Coastguard Worker 	*ptr = val;
1209*053f45beSAndroid Build Coastguard Worker 	ptr = (int *)(buffer->ptr + 5 * self->page_size);
1210*053f45beSAndroid Build Coastguard Worker 	*ptr = val;
1211*053f45beSAndroid Build Coastguard Worker 
1212*053f45beSAndroid Build Coastguard Worker 	/* Now try to migrate pages 2-5 to device 1. */
1213*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = p + 2 * self->page_size;
1214*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd1, buffer, 4);
1215*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1216*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, 4);
1217*053f45beSAndroid Build Coastguard Worker 
1218*053f45beSAndroid Build Coastguard Worker 	/* Page 5 won't be migrated to device 0 because it's on device 1. */
1219*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = p + 5 * self->page_size;
1220*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd0, buffer, 1);
1221*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, -ENOENT);
1222*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = p;
1223*053f45beSAndroid Build Coastguard Worker 
1224*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = p;
1225*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
1226*053f45beSAndroid Build Coastguard Worker }
1227*053f45beSAndroid Build Coastguard Worker 
1228*053f45beSAndroid Build Coastguard Worker /*
1229*053f45beSAndroid Build Coastguard Worker  * Migrate anonymous memory to device memory and back to system memory
1230*053f45beSAndroid Build Coastguard Worker  * multiple times. In case of private zone configuration, this is done
1231*053f45beSAndroid Build Coastguard Worker  * through fault pages accessed by CPU. In case of coherent zone configuration,
1232*053f45beSAndroid Build Coastguard Worker  * the pages from the device should be explicitly migrated back to system memory.
1233*053f45beSAndroid Build Coastguard Worker  * The reason is Coherent device zone has coherent access by CPU, therefore
1234*053f45beSAndroid Build Coastguard Worker  * it will not generate any page fault.
1235*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,migrate_multiple)1236*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, migrate_multiple)
1237*053f45beSAndroid Build Coastguard Worker {
1238*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1239*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1240*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1241*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
1242*053f45beSAndroid Build Coastguard Worker 	unsigned long c;
1243*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1244*053f45beSAndroid Build Coastguard Worker 	int ret;
1245*053f45beSAndroid Build Coastguard Worker 
1246*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
1247*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
1248*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1249*053f45beSAndroid Build Coastguard Worker 
1250*053f45beSAndroid Build Coastguard Worker 	for (c = 0; c < NTIMES; c++) {
1251*053f45beSAndroid Build Coastguard Worker 		buffer = malloc(sizeof(*buffer));
1252*053f45beSAndroid Build Coastguard Worker 		ASSERT_NE(buffer, NULL);
1253*053f45beSAndroid Build Coastguard Worker 
1254*053f45beSAndroid Build Coastguard Worker 		buffer->fd = -1;
1255*053f45beSAndroid Build Coastguard Worker 		buffer->size = size;
1256*053f45beSAndroid Build Coastguard Worker 		buffer->mirror = malloc(size);
1257*053f45beSAndroid Build Coastguard Worker 		ASSERT_NE(buffer->mirror, NULL);
1258*053f45beSAndroid Build Coastguard Worker 
1259*053f45beSAndroid Build Coastguard Worker 		buffer->ptr = mmap(NULL, size,
1260*053f45beSAndroid Build Coastguard Worker 				   PROT_READ | PROT_WRITE,
1261*053f45beSAndroid Build Coastguard Worker 				   MAP_PRIVATE | MAP_ANONYMOUS,
1262*053f45beSAndroid Build Coastguard Worker 				   buffer->fd, 0);
1263*053f45beSAndroid Build Coastguard Worker 		ASSERT_NE(buffer->ptr, MAP_FAILED);
1264*053f45beSAndroid Build Coastguard Worker 
1265*053f45beSAndroid Build Coastguard Worker 		/* Initialize buffer in system memory. */
1266*053f45beSAndroid Build Coastguard Worker 		for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1267*053f45beSAndroid Build Coastguard Worker 			ptr[i] = i;
1268*053f45beSAndroid Build Coastguard Worker 
1269*053f45beSAndroid Build Coastguard Worker 		/* Migrate memory to device. */
1270*053f45beSAndroid Build Coastguard Worker 		ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
1271*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ret, 0);
1272*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(buffer->cpages, npages);
1273*053f45beSAndroid Build Coastguard Worker 
1274*053f45beSAndroid Build Coastguard Worker 		/* Check what the device read. */
1275*053f45beSAndroid Build Coastguard Worker 		for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
1276*053f45beSAndroid Build Coastguard Worker 			ASSERT_EQ(ptr[i], i);
1277*053f45beSAndroid Build Coastguard Worker 
1278*053f45beSAndroid Build Coastguard Worker 		/* Migrate back to system memory and check them. */
1279*053f45beSAndroid Build Coastguard Worker 		if (hmm_is_coherent_type(variant->device_number)) {
1280*053f45beSAndroid Build Coastguard Worker 			ret = hmm_migrate_dev_to_sys(self->fd, buffer, npages);
1281*053f45beSAndroid Build Coastguard Worker 			ASSERT_EQ(ret, 0);
1282*053f45beSAndroid Build Coastguard Worker 			ASSERT_EQ(buffer->cpages, npages);
1283*053f45beSAndroid Build Coastguard Worker 		}
1284*053f45beSAndroid Build Coastguard Worker 
1285*053f45beSAndroid Build Coastguard Worker 		for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1286*053f45beSAndroid Build Coastguard Worker 			ASSERT_EQ(ptr[i], i);
1287*053f45beSAndroid Build Coastguard Worker 
1288*053f45beSAndroid Build Coastguard Worker 		hmm_buffer_free(buffer);
1289*053f45beSAndroid Build Coastguard Worker 	}
1290*053f45beSAndroid Build Coastguard Worker }
1291*053f45beSAndroid Build Coastguard Worker 
1292*053f45beSAndroid Build Coastguard Worker /*
1293*053f45beSAndroid Build Coastguard Worker  * Read anonymous memory multiple times.
1294*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,anon_read_multiple)1295*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, anon_read_multiple)
1296*053f45beSAndroid Build Coastguard Worker {
1297*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1298*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1299*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1300*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
1301*053f45beSAndroid Build Coastguard Worker 	unsigned long c;
1302*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1303*053f45beSAndroid Build Coastguard Worker 	int ret;
1304*053f45beSAndroid Build Coastguard Worker 
1305*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
1306*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
1307*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1308*053f45beSAndroid Build Coastguard Worker 
1309*053f45beSAndroid Build Coastguard Worker 	for (c = 0; c < NTIMES; c++) {
1310*053f45beSAndroid Build Coastguard Worker 		buffer = malloc(sizeof(*buffer));
1311*053f45beSAndroid Build Coastguard Worker 		ASSERT_NE(buffer, NULL);
1312*053f45beSAndroid Build Coastguard Worker 
1313*053f45beSAndroid Build Coastguard Worker 		buffer->fd = -1;
1314*053f45beSAndroid Build Coastguard Worker 		buffer->size = size;
1315*053f45beSAndroid Build Coastguard Worker 		buffer->mirror = malloc(size);
1316*053f45beSAndroid Build Coastguard Worker 		ASSERT_NE(buffer->mirror, NULL);
1317*053f45beSAndroid Build Coastguard Worker 
1318*053f45beSAndroid Build Coastguard Worker 		buffer->ptr = mmap(NULL, size,
1319*053f45beSAndroid Build Coastguard Worker 				   PROT_READ | PROT_WRITE,
1320*053f45beSAndroid Build Coastguard Worker 				   MAP_PRIVATE | MAP_ANONYMOUS,
1321*053f45beSAndroid Build Coastguard Worker 				   buffer->fd, 0);
1322*053f45beSAndroid Build Coastguard Worker 		ASSERT_NE(buffer->ptr, MAP_FAILED);
1323*053f45beSAndroid Build Coastguard Worker 
1324*053f45beSAndroid Build Coastguard Worker 		/* Initialize buffer in system memory. */
1325*053f45beSAndroid Build Coastguard Worker 		for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1326*053f45beSAndroid Build Coastguard Worker 			ptr[i] = i + c;
1327*053f45beSAndroid Build Coastguard Worker 
1328*053f45beSAndroid Build Coastguard Worker 		/* Simulate a device reading system memory. */
1329*053f45beSAndroid Build Coastguard Worker 		ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_READ, buffer,
1330*053f45beSAndroid Build Coastguard Worker 				      npages);
1331*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ret, 0);
1332*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(buffer->cpages, npages);
1333*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(buffer->faults, 1);
1334*053f45beSAndroid Build Coastguard Worker 
1335*053f45beSAndroid Build Coastguard Worker 		/* Check what the device read. */
1336*053f45beSAndroid Build Coastguard Worker 		for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
1337*053f45beSAndroid Build Coastguard Worker 			ASSERT_EQ(ptr[i], i + c);
1338*053f45beSAndroid Build Coastguard Worker 
1339*053f45beSAndroid Build Coastguard Worker 		hmm_buffer_free(buffer);
1340*053f45beSAndroid Build Coastguard Worker 	}
1341*053f45beSAndroid Build Coastguard Worker }
1342*053f45beSAndroid Build Coastguard Worker 
unmap_buffer(void * p)1343*053f45beSAndroid Build Coastguard Worker void *unmap_buffer(void *p)
1344*053f45beSAndroid Build Coastguard Worker {
1345*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer = p;
1346*053f45beSAndroid Build Coastguard Worker 
1347*053f45beSAndroid Build Coastguard Worker 	/* Delay for a bit and then unmap buffer while it is being read. */
1348*053f45beSAndroid Build Coastguard Worker 	hmm_nanosleep(hmm_random() % 32000);
1349*053f45beSAndroid Build Coastguard Worker 	munmap(buffer->ptr + buffer->size / 2, buffer->size / 2);
1350*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = NULL;
1351*053f45beSAndroid Build Coastguard Worker 
1352*053f45beSAndroid Build Coastguard Worker 	return NULL;
1353*053f45beSAndroid Build Coastguard Worker }
1354*053f45beSAndroid Build Coastguard Worker 
1355*053f45beSAndroid Build Coastguard Worker /*
1356*053f45beSAndroid Build Coastguard Worker  * Try reading anonymous memory while it is being unmapped.
1357*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,anon_teardown)1358*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, anon_teardown)
1359*053f45beSAndroid Build Coastguard Worker {
1360*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1361*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1362*053f45beSAndroid Build Coastguard Worker 	unsigned long c;
1363*053f45beSAndroid Build Coastguard Worker 	void *ret;
1364*053f45beSAndroid Build Coastguard Worker 
1365*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
1366*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
1367*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1368*053f45beSAndroid Build Coastguard Worker 
1369*053f45beSAndroid Build Coastguard Worker 	for (c = 0; c < NTIMES; ++c) {
1370*053f45beSAndroid Build Coastguard Worker 		pthread_t thread;
1371*053f45beSAndroid Build Coastguard Worker 		struct hmm_buffer *buffer;
1372*053f45beSAndroid Build Coastguard Worker 		unsigned long i;
1373*053f45beSAndroid Build Coastguard Worker 		int *ptr;
1374*053f45beSAndroid Build Coastguard Worker 		int rc;
1375*053f45beSAndroid Build Coastguard Worker 
1376*053f45beSAndroid Build Coastguard Worker 		buffer = malloc(sizeof(*buffer));
1377*053f45beSAndroid Build Coastguard Worker 		ASSERT_NE(buffer, NULL);
1378*053f45beSAndroid Build Coastguard Worker 
1379*053f45beSAndroid Build Coastguard Worker 		buffer->fd = -1;
1380*053f45beSAndroid Build Coastguard Worker 		buffer->size = size;
1381*053f45beSAndroid Build Coastguard Worker 		buffer->mirror = malloc(size);
1382*053f45beSAndroid Build Coastguard Worker 		ASSERT_NE(buffer->mirror, NULL);
1383*053f45beSAndroid Build Coastguard Worker 
1384*053f45beSAndroid Build Coastguard Worker 		buffer->ptr = mmap(NULL, size,
1385*053f45beSAndroid Build Coastguard Worker 				   PROT_READ | PROT_WRITE,
1386*053f45beSAndroid Build Coastguard Worker 				   MAP_PRIVATE | MAP_ANONYMOUS,
1387*053f45beSAndroid Build Coastguard Worker 				   buffer->fd, 0);
1388*053f45beSAndroid Build Coastguard Worker 		ASSERT_NE(buffer->ptr, MAP_FAILED);
1389*053f45beSAndroid Build Coastguard Worker 
1390*053f45beSAndroid Build Coastguard Worker 		/* Initialize buffer in system memory. */
1391*053f45beSAndroid Build Coastguard Worker 		for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1392*053f45beSAndroid Build Coastguard Worker 			ptr[i] = i + c;
1393*053f45beSAndroid Build Coastguard Worker 
1394*053f45beSAndroid Build Coastguard Worker 		rc = pthread_create(&thread, NULL, unmap_buffer, buffer);
1395*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(rc, 0);
1396*053f45beSAndroid Build Coastguard Worker 
1397*053f45beSAndroid Build Coastguard Worker 		/* Simulate a device reading system memory. */
1398*053f45beSAndroid Build Coastguard Worker 		rc = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_READ, buffer,
1399*053f45beSAndroid Build Coastguard Worker 				     npages);
1400*053f45beSAndroid Build Coastguard Worker 		if (rc == 0) {
1401*053f45beSAndroid Build Coastguard Worker 			ASSERT_EQ(buffer->cpages, npages);
1402*053f45beSAndroid Build Coastguard Worker 			ASSERT_EQ(buffer->faults, 1);
1403*053f45beSAndroid Build Coastguard Worker 
1404*053f45beSAndroid Build Coastguard Worker 			/* Check what the device read. */
1405*053f45beSAndroid Build Coastguard Worker 			for (i = 0, ptr = buffer->mirror;
1406*053f45beSAndroid Build Coastguard Worker 			     i < size / sizeof(*ptr);
1407*053f45beSAndroid Build Coastguard Worker 			     ++i)
1408*053f45beSAndroid Build Coastguard Worker 				ASSERT_EQ(ptr[i], i + c);
1409*053f45beSAndroid Build Coastguard Worker 		}
1410*053f45beSAndroid Build Coastguard Worker 
1411*053f45beSAndroid Build Coastguard Worker 		pthread_join(thread, &ret);
1412*053f45beSAndroid Build Coastguard Worker 		hmm_buffer_free(buffer);
1413*053f45beSAndroid Build Coastguard Worker 	}
1414*053f45beSAndroid Build Coastguard Worker }
1415*053f45beSAndroid Build Coastguard Worker 
1416*053f45beSAndroid Build Coastguard Worker /*
1417*053f45beSAndroid Build Coastguard Worker  * Test memory snapshot without faulting in pages accessed by the device.
1418*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,mixedmap)1419*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, mixedmap)
1420*053f45beSAndroid Build Coastguard Worker {
1421*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1422*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1423*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1424*053f45beSAndroid Build Coastguard Worker 	unsigned char *m;
1425*053f45beSAndroid Build Coastguard Worker 	int ret;
1426*053f45beSAndroid Build Coastguard Worker 
1427*053f45beSAndroid Build Coastguard Worker 	npages = 1;
1428*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1429*053f45beSAndroid Build Coastguard Worker 
1430*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1431*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1432*053f45beSAndroid Build Coastguard Worker 
1433*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
1434*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
1435*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(npages);
1436*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
1437*053f45beSAndroid Build Coastguard Worker 
1438*053f45beSAndroid Build Coastguard Worker 
1439*053f45beSAndroid Build Coastguard Worker 	/* Reserve a range of addresses. */
1440*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
1441*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
1442*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE,
1443*053f45beSAndroid Build Coastguard Worker 			   self->fd, 0);
1444*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
1445*053f45beSAndroid Build Coastguard Worker 
1446*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device snapshotting CPU pagetables. */
1447*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
1448*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1449*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1450*053f45beSAndroid Build Coastguard Worker 
1451*053f45beSAndroid Build Coastguard Worker 	/* Check what the device saw. */
1452*053f45beSAndroid Build Coastguard Worker 	m = buffer->mirror;
1453*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(m[0], HMM_DMIRROR_PROT_READ);
1454*053f45beSAndroid Build Coastguard Worker 
1455*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
1456*053f45beSAndroid Build Coastguard Worker }
1457*053f45beSAndroid Build Coastguard Worker 
1458*053f45beSAndroid Build Coastguard Worker /*
1459*053f45beSAndroid Build Coastguard Worker  * Test memory snapshot without faulting in pages accessed by the device.
1460*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm2,snapshot)1461*053f45beSAndroid Build Coastguard Worker TEST_F(hmm2, snapshot)
1462*053f45beSAndroid Build Coastguard Worker {
1463*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1464*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1465*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1466*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1467*053f45beSAndroid Build Coastguard Worker 	unsigned char *p;
1468*053f45beSAndroid Build Coastguard Worker 	unsigned char *m;
1469*053f45beSAndroid Build Coastguard Worker 	int ret;
1470*053f45beSAndroid Build Coastguard Worker 	int val;
1471*053f45beSAndroid Build Coastguard Worker 
1472*053f45beSAndroid Build Coastguard Worker 	npages = 7;
1473*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1474*053f45beSAndroid Build Coastguard Worker 
1475*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1476*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1477*053f45beSAndroid Build Coastguard Worker 
1478*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
1479*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
1480*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(npages);
1481*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
1482*053f45beSAndroid Build Coastguard Worker 
1483*053f45beSAndroid Build Coastguard Worker 	/* Reserve a range of addresses. */
1484*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
1485*053f45beSAndroid Build Coastguard Worker 			   PROT_NONE,
1486*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
1487*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
1488*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
1489*053f45beSAndroid Build Coastguard Worker 	p = buffer->ptr;
1490*053f45beSAndroid Build Coastguard Worker 
1491*053f45beSAndroid Build Coastguard Worker 	/* Punch a hole after the first page address. */
1492*053f45beSAndroid Build Coastguard Worker 	ret = munmap(buffer->ptr + self->page_size, self->page_size);
1493*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1494*053f45beSAndroid Build Coastguard Worker 
1495*053f45beSAndroid Build Coastguard Worker 	/* Page 2 will be read-only zero page. */
1496*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr + 2 * self->page_size, self->page_size,
1497*053f45beSAndroid Build Coastguard Worker 				PROT_READ);
1498*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1499*053f45beSAndroid Build Coastguard Worker 	ptr = (int *)(buffer->ptr + 2 * self->page_size);
1500*053f45beSAndroid Build Coastguard Worker 	val = *ptr + 3;
1501*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(val, 3);
1502*053f45beSAndroid Build Coastguard Worker 
1503*053f45beSAndroid Build Coastguard Worker 	/* Page 3 will be read-only. */
1504*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr + 3 * self->page_size, self->page_size,
1505*053f45beSAndroid Build Coastguard Worker 				PROT_READ | PROT_WRITE);
1506*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1507*053f45beSAndroid Build Coastguard Worker 	ptr = (int *)(buffer->ptr + 3 * self->page_size);
1508*053f45beSAndroid Build Coastguard Worker 	*ptr = val;
1509*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr + 3 * self->page_size, self->page_size,
1510*053f45beSAndroid Build Coastguard Worker 				PROT_READ);
1511*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1512*053f45beSAndroid Build Coastguard Worker 
1513*053f45beSAndroid Build Coastguard Worker 	/* Page 4-6 will be read-write. */
1514*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr + 4 * self->page_size, 3 * self->page_size,
1515*053f45beSAndroid Build Coastguard Worker 				PROT_READ | PROT_WRITE);
1516*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1517*053f45beSAndroid Build Coastguard Worker 	ptr = (int *)(buffer->ptr + 4 * self->page_size);
1518*053f45beSAndroid Build Coastguard Worker 	*ptr = val;
1519*053f45beSAndroid Build Coastguard Worker 
1520*053f45beSAndroid Build Coastguard Worker 	/* Page 5 will be migrated to device 0. */
1521*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = p + 5 * self->page_size;
1522*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd0, buffer, 1);
1523*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1524*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, 1);
1525*053f45beSAndroid Build Coastguard Worker 
1526*053f45beSAndroid Build Coastguard Worker 	/* Page 6 will be migrated to device 1. */
1527*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = p + 6 * self->page_size;
1528*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd1, buffer, 1);
1529*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1530*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, 1);
1531*053f45beSAndroid Build Coastguard Worker 
1532*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device snapshotting CPU pagetables. */
1533*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = p;
1534*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd0, HMM_DMIRROR_SNAPSHOT, buffer, npages);
1535*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1536*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1537*053f45beSAndroid Build Coastguard Worker 
1538*053f45beSAndroid Build Coastguard Worker 	/* Check what the device saw. */
1539*053f45beSAndroid Build Coastguard Worker 	m = buffer->mirror;
1540*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(m[0], HMM_DMIRROR_PROT_ERROR);
1541*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(m[1], HMM_DMIRROR_PROT_ERROR);
1542*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(m[2], HMM_DMIRROR_PROT_ZERO | HMM_DMIRROR_PROT_READ);
1543*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(m[3], HMM_DMIRROR_PROT_READ);
1544*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(m[4], HMM_DMIRROR_PROT_WRITE);
1545*053f45beSAndroid Build Coastguard Worker 	if (!hmm_is_coherent_type(variant->device_number0)) {
1546*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(m[5], HMM_DMIRROR_PROT_DEV_PRIVATE_LOCAL |
1547*053f45beSAndroid Build Coastguard Worker 				HMM_DMIRROR_PROT_WRITE);
1548*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(m[6], HMM_DMIRROR_PROT_NONE);
1549*053f45beSAndroid Build Coastguard Worker 	} else {
1550*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(m[5], HMM_DMIRROR_PROT_DEV_COHERENT_LOCAL |
1551*053f45beSAndroid Build Coastguard Worker 				HMM_DMIRROR_PROT_WRITE);
1552*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(m[6], HMM_DMIRROR_PROT_DEV_COHERENT_REMOTE |
1553*053f45beSAndroid Build Coastguard Worker 				HMM_DMIRROR_PROT_WRITE);
1554*053f45beSAndroid Build Coastguard Worker 	}
1555*053f45beSAndroid Build Coastguard Worker 
1556*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
1557*053f45beSAndroid Build Coastguard Worker }
1558*053f45beSAndroid Build Coastguard Worker 
1559*053f45beSAndroid Build Coastguard Worker /*
1560*053f45beSAndroid Build Coastguard Worker  * Test the hmm_range_fault() HMM_PFN_PMD flag for large pages that
1561*053f45beSAndroid Build Coastguard Worker  * should be mapped by a large page table entry.
1562*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,compound)1563*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, compound)
1564*053f45beSAndroid Build Coastguard Worker {
1565*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1566*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1567*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1568*053f45beSAndroid Build Coastguard Worker 	unsigned long default_hsize;
1569*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1570*053f45beSAndroid Build Coastguard Worker 	unsigned char *m;
1571*053f45beSAndroid Build Coastguard Worker 	int ret;
1572*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
1573*053f45beSAndroid Build Coastguard Worker 
1574*053f45beSAndroid Build Coastguard Worker 	/* Skip test if we can't allocate a hugetlbfs page. */
1575*053f45beSAndroid Build Coastguard Worker 
1576*053f45beSAndroid Build Coastguard Worker 	default_hsize = file_read_ulong("/proc/meminfo", "Hugepagesize:");
1577*053f45beSAndroid Build Coastguard Worker 	if (default_hsize < 0 || default_hsize*1024 < default_hsize)
1578*053f45beSAndroid Build Coastguard Worker 		SKIP(return, "Huge page size could not be determined");
1579*053f45beSAndroid Build Coastguard Worker 	default_hsize = default_hsize*1024; /* KB to B */
1580*053f45beSAndroid Build Coastguard Worker 
1581*053f45beSAndroid Build Coastguard Worker 	size = ALIGN(TWOMEG, default_hsize);
1582*053f45beSAndroid Build Coastguard Worker 	npages = size >> self->page_shift;
1583*053f45beSAndroid Build Coastguard Worker 
1584*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1585*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1586*053f45beSAndroid Build Coastguard Worker 
1587*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
1588*053f45beSAndroid Build Coastguard Worker 				   PROT_READ | PROT_WRITE,
1589*053f45beSAndroid Build Coastguard Worker 				   MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB,
1590*053f45beSAndroid Build Coastguard Worker 				   -1, 0);
1591*053f45beSAndroid Build Coastguard Worker 	if (buffer->ptr == MAP_FAILED) {
1592*053f45beSAndroid Build Coastguard Worker 		free(buffer);
1593*053f45beSAndroid Build Coastguard Worker 		return;
1594*053f45beSAndroid Build Coastguard Worker 	}
1595*053f45beSAndroid Build Coastguard Worker 
1596*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
1597*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(npages);
1598*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
1599*053f45beSAndroid Build Coastguard Worker 
1600*053f45beSAndroid Build Coastguard Worker 	/* Initialize the pages the device will snapshot in buffer->ptr. */
1601*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1602*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
1603*053f45beSAndroid Build Coastguard Worker 
1604*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device snapshotting CPU pagetables. */
1605*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
1606*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1607*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1608*053f45beSAndroid Build Coastguard Worker 
1609*053f45beSAndroid Build Coastguard Worker 	/* Check what the device saw. */
1610*053f45beSAndroid Build Coastguard Worker 	m = buffer->mirror;
1611*053f45beSAndroid Build Coastguard Worker 	for (i = 0; i < npages; ++i)
1612*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(m[i], HMM_DMIRROR_PROT_WRITE |
1613*053f45beSAndroid Build Coastguard Worker 				HMM_DMIRROR_PROT_PMD);
1614*053f45beSAndroid Build Coastguard Worker 
1615*053f45beSAndroid Build Coastguard Worker 	/* Make the region read-only. */
1616*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr, size, PROT_READ);
1617*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1618*053f45beSAndroid Build Coastguard Worker 
1619*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device snapshotting CPU pagetables. */
1620*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
1621*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1622*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1623*053f45beSAndroid Build Coastguard Worker 
1624*053f45beSAndroid Build Coastguard Worker 	/* Check what the device saw. */
1625*053f45beSAndroid Build Coastguard Worker 	m = buffer->mirror;
1626*053f45beSAndroid Build Coastguard Worker 	for (i = 0; i < npages; ++i)
1627*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(m[i], HMM_DMIRROR_PROT_READ |
1628*053f45beSAndroid Build Coastguard Worker 				HMM_DMIRROR_PROT_PMD);
1629*053f45beSAndroid Build Coastguard Worker 
1630*053f45beSAndroid Build Coastguard Worker 	munmap(buffer->ptr, buffer->size);
1631*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = NULL;
1632*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
1633*053f45beSAndroid Build Coastguard Worker }
1634*053f45beSAndroid Build Coastguard Worker 
1635*053f45beSAndroid Build Coastguard Worker /*
1636*053f45beSAndroid Build Coastguard Worker  * Test two devices reading the same memory (double mapped).
1637*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm2,double_map)1638*053f45beSAndroid Build Coastguard Worker TEST_F(hmm2, double_map)
1639*053f45beSAndroid Build Coastguard Worker {
1640*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1641*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1642*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1643*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
1644*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1645*053f45beSAndroid Build Coastguard Worker 	int ret;
1646*053f45beSAndroid Build Coastguard Worker 
1647*053f45beSAndroid Build Coastguard Worker 	npages = 6;
1648*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1649*053f45beSAndroid Build Coastguard Worker 
1650*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1651*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1652*053f45beSAndroid Build Coastguard Worker 
1653*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
1654*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
1655*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(npages);
1656*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
1657*053f45beSAndroid Build Coastguard Worker 
1658*053f45beSAndroid Build Coastguard Worker 	/* Reserve a range of addresses. */
1659*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
1660*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
1661*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
1662*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
1663*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
1664*053f45beSAndroid Build Coastguard Worker 
1665*053f45beSAndroid Build Coastguard Worker 	/* Initialize buffer in system memory. */
1666*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1667*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
1668*053f45beSAndroid Build Coastguard Worker 
1669*053f45beSAndroid Build Coastguard Worker 	/* Make region read-only. */
1670*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr, size, PROT_READ);
1671*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1672*053f45beSAndroid Build Coastguard Worker 
1673*053f45beSAndroid Build Coastguard Worker 	/* Simulate device 0 reading system memory. */
1674*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd0, HMM_DMIRROR_READ, buffer, npages);
1675*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1676*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1677*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
1678*053f45beSAndroid Build Coastguard Worker 
1679*053f45beSAndroid Build Coastguard Worker 	/* Check what the device read. */
1680*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
1681*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
1682*053f45beSAndroid Build Coastguard Worker 
1683*053f45beSAndroid Build Coastguard Worker 	/* Simulate device 1 reading system memory. */
1684*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd1, HMM_DMIRROR_READ, buffer, npages);
1685*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1686*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1687*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
1688*053f45beSAndroid Build Coastguard Worker 
1689*053f45beSAndroid Build Coastguard Worker 	/* Check what the device read. */
1690*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
1691*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
1692*053f45beSAndroid Build Coastguard Worker 
1693*053f45beSAndroid Build Coastguard Worker 	/* Migrate pages to device 1 and try to read from device 0. */
1694*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd1, buffer, npages);
1695*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1696*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1697*053f45beSAndroid Build Coastguard Worker 
1698*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd0, HMM_DMIRROR_READ, buffer, npages);
1699*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1700*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1701*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->faults, 1);
1702*053f45beSAndroid Build Coastguard Worker 
1703*053f45beSAndroid Build Coastguard Worker 	/* Check what device 0 read. */
1704*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
1705*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
1706*053f45beSAndroid Build Coastguard Worker 
1707*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
1708*053f45beSAndroid Build Coastguard Worker }
1709*053f45beSAndroid Build Coastguard Worker 
1710*053f45beSAndroid Build Coastguard Worker /*
1711*053f45beSAndroid Build Coastguard Worker  * Basic check of exclusive faulting.
1712*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,exclusive)1713*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, exclusive)
1714*053f45beSAndroid Build Coastguard Worker {
1715*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1716*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1717*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1718*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
1719*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1720*053f45beSAndroid Build Coastguard Worker 	int ret;
1721*053f45beSAndroid Build Coastguard Worker 
1722*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
1723*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
1724*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1725*053f45beSAndroid Build Coastguard Worker 
1726*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1727*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1728*053f45beSAndroid Build Coastguard Worker 
1729*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
1730*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
1731*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
1732*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
1733*053f45beSAndroid Build Coastguard Worker 
1734*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
1735*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
1736*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
1737*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
1738*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
1739*053f45beSAndroid Build Coastguard Worker 
1740*053f45beSAndroid Build Coastguard Worker 	/* Initialize buffer in system memory. */
1741*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1742*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
1743*053f45beSAndroid Build Coastguard Worker 
1744*053f45beSAndroid Build Coastguard Worker 	/* Map memory exclusively for device access. */
1745*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_EXCLUSIVE, buffer, npages);
1746*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1747*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1748*053f45beSAndroid Build Coastguard Worker 
1749*053f45beSAndroid Build Coastguard Worker 	/* Check what the device read. */
1750*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
1751*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
1752*053f45beSAndroid Build Coastguard Worker 
1753*053f45beSAndroid Build Coastguard Worker 	/* Fault pages back to system memory and check them. */
1754*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1755*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i]++, i);
1756*053f45beSAndroid Build Coastguard Worker 
1757*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1758*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i+1);
1759*053f45beSAndroid Build Coastguard Worker 
1760*053f45beSAndroid Build Coastguard Worker 	/* Check atomic access revoked */
1761*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_CHECK_EXCLUSIVE, buffer, npages);
1762*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1763*053f45beSAndroid Build Coastguard Worker 
1764*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
1765*053f45beSAndroid Build Coastguard Worker }
1766*053f45beSAndroid Build Coastguard Worker 
TEST_F(hmm,exclusive_mprotect)1767*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, exclusive_mprotect)
1768*053f45beSAndroid Build Coastguard Worker {
1769*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1770*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1771*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1772*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
1773*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1774*053f45beSAndroid Build Coastguard Worker 	int ret;
1775*053f45beSAndroid Build Coastguard Worker 
1776*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
1777*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
1778*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1779*053f45beSAndroid Build Coastguard Worker 
1780*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1781*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1782*053f45beSAndroid Build Coastguard Worker 
1783*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
1784*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
1785*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
1786*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
1787*053f45beSAndroid Build Coastguard Worker 
1788*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
1789*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
1790*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
1791*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
1792*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
1793*053f45beSAndroid Build Coastguard Worker 
1794*053f45beSAndroid Build Coastguard Worker 	/* Initialize buffer in system memory. */
1795*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1796*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
1797*053f45beSAndroid Build Coastguard Worker 
1798*053f45beSAndroid Build Coastguard Worker 	/* Map memory exclusively for device access. */
1799*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_EXCLUSIVE, buffer, npages);
1800*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1801*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1802*053f45beSAndroid Build Coastguard Worker 
1803*053f45beSAndroid Build Coastguard Worker 	/* Check what the device read. */
1804*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
1805*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
1806*053f45beSAndroid Build Coastguard Worker 
1807*053f45beSAndroid Build Coastguard Worker 	ret = mprotect(buffer->ptr, size, PROT_READ);
1808*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1809*053f45beSAndroid Build Coastguard Worker 
1810*053f45beSAndroid Build Coastguard Worker 	/* Simulate a device writing system memory. */
1811*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_WRITE, buffer, npages);
1812*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, -EPERM);
1813*053f45beSAndroid Build Coastguard Worker 
1814*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
1815*053f45beSAndroid Build Coastguard Worker }
1816*053f45beSAndroid Build Coastguard Worker 
1817*053f45beSAndroid Build Coastguard Worker /*
1818*053f45beSAndroid Build Coastguard Worker  * Check copy-on-write works.
1819*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,exclusive_cow)1820*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, exclusive_cow)
1821*053f45beSAndroid Build Coastguard Worker {
1822*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1823*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1824*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1825*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
1826*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1827*053f45beSAndroid Build Coastguard Worker 	int ret;
1828*053f45beSAndroid Build Coastguard Worker 
1829*053f45beSAndroid Build Coastguard Worker 	npages = ALIGN(HMM_BUFFER_SIZE, self->page_size) >> self->page_shift;
1830*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(npages, 0);
1831*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1832*053f45beSAndroid Build Coastguard Worker 
1833*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1834*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1835*053f45beSAndroid Build Coastguard Worker 
1836*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
1837*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
1838*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
1839*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
1840*053f45beSAndroid Build Coastguard Worker 
1841*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
1842*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
1843*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
1844*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
1845*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
1846*053f45beSAndroid Build Coastguard Worker 
1847*053f45beSAndroid Build Coastguard Worker 	/* Initialize buffer in system memory. */
1848*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1849*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
1850*053f45beSAndroid Build Coastguard Worker 
1851*053f45beSAndroid Build Coastguard Worker 	/* Map memory exclusively for device access. */
1852*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_EXCLUSIVE, buffer, npages);
1853*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1854*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1855*053f45beSAndroid Build Coastguard Worker 
1856*053f45beSAndroid Build Coastguard Worker 	fork();
1857*053f45beSAndroid Build Coastguard Worker 
1858*053f45beSAndroid Build Coastguard Worker 	/* Fault pages back to system memory and check them. */
1859*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1860*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i]++, i);
1861*053f45beSAndroid Build Coastguard Worker 
1862*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1863*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i+1);
1864*053f45beSAndroid Build Coastguard Worker 
1865*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
1866*053f45beSAndroid Build Coastguard Worker }
1867*053f45beSAndroid Build Coastguard Worker 
gup_test_exec(int gup_fd,unsigned long addr,int cmd,int npages,int size,int flags)1868*053f45beSAndroid Build Coastguard Worker static int gup_test_exec(int gup_fd, unsigned long addr, int cmd,
1869*053f45beSAndroid Build Coastguard Worker 			 int npages, int size, int flags)
1870*053f45beSAndroid Build Coastguard Worker {
1871*053f45beSAndroid Build Coastguard Worker 	struct gup_test gup = {
1872*053f45beSAndroid Build Coastguard Worker 		.nr_pages_per_call	= npages,
1873*053f45beSAndroid Build Coastguard Worker 		.addr			= addr,
1874*053f45beSAndroid Build Coastguard Worker 		.gup_flags		= FOLL_WRITE | flags,
1875*053f45beSAndroid Build Coastguard Worker 		.size			= size,
1876*053f45beSAndroid Build Coastguard Worker 	};
1877*053f45beSAndroid Build Coastguard Worker 
1878*053f45beSAndroid Build Coastguard Worker 	if (ioctl(gup_fd, cmd, &gup)) {
1879*053f45beSAndroid Build Coastguard Worker 		perror("ioctl on error\n");
1880*053f45beSAndroid Build Coastguard Worker 		return errno;
1881*053f45beSAndroid Build Coastguard Worker 	}
1882*053f45beSAndroid Build Coastguard Worker 
1883*053f45beSAndroid Build Coastguard Worker 	return 0;
1884*053f45beSAndroid Build Coastguard Worker }
1885*053f45beSAndroid Build Coastguard Worker 
1886*053f45beSAndroid Build Coastguard Worker /*
1887*053f45beSAndroid Build Coastguard Worker  * Test get user device pages through gup_test. Setting PIN_LONGTERM flag.
1888*053f45beSAndroid Build Coastguard Worker  * This should trigger a migration back to system memory for both, private
1889*053f45beSAndroid Build Coastguard Worker  * and coherent type pages.
1890*053f45beSAndroid Build Coastguard Worker  * This test makes use of gup_test module. Make sure GUP_TEST_CONFIG is added
1891*053f45beSAndroid Build Coastguard Worker  * to your configuration before you run it.
1892*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,hmm_gup_test)1893*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, hmm_gup_test)
1894*053f45beSAndroid Build Coastguard Worker {
1895*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1896*053f45beSAndroid Build Coastguard Worker 	int gup_fd;
1897*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1898*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1899*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
1900*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1901*053f45beSAndroid Build Coastguard Worker 	int ret;
1902*053f45beSAndroid Build Coastguard Worker 	unsigned char *m;
1903*053f45beSAndroid Build Coastguard Worker 
1904*053f45beSAndroid Build Coastguard Worker 	gup_fd = open("/sys/kernel/debug/gup_test", O_RDWR);
1905*053f45beSAndroid Build Coastguard Worker 	if (gup_fd == -1)
1906*053f45beSAndroid Build Coastguard Worker 		SKIP(return, "Skipping test, could not find gup_test driver");
1907*053f45beSAndroid Build Coastguard Worker 
1908*053f45beSAndroid Build Coastguard Worker 	npages = 4;
1909*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1910*053f45beSAndroid Build Coastguard Worker 
1911*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1912*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1913*053f45beSAndroid Build Coastguard Worker 
1914*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
1915*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
1916*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
1917*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
1918*053f45beSAndroid Build Coastguard Worker 
1919*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
1920*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
1921*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
1922*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
1923*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
1924*053f45beSAndroid Build Coastguard Worker 
1925*053f45beSAndroid Build Coastguard Worker 	/* Initialize buffer in system memory. */
1926*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1927*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
1928*053f45beSAndroid Build Coastguard Worker 
1929*053f45beSAndroid Build Coastguard Worker 	/* Migrate memory to device. */
1930*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
1931*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1932*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1933*053f45beSAndroid Build Coastguard Worker 	/* Check what the device read. */
1934*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->mirror; i < size / sizeof(*ptr); ++i)
1935*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
1936*053f45beSAndroid Build Coastguard Worker 
1937*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(gup_test_exec(gup_fd,
1938*053f45beSAndroid Build Coastguard Worker 				(unsigned long)buffer->ptr,
1939*053f45beSAndroid Build Coastguard Worker 				GUP_BASIC_TEST, 1, self->page_size, 0), 0);
1940*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(gup_test_exec(gup_fd,
1941*053f45beSAndroid Build Coastguard Worker 				(unsigned long)buffer->ptr + 1 * self->page_size,
1942*053f45beSAndroid Build Coastguard Worker 				GUP_FAST_BENCHMARK, 1, self->page_size, 0), 0);
1943*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(gup_test_exec(gup_fd,
1944*053f45beSAndroid Build Coastguard Worker 				(unsigned long)buffer->ptr + 2 * self->page_size,
1945*053f45beSAndroid Build Coastguard Worker 				PIN_FAST_BENCHMARK, 1, self->page_size, FOLL_LONGTERM), 0);
1946*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(gup_test_exec(gup_fd,
1947*053f45beSAndroid Build Coastguard Worker 				(unsigned long)buffer->ptr + 3 * self->page_size,
1948*053f45beSAndroid Build Coastguard Worker 				PIN_LONGTERM_BENCHMARK, 1, self->page_size, 0), 0);
1949*053f45beSAndroid Build Coastguard Worker 
1950*053f45beSAndroid Build Coastguard Worker 	/* Take snapshot to CPU pagetables */
1951*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
1952*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
1953*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
1954*053f45beSAndroid Build Coastguard Worker 	m = buffer->mirror;
1955*053f45beSAndroid Build Coastguard Worker 	if (hmm_is_coherent_type(variant->device_number)) {
1956*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(HMM_DMIRROR_PROT_DEV_COHERENT_LOCAL | HMM_DMIRROR_PROT_WRITE, m[0]);
1957*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(HMM_DMIRROR_PROT_DEV_COHERENT_LOCAL | HMM_DMIRROR_PROT_WRITE, m[1]);
1958*053f45beSAndroid Build Coastguard Worker 	} else {
1959*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[0]);
1960*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[1]);
1961*053f45beSAndroid Build Coastguard Worker 	}
1962*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[2]);
1963*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[3]);
1964*053f45beSAndroid Build Coastguard Worker 	/*
1965*053f45beSAndroid Build Coastguard Worker 	 * Check again the content on the pages. Make sure there's no
1966*053f45beSAndroid Build Coastguard Worker 	 * corrupted data.
1967*053f45beSAndroid Build Coastguard Worker 	 */
1968*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
1969*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(ptr[i], i);
1970*053f45beSAndroid Build Coastguard Worker 
1971*053f45beSAndroid Build Coastguard Worker 	close(gup_fd);
1972*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
1973*053f45beSAndroid Build Coastguard Worker }
1974*053f45beSAndroid Build Coastguard Worker 
1975*053f45beSAndroid Build Coastguard Worker /*
1976*053f45beSAndroid Build Coastguard Worker  * Test copy-on-write in device pages.
1977*053f45beSAndroid Build Coastguard Worker  * In case of writing to COW private page(s), a page fault will migrate pages
1978*053f45beSAndroid Build Coastguard Worker  * back to system memory first. Then, these pages will be duplicated. In case
1979*053f45beSAndroid Build Coastguard Worker  * of COW device coherent type, pages are duplicated directly from device
1980*053f45beSAndroid Build Coastguard Worker  * memory.
1981*053f45beSAndroid Build Coastguard Worker  */
TEST_F(hmm,hmm_cow_in_device)1982*053f45beSAndroid Build Coastguard Worker TEST_F(hmm, hmm_cow_in_device)
1983*053f45beSAndroid Build Coastguard Worker {
1984*053f45beSAndroid Build Coastguard Worker 	struct hmm_buffer *buffer;
1985*053f45beSAndroid Build Coastguard Worker 	unsigned long npages;
1986*053f45beSAndroid Build Coastguard Worker 	unsigned long size;
1987*053f45beSAndroid Build Coastguard Worker 	unsigned long i;
1988*053f45beSAndroid Build Coastguard Worker 	int *ptr;
1989*053f45beSAndroid Build Coastguard Worker 	int ret;
1990*053f45beSAndroid Build Coastguard Worker 	unsigned char *m;
1991*053f45beSAndroid Build Coastguard Worker 	pid_t pid;
1992*053f45beSAndroid Build Coastguard Worker 	int status;
1993*053f45beSAndroid Build Coastguard Worker 
1994*053f45beSAndroid Build Coastguard Worker 	npages = 4;
1995*053f45beSAndroid Build Coastguard Worker 	size = npages << self->page_shift;
1996*053f45beSAndroid Build Coastguard Worker 
1997*053f45beSAndroid Build Coastguard Worker 	buffer = malloc(sizeof(*buffer));
1998*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer, NULL);
1999*053f45beSAndroid Build Coastguard Worker 
2000*053f45beSAndroid Build Coastguard Worker 	buffer->fd = -1;
2001*053f45beSAndroid Build Coastguard Worker 	buffer->size = size;
2002*053f45beSAndroid Build Coastguard Worker 	buffer->mirror = malloc(size);
2003*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->mirror, NULL);
2004*053f45beSAndroid Build Coastguard Worker 
2005*053f45beSAndroid Build Coastguard Worker 	buffer->ptr = mmap(NULL, size,
2006*053f45beSAndroid Build Coastguard Worker 			   PROT_READ | PROT_WRITE,
2007*053f45beSAndroid Build Coastguard Worker 			   MAP_PRIVATE | MAP_ANONYMOUS,
2008*053f45beSAndroid Build Coastguard Worker 			   buffer->fd, 0);
2009*053f45beSAndroid Build Coastguard Worker 	ASSERT_NE(buffer->ptr, MAP_FAILED);
2010*053f45beSAndroid Build Coastguard Worker 
2011*053f45beSAndroid Build Coastguard Worker 	/* Initialize buffer in system memory. */
2012*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
2013*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
2014*053f45beSAndroid Build Coastguard Worker 
2015*053f45beSAndroid Build Coastguard Worker 	/* Migrate memory to device. */
2016*053f45beSAndroid Build Coastguard Worker 
2017*053f45beSAndroid Build Coastguard Worker 	ret = hmm_migrate_sys_to_dev(self->fd, buffer, npages);
2018*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
2019*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
2020*053f45beSAndroid Build Coastguard Worker 
2021*053f45beSAndroid Build Coastguard Worker 	pid = fork();
2022*053f45beSAndroid Build Coastguard Worker 	if (pid == -1)
2023*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(pid, 0);
2024*053f45beSAndroid Build Coastguard Worker 	if (!pid) {
2025*053f45beSAndroid Build Coastguard Worker 		/* Child process waitd for SIGTERM from the parent. */
2026*053f45beSAndroid Build Coastguard Worker 		while (1) {
2027*053f45beSAndroid Build Coastguard Worker 		}
2028*053f45beSAndroid Build Coastguard Worker 		perror("Should not reach this\n");
2029*053f45beSAndroid Build Coastguard Worker 		exit(0);
2030*053f45beSAndroid Build Coastguard Worker 	}
2031*053f45beSAndroid Build Coastguard Worker 	/* Parent process writes to COW pages(s) and gets a
2032*053f45beSAndroid Build Coastguard Worker 	 * new copy in system. In case of device private pages,
2033*053f45beSAndroid Build Coastguard Worker 	 * this write causes a migration to system mem first.
2034*053f45beSAndroid Build Coastguard Worker 	 */
2035*053f45beSAndroid Build Coastguard Worker 	for (i = 0, ptr = buffer->ptr; i < size / sizeof(*ptr); ++i)
2036*053f45beSAndroid Build Coastguard Worker 		ptr[i] = i;
2037*053f45beSAndroid Build Coastguard Worker 
2038*053f45beSAndroid Build Coastguard Worker 	/* Terminate child and wait */
2039*053f45beSAndroid Build Coastguard Worker 	EXPECT_EQ(0, kill(pid, SIGTERM));
2040*053f45beSAndroid Build Coastguard Worker 	EXPECT_EQ(pid, waitpid(pid, &status, 0));
2041*053f45beSAndroid Build Coastguard Worker 	EXPECT_NE(0, WIFSIGNALED(status));
2042*053f45beSAndroid Build Coastguard Worker 	EXPECT_EQ(SIGTERM, WTERMSIG(status));
2043*053f45beSAndroid Build Coastguard Worker 
2044*053f45beSAndroid Build Coastguard Worker 	/* Take snapshot to CPU pagetables */
2045*053f45beSAndroid Build Coastguard Worker 	ret = hmm_dmirror_cmd(self->fd, HMM_DMIRROR_SNAPSHOT, buffer, npages);
2046*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(ret, 0);
2047*053f45beSAndroid Build Coastguard Worker 	ASSERT_EQ(buffer->cpages, npages);
2048*053f45beSAndroid Build Coastguard Worker 	m = buffer->mirror;
2049*053f45beSAndroid Build Coastguard Worker 	for (i = 0; i < npages; i++)
2050*053f45beSAndroid Build Coastguard Worker 		ASSERT_EQ(HMM_DMIRROR_PROT_WRITE, m[i]);
2051*053f45beSAndroid Build Coastguard Worker 
2052*053f45beSAndroid Build Coastguard Worker 	hmm_buffer_free(buffer);
2053*053f45beSAndroid Build Coastguard Worker }
2054*053f45beSAndroid Build Coastguard Worker TEST_HARNESS_MAIN
2055