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