android13/hardware/google/graphics/common/libion/test/ion_test_fixture.cpp

273 lines
6.8 KiB
C++

/*
* 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 <iostream>
#include <fstream>
#include <string>
#include <cerrno>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <fcntl.h>
#include "ion_test_fixture.h"
#include "ion_test_define.h"
using namespace std;
IonTest::IonTest() : m_ionFd(-1), m_heapCount(0), m_allHeapMask(0)
{
m_idTable[0].legacy_id = ION_EXYNOS_HEAP_ID_SYSTEM;
m_idTable[1].legacy_id = ION_EXYNOS_HEAP_ID_CRYPTO;
m_idTable[2].legacy_id = ION_EXYNOS_HEAP_ID_VIDEO_STREAM;
m_idTable[3].legacy_id = ION_EXYNOS_HEAP_ID_VIDEO_FRAME;
m_idTable[4].legacy_id = ION_EXYNOS_HEAP_ID_VIDEO_SCALER;
m_idTable[5].legacy_id = ION_EXYNOS_HEAP_ID_CAMERA;
m_idTable[6].legacy_id = ION_EXYNOS_HEAP_ID_SECURE_CAMERA;
for (unsigned int i = 0; i < MAX_LEGACY_HEAP_IDS; i++)
m_idTable[i].heap_id = ION_NUM_HEAP_IDS;
}
void IonTest::SetUp()
{
m_ionFd = open("/dev/ion", O_RDWR);
m_ionHeapData = new ion_heap_data[ION_NUM_HEAP_IDS];
if (m_ionHeapData != NULL) {
ion_heap_query query;
int ret;
memset(&query, 0, sizeof(query));
memset(m_ionHeapData, 0, sizeof(ion_heap_data) * ION_NUM_HEAP_IDS);
query.cnt = ION_NUM_HEAP_IDS;
query.heaps = reinterpret_cast<__u64>(m_ionHeapData);
ret = ioctl(m_ionFd, ION_IOC_HEAP_QUERY, &query);
if (ret < 0) {
FAIL() << "ION_IOC_HEAP_QUERY failed: " << strerror(errno);
} else {
m_heapCount = query.cnt;
}
}
for (unsigned int i = 0; i < MAX_LEGACY_HEAP_IDS; i++) {
const char *name = exynos_ion_get_heap_name(m_idTable[i].legacy_id);
for (unsigned int k = 0; k < m_heapCount; k++) {
if (!strcmp(name, m_ionHeapData[k].name) &&
(strlen(name) == strlen(m_ionHeapData[k].name))) {
m_allHeapMask |= 1 << m_idTable[i].legacy_id;
m_idTable[i].heap_id = m_ionHeapData[k].heap_id;
}
}
}
RecordProperty("Heaps", m_heapCount);
SUCCEED() << "Found " << m_heapCount << " heaps found";
}
void IonTest::TearDown()
{
delete [] m_ionHeapData;
close(m_ionFd);
}
size_t IonTest::getCmaUsed(std::string heapname)
{
std::string pathname = "/sys/kernel/debug/cma/cma-";
pathname = pathname + heapname;
pathname = pathname + "/used";
ifstream ifs;
ifs.open(pathname);
// CONFIG_CMA_DEBUGFS is not enabled or @heapname is not defined
if (!ifs)
return 0;
size_t len;
ifs >> len;
return len * sysconf(_SC_PAGESIZE);
}
IonAllocTest::IonAllocTest() : m_memTotal(0)
{
}
void IonAllocTest::SetUp()
{
IonTest::SetUp();
ifstream ifs;
ifs.open("/proc/meminfo");
string title, kb;
size_t size;
ifs >> title >> size >> kb;
m_memTotal = size;
RecordProperty("MemTotalInKb", m_memTotal);
SUCCEED() << "MemTotal: " << m_memTotal << " kb";
}
void IonAllocTest::TearDown()
{
IonTest::TearDown();
}
IonSpecialTest::IonSpecialTest() : m_ionTestDevFd(-1)
{
}
void IonSpecialTest::SetUp()
{
IonTest::SetUp();
m_ionTestDevFd = open("/dev/ion-test", O_RDWR);
if (m_ionTestDevFd < 0) {
FAIL() << "Failed to open /dev/ion-test: " << strerror(errno);
}
}
void IonSpecialTest::TearDown()
{
IonTest::TearDown();
close(m_ionTestDevFd);
}
int IonSpecialTest::ionAlloc(size_t size, unsigned int heapmask,
unsigned int flags)
{
int fd = -1;
ion_allocation_data_modern data;
data.len = size;
data.heap_id_mask = heapmask;
data.flags = flags;
data.fd = 0;
if (ioctl(getIonFd(), ION_IOC_ALLOC_MODERN, &data) == 0)
fd = static_cast<int>(data.fd);
return fd;
}
char *IonClientDeviceTest::ionMmap(int fd, size_t size)
{
void *p = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (p == MAP_FAILED)
return NULL;
return reinterpret_cast<char *>(p);
}
void IonClientDeviceTest::ionMunmap(void *ptr, size_t size)
{
munmap(ptr, size);
}
void IonClientDeviceTest::ionTestMapping(int fd, bool write, unsigned long cmd,
void *ptr, size_t size, off_t offset)
{
EXPECT_EQ(0, ioctl(getTestDevFd(), ION_IOC_TEST_SET_FD, fd));
ion_test_rw_data data;
data.ptr = reinterpret_cast<__u64>(ptr);
data.offset = offset;
data.size = size;
data.write = write ? 1 : 0;
EXPECT_EQ(0, ioctl(getTestDevFd(), cmd, &data)) << strerror(errno);
EXPECT_EQ(0, ioctl(getTestDevFd(), ION_IOC_TEST_SET_FD, -1));
}
void IonClientDeviceTest::blowCache()
{
const size_t bigger_than_cache = mb(8);
const size_t nelem = bigger_than_cache / sizeof(unsigned int);
unsigned int *buf1 = new unsigned int[nelem];
unsigned int *buf2 = new unsigned int[nelem];
// write order is swizzled to prevent
// detection of streaming write by a high-performance CPU.
// Such CPUs skip storing streaming writes to caches.
for (size_t i = 0; i < (nelem / 2); i++) {
buf1[i] = i;
buf1[nelem - i - 1] = i;
}
memcpy(buf2, buf1, bigger_than_cache);
delete [] buf2;
delete [] buf1;
}
void IonClientDeviceTest::dirtyCache(void *ptr, size_t size)
{
unsigned int *uip = reinterpret_cast<unsigned int *>(ptr);
const size_t nelem = size / sizeof(unsigned int);
for (size_t i = 0; i < (nelem / 2); i++) {
uip[i] = 0x5a6b5a6b;
uip[nelem - i - 1] = 0x6b5a6b5a;
}
}
void IonClientDeviceTest::fill(void *ptr, size_t size, off_t offset)
{
unsigned int *uip = reinterpret_cast<unsigned int *>(ptr);
size /= sizeof(unsigned int);
offset /= sizeof(unsigned int);
uip += offset;
for (size_t i = 0; i < (size / 2); i++) {
uip[i] = i;
uip[size - i - 1] = size - i - 1;
}
}
bool IonClientDeviceTest::check(void *ptr, size_t size, off_t offset)
{
unsigned int *uip = reinterpret_cast<unsigned int *>(ptr);
size /= sizeof(unsigned int);
offset /= sizeof(unsigned int);
uip += offset;
for (size_t i = 0; i < size; i++) {
if (uip[i] != i) {
cerr << "Expected " << i << " at offset " << i * sizeof(i) << " byte but found " << uip[i] << endl;
return false;
}
}
return true;
}