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