1 /*
2 * Copyright (C) 2018 Samsung Electronics Co., Ltd.
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 #include <unistd.h>
17 #include <fcntl.h>
18 #include <sys/mman.h>
19 #include <sys/ioctl.h>
20
21 #include "ion_test_fixture.h"
22 #include "ion_test_define.h"
23
24 static const size_t allocation_sizes[] = {
25 mkb(16, 716), mkb(12, 4), mkb(8, 912), mkb(4, 60), mkb(2, 520), mkb(1, 92),
26 mb(16), mb(12), mb(8), mb(4), mb(2), mb(1), kb(64), kb(4),
27 };
28
flushShrinker(const char * heapname)29 void flushShrinker(const char *heapname) {
30 std::string pathname = "/sys/kernel/debug/";
31
32 pathname += heapname;
33 pathname += "_shrink";
34
35 int fd = open(pathname.c_str(), O_RDWR);
36 if (fd < 0)
37 return;
38
39 unsigned long val = mb(256); // This is very big enough to flush shrinker
40 if (write(fd, &val, sizeof(val)) < 0)
41 FAIL() << "Failed to write " << val << " to '" << heapname << "_shrink': " << strerror(errno);
42 if (read(fd, &val, sizeof(val)) < 0)
43 FAIL() << "Failed to read from '" << heapname << "_shrink': " << strerror(errno);
44 if (val > 0)
45 FAIL() << heapname << "_shrink still has value " << val;
46 close(fd);
47 }
48
49 class PhysTest : public IonSpecialTest {
50 protected:
ionTestPhys(int fd,unsigned int cmd)51 void ionTestPhys(int fd, unsigned int cmd) {
52 int ret;
53
54 EXPECT_EQ(0, ret = ioctl(getTestDevFd(), ION_IOC_TEST_SET_FD, fd));
55
56 if (ret == 0) {
57 ion_test_phys_data data;
58 data.cmd = cmd;
59 data.arg = 0;
60 data.result = 0;
61
62 EXPECT_EQ(0, ioctl(getTestDevFd(), ION_IOC_TEST_PHYS, &data));
63
64 EXPECT_EQ(0, ioctl(getTestDevFd(), ION_IOC_TEST_SET_FD, -1));
65 }
66 }
67 };
68
TEST_F(PhysTest,Carveout)69 TEST_F(PhysTest, Carveout)
70 {
71 for (unsigned int i = 0; i < getHeapCount(); i++) {
72 if (getHeapType(i) != ION_HEAP_TYPE_CARVEOUT)
73 continue;
74
75 for (size_t size : allocation_sizes) {
76 if (size > getHeapSize(i))
77 continue;
78
79 int fd = ionAlloc(size, getHeapMask(i), 0);
80
81 SCOPED_TRACE(::testing::Message() << "heap " << getHeapName(i) << " mask " << getHeapMask(i));
82 SCOPED_TRACE(::testing::Message() << "size " << size);
83
84 EXPECT_LT(2, fd);
85 EXPECT_GT(1024, fd);
86
87 ionTestPhys(fd, PHYS_IS_RESERVED);
88
89 EXPECT_EQ(0, close(fd));
90 }
91 }
92 }
93
TEST_F(PhysTest,Cma)94 TEST_F(PhysTest, Cma)
95 {
96 for (unsigned int i = 0; i < getHeapCount(); i++) {
97 if (getCmaUsed(getHeapName(i)) > 0)
98 continue;
99
100 if (getHeapType(i) != ION_HEAP_TYPE_DMA)
101 continue;
102
103 for (size_t size : allocation_sizes) {
104 if (size > getHeapSize(i))
105 continue;
106
107 int fd = ionAlloc(size, getHeapMask(i), 0);
108
109 SCOPED_TRACE(::testing::Message() << "heap " << getHeapName(i) << " mask " << getHeapMask(i));
110 SCOPED_TRACE(::testing::Message() << "size " << size);
111
112 EXPECT_LT(2, fd);
113 EXPECT_GT(1024, fd);
114
115 ionTestPhys(fd, PHYS_IS_CMA);
116
117 EXPECT_EQ(0, close(fd));
118 }
119 }
120 }
121
TEST_F(PhysTest,Hpa)122 TEST_F(PhysTest, Hpa)
123 {
124 for (unsigned int i = 0; i < getHeapCount(); i++) {
125 if (getHeapType(i) != ION_HEAP_TYPE_CARVEOUT)
126 continue;
127
128 for (size_t size : allocation_sizes) {
129 if (getHeapFlags(i) & ION_HEAPDATA_FLAGS_DEFER_FREE)
130 flushShrinker(getHeapName(i));
131
132 int fd = ionAlloc(size, getHeapMask(i), 0);
133
134 SCOPED_TRACE(::testing::Message() << "heap " << getHeapName(i) << " mask " << getHeapMask(i));
135 SCOPED_TRACE(::testing::Message() << "size " << size);
136
137 EXPECT_LT(2, fd);
138 EXPECT_GT(1024, fd);
139
140 ionTestPhys(fd, PHYS_CHUNK_IS_IDENTICAL_SIZE);
141 ionTestPhys(fd, PHYS_IS_ORDERED_IN_ADDRESS);
142
143 EXPECT_EQ(0, close(fd));
144 }
145 }
146 }
147