blob: 67a31af67a5886d3289e2be0859bfb136d8a9220 [file] [log] [blame]
/*
* Copyright (C) 2018 Samsung Electronics Co., Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include "ion_test_fixture.h"
#include "ion_test_define.h"
static const size_t allocation_sizes[] = {
mkb(16, 716), mkb(12, 4), mkb(8, 912), mkb(4, 60), mkb(2, 520), mkb(1, 92),
mb(16), mb(12), mb(8), mb(4), mb(2), mb(1), kb(64), kb(4),
};
void flushShrinker(const char *heapname) {
std::string pathname = "/sys/kernel/debug/";
pathname += heapname;
pathname += "_shrink";
int fd = open(pathname.c_str(), O_RDWR);
if (fd < 0)
return;
unsigned long val = mb(256); // This is very big enough to flush shrinker
if (write(fd, &val, sizeof(val)) < 0)
FAIL() << "Failed to write " << val << " to '" << heapname << "_shrink': " << strerror(errno);
if (read(fd, &val, sizeof(val)) < 0)
FAIL() << "Failed to read from '" << heapname << "_shrink': " << strerror(errno);
if (val > 0)
FAIL() << heapname << "_shrink still has value " << val;
close(fd);
}
class PhysTest : public IonSpecialTest {
protected:
void ionTestPhys(int fd, unsigned int cmd) {
int ret;
EXPECT_EQ(0, ret = ioctl(getTestDevFd(), ION_IOC_TEST_SET_FD, fd));
if (ret == 0) {
ion_test_phys_data data;
data.cmd = cmd;
data.arg = 0;
data.result = 0;
EXPECT_EQ(0, ioctl(getTestDevFd(), ION_IOC_TEST_PHYS, &data));
EXPECT_EQ(0, ioctl(getTestDevFd(), ION_IOC_TEST_SET_FD, -1));
}
}
};
TEST_F(PhysTest, Carveout)
{
for (unsigned int i = 0; i < getHeapCount(); i++) {
if (getHeapType(i) != ION_HEAP_TYPE_CARVEOUT)
continue;
for (size_t size : allocation_sizes) {
if (size > getHeapSize(i))
continue;
int fd = ionAlloc(size, getHeapMask(i), 0);
SCOPED_TRACE(::testing::Message() << "heap " << getHeapName(i) << " mask " << getHeapMask(i));
SCOPED_TRACE(::testing::Message() << "size " << size);
EXPECT_LT(2, fd);
EXPECT_GT(1024, fd);
ionTestPhys(fd, PHYS_IS_RESERVED);
EXPECT_EQ(0, close(fd));
}
}
}
TEST_F(PhysTest, Cma)
{
for (unsigned int i = 0; i < getHeapCount(); i++) {
if (getCmaUsed(getHeapName(i)) > 0)
continue;
if (getHeapType(i) != ION_HEAP_TYPE_DMA)
continue;
for (size_t size : allocation_sizes) {
if (size > getHeapSize(i))
continue;
int fd = ionAlloc(size, getHeapMask(i), 0);
SCOPED_TRACE(::testing::Message() << "heap " << getHeapName(i) << " mask " << getHeapMask(i));
SCOPED_TRACE(::testing::Message() << "size " << size);
EXPECT_LT(2, fd);
EXPECT_GT(1024, fd);
ionTestPhys(fd, PHYS_IS_CMA);
EXPECT_EQ(0, close(fd));
}
}
}
TEST_F(PhysTest, Hpa)
{
for (unsigned int i = 0; i < getHeapCount(); i++) {
if (getHeapType(i) != ION_HEAP_TYPE_CARVEOUT)
continue;
for (size_t size : allocation_sizes) {
if (getHeapFlags(i) & ION_HEAPDATA_FLAGS_DEFER_FREE)
flushShrinker(getHeapName(i));
int fd = ionAlloc(size, getHeapMask(i), 0);
SCOPED_TRACE(::testing::Message() << "heap " << getHeapName(i) << " mask " << getHeapMask(i));
SCOPED_TRACE(::testing::Message() << "size " << size);
EXPECT_LT(2, fd);
EXPECT_GT(1024, fd);
ionTestPhys(fd, PHYS_CHUNK_IS_IDENTICAL_SIZE);
ionTestPhys(fd, PHYS_IS_ORDERED_IN_ADDRESS);
EXPECT_EQ(0, close(fd));
}
}
}