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 32 class 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 45 void Device::SetUp() 46 { 47 IonAllHeapsTest::SetUp(); 48 m_deviceFd = open("/dev/ion-test", O_RDWR); 49 ASSERT_GE(m_deviceFd, 0); 50 } 51 52 void Device::TearDown() 53 { 54 ASSERT_EQ(0, close(m_deviceFd)); 55 IonAllHeapsTest::TearDown(); 56 } 57 58 void 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 72 void 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 86 void 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 100 void 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 114 void 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 125 void 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 134 TEST_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 168 TEST_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 202 TEST_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 234 TEST_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 268 TEST_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 302 TEST_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 336 TEST_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 370 TEST_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 } 405 TEST_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 439 TEST_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 473 TEST_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 505 TEST_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 539 TEST_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