M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions

View File

@@ -0,0 +1,39 @@
ifeq ($(call is-vendor-board-platform,QCOM),true)
ifeq ($(TARGET_ARCH),arm)
LOCAL_PATH := $(call my-dir)
commonSources :=
# the dlkm
DLKM_DIR := device/qcom/common/dlkm
include $(CLEAR_VARS)
LOCAL_MODULE := msm_ion_test_module.ko
LOCAL_MODULE_TAGS := debug
include $(DLKM_DIR)/AndroidKernelModule.mk
# the userspace test program
include $(CLEAR_VARS)
LOCAL_MODULE := msm_iontest
LOCAL_SRC_FILES += $(commonSources) msm_iontest.c kernel_ion_tests.c user_ion_tests.c cp_ion_tests.c
LOCAL_SRC_FILES += ion_test_utils.c
LOCAL_C_INCLUDES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include/
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
LOCAL_SHARED_LIBRARIES := \
libc \
libcutils \
libutils
LOCAL_MODULE_TAGS := optional debug
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/kernel-tests
include $(BUILD_EXECUTABLE)
# the test script
include $(CLEAR_VARS)
LOCAL_MODULE := iontest.sh
LOCAL_MODULE_CLASS := EXECUTABLES
LOCAL_SRC_FILES := iontest.sh
LOCAL_MODULE_TAGS := optional debug
LOCAL_MODULE_PATH := $(TARGET_OUT_DATA)/kernel-tests
include $(BUILD_PREBUILT)
endif
endif

View File

@@ -0,0 +1 @@
obj-m := msm_ion_test_module.o

View File

@@ -0,0 +1,29 @@
iondir = $(prefix)/ion
ion_PROGRAMS = msm_iontest
msm_iontest_SOURCES = msm_iontest.c cp_ion_tests.c ion_test_utils.c kernel_ion_tests.c user_ion_tests.c
dist_ion_SCRIPTS = iontest.sh run.sh
KERNEL_FLAGS ?= ARCH=arm
module = msm_ion_test_module.ko
kmake = $(MAKE) $(KERNEL_FLAGS) -C $(KERNEL_DIR) M=$(CURDIR)
$(module):
$(kmake) modules
all-local: $(module)
install-exec-local: $(module)
$(kmake) INSTALL_MOD_PATH=$(DESTDIR)$(prefix)/modules modules_install
dist_ion_DATA = README.txt $(module)
# "make distclean" will always run clean-local in this directory,
# regardless of the KERNELMODULES conditional. Therefore, ensure
# KERNEL_DIR exists before running clean. Further, don't fail even
# if there is a problem.
clean-local:
-test ! -d "$(KERNEL_DIR)" || $(kmake) clean

View File

@@ -0,0 +1,20 @@
Test: iontest
Usage: iontest [OPTIONS]...
OPTIONS can be (defaults in parenthesis):
-n, --nominal nominal test cases
-a, --adversarial adversarial test cases
-V run with debug messages on (off)
Description:
Ion is a memory allocator used by multimedia clients.
This test simulates a ion client to exercise the allocator framework
The ion framework provides, kernel space and user space interfaces.
Ion apis : linux/msm_ion.h and linux/ion.h
For running tests, the iontest.sh script should be used.
The script loads msm_ion_test_module kernel module.
This module is used to drive kernel space ion test cases.
Target support: 8960, 8930, 8064, 8974

View File

@@ -0,0 +1,351 @@
/*
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* MSM ION content protection tests. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <sys/types.h>
#include <ctype.h>
#include <linux/input.h>
#include <linux/msm_ion.h>
#include <sys/mman.h>
#include "ion_test_plan.h"
#include "ion_test_utils.h"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
static struct ion_test_data mm_heap_test = {
.align = 0x1000,
.size = 0x1000,
.heap_mask = ION_HEAP(ION_CP_MM_HEAP_ID),
.flags = ION_FLAG_SECURE,
.heap_type_req = CP,
};
static struct ion_test_data adv_mm_heap_test = {
.align = 0x1000,
.size = 0x1000,
.heap_mask = ION_HEAP(ION_CP_MM_HEAP_ID),
.heap_type_req = CP,
.flags = 0,
};
static struct ion_test_data *mm_heap_data_settings[] = {
[NOMINAL_TEST] = &mm_heap_test,
[ADV_TEST] = &adv_mm_heap_test,
};
static int test_sec_alloc(const char *ion_dev, const char *msm_ion_dev,
struct ion_test_plan *ion_tp, int test_type,
int *test_skipped)
{
int ion_fd, ion_kernel_fd, map_fd, rc;
unsigned long addr;
struct ion_allocation_data alloc_data, sec_alloc_data;
struct ion_fd_data fd_data;
struct ion_test_data ktest_data;
struct ion_test_data *test_data;
struct ion_test_data **test_data_table =
(struct ion_test_data **)ion_tp->test_plan_data;
if (test_type == NOMINAL_TEST)
test_data = test_data_table[NOMINAL_TEST];
else
test_data = test_data_table[ADV_TEST];
*test_skipped = !test_data->valid;
if (!test_data->valid) {
rc = 0;
debug(INFO, "%s was skipped\n",__func__);
goto out;
}
ion_fd = open(ion_dev, O_RDONLY);
if (ion_fd < 0) {
debug(INFO, "Failed to open ion device\n");
perror("msm ion");
return ion_fd;
}
ion_kernel_fd = open(msm_ion_dev, O_RDONLY);
if (ion_kernel_fd < 0) {
debug(INFO, "Failed to open msm ion test device\n");
perror("msm ion");
close(ion_fd);
return ion_kernel_fd;
}
alloc_data.len = test_data->size;
alloc_data.align = test_data->align;
alloc_data.heap_mask = test_data->heap_mask;
alloc_data.flags = ION_SECURE;
rc = ioctl(ion_fd, ION_IOC_ALLOC, &alloc_data);
if (rc) {
debug(ERR, "alloc buf failed\n");
goto cp_alloc_err;
}
rc = ioctl(ion_kernel_fd, IOC_ION_SEC, NULL);
if (rc) {
debug(INFO, "unable to secure heap\n");
goto cp_alloc_sec_err;
}
sec_alloc_data.len = test_data->size;
sec_alloc_data.heap_mask = test_data->heap_mask;
sec_alloc_data.flags = test_data->flags;
sec_alloc_data.align = test_data->align;
rc = ioctl(ion_fd, ION_IOC_ALLOC, &sec_alloc_data);
if (rc < 0 && test_type == NOMINAL_TEST) {
debug(ERR, "Nominal cp alloc buf failed\n");
goto cp_alloc_sec_err;
} else if (rc < 0 && test_type == ADV_TEST) {
rc = 0;
goto cp_alloc_sec_err;
} else if (rc == 0 && test_type == ADV_TEST) {
debug(INFO, "erroneous alloc request succeeded\n");
rc = -EIO;
ioctl(ion_fd, ION_IOC_FREE, &sec_alloc_data.handle);
goto cp_alloc_sec_err;
} else {
ioctl(ion_fd, ION_IOC_FREE, &sec_alloc_data.handle);
}
ioctl(ion_kernel_fd, IOC_ION_UNSEC, NULL);
if (test_type == ADV_TEST) {
fd_data.handle = alloc_data.handle;
rc = ioctl(ion_fd, ION_IOC_MAP, &fd_data);
if (rc < 0) {
debug(INFO, "unable to ion map buffer\n");
goto cp_alloc_sec_err;
}
map_fd = fd_data.fd;
addr = (unsigned long)mmap(NULL, alloc_data.len,
PROT_READ | PROT_WRITE,
MAP_SHARED , map_fd, 0);
sec_alloc_data.flags |= ION_FLAG_SECURE;
rc = ioctl(ion_fd, ION_IOC_ALLOC, &sec_alloc_data);
if (rc == 0) {
rc = -EIO;
debug(INFO, "Sec alloc succeded with umapped buf\n");
ioctl(ion_fd, ION_IOC_FREE, &sec_alloc_data.handle);
close(fd_data.fd);
goto cp_alloc_sec_err;
}
close(fd_data.fd);
rc = ioctl(ion_kernel_fd, IOC_ION_KCLIENT_CREATE, NULL);
if (rc) {
debug(INFO, "failed to create kernel client\n");
goto cp_alloc_sec_err;
}
rc = ioctl(ion_fd, ION_IOC_SHARE, &fd_data);
if (rc < 0) {
debug(INFO, "unable to share ion buffer\n");
goto cp_alloc_sec_err;
}
ktest_data.align = test_data->align;
ktest_data.size = test_data->size;
ktest_data.heap_mask = test_data->heap_mask;
ktest_data.flags = test_data->flags;
ktest_data.shared_fd = fd_data.fd;
rc = ioctl(ion_kernel_fd, IOC_ION_UIMPORT, &ktest_data);
if (rc) {
debug(INFO, "unable to import ubuf to kernel space\n");
ioctl(ion_kernel_fd, IOC_ION_KCLIENT_DESTROY, NULL);
goto cp_alloc_sec_err;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KMAP, NULL);
if (rc) {
debug(INFO, "unable to map ubuf to kernel space\n");
ioctl(ion_kernel_fd, IOC_ION_KFREE, NULL);
ioctl(ion_kernel_fd, IOC_ION_KCLIENT_DESTROY, NULL);
goto cp_alloc_sec_err;
}
rc = ioctl(ion_fd, ION_IOC_ALLOC, &sec_alloc_data);
if (rc == 0) {
rc = -EIO;
ioctl(ion_fd, ION_IOC_FREE, &sec_alloc_data.handle);
debug(INFO, "Sec alloc succeded with kmapped buf\n");
}
ioctl(ion_kernel_fd, IOC_ION_KUMAP, NULL);
ioctl(ion_kernel_fd, IOC_ION_KFREE, NULL);
ioctl(ion_kernel_fd, IOC_ION_KCLIENT_DESTROY, NULL);
close(fd_data.fd);
}
cp_alloc_sec_err:
ioctl(ion_fd, ION_IOC_FREE, &alloc_data.handle);
cp_alloc_err:
close(ion_kernel_fd);
close(ion_fd);
out:
return rc;
}
static struct ion_test_plan sec_alloc_test = {
.name = "CP ion alloc buf",
.test_plan_data = &mm_heap_data_settings,
.test_plan_data_len = 3,
.test_type_flags = NOMINAL_TEST | ADV_TEST,
.test_fn = test_sec_alloc,
};
static int test_sec_map(const char *ion_dev, const char *msm_ion_dev,
struct ion_test_plan *ion_tp, int test_type,
int *test_skipped)
{
int ion_fd, rc, ion_kernel_fd, map_fd;
unsigned long addr;
struct ion_allocation_data alloc_data;
struct ion_fd_data fd_data;
struct ion_test_data *test_data, ktest_data;
struct ion_test_data **test_data_table =
(struct ion_test_data **)ion_tp->test_plan_data;
if (test_type == NOMINAL_TEST)
test_data = test_data_table[NOMINAL_TEST];
else
test_data = test_data_table[ADV_TEST];
*test_skipped = !test_data->valid;
if (!test_data->valid) {
rc = 0;
debug(INFO, "%s was skipped\n",__func__);
goto out;
}
ion_fd = open(ion_dev, O_RDONLY);
if (ion_fd < 0) {
debug(INFO, "Failed to open ion device\n");
perror("msm ion");
return -EIO;
}
ion_kernel_fd = open(msm_ion_dev, O_RDWR);
if (ion_kernel_fd < 0) {
debug(INFO, "Failed to open msm ion test device\n");
perror("msm ion");
close(ion_fd);
return -EIO;
}
alloc_data.len = test_data->size;
alloc_data.align = test_data->align;
alloc_data.heap_mask = test_data->heap_mask;
alloc_data.flags = test_data->flags;
rc = ioctl(ion_fd, ION_IOC_ALLOC, &alloc_data);
if (rc) {
debug(INFO, "Failed to allocate uspace ion buffer\n");
goto sec_map_alloc_err;
}
rc = ioctl(ion_kernel_fd, IOC_ION_SEC, NULL);
if (rc) {
debug(INFO, "unable to secure heap\n");
goto sec_map_alloc_err;
}
debug(INFO, "passed secure heap\n");
fd_data.handle = alloc_data.handle;
rc = ioctl(ion_fd, ION_IOC_MAP, &fd_data);
if (rc == 0) {
if (test_type == ADV_TEST) {
debug(ERR, "mapping buffer to uspace succeeded\n");
rc = -EIO;
close(fd_data.fd);
goto sec_map_err;
}
}
map_fd = fd_data.fd;
addr = (unsigned long)mmap(NULL, alloc_data.len,
PROT_READ | PROT_WRITE,
MAP_SHARED, map_fd, 0);
rc = ioctl(ion_fd, ION_IOC_SHARE, &fd_data);
if (rc) {
debug(INFO, "unable to share user buffer\n");
goto sec_map_share_err;
}
debug(INFO, "shared user buffer\n");
rc = ioctl(ion_kernel_fd, IOC_ION_KCLIENT_CREATE, NULL);
if (rc) {
debug(INFO, "failed to create kernel client\n");
goto sec_map_kc_err;
}
ktest_data.align = test_data->align;
ktest_data.size = test_data->size;
ktest_data.heap_mask = test_data->heap_mask;
ktest_data.flags = test_data->flags;
ktest_data.shared_fd = fd_data.fd;
rc = ioctl(ion_kernel_fd, IOC_ION_UIMPORT, &ktest_data);
if (rc) {
debug(INFO, "unable to import ubuf to kernel space\n");
goto sec_map_uimp_err;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KMAP, NULL);
if (rc == 0 && test_type == ADV_TEST) {
rc = -EIO;
debug(INFO, "able to map ubuf to kernel space\n");
ioctl(ion_kernel_fd, IOC_ION_KUMAP, NULL);
} else if (rc < 0) {
rc = 0;
} else {
ioctl(ion_kernel_fd, IOC_ION_KUMAP, NULL);
}
ioctl(ion_kernel_fd, IOC_ION_KFREE, NULL);
sec_map_uimp_err:
ioctl(ion_kernel_fd, IOC_ION_KCLIENT_DESTROY, NULL);
sec_map_kc_err:
close(fd_data.fd);
sec_map_share_err:
munmap((void *)addr, alloc_data.len);
sec_map_err:
ioctl(ion_kernel_fd, IOC_ION_UNSEC, NULL);
sec_map_alloc_err:
ioctl(ion_fd, ION_IOC_FREE, &alloc_data.handle);
close(ion_kernel_fd);
close(ion_fd);
out:
return rc;
}
static struct ion_test_plan sec_map_test = {
.name = "CP ion map test",
.test_plan_data = mm_heap_data_settings,
.test_plan_data_len = 3,
.test_type_flags = NOMINAL_TEST,
.test_fn = test_sec_map,
};
static struct ion_test_plan *cp_tests[] = {
&sec_alloc_test,
&sec_map_test,
};
struct ion_test_plan **get_cp_ion_tests(const char *dev, size_t *size)
{
*size = ARRAY_SIZE(cp_tests);
setup_heaps_for_tests(dev, cp_tests, *size);
return cp_tests;
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* MSM ION test plan */
#ifndef __ION_TEST_PLAN_
#define __ION_TEST_PLAN_
/*
* Test types
*/
#define NOMINAL_TEST 1
#define ADV_TEST 2
struct ion_test_plan {
const char *name;
void *test_plan_data;
unsigned int test_plan_data_len;
unsigned long test_type_flags;
int (*test_fn)(const char *ion_dev, const char *msm_ion_test,
struct ion_test_plan *, int test_type, int *skipped);
};
struct ion_test_plan **get_kernel_ion_tests(const char *dev, size_t *size);
struct ion_test_plan **get_user_ion_tests(const char *dev, size_t *size);
struct ion_test_plan **get_cp_ion_tests(const char *dev, size_t *size);
#endif

View File

@@ -0,0 +1,149 @@
/*
* Copyright (c) 2012, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* MSM ION test Utils. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <linux/input.h>
#include <linux/msm_ion.h>
#include <linux/kernel.h>
#include <linux/types.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include "ion_test_plan.h"
#include "ion_test_utils.h"
int debug_level = ERR;
void set_debug_level(int level)
{
debug_level = level;
}
char *itoa(int num, char *buf, size_t len)
{
if (snprintf(buf, len, "%d", num) == -1)
return NULL;
else
return buf;
}
int sock_write(int fd, const char *buf, int size)
{
int sent = 0, wc = 0;
int index = 0;
const char *data = buf;
while (sent < size) {
wc = write(fd, &data[sent], size - sent);
if (wc < 0) {
debug(INFO, "\n error in writing to socket\n");
return -EIO;
} else {
sent += wc;
}
};
return 0;
}
int sock_read(int fd, char *buf, int size)
{
int rc = 0, rd = 0;
int index = 0;
char *data = buf;
while (rd < size) {
rc = read(fd, &data[rd], size - rd);
if (rc < 0) {
debug(INFO, "\n error in reading from socket\n");
return -EIO;
} else {
rd += rc;
}
}
return 0;
}
static int get_heap_data(const char *msm_ion_dev, struct ion_test_data *data)
{
int ion_kernel_fd, rc;
struct ion_heap_data heap_data;
ion_kernel_fd = open(msm_ion_dev, O_RDWR);
if (ion_kernel_fd < 0) {
debug(ERR, "Failed to open msm ion test device\n");
perror("msm ion");
return -EIO;
}
heap_data.type = data->heap_type_req;
heap_data.heap_mask = data->heap_mask;
rc = ioctl(ion_kernel_fd, IOC_ION_FIND_PROPER_HEAP, &heap_data);
if (!rc) {
data->valid = heap_data.valid;
data->heap_mask = heap_data.heap_mask;
} else {
data->valid = 0;
}
close(ion_kernel_fd);
return rc;
}
void setup_heaps_for_tests(const char *dev, struct ion_test_plan **tp_array,
unsigned int len)
{
unsigned int i;
unsigned int j;
struct ion_test_plan *tp;
for (i = 0; i < len; ++i) {
tp = tp_array[i];
for (j = 0; j < tp->test_plan_data_len; ++j) {
struct ion_test_data *test_data;
if (tp->test_plan_data_len > 1) {
struct ion_test_data **test_data_table =
tp->test_plan_data;
test_data = test_data_table[j];
} else {
test_data = tp->test_plan_data;
}
if (test_data)
get_heap_data(dev, test_data);
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* MSM ION test utils */
#ifndef __ION_TEST_UTILS_
#define __ION_TEST_UTILS_
#include <stdint.h>
#include "iontest.h"
/* Debug level */
#define ERR 0
#define INFO 1
extern int debug_level;
#define debug(level, x...) do { (level > debug_level) ? 0 : printf(x); } \
while (0)
void set_debug_level(int level);
int sock_read(int sock_fd, char *buf, int size);
int sock_write(int sock_fd, const char *buf, int size);
char *itoa(int num, char *buf, size_t len);
void setup_heaps_for_tests(const char *dev, struct ion_test_plan **tp_array,
unsigned int len);
#endif

View File

@@ -0,0 +1,90 @@
#ifndef __MSM_ION_TEST__
#define __MSM_ION_TEST__
#include <linux/ioctl.h>
enum ion_test_heap_type {
SYSTEM_MEM = 1, /* SYSTEM_HEAP */
SYSTEM_MEM2, /* IOMMU_HEAP */
SYSTEM_CONTIG,
CARVEOUT,
CP_CARVEOUT,
CP,
};
struct ion_test_data {
unsigned int align;
unsigned int size;
enum ion_test_heap_type heap_type_req;
unsigned long heap_mask; /* Auto-detected if possible */
unsigned long flags;
unsigned long vaddr;
unsigned long cache;
int shared_fd;
unsigned int valid; /* Valid for this target. Auto-detected */
};
struct ion_heap_data {
enum ion_test_heap_type type;
unsigned int size;
unsigned long heap_mask;
unsigned int valid;
};
#define MSM_ION_MAGIC 'M'
#define IOC_ION_KCLIENT_CREATE _IO(MSM_ION_MAGIC, 0)
#define IOC_ION_KCLIENT_DESTROY _IO(MSM_ION_MAGIC, 1)
#define IOC_ION_KALLOC _IOW(MSM_ION_MAGIC, 2, struct ion_test_data)
#define IOC_ION_KFREE _IO(MSM_ION_MAGIC, 3)
#define IOC_ION_KPHYS _IO(MSM_ION_MAGIC, 4)
#define IOC_ION_KMAP _IO(MSM_ION_MAGIC, 5)
#define IOC_ION_KUMAP _IO(MSM_ION_MAGIC, 6)
#define IOC_ION_UIMPORT _IOW(MSM_ION_MAGIC, 7, struct ion_test_data)
#define IOC_ION_WRITE_VERIFY _IO(MSM_ION_MAGIC, 8)
#define IOC_ION_VERIFY _IO(MSM_ION_MAGIC, 9)
#define IOC_ION_UBUF_FLAGS _IOR(MSM_ION_MAGIC, 10, unsigned long)
#define IOC_ION_UBUF_SIZE _IOR(MSM_ION_MAGIC, 11, unsigned long)
#define IOC_ION_SEC _IO(MSM_ION_MAGIC, 12)
#define IOC_ION_UNSEC _IO(MSM_ION_MAGIC, 13)
#define IOC_ION_FIND_PROPER_HEAP _IOWR(MSM_ION_MAGIC, 14, struct ion_heap_data)
static inline void write_pattern(unsigned long buf, size_t size)
{
uint8_t *addr = (uint8_t *)buf;
uint8_t count = 0;
unsigned int i;
for (i = 0; i < size; i++) {
addr[i] = count;
if (count == 0xFF)
count = 0;
else
count++;
}
}
static inline int verify_pattern(unsigned long buf, size_t size)
{
uint8_t *addr = (uint8_t *)buf;
uint8_t count = 0;
unsigned int i;
for (i = 0; i < size; i++) {
if (addr[i] != count)
return -EIO;
if (count == 0xFF)
count = 0;
else
count++;
}
return 0;
}
#endif

View File

@@ -0,0 +1,107 @@
# Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of The Linux Foundation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Unit test for the ion.
#
# Invoked by run.sh
# This will run nominal and adversarial testcases.
chmod 755 msm_iontest
if [ -d /system/lib/modules/ ]; then
modpath=/system/lib/modules
else
modpath=/kernel-tests/modules/lib/modules/$(uname -r)/extra
fi
ion_test_mod=${modpath}/msm_ion_test_module.ko
ion_dev=/dev/ion
ion_dev_misc=/sys/class/misc/ion/dev
ion_test_dev=/dev/msm_ion_test
ion_test_dev_sys=/sys/class/msm_ion_test/msm_ion_test/dev
test_type=n
level=0
maybe_make_node()
{
thedev=$1
themisc=$2
[ -e $thedev ] || \
mknod $thedev c $(cut -d: -f1 $themisc) $(cut -d: -f2 $themisc)
}
for i in $*
do
case $i in
-n | --nominal)
# already nominal test case by default
;;
-a | --adversarial)
test_type=a
;;
-V)
level=1
;;
-h | --help | *)
echo "Usage: $0 [-n | --nominal] [-a | --adversarial] [-V]";
exit 1
;;
esac
done
# create ion device if it doesn't exist
maybe_make_node $ion_dev $ion_dev_misc
if [ ! -e $ion_test_mod ]; then
echo "ERROR: Kernel Test Module not present"
exit 1
fi
# insert msm_ion_test_module if needed
if [ ! -e $ion_test_dev_sys ]; then
insmod $ion_test_mod
if [ $? -ne 0 ]; then
echo "ERROR: failed to load module $ion_test_mod"
exit 1
fi
fi
# create the ion test device if it doesn't exist
maybe_make_node $ion_test_dev $ion_test_dev_sys
#invoke test
./msm_iontest $test_type $level
ret=$?
if [ $ret -ne 0 ];then
echo "Test Failed"
else
echo "Test Passed"
fi
rmmod msm_ion_test_module
exit $ret

View File

@@ -0,0 +1,676 @@
/*
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* MSM ION Kernel api tests. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <sys/types.h>
#include <ctype.h>
#include <linux/input.h>
#include <linux/msm_ion.h>
#include <sys/mman.h>
#include "ion_test_plan.h"
#include "ion_test_utils.h"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
static struct ion_test_data mm_heap_test = {
.align = 0x1000,
.size = 0x1000,
.heap_mask = ION_HEAP(ION_SYSTEM_HEAP_ID),
.heap_type_req = SYSTEM_MEM,
.flags = ION_FLAG_CACHED,
};
static struct ion_test_data phys_heap_test = {
.align = 0x1000,
.size = 0x1000,
.heap_mask = ION_HEAP(ION_QSECOM_HEAP_ID),
.heap_type_req = CARVEOUT,
.flags = 0,
};
static struct ion_test_data adv_mm_heap_test = {
.align = 0x1000,
.size = 0xC0000000,
.heap_mask = ION_HEAP(ION_QSECOM_HEAP_ID),
.heap_type_req = CARVEOUT,
.flags = 0,
};
static struct ion_test_data adv_system_heap_test = {
.align = 0x1000,
.size = 0x1000,
.heap_mask = ION_HEAP(ION_SYSTEM_HEAP_ID),
.heap_type_req = SYSTEM_MEM,
.flags = 0,
};
static struct ion_test_data *mm_heap_data_settings[] = {
[NOMINAL_TEST] = &mm_heap_test,
[ADV_TEST] = &adv_mm_heap_test,
};
/*
* Kernel ion client create test
*/
int test_kclient(const char *ion_dev, const char *msm_ion_dev,
struct ion_test_plan *ion_tp, int test_type,
int *test_skipped)
{
int ion_kernel_fd, rc;
ion_kernel_fd = open(msm_ion_dev, O_RDWR);
if (ion_kernel_fd < 0) {
debug(ERR, "Failed to open msm ion test device\n");
perror("msm ion");
return -EIO;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KCLIENT_CREATE, NULL);
if (rc < 0) {
debug(ERR, "kernel client create failed\n");
return -EIO;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KCLIENT_DESTROY, NULL);
close(ion_kernel_fd);
*test_skipped = 0;
return 0;
}
static struct ion_test_plan kclient_test = {
.name = "Kernel ion client",
.test_type_flags = NOMINAL_TEST,
.test_plan_data_len = 0,
.test_fn = test_kclient,
};
/*
* Kernel ion buf alloc
* Nominal test: Using mm heap.
* ADV test: Invalid client, and erroneous alloc request
*/
int test_kalloc(const char *ion_dev, const char *msm_ion_dev,
struct ion_test_plan *ion_tp, int test_type,
int *test_skipped)
{
int ion_kernel_fd, rc;
struct ion_test_data *test_data;
struct ion_test_data **test_data_table =
(struct ion_test_data **)ion_tp->test_plan_data;
if (test_type == NOMINAL_TEST)
test_data = test_data_table[NOMINAL_TEST];
else
test_data = test_data_table[ADV_TEST];
*test_skipped = !test_data->valid;
if (!test_data->valid) {
rc = 0;
debug(INFO, "%s was skipped\n",__func__);
goto out;
}
ion_kernel_fd = open(msm_ion_dev, O_RDWR);
if (ion_kernel_fd < 0) {
debug(ERR, "Failed to open msm ion test device\n");
perror("msm ion");
return -EIO;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KCLIENT_CREATE, NULL);
if (rc < 0) {
debug(ERR, "kernel client create failed\n");
close(ion_kernel_fd);
return -EIO;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KALLOC, test_data);
if (rc < 0 && test_type == NOMINAL_TEST) {
debug(ERR, "Nominal kernel alloc buf failed\n");
goto alloc_err;
} else if (rc < 0 && test_type == ADV_TEST) {
rc = 0;
goto alloc_err;
} else if (rc == 0 && test_type == ADV_TEST) {
debug(INFO, "erroneous alloc request succeeded\n");
rc = EIO;
}
ioctl(ion_kernel_fd, IOC_ION_KFREE, NULL);
alloc_err:
ioctl(ion_kernel_fd, IOC_ION_KCLIENT_DESTROY, NULL);
close(ion_kernel_fd);
out:
return rc;
}
static struct ion_test_plan kalloc_test = {
.name = "Kernel ion alloc buf",
.test_plan_data = mm_heap_data_settings,
.test_plan_data_len = 3,
.test_type_flags = NOMINAL_TEST | ADV_TEST,
.test_fn = test_kalloc,
};
/*
* Kernel ion phys attr
* Nominal test: use mm heap settings
* Adeveserial test: Invalid handle and client
*/
int test_kphys(const char *ion_dev, const char *msm_ion_dev,
struct ion_test_plan *ion_tp, int test_type,
int *test_skipped)
{
int ion_kernel_fd, rc;
struct ion_test_data *test_data =
(struct ion_test_data *)ion_tp->test_plan_data;
*test_skipped = !test_data->valid;
if (!test_data->valid) {
rc = 0;
debug(INFO, "%s was skipped\n",__func__);
goto out;
}
ion_kernel_fd = open(msm_ion_dev, O_RDWR);
if (ion_kernel_fd < 0) {
debug(ERR, "Failed to open msm ion test device\n");
perror("msm ion");
return -EIO;
}
/*
* ADV test 1: invalid client
* TODO: Requires fix in ion_phys
* Currently causes a creash
*/
if (test_type == ADV_TEST) {
rc = ioctl(ion_kernel_fd, IOC_ION_KPHYS, NULL);
if (!rc) {
debug(INFO, "phys attr obtained with invalid handle\n");
rc = -EIO;
close(ion_kernel_fd);
return rc;
}
}
rc = ioctl(ion_kernel_fd, IOC_ION_KCLIENT_CREATE, NULL);
if (rc < 0) {
debug(ERR, "kernel client create failed\n");
goto n_kphys_kc_err;
}
/*
* ADV test 2: invalid handle
* TODO: Requires fix in ion_phys
* Currently causes a creash
*/
if (test_type == ADV_TEST) {
rc = ioctl(ion_kernel_fd, IOC_ION_KPHYS, NULL);
if (!rc) {
debug(INFO, "phys attr obtained with invalid handle\n");
rc = -EIO;
goto n_kphys_alloc_err;
}
}
rc = ioctl(ion_kernel_fd, IOC_ION_KALLOC, test_data);
if (rc < 0) {
debug(ERR, "kernel alloc buf failed\n");
goto n_kphys_alloc_err;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KPHYS, NULL);
ioctl(ion_kernel_fd, IOC_ION_KFREE, NULL);
n_kphys_alloc_err:
ioctl(ion_kernel_fd, IOC_ION_KCLIENT_DESTROY, NULL);
n_kphys_kc_err:
close(ion_kernel_fd);
out:
return rc;
}
static struct ion_test_plan kphys_test = {
.name = "Kernel ion buf phys attr test",
.test_plan_data = &phys_heap_test,
.test_plan_data_len = 1,
/*
* TODO: Enable ADV test after ion phys api
* can handle erroneous input
*/
.test_type_flags = NOMINAL_TEST,
.test_fn = test_kphys,
};
/*
* Kernel ion system phys attr
* Adeveserial test: get phys attr from system heap
*/
int test_ksystem_phys(const char *ion_dev, const char *msm_ion_dev,
struct ion_test_plan *ion_tp, int test_type,
int *test_skipped)
{
int ion_kernel_fd, rc;
struct ion_test_data *test_data =
(struct ion_test_data *)ion_tp->test_plan_data;
*test_skipped = !test_data->valid;
if (!test_data->valid) {
rc = 0;
debug(INFO, "%s was skipped\n",__func__);
goto out;
}
ion_kernel_fd = open(msm_ion_dev, O_RDWR);
if (ion_kernel_fd < 0) {
debug(ERR, "Failed to open msm ion test device\n");
perror("msm ion");
return -EIO;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KCLIENT_CREATE, NULL);
if (rc < 0) {
debug(ERR, "kernel client create failed\n");
goto n_kphys_kc_err;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KALLOC, test_data);
if (rc < 0) {
debug(ERR, "kernel system alloc buf failed\n");
goto n_kphys_alloc_err;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KPHYS, NULL);
if (rc < 0 && test_type == ADV_TEST)
rc = 0;
ioctl(ion_kernel_fd, IOC_ION_KFREE, NULL);
n_kphys_alloc_err:
ioctl(ion_kernel_fd, IOC_ION_KCLIENT_DESTROY, NULL);
n_kphys_kc_err:
close(ion_kernel_fd);
out:
return rc;
}
static struct ion_test_plan ksystem_test = {
.name = "Kernel system buf phys attr test",
.test_plan_data = &adv_system_heap_test,
.test_plan_data_len = 1,
.test_type_flags = ADV_TEST,
.test_fn = test_ksystem_phys,
};
/*
* Kernel ion map
*/
int test_kmap(const char *ion_dev, const char *msm_ion_dev,
struct ion_test_plan *ion_tp, int test_type,
int *test_skipped)
{
*test_skipped = 0;
if (test_type == NOMINAL_TEST) {
int ion_kernel_fd, rc;
struct ion_test_data *test_data =
(struct ion_test_data *)ion_tp->test_plan_data;
*test_skipped = !test_data->valid;
if (!test_data->valid) {
rc = 0;
debug(INFO, "%s was skipped\n",__func__);
goto out;
}
ion_kernel_fd = open(msm_ion_dev, O_RDWR);
if (ion_kernel_fd < 0) {
debug(ERR, "Failed to open msm ion test device\n");
perror("msm ion");
return -EIO;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KCLIENT_CREATE, NULL);
if (rc < 0) {
debug(ERR, "kernel client create failed\n");
goto n_kmap_kc_err;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KALLOC, test_data);
if (rc < 0) {
debug(ERR, "kernel alloc buf failed\n");
goto n_kmap_alloc_err;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KMAP, NULL);
if (!rc) {
rc = ioctl(ion_kernel_fd, IOC_ION_WRITE_VERIFY, NULL);
if (rc < 0)
debug(ERR, "kernel map verification fails\n");
ioctl(ion_kernel_fd, IOC_ION_KUMAP, NULL);
}
ioctl(ion_kernel_fd, IOC_ION_KFREE, NULL);
n_kmap_alloc_err:
ioctl(ion_kernel_fd, IOC_ION_KCLIENT_DESTROY, NULL);
n_kmap_kc_err:
close(ion_kernel_fd);
return rc;
}
out:
return 0;
}
static struct ion_test_plan kmap_test = {
.name = "Kernel ion map test",
.test_plan_data = &mm_heap_test,
.test_plan_data_len = 1,
.test_type_flags = NOMINAL_TEST,
.test_fn = test_kmap,
};
/*
* Kernel ion user import test
*/
int test_kuimport(const char *ion_dev, const char *msm_ion_dev,
struct ion_test_plan *ion_tp, int test_type,
int *test_skipped)
{
int ion_kernel_fd, rc, ion_fd, map_fd;
struct ion_allocation_data alloc_data;
struct ion_fd_data fd_data;
unsigned long addr;
struct ion_test_data *test_data =
(struct ion_test_data *)ion_tp->test_plan_data;
*test_skipped = !test_data->valid;
if (!test_data->valid) {
rc = 0;
debug(INFO, "%s was skipped\n",__func__);
goto out;
}
ion_kernel_fd = open(msm_ion_dev, O_RDWR);
if (ion_kernel_fd < 0) {
debug(ERR, "Failed to open msm ion test device\n");
perror("msm ion");
return -EIO;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KCLIENT_CREATE, NULL);
if (rc < 0) {
debug(ERR, "kernel client create failed\n");
close(ion_kernel_fd);
return -EIO;
}
ion_fd = open(ion_dev, O_RDONLY);
if (ion_fd < 0) {
debug(ERR, "Failed to open ion device\n");
perror("msm ion");
rc = -EIO;
goto kuimp_id_err;
}
if (test_type == ADV_TEST) {
rc = ioctl(ion_kernel_fd, IOC_ION_UIMPORT, &ion_fd);
if (rc < 0)
rc = 0;
else
rc = -EIO;
goto kuimp_adv_test_close;
}
if (test_type == NOMINAL_TEST) {
alloc_data.len = test_data->size;
alloc_data.align = test_data->align;
alloc_data.heap_mask = test_data->heap_mask;
alloc_data.flags = test_data->flags;
rc = ioctl(ion_fd, ION_IOC_ALLOC, &alloc_data);
if (rc) {
debug(ERR, "Failed to allocate uspace ion buffer\n");
goto kuimp_adv_test_close;
}
fd_data.handle = alloc_data.handle;
rc = ioctl(ion_fd, ION_IOC_MAP, &fd_data);
if (rc) {
debug(ERR, "Failed to map uspace ion buffer\n");
goto kuimp_map_err;
}
map_fd = fd_data.fd;
addr = (unsigned long)mmap(NULL, alloc_data.len,
PROT_READ | PROT_WRITE,
MAP_SHARED , map_fd, 0);
write_pattern(addr, alloc_data.len);
rc = ioctl(ion_fd, ION_IOC_SHARE, &fd_data);
if (rc) {
debug(ERR, "Failed to share uspace ion buffer fd\n");
goto kuimp_share_err;
}
test_data->shared_fd = fd_data.fd;
rc = ioctl(ion_kernel_fd, IOC_ION_UIMPORT, test_data);
if (!rc) {
rc = ioctl(ion_kernel_fd, IOC_ION_KMAP, NULL);
if (!rc)
rc = ioctl(ion_kernel_fd, IOC_ION_VERIFY, NULL);
else
debug(ERR, "failed to map uimp buffer\n");
ioctl(ion_kernel_fd, IOC_ION_KUMAP, NULL);
ioctl(ion_kernel_fd, IOC_ION_KFREE, NULL);
}
if (rc)
debug(ERR, "Failed to import uspace buffer\n");
kuimp_share_err:
munmap((void *)addr, alloc_data.len);
close(map_fd);
kuimp_map_err:
ioctl(ion_fd, ION_IOC_FREE, &alloc_data.handle);
}
kuimp_adv_test_close:
close(ion_fd);
kuimp_id_err:
ioctl(ion_kernel_fd, IOC_ION_KCLIENT_DESTROY, NULL);
close(ion_kernel_fd);
out:
return rc;
}
static struct ion_test_plan kuimp_test = {
.name = "Kernel ion uspace buffer import",
.test_plan_data = &mm_heap_test,
.test_plan_data_len = 1,
.test_type_flags = ADV_TEST,
.test_fn = test_kuimport,
};
/*
* Kernel ion imported user buf attributes test
*/
int test_ubuf_attr(const char *ion_dev, const char *msm_ion_dev,
struct ion_test_plan *ion_tp, int test_type,
int *test_skipped)
{
*test_skipped = 0;
if (test_type == NOMINAL_TEST) {
int ion_kernel_fd, rc, ion_fd, map_fd;
struct ion_allocation_data alloc_data;
struct ion_fd_data fd_data;
unsigned long addr, flags, size;
struct ion_test_data *test_data =
(struct ion_test_data *)ion_tp->test_plan_data;
*test_skipped = !test_data->valid;
if (!test_data->valid) {
rc = 0;
debug(INFO, "%s was skipped (nom)\n",__func__);
goto out;
}
ion_kernel_fd = open(msm_ion_dev, O_RDWR);
if (ion_kernel_fd < 0) {
debug(ERR, "Failed to open msm ion test device\n");
perror("msm ion");
return -EIO;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KCLIENT_CREATE, NULL);
if (rc < 0) {
debug(ERR, "kernel client create failed\n");
close(ion_kernel_fd);
return -EIO;
}
ion_fd = open(ion_dev, O_RDONLY);
if (ion_fd < 0) {
debug(ERR, "Failed to open ion device\n");
perror("msm ion");
rc = -EIO;
goto kubuf_id_err;
}
alloc_data.len = test_data->size;
alloc_data.align = test_data->align;
alloc_data.heap_mask = test_data->heap_mask;
alloc_data.flags = test_data->flags;
rc = ioctl(ion_fd, ION_IOC_ALLOC, &alloc_data);
if (rc) {
debug(ERR, "Failed to allocate uspace ion buffer\n");
goto n_kubuf_alloc_err;
}
fd_data.handle = alloc_data.handle;
rc = ioctl(ion_fd, ION_IOC_SHARE, &fd_data);
if (rc) {
debug(ERR, "Failed to share uspace ion buffer fd\n");
goto n_kubuf_share_err;
}
test_data->shared_fd = fd_data.fd;
rc = ioctl(ion_kernel_fd, IOC_ION_UIMPORT, test_data);
if (!rc) {
rc = ioctl(ion_kernel_fd, IOC_ION_UBUF_FLAGS, &flags);
if (!rc)
rc = ioctl(ion_kernel_fd, IOC_ION_UBUF_SIZE,
&size);
else if (rc < 0) {
debug(ERR, "failed to get ubuf attributes\n");
} else {
rc = ((size == alloc_data.len) &&
(flags == alloc_data.flags)) ?
0 : -EIO;
}
ioctl(ion_kernel_fd, IOC_ION_KFREE, NULL);
} else
debug(ERR, "failed to import uspace buf\n");
close(fd_data.fd);
n_kubuf_share_err:
ioctl(ion_fd, ION_IOC_FREE, &alloc_data.handle);
n_kubuf_alloc_err:
close(ion_fd);
kubuf_id_err:
ioctl(ion_kernel_fd, IOC_ION_KCLIENT_DESTROY, NULL);
close(ion_kernel_fd);
return rc;
} else if (test_type == ADV_TEST) {
int ion_kernel_fd, rc, ion_fd, map_fd;
struct ion_allocation_data alloc_data;
struct ion_fd_data fd_data;
unsigned long addr, flags, size;
struct ion_test_data *test_data =
(struct ion_test_data *)ion_tp->test_plan_data;
*test_skipped = !test_data->valid;
if (!test_data->valid) {
rc = 0;
debug(INFO, "%s was skipped (adv)\n",__func__);
goto out;
}
ion_kernel_fd = open(msm_ion_dev, O_RDWR);
if (ion_kernel_fd < 0) {
debug(ERR, "Failed to open msm ion test device\n");
perror("msm ion");
return -EIO;
}
ion_fd = open(ion_dev, O_RDONLY);
if (ion_fd < 0) {
debug(ERR, "Failed to open ion device\n");
perror("msm ion");
close(ion_kernel_fd);
return -EIO;
}
alloc_data.len = test_data->size;
alloc_data.align = test_data->align;
alloc_data.heap_mask = test_data->heap_mask;
alloc_data.flags = test_data->flags;
rc = ioctl(ion_fd, ION_IOC_ALLOC, &alloc_data);
if (rc) {
debug(ERR, "Failed to allocate uspace ion buffer\n");
goto a_kubuf_alloc_err;
}
fd_data.handle = alloc_data.handle;
rc = ioctl(ion_fd, ION_IOC_SHARE, &fd_data);
if (rc) {
debug(ERR, "Failed to share uspace ion buffer fd\n");
goto a_kubuf_share_err;
}
test_data->shared_fd = fd_data.fd;
rc = ioctl(ion_kernel_fd, IOC_ION_UBUF_FLAGS, &flags);
if (rc)
rc = ioctl(ion_kernel_fd, IOC_ION_UBUF_SIZE, &size);
if (rc == 0) {
debug(INFO, "can read ubuf attr with invalid client\n");
goto a_kubuf_attr_client_err;
}
rc = ioctl(ion_kernel_fd, IOC_ION_KCLIENT_CREATE, NULL);
if (rc < 0) {
debug(INFO, "kernel client create failed\n");
goto a_kubuf_attr_client_err;
}
rc = ioctl(ion_kernel_fd, IOC_ION_UBUF_FLAGS, &flags);
if (rc)
rc = ioctl(ion_kernel_fd, IOC_ION_UBUF_SIZE, &size);
if (rc == 0) {
debug(INFO, "can read ubuf attr with invalid handle\n");
goto a_kubuf_attr_handle_err;
}
rc = 0;
a_kubuf_attr_handle_err:
ioctl(ion_kernel_fd, IOC_ION_KCLIENT_DESTROY, NULL);
a_kubuf_attr_client_err:
a_kubuf_share_err:
ioctl(ion_fd, ION_IOC_FREE, &alloc_data.handle);
a_kubuf_alloc_err:
close(ion_fd);
close(ion_kernel_fd);
}
out:
return 0;
}
static struct ion_test_plan kubuf_attr_test = {
.name = "Kernel ion uspace buffer size and flags",
.test_plan_data = &mm_heap_test,
.test_plan_data_len = 1,
/* TODO: ADV test causes crash in ion.
* Needs to be fixed till then ADV test
* diabled
*/
.test_type_flags = NOMINAL_TEST,
.test_fn = test_ubuf_attr,
};
static struct ion_test_plan *kernel_tests[] = {
&kclient_test,
&kalloc_test,
&kphys_test,
&ksystem_test,
&kmap_test,
&kuimp_test,
&kubuf_attr_test,
};
struct ion_test_plan **get_kernel_ion_tests(const char *dev, size_t *size)
{
*size = ARRAY_SIZE(kernel_tests);
setup_heaps_for_tests(dev, kernel_tests, *size);
return kernel_tests;
}

View File

@@ -0,0 +1,450 @@
/* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/init.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/msm_ion.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include "iontest.h"
#define ION_TEST_DEV_NAME "msm_ion_test"
#define CLIENT_NAME "ion_test_client"
struct msm_ion_test {
struct ion_client *ion_client;
struct ion_handle *ion_handle;
struct ion_test_data test_data;
};
struct heap {
unsigned int id;
unsigned int size;
enum ion_test_heap_type type;
};
static struct class *ion_test_class;
static int ion_test_major;
static struct device *ion_test_dev;
static struct heap *heap_list;
static unsigned int heap_list_len;
/*Utility apis*/
static inline int create_ion_client(struct msm_ion_test *ion_test)
{
ion_test->ion_client = msm_ion_client_create(UINT_MAX, CLIENT_NAME);
if (IS_ERR_OR_NULL(ion_test->ion_client))
return -EIO;
return 0;
}
static inline void free_ion_client(struct msm_ion_test *ion_test)
{
ion_client_destroy(ion_test->ion_client);
}
static int alloc_ion_buf(struct msm_ion_test *ion_test,
struct ion_test_data *test_data)
{
ion_test->ion_handle = ion_alloc(ion_test->ion_client, test_data->size,
test_data->align, test_data->heap_mask,
test_data->flags);
if (IS_ERR_OR_NULL(ion_test->ion_handle))
return -EIO;
return 0;
}
static inline void free_ion_buf(struct msm_ion_test *ion_test)
{
ion_free(ion_test->ion_client, ion_test->ion_handle);
}
static int heap_detected;
#ifdef CONFIG_OF_DEVICE
static int ion_find_heaps_available(void)
{
struct device_node *ion_node;
struct device_node *ion_child;
unsigned int i = 0;
int ret = 0;
unsigned int val = 0;
ion_node = of_find_compatible_node(NULL, NULL, "qcom,msm-ion");
for_each_child_of_node(ion_node, ion_child)
heap_list_len++;
heap_list = kzalloc(sizeof(struct heap) * heap_list_len, GFP_KERNEL);
if (!heap_list) {
ret = -ENOMEM;
goto out;
}
for_each_child_of_node(ion_node, ion_child) {
ret = of_property_read_u32(ion_child, "reg", &val);
if (ret) {
pr_err("%s: Unable to find reg key", __func__);
goto free_heaps;
}
heap_list[i].id = val;
switch (val) {
case ION_SYSTEM_HEAP_ID:
{
heap_list[i].type = SYSTEM_MEM;
break;
}
case ION_SYSTEM_CONTIG_HEAP_ID:
{
heap_list[i].type = SYSTEM_CONTIG;
break;
}
case ION_CP_MM_HEAP_ID:
{
ret = of_property_read_u32(ion_child,
"qcom,memory-reservation-size", &val);
if (ret) {
heap_list[i].type = CP;
} else {
heap_list[i].size = val;
heap_list[i].type = CP_CARVEOUT;
}
break;
}
case ION_IOMMU_HEAP_ID:
{
heap_list[i].type = SYSTEM_MEM2;
break;
}
case ION_QSECOM_HEAP_ID:
case ION_AUDIO_HEAP_ID:
{
ret = of_property_read_u32(ion_child,
"qcom,memory-reservation-size", &val);
if (ret) {
heap_list[i].type = 0;
} else {
heap_list[i].size = val;
heap_list[i].type = CARVEOUT;
}
break;
}
default:
break;
}
++i;
}
heap_detected = 1;
goto out;
free_heaps:
kfree(heap_list);
heap_list = 0;
out:
return ret;
}
#else
static int ion_find_heaps_available(void)
{
return 0;
}
#endif
static int ion_test_open(struct inode *inode, struct file *file)
{
struct msm_ion_test *ion_test = kzalloc(sizeof(struct msm_ion_test),
GFP_KERNEL);
if (!ion_test)
return -ENOMEM;
pr_debug("ion test device opened\n");
file->private_data = ion_test;
return ion_find_heaps_available();
}
static int get_proper_heap(struct ion_heap_data *data)
{
int ret = -EINVAL;
unsigned int i;
if (!heap_detected) {
data->valid = 1;
ret = 0;
} else {
data->heap_mask = 0;
data->size = 0;
data->valid = 0;
for (i = 0; i < heap_list_len; ++i) {
if (data->type == heap_list[i].type) {
data->size = heap_list[i].size;
data->heap_mask = ION_HEAP(heap_list[i].id);
data->valid = 1;
ret = 0;
break;
}
}
}
return ret;
}
static long ion_test_ioctl(struct file *file, unsigned cmd, unsigned long arg)
{
int ret;
ion_phys_addr_t phys_addr;
void *addr;
size_t len;
unsigned long flags, size;
struct msm_ion_test *ion_test = file->private_data;
struct ion_test_data *test_data = &ion_test->test_data;
switch (cmd) {
case IOC_ION_KCLIENT_CREATE:
{
ret = create_ion_client(ion_test);
break;
}
case IOC_ION_KCLIENT_DESTROY:
{
free_ion_client(ion_test);
ret = 0;
break;
}
case IOC_ION_KALLOC:
{
if (copy_from_user(test_data, (void __user *)arg,
sizeof(struct ion_test_data)))
return -EFAULT;
ret = alloc_ion_buf(ion_test, test_data);
if (ret)
pr_info("allocating ion buffer failed\n");
break;
}
case IOC_ION_KFREE:
{
free_ion_buf(ion_test);
ret = 0;
break;
}
case IOC_ION_KPHYS:
{
ret = ion_phys(ion_test->ion_client, ion_test->ion_handle,
&phys_addr, &len);
if (!ret)
pr_info("size is 0x%x\n phys addr 0x%x", len,
(unsigned int)phys_addr);
break;
}
case IOC_ION_KMAP:
{
addr = ion_map_kernel(ion_test->ion_client,
ion_test->ion_handle);
if (IS_ERR_OR_NULL(addr)) {
ret = -EIO;
pr_info("mapping kernel buffer failed\n");
} else {
ret = 0;
test_data->vaddr = (unsigned long)addr;
}
break;
}
case IOC_ION_KUMAP:
{
ion_unmap_kernel(ion_test->ion_client, ion_test->ion_handle);
ret = 0;
break;
}
case IOC_ION_UIMPORT:
{
if (copy_from_user(test_data, (void __user *)arg,
sizeof(struct ion_test_data)))
return -EFAULT;
ion_test->ion_handle = ion_import_dma_buf(ion_test->ion_client,
test_data->shared_fd);
if (IS_ERR_OR_NULL(ion_test->ion_handle)) {
ret = -EIO;
pr_info("import of user buf failed\n");
} else
ret = 0;
break;
}
case IOC_ION_UBUF_FLAGS:
{
ret = ion_handle_get_flags(ion_test->ion_client,
ion_test->ion_handle, &flags);
if (ret)
pr_info("user flags cannot be retrieved\n");
else
if (copy_to_user((void __user *)arg, &flags,
sizeof(unsigned long)))
ret = -EFAULT;
break;
}
case IOC_ION_UBUF_SIZE:
{
ret = ion_handle_get_size(ion_test->ion_client,
ion_test->ion_handle, &size);
if (ret)
pr_info("buffer size cannot be retrieved\n");
else
if (copy_to_user((void __user *)arg, &size,
sizeof(unsigned long)))
ret = -EFAULT;
break;
}
case IOC_ION_WRITE_VERIFY:
{
write_pattern(test_data->vaddr, test_data->size);
if (verify_pattern(test_data->vaddr, test_data->size)) {
pr_info("verify of mapped buf failed\n");
ret = -EIO;
} else
ret = 0;
break;
}
case IOC_ION_VERIFY:
{
if (verify_pattern(test_data->vaddr, test_data->size)) {
pr_info("fail in verifying imported buffer\n");
ret = -EIO;
} else
ret = 0;
break;
}
case IOC_ION_SEC:
{
ret = msm_ion_secure_heap(ION_CP_MM_HEAP_ID);
if (ret)
pr_info("unable to secure heap\n");
else
pr_info("able to secure heap\n");
break;
}
case IOC_ION_UNSEC:
{
ret = msm_ion_unsecure_heap(ION_CP_MM_HEAP_ID);
if (ret)
pr_info("unable to unsecure heap\n");
else
pr_info("able to unsecure heap\n");
break;
}
case IOC_ION_FIND_PROPER_HEAP:
{
struct ion_heap_data data;
if (copy_from_user(&data, (void __user *)arg,
sizeof(struct ion_heap_data)))
return -EFAULT;
ret = get_proper_heap(&data);
if (!ret) {
if (copy_to_user((void __user *)arg, &data,
sizeof(struct ion_heap_data)))
ret = -EFAULT;
}
break;
}
default:
{
pr_info("command not supported\n");
ret = -EINVAL;
}
};
return ret;
}
static int ion_test_release(struct inode *inode, struct file *file)
{
struct msm_ion_test *ion_test = file->private_data;
pr_debug("ion test device closed\n");
kfree(ion_test);
return 0;
}
/*
* Register ourselves as a device to be able to test the ion code
* from userspace.
*/
static const struct file_operations ion_test_fops = {
.owner = THIS_MODULE,
.unlocked_ioctl = ion_test_ioctl,
.open = ion_test_open,
.release = ion_test_release,
};
static int ion_test_device_create(void)
{
int ret_val = 0;
ion_test_major = register_chrdev(0, ION_TEST_DEV_NAME, &ion_test_fops);
if (ion_test_major < 0) {
pr_err("Unable to register chrdev: %d\n", ion_test_major);
ret_val = ion_test_major;
goto out;
}
ion_test_class = class_create(THIS_MODULE, ION_TEST_DEV_NAME);
if (IS_ERR(ion_test_class)) {
ret_val = PTR_ERR(ion_test_class);
pr_err("Unable to create class: %d\n", ret_val);
goto err_create_class;
}
ion_test_dev = device_create(ion_test_class, NULL, MKDEV(ion_test_major, 0), NULL, ION_TEST_DEV_NAME);
if (IS_ERR(ion_test_dev)) {
ret_val = PTR_ERR(ion_test_dev);
pr_err("Unable to create device: %d\n", ret_val);
goto err_create_device;
}
goto out;
err_create_device:
class_destroy(ion_test_class);
err_create_class:
unregister_chrdev(ion_test_major, ION_TEST_DEV_NAME);
out:
return ret_val;
}
static void ion_test_device_destroy(void)
{
device_destroy(ion_test_class, MKDEV(ion_test_major, 0));
class_destroy(ion_test_class);
unregister_chrdev(ion_test_major, ION_TEST_DEV_NAME);
kfree(heap_list);
}
static int ion_test_init(void)
{
return ion_test_device_create();
}
static void ion_test_exit(void)
{
return ion_test_device_destroy();
}
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Test for MSM ION implementation");
module_init(ion_test_init);
module_exit(ion_test_exit);

View File

@@ -0,0 +1,197 @@
/*
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* MSM ION tester. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <sys/types.h>
#include <ctype.h>
#include <linux/input.h>
#include <linux/msm_ion.h>
#include <linux/kernel.h>
#include <sys/mman.h>
#include "ion_test_plan.h"
#include "ion_test_utils.h"
/* Device path names */
#define MSM_ION_TEST "/dev/msm_ion_test"
#define MSM_ION "/dev/ion"
unsigned int TEST_TYPE = NOMINAL_TEST;
static int run_tests(struct ion_test_plan **table, const char *test_plan,
unsigned int type, size_t size,
unsigned int *total_tests,
unsigned int *tests_skipped)
{
struct ion_test_plan *test;
unsigned int i;
int ret = 0;
int skipped = 0;
for (i = 0; i < size; i++) {
test = table[i];
if (!test) {
printf("%s test table size mismatch\n", test_plan);
break;
}
if (test->test_type_flags & type) {
ret = test->test_fn(MSM_ION, MSM_ION_TEST, test,
type, &skipped);
if (ret) {
debug(INFO, "%s test failed, stopping\n",
test->name);
break;
} else {
debug(INFO, "%s test passed\n", test->name);
}
++(*total_tests);
if (skipped)
++(*tests_skipped);
}
}
return ret;
}
int parse_args(int argc, char **argv)
{
unsigned int level;
if (argc != 3)
return 1;
switch (argv[1][0]) {
case 'n':
{
TEST_TYPE = NOMINAL_TEST;
break;
}
case 'a':
{
TEST_TYPE = ADV_TEST;
break;
}
default:
return -EINVAL;
}
level = atoi(argv[2]);
if (level != INFO && level != ERR)
return -EINVAL;
set_debug_level(level);
return 0;
}
int main(int argc, char **argv)
{
unsigned int i = 0, type;
int ret = 0;
size_t usize, ksize, cpsize;
struct ion_test_plan **utable, **ktable, **cptable;
unsigned int total_tests_run = 0;
unsigned int total_skipped = 0;
if (parse_args(argc, argv)) {
debug(ERR, "incorrect arguments passed\n");
return -EINVAL;
}
/* Get test tables */
utable = get_user_ion_tests(MSM_ION_TEST, &usize);
if (!utable) {
debug(ERR, "no user tests\n");
return -EIO;
}
ktable = get_kernel_ion_tests(MSM_ION_TEST, &ksize);
if (!ktable) {
debug(ERR, "no kernel tests\n");
return -EIO;
}
cptable = get_cp_ion_tests(MSM_ION_TEST, &cpsize);
if (!cptable) {
debug(ERR, "no user tests\n");
return -EIO;
}
/* Run tests */
if (TEST_TYPE == NOMINAL_TEST) {
debug(INFO, "\n\nRunning Nominal user space ion tests :\n\n");
ret = run_tests(utable, "user space", NOMINAL_TEST, usize,
&total_tests_run, &total_skipped);
if (ret) {
debug(INFO, "user space Nominal tests failed\n");
return ret;
}
type = NOMINAL_TEST;
debug(INFO, "\n\nRunning Nominal kernel space ion tests :\n\n");
ret = run_tests(ktable, "kernel space", type, ksize,
&total_tests_run, &total_skipped);
if (ret) {
debug(INFO, "kernel space Nominal tests failed\n");
return ret;
}
debug(INFO, "\n\nRunning Nominal cp ion tests :\n\n");
ret = run_tests(cptable, "CP", type, cpsize,
&total_tests_run, &total_skipped);
if (ret) {
debug(INFO, "cp ion Nominal tests failed\n");
return ret;
}
}
if (TEST_TYPE == ADV_TEST) {
type = ADV_TEST;
debug(INFO, "\n\nRunning Adversarial user space ion tests:\n");
ret = run_tests(utable, "user space", type, usize,
&total_tests_run, &total_skipped);
if (ret) {
debug(INFO, "user space Adversarial tests failed\n");
return ret;
}
debug(INFO,
"\n\nRunning Adversarial kernel space ion tests:\n");
ret = run_tests(ktable, "kernel space", type, ksize,
&total_tests_run, &total_skipped);
if (ret) {
debug(INFO, "kernel space Adversarial tests failed\n");
return ret;
}
debug(INFO, "\n\nRunning Adversarial cp ion tests :\n\n");
ret = run_tests(cptable, "CP", type, cpsize,
&total_tests_run, &total_skipped);
if (ret) {
debug(INFO, "cp ion Adversarial tests failed\n");
return ret;
}
}
printf("Ran %u tests out of which %u were skipped\n",
total_tests_run, total_skipped);
return ret;
}

View File

@@ -0,0 +1,32 @@
#! /bin/sh --
# Copyright (c) 2012, The Linux Foundation. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following
# disclaimer in the documentation and/or other materials provided
# with the distribution.
# * Neither the name of The Linux Foundation nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
# OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
# IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set -e
cd `dirname $0` && exec ./iontest.sh $@

View File

@@ -0,0 +1,457 @@
/*
* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* MSM ION User space tests. */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <malloc.h>
#include <linux/input.h>
#include <linux/msm_ion.h>
#include <linux/types.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <sys/types.h>
#include "ion_test_plan.h"
#include "ion_test_utils.h"
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
static struct ion_test_data mm_heap_test = {
.align = 0x1000,
.size = 0x1000,
.heap_type_req = SYSTEM_MEM2,
.heap_mask = ION_HEAP(ION_IOMMU_HEAP_ID),
};
static struct ion_test_data adv_mm_heap_test = {
.align = 0x1000,
.size = 0xC0000000,
.heap_type_req = CARVEOUT,
.heap_mask = ION_HEAP(ION_QSECOM_HEAP_ID),
};
static struct ion_test_data *mm_heap_data_settings[] = {
[NOMINAL_TEST] = &mm_heap_test,
[ADV_TEST] = &adv_mm_heap_test,
};
static int test_ualloc(const char *ion_dev, const char *msm_ion_dev,
struct ion_test_plan *ion_tp, int test_type,
int *test_skipped)
{
int ion_fd, rc;
struct ion_allocation_data alloc_data;
struct ion_test_data *test_data;
struct ion_test_data **test_data_table =
(struct ion_test_data **)ion_tp->test_plan_data;
if (test_type == NOMINAL_TEST)
test_data = test_data_table[NOMINAL_TEST];
else
test_data = test_data_table[ADV_TEST];
*test_skipped = !test_data->valid;
if (!test_data->valid) {
rc = 0;
debug(INFO, "%s was skipped\n",__func__);
goto out;
}
ion_fd = open(ion_dev, O_RDONLY);
if (ion_fd < 0) {
debug(ERR, "Failed to open msm ion test device\n");
perror("msm ion");
return -EIO;
}
alloc_data.len = test_data->size;
alloc_data.align = test_data->align;
alloc_data.heap_mask = test_data->heap_mask;
alloc_data.flags = test_data->flags;
rc = ioctl(ion_fd, ION_IOC_ALLOC, &alloc_data);
if (rc < 0 && test_type == NOMINAL_TEST) {
debug(ERR, "Nominal user alloc buf failed\n");
perror("msm ion");
goto ualloc_err;
} else if (rc < 0 && test_type == ADV_TEST) {
rc = 0;
goto ualloc_err;
} else if (rc == 0 && test_type == ADV_TEST) {
debug(INFO, "erroneous alloc request succeeded\n");
rc = -EIO;
}
ioctl(ion_fd, ION_IOC_FREE, &alloc_data.handle);
ualloc_err:
close(ion_fd);
out:
return rc;
}
static struct ion_test_plan ualloc_test = {
.name = "User ion alloc buf",
.test_plan_data = mm_heap_data_settings,
.test_plan_data_len = 3,
.test_type_flags = NOMINAL_TEST | ADV_TEST,
.test_fn = test_ualloc,
};
static int test_umap(const char *ion_dev, const char *msm_ion_dev,
struct ion_test_plan *ion_tp, int test_type,
int *test_skipped)
{
int ion_fd, map_fd, rc;
void *addr;
struct ion_allocation_data alloc_data;
struct ion_fd_data fd_data;
struct ion_test_data *test_data =
(struct ion_test_data *)ion_tp->test_plan_data;
*test_skipped = !test_data->valid;
if (!test_data->valid) {
rc = 0;
debug(INFO, "%s was skipped\n",__func__);
goto out;
}
ion_fd = open(ion_dev, O_RDONLY);
if (ion_fd < 0) {
debug(INFO, "Failed to open ion device\n");
perror("msm ion");
return -EIO;
}
alloc_data.len = test_data->size;
alloc_data.align = test_data->align;
alloc_data.heap_mask = test_data->heap_mask;
alloc_data.flags = test_data->flags;
rc = ioctl(ion_fd, ION_IOC_ALLOC, &alloc_data);
if (rc) {
debug(ERR, "Failed to allocate uspace ion buffer\n");
goto umap_alloc_err;
}
/*
* ADV TEST1: Use invalid handle
*/
if (test_type == ADV_TEST) {
rc = ioctl(ion_fd, ION_IOC_MAP, &fd_data);
if (!rc) {
debug(INFO, "mapped using invalid handle\n");
rc = -EIO;
goto umap_map_err;
}
}
fd_data.handle = alloc_data.handle;
rc = ioctl(ion_fd, ION_IOC_MAP, &fd_data);
if (rc < 0) {
debug(INFO, "unable to ion map buffer\n");
goto umap_map_err;
}
map_fd = fd_data.fd;
/*
* ADV test2: map twice the allocted length
*/
if (test_type == ADV_TEST) {
addr = mmap(NULL, alloc_data.len * 2,
PROT_READ | PROT_WRITE,
MAP_SHARED, map_fd, 0);
if (!addr) {
debug(INFO, "mmap succeded using larger map length\n");
munmap(addr, alloc_data.len * 2);
rc = -EIO;
goto umap_map_err;
}
}
addr = mmap(NULL, alloc_data.len,
PROT_READ | PROT_WRITE,
MAP_SHARED, map_fd, 0);
if (!addr) {
debug(INFO, "mmap failed\n");
goto umap_map_err;
}
write_pattern((unsigned long)addr, alloc_data.len);
if (verify_pattern((unsigned long)addr, alloc_data.len)) {
debug(INFO, "mapped buffer not writeable\n");
rc = -EIO;
} else
rc = 0;
munmap(addr, alloc_data.len);
close(map_fd);
ioctl(ion_fd, ION_IOC_FREE, &alloc_data.handle);
/*
* Nominal Test with alloc length / 2
*/
alloc_data.len = test_data->size * 2;
rc = ioctl(ion_fd, ION_IOC_ALLOC, &alloc_data);
if (rc) {
debug(ERR, "Failed to allocate uspace ion buffer\n");
goto umap_alloc_err;
}
fd_data.handle = alloc_data.handle;
rc = ioctl(ion_fd, ION_IOC_MAP, &fd_data);
if (rc < 0) {
debug(INFO, "unable to ion map buffer\n");
goto umap_map_err;
}
map_fd = fd_data.fd;
addr = mmap(NULL, alloc_data.len/2,
PROT_READ | PROT_WRITE,
MAP_SHARED, map_fd, 0);
if (!addr) {
debug(INFO, "mmap failed\n");
close(map_fd);
goto umap_map_err;
}
write_pattern((unsigned long)addr, alloc_data.len/2);
if (verify_pattern((unsigned long)addr, alloc_data.len/2)) {
debug(INFO, "mapped buffer not writeable\n");
rc = -EIO;
} else
rc = 0;
munmap(addr, alloc_data.len/2);
close(map_fd);
umap_map_err:
ioctl(ion_fd, ION_IOC_FREE, &alloc_data.handle);
umap_alloc_err:
close(ion_fd);
out:
return rc;
}
static struct ion_test_plan umap_test = {
.name = "User ion buf map",
.test_plan_data = &mm_heap_test,
.test_plan_data_len = 1,
.test_type_flags = NOMINAL_TEST | ADV_TEST,
.test_fn = test_umap,
};
static int uimport_ion_buf(int fd)
{
static char cbuf[100];
int ion_fd, size, rc;
void *addr;
struct ion_fd_data fd_data;
debug(INFO, "importing data in child done\n");
/* receive buf fd */
if (-EIO == sock_read(fd, cbuf, sizeof(int)*8))
return -EIO;
fd_data.fd = atoi(cbuf);
/* receive buf length */
if (-EIO == sock_read(fd, cbuf, sizeof(int)*8))
return -EIO;
size = atoi(cbuf);
/* receive ion dev name */
if (-EIO == sock_read(fd, cbuf, sizeof(cbuf)))
return -EIO;
ion_fd = open(cbuf, O_RDONLY);
if (ion_fd < 1) {
debug(INFO, "unable to open ion device\n");
rc = -EINVAL;
goto child_args_err;
}
rc = ioctl(ion_fd, ION_IOC_IMPORT, &fd_data);
if (rc) {
debug(INFO, "ION_IOC_IMPORT failed\n");
rc = -EIO;
goto child_imp_err;
}
addr = mmap(NULL, size, PROT_READ | PROT_WRITE,
MAP_SHARED, fd_data.fd, 0);
if (!addr) {
debug(INFO, "failed to map buffer\n");
rc = -EIO;
goto child_mmap_err;
}
if (verify_pattern((unsigned long)addr, (size_t)size)) {
debug(INFO, "unable to verify imported buffer\n");
rc = -EIO;
} else
debug(INFO, "import test passed\n");
munmap(addr, size);
child_mmap_err:
close(fd_data.fd);
ioctl(ion_fd, ION_IOC_FREE, &fd_data.handle);
child_imp_err:
close(ion_fd);
child_args_err:
itoa(rc, cbuf, sizeof(int)*8);
child_sock_err:
close(fd);
return rc;
}
static int uimp_spawn_process(pid_t *pid, int *wr_fd)
{
int socket[2], child;
if (pipe(socket) < 0) {
debug(INFO, "unable to create pipe\n");
return -EIO;
}
child = fork();
if (child == -1) {
debug(INFO, "unable to fork process\n");
return -EIO;
} else if (child == 0) {
close(socket[1]);
if (uimport_ion_buf(socket[0]))
exit(1) ;
exit(0);
} else {
*pid = child;
close(socket[0]);
*wr_fd = socket[1];
return 0;
}
}
static int test_uimp(const char *ion_dev, const char *msm_ion_dev,
struct ion_test_plan *ion_tp, int test_type,
int *test_skipped)
{
int ion_fd, map_fd, rc, wr_fd;
int sock_fd;
char buf[32];
void *addr;
struct ion_allocation_data alloc_data;
struct ion_fd_data fd_data;
int child_status;
static char ubuf[100];
pid_t tpid, child_pid;
struct ion_test_data *test_data =
(struct ion_test_data *)ion_tp->test_plan_data;
*test_skipped = !test_data->valid;
if (!test_data->valid) {
rc = 0;
debug(INFO, "%s was skipped\n",__func__);
goto out;
}
rc = uimp_spawn_process(&child_pid, &wr_fd);
if (rc)
return -EIO;
ion_fd = open(ion_dev, O_RDONLY);
if (ion_fd < 0) {
debug(INFO, "Failed to open ion device\n");
perror("msm ion");
return -EIO;
}
alloc_data.len = test_data->size;
alloc_data.align = test_data->align;
alloc_data.heap_mask = test_data->heap_mask;
alloc_data.flags = test_data->flags;
rc = ioctl(ion_fd, ION_IOC_ALLOC, &alloc_data);
if (rc) {
debug(INFO, "Failed to allocate uspace ion buffer\n");
goto uimp_alloc_err;
}
fd_data.handle = alloc_data.handle;
rc = ioctl(ion_fd, ION_IOC_MAP, &fd_data);
if (rc < 0) {
debug(INFO, "unable to ion map buffer\n");
goto uimp_map_err;
}
map_fd = fd_data.fd;
addr = mmap(NULL, alloc_data.len,
PROT_READ | PROT_WRITE,
MAP_SHARED , map_fd, 0);
if (!addr) {
debug(INFO, "mmap failed\n");
rc = -EIO;
goto uimp_mmap_err;
}
write_pattern((unsigned long)addr, alloc_data.len);
fd_data.handle = alloc_data.handle;
rc = ioctl(ion_fd, ION_IOC_SHARE, &fd_data);
if (rc < 0) {
debug(INFO, "unable to share ion buffer\n");
goto uimp_share_err;
}
if (test_type == NOMINAL_TEST)
itoa(fd_data.fd, ubuf, sizeof(int) * 8);
else
itoa(ion_fd, ubuf, sizeof(int) * 8);
if (-EIO == sock_write(wr_fd, ubuf, sizeof(int) * 8))
goto uimp_sock_err;
itoa(alloc_data.len, ubuf, sizeof(int) * 8);
if (-EIO == sock_write(wr_fd, ubuf, sizeof(int) * 8))
goto uimp_sock_err;
strncpy(ubuf, ion_dev, sizeof(ubuf));
if (-EIO == sock_write(wr_fd, ubuf, sizeof(ubuf)))
goto uimp_sock_err;
do {
tpid = wait(&child_status);
} while (tpid != child_pid);
if (test_type == NOMINAL_TEST && child_status != 0)
rc = child_status;
else if (test_type == ADV_TEST && child_status == 0)
rc = -EIO;
else
rc = 0;
uimp_sock_err:
close(fd_data.fd);
uimp_share_err:
munmap(addr, alloc_data.len);
uimp_mmap_err:
close(map_fd);
uimp_map_err:
ioctl(ion_fd, ION_IOC_FREE, &alloc_data.handle);
uimp_alloc_err:
close(ion_fd);
close(wr_fd);
out:
return rc;
}
static struct ion_test_plan uimp_test = {
.name = "User ion import test ",
.test_plan_data = &mm_heap_test,
.test_plan_data_len = 1,
.test_type_flags = ADV_TEST,
.test_fn = test_uimp,
};
static struct ion_test_plan *user_tests[] = {
&ualloc_test,
&umap_test,
&uimp_test,
};
struct ion_test_plan **get_user_ion_tests(const char *dev, size_t *size)
{
*size = ARRAY_SIZE(user_tests);
setup_heaps_for_tests(dev, user_tests, *size);
return user_tests;
}