device_test.cpp revision 363441b120aa7ff4ec7c639bac099e775c2ace69
1/*
2 * Copyright (C) 2013 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <fcntl.h>
18#include <sys/mman.h>
19#include <sys/stat.h>
20#include <sys/types.h>
21
22#include <linux/ion_test.h>
23
24#include <gtest/gtest.h>
25
26#include <ion/ion.h>
27
28#include "ion_test_fixture.h"
29
30#define ALIGN(x,y) (((x) + ((y) - 1)) & ~((y) - 1))
31
32class Device : public IonAllHeapsTest {
33 public:
34    virtual void SetUp();
35    virtual void TearDown();
36    int m_deviceFd;
37    void readDMA(int fd, void *buf, size_t size);
38    void writeDMA(int fd, void *buf, size_t size);
39    void readKernel(int fd, void *buf, size_t size);
40    void writeKernel(int fd, void *buf, size_t size);
41    void blowCache();
42    void dirtyCache(void *ptr, size_t size);
43};
44
45void Device::SetUp()
46{
47    IonAllHeapsTest::SetUp();
48    m_deviceFd = open("/dev/ion-test", O_RDWR);
49    ASSERT_GE(m_deviceFd, 0);
50}
51
52void Device::TearDown()
53{
54    ASSERT_EQ(0, close(m_deviceFd));
55    IonAllHeapsTest::TearDown();
56}
57
58void Device::readDMA(int fd, void *buf, size_t size)
59{
60    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, fd));
61    struct ion_test_rw_data ion_test_rw_data = {
62            .ptr = (uint64_t)buf,
63            .offset = 0,
64            .size = size,
65            .write = 0,
66    };
67
68    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_DMA_MAPPING, &ion_test_rw_data));
69    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, -1));
70}
71
72void Device::writeDMA(int fd, void *buf, size_t size)
73{
74    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, fd));
75    struct ion_test_rw_data ion_test_rw_data = {
76            .ptr = (uint64_t)buf,
77            .offset = 0,
78            .size = size,
79            .write = 1,
80    };
81
82    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_DMA_MAPPING, &ion_test_rw_data));
83    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, -1));
84}
85
86void Device::readKernel(int fd, void *buf, size_t size)
87{
88    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, fd));
89    struct ion_test_rw_data ion_test_rw_data = {
90            .ptr = (uint64_t)buf,
91            .offset = 0,
92            .size = size,
93            .write = 0,
94    };
95
96    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_KERNEL_MAPPING, &ion_test_rw_data));
97    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, -1));
98}
99
100void Device::writeKernel(int fd, void *buf, size_t size)
101{
102    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, fd));
103    struct ion_test_rw_data ion_test_rw_data = {
104            .ptr = (uint64_t)buf,
105            .offset = 0,
106            .size = size,
107            .write = 1,
108    };
109
110    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_KERNEL_MAPPING, &ion_test_rw_data));
111    ASSERT_EQ(0, ioctl(m_deviceFd, ION_IOC_TEST_SET_FD, -1));
112}
113
114void Device::blowCache()
115{
116    const size_t bigger_than_cache = 8*1024*1024;
117    void *buf1 = malloc(bigger_than_cache);
118    void *buf2 = malloc(bigger_than_cache);
119    memset(buf1, 0xaa, bigger_than_cache);
120    memcpy(buf2, buf1, bigger_than_cache);
121    free(buf1);
122    free(buf2);
123}
124
125void Device::dirtyCache(void *ptr, size_t size)
126{
127    /* try to dirty cache lines */
128    for (size_t i = size-1; i > 0; i--) {
129        ((volatile char *)ptr)[i];
130        ((char *)ptr)[i] = i;
131    }
132}
133
134TEST_F(Device, KernelReadCached)
135{
136    void *alloc = malloc(8192 + 1024);
137    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
138
139    for (unsigned int heapMask : m_allHeaps) {
140        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
141        int map_fd = -1;
142        unsigned int flags = ION_FLAG_CACHED;
143
144        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
145        ASSERT_GE(map_fd, 0);
146
147        void *ptr;
148        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
149        ASSERT_TRUE(ptr != NULL);
150
151        for (int i = 0; i < 4096; i++)
152            ((char *)ptr)[i] = i;
153
154        ((char*)buf)[4096] = 0x12;
155        readKernel(map_fd, buf, 4096);
156        ASSERT_EQ(((char*)buf)[4096], 0x12);
157
158        for (int i = 0; i < 4096; i++)
159            ASSERT_EQ((char)i, ((char *)buf)[i]);
160
161        ASSERT_EQ(0, munmap(ptr, 4096));
162        ASSERT_EQ(0, close(map_fd));
163    }
164
165    free(alloc);
166}
167
168TEST_F(Device, KernelWriteCached)
169{
170    void *alloc = malloc(8192 + 1024);
171    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
172
173    for (int i = 0; i < 4096; i++)
174        ((char *)buf)[i] = i;
175
176    for (unsigned int heapMask : m_allHeaps) {
177        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
178        int map_fd = -1;
179        unsigned int flags = ION_FLAG_CACHED;
180
181        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
182        ASSERT_GE(map_fd, 0);
183
184        void *ptr;
185        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
186        ASSERT_TRUE(ptr != NULL);
187
188        dirtyCache(ptr, 4096);
189
190        writeKernel(map_fd, buf, 4096);
191
192        for (int i = 0; i < 4096; i++)
193            ASSERT_EQ((char)i, ((char *)ptr)[i]) << i;
194
195        ASSERT_EQ(0, munmap(ptr, 4096));
196        ASSERT_EQ(0, close(map_fd));
197    }
198
199    free(alloc);
200}
201
202TEST_F(Device, DMAReadCached)
203{
204    void *alloc = malloc(8192 + 1024);
205    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
206
207    for (unsigned int heapMask : m_allHeaps) {
208        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
209        int map_fd = -1;
210        unsigned int flags = ION_FLAG_CACHED;
211
212        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
213        ASSERT_GE(map_fd, 0);
214
215        void *ptr;
216        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
217        ASSERT_TRUE(ptr != NULL);
218
219        for (int i = 0; i < 4096; i++)
220            ((char *)ptr)[i] = i;
221
222        readDMA(map_fd, buf, 4096);
223
224        for (int i = 0; i < 4096; i++)
225            ASSERT_EQ((char)i, ((char *)buf)[i]);
226
227        ASSERT_EQ(0, munmap(ptr, 4096));
228        ASSERT_EQ(0, close(map_fd));
229    }
230
231    free(alloc);
232}
233
234TEST_F(Device, DMAWriteCached)
235{
236    void *alloc = malloc(8192 + 1024);
237    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
238
239    for (int i = 0; i < 4096; i++)
240        ((char *)buf)[i] = i;
241
242    for (unsigned int heapMask : m_allHeaps) {
243        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
244        int map_fd = -1;
245        unsigned int flags = ION_FLAG_CACHED;
246
247        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
248        ASSERT_GE(map_fd, 0);
249
250        void *ptr;
251        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
252        ASSERT_TRUE(ptr != NULL);
253
254        dirtyCache(ptr, 4096);
255
256        writeDMA(map_fd, buf, 4096);
257
258        for (int i = 0; i < 4096; i++)
259            ASSERT_EQ((char)i, ((char *)ptr)[i]) << i;
260
261        ASSERT_EQ(0, munmap(ptr, 4096));
262        ASSERT_EQ(0, close(map_fd));
263    }
264
265    free(alloc);
266}
267
268TEST_F(Device, KernelReadCachedNeedsSync)
269{
270    void *alloc = malloc(8192 + 1024);
271    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
272
273    for (unsigned int heapMask : m_allHeaps) {
274        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
275        int map_fd = -1;
276        unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
277
278        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
279        ASSERT_GE(map_fd, 0);
280
281        void *ptr;
282        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
283        ASSERT_TRUE(ptr != NULL);
284
285        for (int i = 0; i < 4096; i++)
286            ((char *)ptr)[i] = i;
287
288        ((char*)buf)[4096] = 0x12;
289        readKernel(map_fd, buf, 4096);
290        ASSERT_EQ(((char*)buf)[4096], 0x12);
291
292        for (int i = 0; i < 4096; i++)
293            ASSERT_EQ((char)i, ((char *)buf)[i]);
294
295        ASSERT_EQ(0, munmap(ptr, 4096));
296        ASSERT_EQ(0, close(map_fd));
297    }
298
299    free(alloc);
300}
301
302TEST_F(Device, KernelWriteCachedNeedsSync)
303{
304    void *alloc = malloc(8192 + 1024);
305    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
306
307    for (int i = 0; i < 4096; i++)
308        ((char *)buf)[i] = i;
309
310    for (unsigned int heapMask : m_allHeaps) {
311        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
312        int map_fd = -1;
313        unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
314
315        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
316        ASSERT_GE(map_fd, 0);
317
318        void *ptr;
319        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
320        ASSERT_TRUE(ptr != NULL);
321
322        dirtyCache(ptr, 4096);
323
324        writeKernel(map_fd, buf, 4096);
325
326        for (int i = 0; i < 4096; i++)
327            ASSERT_EQ((char)i, ((char *)ptr)[i]) << i;
328
329        ASSERT_EQ(0, munmap(ptr, 4096));
330        ASSERT_EQ(0, close(map_fd));
331    }
332
333    free(alloc);
334}
335
336TEST_F(Device, DMAReadCachedNeedsSync)
337{
338    void *alloc = malloc(8192 + 1024);
339    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
340
341    for (unsigned int heapMask : m_allHeaps) {
342        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
343        int map_fd = -1;
344        unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
345
346        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
347        ASSERT_GE(map_fd, 0);
348
349        void *ptr;
350        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
351        ASSERT_TRUE(ptr != NULL);
352
353        for (int i = 0; i < 4096; i++)
354            ((char *)ptr)[i] = i;
355
356        ion_sync_fd(m_ionFd, map_fd);
357
358        readDMA(map_fd, buf, 4096);
359
360        for (int i = 0; i < 4096; i++)
361            ASSERT_EQ((char)i, ((char *)buf)[i]);
362
363        ASSERT_EQ(0, munmap(ptr, 4096));
364        ASSERT_EQ(0, close(map_fd));
365    }
366
367    free(alloc);
368}
369
370TEST_F(Device, DMAWriteCachedNeedsSync)
371{
372    void *alloc = malloc(8192 + 1024);
373    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
374
375    for (int i = 0; i < 4096; i++)
376        ((char *)buf)[i] = i;
377
378    for (unsigned int heapMask : m_allHeaps) {
379        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
380        int map_fd = -1;
381        unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
382
383        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
384        ASSERT_GE(map_fd, 0);
385
386        void *ptr;
387        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
388        ASSERT_TRUE(ptr != NULL);
389
390        dirtyCache(ptr, 4096);
391
392        writeDMA(map_fd, buf, 4096);
393
394        ion_sync_fd(m_ionFd, map_fd);
395
396        for (int i = 0; i < 4096; i++)
397            ASSERT_EQ((char)i, ((char *)ptr)[i]) << i;
398
399        ASSERT_EQ(0, munmap(ptr, 4096));
400        ASSERT_EQ(0, close(map_fd));
401    }
402
403    free(alloc);
404}
405TEST_F(Device, KernelRead)
406{
407    void *alloc = malloc(8192 + 1024);
408    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
409
410    for (unsigned int heapMask : m_allHeaps) {
411        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
412        int map_fd = -1;
413        unsigned int flags = 0;
414
415        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
416        ASSERT_GE(map_fd, 0);
417
418        void *ptr;
419        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
420        ASSERT_TRUE(ptr != NULL);
421
422        for (int i = 0; i < 4096; i++)
423            ((char *)ptr)[i] = i;
424
425        ((char*)buf)[4096] = 0x12;
426        readKernel(map_fd, buf, 4096);
427        ASSERT_EQ(((char*)buf)[4096], 0x12);
428
429        for (int i = 0; i < 4096; i++)
430            ASSERT_EQ((char)i, ((char *)buf)[i]);
431
432        ASSERT_EQ(0, munmap(ptr, 4096));
433        ASSERT_EQ(0, close(map_fd));
434    }
435
436    free(alloc);
437}
438
439TEST_F(Device, KernelWrite)
440{
441    void *alloc = malloc(8192 + 1024);
442    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
443
444    for (int i = 0; i < 4096; i++)
445        ((char *)buf)[i] = i;
446
447    for (unsigned int heapMask : m_allHeaps) {
448        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
449        int map_fd = -1;
450        unsigned int flags = 0;
451
452        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
453        ASSERT_GE(map_fd, 0);
454
455        void *ptr;
456        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
457        ASSERT_TRUE(ptr != NULL);
458
459        dirtyCache(ptr, 4096);
460
461        writeKernel(map_fd, buf, 4096);
462
463        for (int i = 0; i < 4096; i++)
464            ASSERT_EQ((char)i, ((char *)ptr)[i]) << i;
465
466        ASSERT_EQ(0, munmap(ptr, 4096));
467        ASSERT_EQ(0, close(map_fd));
468    }
469
470    free(alloc);
471}
472
473TEST_F(Device, DMARead)
474{
475    void *alloc = malloc(8192 + 1024);
476    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
477
478    for (unsigned int heapMask : m_allHeaps) {
479        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
480        int map_fd = -1;
481        unsigned int flags = 0;
482
483        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
484        ASSERT_GE(map_fd, 0);
485
486        void *ptr;
487        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
488        ASSERT_TRUE(ptr != NULL);
489
490        for (int i = 0; i < 4096; i++)
491            ((char *)ptr)[i] = i;
492
493        readDMA(map_fd, buf, 4096);
494
495        for (int i = 0; i < 4096; i++)
496            ASSERT_EQ((char)i, ((char *)buf)[i]);
497
498        ASSERT_EQ(0, munmap(ptr, 4096));
499        ASSERT_EQ(0, close(map_fd));
500    }
501
502    free(alloc);
503}
504
505TEST_F(Device, DMAWrite)
506{
507    void *alloc = malloc(8192 + 1024);
508    void *buf = (void *)(ALIGN((unsigned long)alloc, 4096) + 1024);
509
510    for (int i = 0; i < 4096; i++)
511        ((char *)buf)[i] = i;
512
513    for (unsigned int heapMask : m_allHeaps) {
514        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
515        int map_fd = -1;
516        unsigned int flags = 0;
517
518        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
519        ASSERT_GE(map_fd, 0);
520
521        void *ptr;
522        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
523        ASSERT_TRUE(ptr != NULL);
524
525        dirtyCache(ptr, 4096);
526
527        writeDMA(map_fd, buf, 4096);
528
529        for (int i = 0; i < 4096; i++)
530            ASSERT_EQ((char)i, ((char *)ptr)[i]) << i;
531
532        ASSERT_EQ(0, munmap(ptr, 4096));
533        ASSERT_EQ(0, close(map_fd));
534    }
535
536    free(alloc);
537}
538
539TEST_F(Device, IsCached)
540{
541    void *buf = malloc(4096);
542
543    for (unsigned int heapMask : m_allHeaps) {
544        SCOPED_TRACE(::testing::Message() << "heap " << heapMask);
545        int map_fd = -1;
546        unsigned int flags = ION_FLAG_CACHED | ION_FLAG_CACHED_NEEDS_SYNC;
547
548        ASSERT_EQ(0, ion_alloc_fd(m_ionFd, 4096, 0, heapMask, flags, &map_fd));
549        ASSERT_GE(map_fd, 0);
550
551        void *ptr;
552        ptr = mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, map_fd, 0);
553        ASSERT_TRUE(ptr != NULL);
554
555        dirtyCache(ptr, 4096);
556
557        readDMA(map_fd, buf, 4096);
558
559        bool same = true;
560        for (int i = 4096-16; i >= 0; i -= 16)
561            if (((char *)buf)[i] != i)
562                same = false;
563        ASSERT_FALSE(same);
564
565        ASSERT_EQ(0, munmap(ptr, 4096));
566        ASSERT_EQ(0, close(map_fd));
567    }
568}
569