Merge tag 'linux-kselftest-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Nov 2017 22:56:14 +0000 (14:56 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 17 Nov 2017 22:56:14 +0000 (14:56 -0800)
Pull kselftest updates from Shuah Khan:
 "This update to Kselftest consists of cleanup patches, fixes, and a new
  test for ion buffer sharing.

  Fixes include changes to skip firmware tests on systems that aren't
  configured to support them, as opposed to failing them"

* tag 'linux-kselftest-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
  selftests: firmware: skip unsupported custom firmware fallback tests
  selftests: firmware: skip unsupported async loading tests
  selftests: memfd_test.c: fix compilation warning.
  selftests/ftrace: Introduce exit_pass and exit_fail
  selftests: ftrace: add more config fragments
  android/ion: userspace test utility for ion buffer sharing
  selftests: remove obsolete kconfig fragment for cpu-hotplug
  selftests: vdso_test: support ARM64 targets
  selftests/ftrace: Do not use arch dependent do_IRQ as a target function
  selftests: breakpoints: fix compile error on breakpoint_test_arm64
  selftests: add missing test result status in memory-hotplug test
  selftests/exec: include cwd in long path calculation
  selftests: seccomp: update .gitignore with newly added tests
  selftests: vm: Update .gitignore with newly added tests
  selftests: timers: Update .gitignore with newly added tests

55 files changed:
tools/testing/selftests/Makefile
tools/testing/selftests/android/Makefile [new file with mode: 0644]
tools/testing/selftests/android/ion/.gitignore [new file with mode: 0644]
tools/testing/selftests/android/ion/Makefile [new file with mode: 0644]
tools/testing/selftests/android/ion/README [new file with mode: 0644]
tools/testing/selftests/android/ion/config [new file with mode: 0644]
tools/testing/selftests/android/ion/ion.h [new file with mode: 0644]
tools/testing/selftests/android/ion/ion_test.sh [new file with mode: 0755]
tools/testing/selftests/android/ion/ionapp_export.c [new file with mode: 0644]
tools/testing/selftests/android/ion/ionapp_import.c [new file with mode: 0644]
tools/testing/selftests/android/ion/ionutils.c [new file with mode: 0644]
tools/testing/selftests/android/ion/ionutils.h [new file with mode: 0644]
tools/testing/selftests/android/ion/ipcsocket.c [new file with mode: 0644]
tools/testing/selftests/android/ion/ipcsocket.h [new file with mode: 0644]
tools/testing/selftests/android/run.sh [new file with mode: 0755]
tools/testing/selftests/breakpoints/breakpoint_test_arm64.c
tools/testing/selftests/cpu-hotplug/config
tools/testing/selftests/exec/execveat.c
tools/testing/selftests/firmware/fw_fallback.sh
tools/testing/selftests/firmware/fw_filesystem.sh
tools/testing/selftests/ftrace/config
tools/testing/selftests/ftrace/ftracetest
tools/testing/selftests/ftrace/test.d/00basic/basic4.tc
tools/testing/selftests/ftrace/test.d/event/event-enable.tc
tools/testing/selftests/ftrace/test.d/event/event-pid.tc
tools/testing/selftests/ftrace/test.d/event/subsystem-enable.tc
tools/testing/selftests/ftrace/test.d/event/toplevel-enable.tc
tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter-stack.tc
tools/testing/selftests/ftrace/test.d/ftrace/fgraph-filter.tc
tools/testing/selftests/ftrace/test.d/ftrace/func-filter-pid.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_event_triggers.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_profiler.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_set_ftrace_file.tc
tools/testing/selftests/ftrace/test.d/ftrace/func_traceonoff_triggers.tc
tools/testing/selftests/ftrace/test.d/instances/instance-event.tc
tools/testing/selftests/ftrace/test.d/instances/instance.tc
tools/testing/selftests/ftrace/test.d/kprobe/busy_check.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args.tc
tools/testing/selftests/ftrace/test.d/kprobe/kprobe_args_type.tc
tools/testing/selftests/ftrace/test.d/kprobe/kretprobe_args.tc
tools/testing/selftests/ftrace/test.d/template
tools/testing/selftests/ftrace/test.d/trigger/trigger-eventonoff.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-filter.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-snapshot.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-stacktrace.tc
tools/testing/selftests/ftrace/test.d/trigger/trigger-traceonoff.tc
tools/testing/selftests/memfd/memfd_test.c
tools/testing/selftests/memory-hotplug/Makefile
tools/testing/selftests/seccomp/.gitignore
tools/testing/selftests/timers/.gitignore
tools/testing/selftests/vDSO/vdso_test.c
tools/testing/selftests/vm/.gitignore

index 3c9c0bbe7dbb669786f6700c8418f35edc74b6b6..eaf599dc2137b85c18dbb09b80465528ca07c7b0 100644 (file)
@@ -1,5 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
-TARGETS =  bpf
+TARGETS = android
+TARGETS += bpf
 TARGETS += breakpoints
 TARGETS += capabilities
 TARGETS += cpufreq
diff --git a/tools/testing/selftests/android/Makefile b/tools/testing/selftests/android/Makefile
new file mode 100644 (file)
index 0000000..1a74922
--- /dev/null
@@ -0,0 +1,46 @@
+SUBDIRS := ion
+
+TEST_PROGS := run.sh
+
+.PHONY: all clean
+
+include ../lib.mk
+
+all:
+       @for DIR in $(SUBDIRS); do              \
+               BUILD_TARGET=$(OUTPUT)/$$DIR;   \
+               mkdir $$BUILD_TARGET  -p;       \
+               make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
+               #SUBDIR test prog name should be in the form: SUBDIR_test.sh
+               TEST=$$DIR"_test.sh"; \
+               if [ -e $$DIR/$$TEST ]; then
+                       rsync -a $$DIR/$$TEST $$BUILD_TARGET/;
+               fi
+       done
+
+override define RUN_TESTS
+       @cd $(OUTPUT); ./run.sh
+endef
+
+override define INSTALL_RULE
+       mkdir -p $(INSTALL_PATH)
+       install -t $(INSTALL_PATH) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES)
+
+       @for SUBDIR in $(SUBDIRS); do \
+               BUILD_TARGET=$(OUTPUT)/$$SUBDIR;        \
+               mkdir $$BUILD_TARGET  -p;       \
+               $(MAKE) OUTPUT=$$BUILD_TARGET -C $$SUBDIR INSTALL_PATH=$(INSTALL_PATH)/$$SUBDIR install; \
+       done;
+endef
+
+override define EMIT_TESTS
+       echo "./run.sh"
+endef
+
+override define CLEAN
+       @for DIR in $(SUBDIRS); do              \
+               BUILD_TARGET=$(OUTPUT)/$$DIR;   \
+               mkdir $$BUILD_TARGET  -p;       \
+               make OUTPUT=$$BUILD_TARGET -C $$DIR $@;\
+       done
+endef
diff --git a/tools/testing/selftests/android/ion/.gitignore b/tools/testing/selftests/android/ion/.gitignore
new file mode 100644 (file)
index 0000000..67e6f39
--- /dev/null
@@ -0,0 +1,2 @@
+ionapp_export
+ionapp_import
diff --git a/tools/testing/selftests/android/ion/Makefile b/tools/testing/selftests/android/ion/Makefile
new file mode 100644 (file)
index 0000000..96e0c44
--- /dev/null
@@ -0,0 +1,16 @@
+
+INCLUDEDIR := -I. -I../../../../../drivers/staging/android/uapi/
+CFLAGS := $(CFLAGS) $(INCLUDEDIR) -Wall -O2 -g
+
+TEST_GEN_FILES := ionapp_export ionapp_import
+
+all: $(TEST_GEN_FILES)
+
+$(TEST_GEN_FILES): ipcsocket.c ionutils.c
+
+TEST_PROGS := ion_test.sh
+
+include ../../lib.mk
+
+$(OUTPUT)/ionapp_export: ionapp_export.c ipcsocket.c ionutils.c
+$(OUTPUT)/ionapp_import: ionapp_import.c ipcsocket.c ionutils.c
diff --git a/tools/testing/selftests/android/ion/README b/tools/testing/selftests/android/ion/README
new file mode 100644 (file)
index 0000000..21783e9
--- /dev/null
@@ -0,0 +1,101 @@
+ION BUFFER SHARING UTILITY
+==========================
+File: ion_test.sh : Utility to test ION driver buffer sharing mechanism.
+Author: Pintu Kumar <pintu.ping@gmail.com>
+
+Introduction:
+-------------
+This is a test utility to verify ION buffer sharing in user space
+between 2 independent processes.
+It uses unix domain socket (with SCM_RIGHTS) as IPC to transfer an FD to
+another process to share the same buffer.
+This utility demonstrates how ION buffer sharing can be implemented between
+two user space processes, using various heap types.
+The following heap types are supported by ION driver.
+ION_HEAP_TYPE_SYSTEM (0)
+ION_HEAP_TYPE_SYSTEM_CONTIG (1)
+ION_HEAP_TYPE_CARVEOUT (2)
+ION_HEAP_TYPE_CHUNK (3)
+ION_HEAP_TYPE_DMA (4)
+
+By default only the SYSTEM and SYSTEM_CONTIG heaps are supported.
+Each heap is associated with the respective heap id.
+This utility is designed in the form of client/server program.
+The server part (ionapp_export) is the exporter of the buffer.
+It is responsible for creating an ION client, allocating the buffer based on
+the heap id, writing some data to this buffer and then exporting the FD
+(associated with this buffer) to another process using socket IPC.
+This FD is called as buffer FD (which is different than the ION client FD).
+
+The client part (ionapp_import) is the importer of the buffer.
+It retrives the FD from the socket data and installs into its address space.
+This new FD internally points to the same kernel buffer.
+So first it reads the data that is stored in this buffer and prints it.
+Then it writes the different size of data (it could be different data) to the
+same buffer.
+Finally the buffer FD must be closed by both the exporter and importer.
+Thus the same kernel buffer is shared among two user space processes using
+ION driver and only one time allocation.
+
+Prerequisite:
+-------------
+This utility works only if /dev/ion interface is present.
+The following configs needs to be enabled in kernel to include ion driver.
+CONFIG_ANDROID=y
+CONFIG_STAGING=y
+CONFIG_ION=y
+CONFIG_ION_SYSTEM_HEAP=y
+
+This utility requires to be run as root user.
+
+
+Compile and test:
+-----------------
+This utility is made to be run as part of kselftest framework in kernel.
+To compile and run using kselftest you can simply do the following from the
+kernel top directory.
+linux$ make TARGETS=android kselftest
+Or you can also use:
+linux$ make -C tools/testing/selftests TARGETS=android run_tests
+Using the selftest it can directly execute the ion_test.sh script to test the
+buffer sharing using ion system heap.
+Currently the heap size is hard coded as just 10 bytes inside this script.
+You need to be a root user to run under selftest.
+
+You can also compile and test manually using the following steps:
+ion$ make
+These will generate 2 executable: ionapp_export, ionapp_import
+Now you can run the export and import manually by specifying the heap type
+and the heap size.
+You can also directly execute the shell script to run the test automatically.
+Simply use the following command to run the test.
+ion$ sudo ./ion_test.sh
+
+Test Results:
+-------------
+The utility is verified on Ubuntu-32 bit system with Linux Kernel 4.14.
+Here is the snapshot of the test result using kselftest.
+
+linux# make TARGETS=android kselftest
+heap_type: 0, heap_size: 10
+--------------------------------------
+heap type: 0
+  heap id: 1
+heap name: ion_system_heap
+--------------------------------------
+Fill buffer content:
+0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd
+Sharing fd: 6, Client fd: 5
+<ion_close_buffer_fd>: buffer release successfully....
+Received buffer fd: 4
+Read buffer content:
+0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0x0 0x0 0x0 0x0 0x0 0x0
+0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0 0x0
+Fill buffer content:
+0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd
+0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd 0xfd
+0xfd 0xfd
+<ion_close_buffer_fd>: buffer release successfully....
+ion_test.sh: heap_type: 0 - [PASS]
+
+ion_test.sh: done
diff --git a/tools/testing/selftests/android/ion/config b/tools/testing/selftests/android/ion/config
new file mode 100644 (file)
index 0000000..19db6ca
--- /dev/null
@@ -0,0 +1,4 @@
+CONFIG_ANDROID=y
+CONFIG_STAGING=y
+CONFIG_ION=y
+CONFIG_ION_SYSTEM_HEAP=y
diff --git a/tools/testing/selftests/android/ion/ion.h b/tools/testing/selftests/android/ion/ion.h
new file mode 100644 (file)
index 0000000..f7021ac
--- /dev/null
@@ -0,0 +1,143 @@
+/*
+ * ion.h
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+/* This file is copied from drivers/staging/android/uapi/ion.h
+ * This local copy is required for the selftest to pass, when build
+ * outside the kernel source tree.
+ * Please keep this file in sync with its original file until the
+ * ion driver is moved outside the staging tree.
+ */
+
+#ifndef _UAPI_LINUX_ION_H
+#define _UAPI_LINUX_ION_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+/**
+ * enum ion_heap_types - list of all possible types of heaps
+ * @ION_HEAP_TYPE_SYSTEM:       memory allocated via vmalloc
+ * @ION_HEAP_TYPE_SYSTEM_CONTIG: memory allocated via kmalloc
+ * @ION_HEAP_TYPE_CARVEOUT:     memory allocated from a prereserved
+ *                              carveout heap, allocations are physically
+ *                              contiguous
+ * @ION_HEAP_TYPE_DMA:          memory allocated via DMA API
+ * @ION_NUM_HEAPS:              helper for iterating over heaps, a bit mask
+ *                              is used to identify the heaps, so only 32
+ *                              total heap types are supported
+ */
+enum ion_heap_type {
+       ION_HEAP_TYPE_SYSTEM,
+       ION_HEAP_TYPE_SYSTEM_CONTIG,
+       ION_HEAP_TYPE_CARVEOUT,
+       ION_HEAP_TYPE_CHUNK,
+       ION_HEAP_TYPE_DMA,
+       ION_HEAP_TYPE_CUSTOM, /*
+                              * must be last so device specific heaps always
+                              * are at the end of this enum
+                              */
+};
+
+#define ION_NUM_HEAP_IDS               (sizeof(unsigned int) * 8)
+
+/**
+ * allocation flags - the lower 16 bits are used by core ion, the upper 16
+ * bits are reserved for use by the heaps themselves.
+ */
+
+/*
+ * mappings of this buffer should be cached, ion will do cache maintenance
+ * when the buffer is mapped for dma
+ */
+#define ION_FLAG_CACHED 1
+
+/**
+ * DOC: Ion Userspace API
+ *
+ * create a client by opening /dev/ion
+ * most operations handled via following ioctls
+ *
+ */
+
+/**
+ * struct ion_allocation_data - metadata passed from userspace for allocations
+ * @len:               size of the allocation
+ * @heap_id_mask:      mask of heap ids to allocate from
+ * @flags:             flags passed to heap
+ * @handle:            pointer that will be populated with a cookie to use to
+ *                     refer to this allocation
+ *
+ * Provided by userspace as an argument to the ioctl
+ */
+struct ion_allocation_data {
+       __u64 len;
+       __u32 heap_id_mask;
+       __u32 flags;
+       __u32 fd;
+       __u32 unused;
+};
+
+#define MAX_HEAP_NAME                  32
+
+/**
+ * struct ion_heap_data - data about a heap
+ * @name - first 32 characters of the heap name
+ * @type - heap type
+ * @heap_id - heap id for the heap
+ */
+struct ion_heap_data {
+       char name[MAX_HEAP_NAME];
+       __u32 type;
+       __u32 heap_id;
+       __u32 reserved0;
+       __u32 reserved1;
+       __u32 reserved2;
+};
+
+/**
+ * struct ion_heap_query - collection of data about all heaps
+ * @cnt - total number of heaps to be copied
+ * @heaps - buffer to copy heap data
+ */
+struct ion_heap_query {
+       __u32 cnt; /* Total number of heaps to be copied */
+       __u32 reserved0; /* align to 64bits */
+       __u64 heaps; /* buffer to be populated */
+       __u32 reserved1;
+       __u32 reserved2;
+};
+
+#define ION_IOC_MAGIC          'I'
+
+/**
+ * DOC: ION_IOC_ALLOC - allocate memory
+ *
+ * Takes an ion_allocation_data struct and returns it with the handle field
+ * populated with the opaque handle for the allocation.
+ */
+#define ION_IOC_ALLOC          _IOWR(ION_IOC_MAGIC, 0, \
+                                     struct ion_allocation_data)
+
+/**
+ * DOC: ION_IOC_HEAP_QUERY - information about available heaps
+ *
+ * Takes an ion_heap_query structure and populates information about
+ * available Ion heaps.
+ */
+#define ION_IOC_HEAP_QUERY     _IOWR(ION_IOC_MAGIC, 8, \
+                                       struct ion_heap_query)
+
+#endif /* _UAPI_LINUX_ION_H */
diff --git a/tools/testing/selftests/android/ion/ion_test.sh b/tools/testing/selftests/android/ion/ion_test.sh
new file mode 100755 (executable)
index 0000000..a1aff50
--- /dev/null
@@ -0,0 +1,55 @@
+#!/bin/bash
+
+heapsize=4096
+TCID="ion_test.sh"
+errcode=0
+
+run_test()
+{
+       heaptype=$1
+       ./ionapp_export -i $heaptype -s $heapsize &
+       sleep 1
+       ./ionapp_import
+       if [ $? -ne 0 ]; then
+               echo "$TCID: heap_type: $heaptype - [FAIL]"
+               errcode=1
+       else
+               echo "$TCID: heap_type: $heaptype - [PASS]"
+       fi
+       sleep 1
+       echo ""
+}
+
+check_root()
+{
+       uid=$(id -u)
+       if [ $uid -ne 0 ]; then
+               echo $TCID: must be run as root >&2
+               exit 0
+       fi
+}
+
+check_device()
+{
+       DEVICE=/dev/ion
+       if [ ! -e $DEVICE ]; then
+               echo $TCID: No $DEVICE device found >&2
+               echo $TCID: May be CONFIG_ION is not set >&2
+               exit 0
+       fi
+}
+
+main_function()
+{
+       check_device
+       check_root
+
+       # ION_SYSTEM_HEAP TEST
+       run_test 0
+       # ION_SYSTEM_CONTIG_HEAP TEST
+       run_test 1
+}
+
+main_function
+echo "$TCID: done"
+exit $errcode
diff --git a/tools/testing/selftests/android/ion/ionapp_export.c b/tools/testing/selftests/android/ion/ionapp_export.c
new file mode 100644 (file)
index 0000000..a944e72
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * ionapp_export.c
+ *
+ * It is a user space utility to create and export android
+ * ion memory buffer fd to another process using unix domain socket as IPC.
+ * This acts like a server for ionapp_import(client).
+ * So, this server has to be started first before the client.
+ *
+ * Copyright (C) 2017 Pintu Kumar <pintu.ping@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/time.h>
+#include "ionutils.h"
+#include "ipcsocket.h"
+
+
+void print_usage(int argc, char *argv[])
+{
+       printf("Usage: %s [-h <help>] [-i <heap id>] [-s <size in bytes>]\n",
+               argv[0]);
+}
+
+int main(int argc, char *argv[])
+{
+       int opt, ret, status, heapid;
+       int sockfd, client_fd, shared_fd;
+       unsigned char *map_buf;
+       unsigned long map_len, heap_type, heap_size, flags;
+       struct ion_buffer_info info;
+       struct socket_info skinfo;
+
+       if (argc < 2) {
+               print_usage(argc, argv);
+               return -1;
+       }
+
+       heap_size = 0;
+       flags = 0;
+
+       while ((opt = getopt(argc, argv, "hi:s:")) != -1) {
+               switch (opt) {
+               case 'h':
+                       print_usage(argc, argv);
+                       exit(0);
+                       break;
+               case 'i':
+                       heapid = atoi(optarg);
+                       switch (heapid) {
+                       case 0:
+                               heap_type = ION_HEAP_TYPE_SYSTEM;
+                               break;
+                       case 1:
+                               heap_type = ION_HEAP_TYPE_SYSTEM_CONTIG;
+                               break;
+                       default:
+                               printf("ERROR: heap type not supported\n");
+                               exit(1);
+                       }
+                       break;
+               case 's':
+                       heap_size = atoi(optarg);
+                       break;
+               default:
+                       print_usage(argc, argv);
+                       exit(1);
+                       break;
+               }
+       }
+
+       if (heap_size <= 0) {
+               printf("heap_size cannot be 0\n");
+               print_usage(argc, argv);
+               exit(1);
+       }
+
+       printf("heap_type: %ld, heap_size: %ld\n", heap_type, heap_size);
+       info.heap_type = heap_type;
+       info.heap_size = heap_size;
+       info.flag_type = flags;
+
+       /* This is server: open the socket connection first */
+       /* Here; 1 indicates server or exporter */
+       status = opensocket(&sockfd, SOCKET_NAME, 1);
+       if (status < 0) {
+               fprintf(stderr, "<%s>: Failed opensocket.\n", __func__);
+               goto err_socket;
+       }
+       skinfo.sockfd = sockfd;
+
+       ret = ion_export_buffer_fd(&info);
+       if (ret < 0) {
+               fprintf(stderr, "FAILED: ion_get_buffer_fd\n");
+               goto err_export;
+       }
+       client_fd = info.ionfd;
+       shared_fd = info.buffd;
+       map_buf = info.buffer;
+       map_len = info.buflen;
+       write_buffer(map_buf, map_len);
+
+       /* share ion buf fd with other user process */
+       printf("Sharing fd: %d, Client fd: %d\n", shared_fd, client_fd);
+       skinfo.datafd = shared_fd;
+       skinfo.buflen = map_len;
+
+       ret = socket_send_fd(&skinfo);
+       if (ret < 0) {
+               fprintf(stderr, "FAILED: socket_send_fd\n");
+               goto err_send;
+       }
+
+err_send:
+err_export:
+       ion_close_buffer_fd(&info);
+
+err_socket:
+       closesocket(sockfd, SOCKET_NAME);
+
+       return 0;
+}
diff --git a/tools/testing/selftests/android/ion/ionapp_import.c b/tools/testing/selftests/android/ion/ionapp_import.c
new file mode 100644 (file)
index 0000000..ae2d704
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * ionapp_import.c
+ *
+ * It is a user space utility to receive android ion memory buffer fd
+ * over unix domain socket IPC that can be exported by ionapp_export.
+ * This acts like a client for ionapp_export.
+ *
+ * Copyright (C) 2017 Pintu Kumar <pintu.ping@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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 <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "ionutils.h"
+#include "ipcsocket.h"
+
+
+int main(void)
+{
+       int ret, status;
+       int sockfd, shared_fd;
+       unsigned char *map_buf;
+       unsigned long map_len;
+       struct ion_buffer_info info;
+       struct socket_info skinfo;
+
+       /* This is the client part. Here 0 means client or importer */
+       status = opensocket(&sockfd, SOCKET_NAME, 0);
+       if (status < 0) {
+               fprintf(stderr, "No exporter exists...\n");
+               ret = status;
+               goto err_socket;
+       }
+
+       skinfo.sockfd = sockfd;
+
+       ret = socket_receive_fd(&skinfo);
+       if (ret < 0) {
+               fprintf(stderr, "Failed: socket_receive_fd\n");
+               goto err_recv;
+       }
+
+       shared_fd = skinfo.datafd;
+       printf("Received buffer fd: %d\n", shared_fd);
+       if (shared_fd <= 0) {
+               fprintf(stderr, "ERROR: improper buf fd\n");
+               ret = -1;
+               goto err_fd;
+       }
+
+       memset(&info, 0, sizeof(info));
+       info.buffd = shared_fd;
+       info.buflen = ION_BUFFER_LEN;
+
+       ret = ion_import_buffer_fd(&info);
+       if (ret < 0) {
+               fprintf(stderr, "Failed: ion_use_buffer_fd\n");
+               goto err_import;
+       }
+
+       map_buf = info.buffer;
+       map_len = info.buflen;
+       read_buffer(map_buf, map_len);
+
+       /* Write probably new data to the same buffer again */
+       map_len = ION_BUFFER_LEN;
+       write_buffer(map_buf, map_len);
+
+err_import:
+       ion_close_buffer_fd(&info);
+err_fd:
+err_recv:
+err_socket:
+       closesocket(sockfd, SOCKET_NAME);
+
+       return ret;
+}
diff --git a/tools/testing/selftests/android/ion/ionutils.c b/tools/testing/selftests/android/ion/ionutils.c
new file mode 100644 (file)
index 0000000..ce69c14
--- /dev/null
@@ -0,0 +1,259 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+//#include <stdint.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include "ionutils.h"
+#include "ipcsocket.h"
+
+
+void write_buffer(void *buffer, unsigned long len)
+{
+       int i;
+       unsigned char *ptr = (unsigned char *)buffer;
+
+       if (!ptr) {
+               fprintf(stderr, "<%s>: Invalid buffer...\n", __func__);
+               return;
+       }
+
+       printf("Fill buffer content:\n");
+       memset(ptr, 0xfd, len);
+       for (i = 0; i < len; i++)
+               printf("0x%x ", ptr[i]);
+       printf("\n");
+}
+
+void read_buffer(void *buffer, unsigned long len)
+{
+       int i;
+       unsigned char *ptr = (unsigned char *)buffer;
+
+       if (!ptr) {
+               fprintf(stderr, "<%s>: Invalid buffer...\n", __func__);
+               return;
+       }
+
+       printf("Read buffer content:\n");
+       for (i = 0; i < len; i++)
+               printf("0x%x ", ptr[i]);
+       printf("\n");
+}
+
+int ion_export_buffer_fd(struct ion_buffer_info *ion_info)
+{
+       int i, ret, ionfd, buffer_fd;
+       unsigned int heap_id;
+       unsigned long maplen;
+       unsigned char *map_buffer;
+       struct ion_allocation_data alloc_data;
+       struct ion_heap_query query;
+       struct ion_heap_data heap_data[MAX_HEAP_COUNT];
+
+       if (!ion_info) {
+               fprintf(stderr, "<%s>: Invalid ion info\n", __func__);
+               return -1;
+       }
+
+       /* Create an ION client */
+       ionfd = open(ION_DEVICE, O_RDWR);
+       if (ionfd < 0) {
+               fprintf(stderr, "<%s>: Failed to open ion client: %s\n",
+                       __func__, strerror(errno));
+               return -1;
+       }
+
+       memset(&query, 0, sizeof(query));
+       query.cnt = MAX_HEAP_COUNT;
+       query.heaps = (unsigned long int)&heap_data[0];
+       /* Query ION heap_id_mask from ION heap */
+       ret = ioctl(ionfd, ION_IOC_HEAP_QUERY, &query);
+       if (ret < 0) {
+               fprintf(stderr, "<%s>: Failed: ION_IOC_HEAP_QUERY: %s\n",
+                       __func__, strerror(errno));
+               goto err_query;
+       }
+
+       heap_id = MAX_HEAP_COUNT + 1;
+       for (i = 0; i < query.cnt; i++) {
+               if (heap_data[i].type == ion_info->heap_type) {
+                       printf("--------------------------------------\n");
+                       printf("heap type: %d\n", heap_data[i].type);
+                       printf("  heap id: %d\n", heap_data[i].heap_id);
+                       printf("heap name: %s\n", heap_data[i].name);
+                       printf("--------------------------------------\n");
+                       heap_id = heap_data[i].heap_id;
+                       break;
+               }
+       }
+
+       if (heap_id > MAX_HEAP_COUNT) {
+               fprintf(stderr, "<%s>: ERROR: heap type does not exists\n",
+                       __func__);
+               goto err_heap;
+       }
+
+       alloc_data.len = ion_info->heap_size;
+       alloc_data.heap_id_mask = 1 << heap_id;
+       alloc_data.flags = ion_info->flag_type;
+
+       /* Allocate memory for this ION client as per heap_type */
+       ret = ioctl(ionfd, ION_IOC_ALLOC, &alloc_data);
+       if (ret < 0) {
+               fprintf(stderr, "<%s>: Failed: ION_IOC_ALLOC: %s\n",
+                       __func__, strerror(errno));
+               goto err_alloc;
+       }
+
+       /* This will return a valid buffer fd */
+       buffer_fd = alloc_data.fd;
+       maplen = alloc_data.len;
+
+       if (buffer_fd < 0 || maplen <= 0) {
+               fprintf(stderr, "<%s>: Invalid map data, fd: %d, len: %ld\n",
+                       __func__, buffer_fd, maplen);
+               goto err_fd_data;
+       }
+
+       /* Create memory mapped buffer for the buffer fd */
+       map_buffer = (unsigned char *)mmap(NULL, maplen, PROT_READ|PROT_WRITE,
+                       MAP_SHARED, buffer_fd, 0);
+       if (map_buffer == MAP_FAILED) {
+               fprintf(stderr, "<%s>: Failed: mmap: %s\n",
+                       __func__, strerror(errno));
+               goto err_mmap;
+       }
+
+       ion_info->ionfd = ionfd;
+       ion_info->buffd = buffer_fd;
+       ion_info->buffer = map_buffer;
+       ion_info->buflen = maplen;
+
+       return 0;
+
+       munmap(map_buffer, maplen);
+
+err_fd_data:
+err_mmap:
+       /* in case of error: close the buffer fd */
+       if (buffer_fd)
+               close(buffer_fd);
+
+err_query:
+err_heap:
+err_alloc:
+       /* In case of error: close the ion client fd */
+       if (ionfd)
+               close(ionfd);
+
+       return -1;
+}
+
+int ion_import_buffer_fd(struct ion_buffer_info *ion_info)
+{
+       int buffd;
+       unsigned char *map_buf;
+       unsigned long map_len;
+
+       if (!ion_info) {
+               fprintf(stderr, "<%s>: Invalid ion info\n", __func__);
+               return -1;
+       }
+
+       map_len = ion_info->buflen;
+       buffd = ion_info->buffd;
+
+       if (buffd < 0 || map_len <= 0) {
+               fprintf(stderr, "<%s>: Invalid map data, fd: %d, len: %ld\n",
+                       __func__, buffd, map_len);
+               goto err_buffd;
+       }
+
+       map_buf = (unsigned char *)mmap(NULL, map_len, PROT_READ|PROT_WRITE,
+                       MAP_SHARED, buffd, 0);
+       if (map_buf == MAP_FAILED) {
+               printf("<%s>: Failed - mmap: %s\n",
+                       __func__, strerror(errno));
+               goto err_mmap;
+       }
+
+       ion_info->buffer = map_buf;
+       ion_info->buflen = map_len;
+
+       return 0;
+
+err_mmap:
+       if (buffd)
+               close(buffd);
+
+err_buffd:
+       return -1;
+}
+
+void ion_close_buffer_fd(struct ion_buffer_info *ion_info)
+{
+       if (ion_info) {
+               /* unmap the buffer properly in the end */
+               munmap(ion_info->buffer, ion_info->buflen);
+               /* close the buffer fd */
+               if (ion_info->buffd > 0)
+                       close(ion_info->buffd);
+               /* Finally, close the client fd */
+               if (ion_info->ionfd > 0)
+                       close(ion_info->ionfd);
+               printf("<%s>: buffer release successfully....\n", __func__);
+       }
+}
+
+int socket_send_fd(struct socket_info *info)
+{
+       int status;
+       int fd, sockfd;
+       struct socketdata skdata;
+
+       if (!info) {
+               fprintf(stderr, "<%s>: Invalid socket info\n", __func__);
+               return -1;
+       }
+
+       sockfd = info->sockfd;
+       fd = info->datafd;
+       memset(&skdata, 0, sizeof(skdata));
+       skdata.data = fd;
+       skdata.len = sizeof(skdata.data);
+       status = sendtosocket(sockfd, &skdata);
+       if (status < 0) {
+               fprintf(stderr, "<%s>: Failed: sendtosocket\n", __func__);
+               return -1;
+       }
+
+       return 0;
+}
+
+int socket_receive_fd(struct socket_info *info)
+{
+       int status;
+       int fd, sockfd;
+       struct socketdata skdata;
+
+       if (!info) {
+               fprintf(stderr, "<%s>: Invalid socket info\n", __func__);
+               return -1;
+       }
+
+       sockfd = info->sockfd;
+       memset(&skdata, 0, sizeof(skdata));
+       status = receivefromsocket(sockfd, &skdata);
+       if (status < 0) {
+               fprintf(stderr, "<%s>: Failed: receivefromsocket\n", __func__);
+               return -1;
+       }
+
+       fd = (int)skdata.data;
+       info->datafd = fd;
+
+       return status;
+}
diff --git a/tools/testing/selftests/android/ion/ionutils.h b/tools/testing/selftests/android/ion/ionutils.h
new file mode 100644 (file)
index 0000000..9941eb8
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef __ION_UTILS_H
+#define __ION_UTILS_H
+
+#include "ion.h"
+
+#define SOCKET_NAME "ion_socket"
+#define ION_DEVICE "/dev/ion"
+
+#define ION_BUFFER_LEN 4096
+#define MAX_HEAP_COUNT ION_HEAP_TYPE_CUSTOM
+
+struct socket_info {
+       int sockfd;
+       int datafd;
+       unsigned long buflen;
+};
+
+struct ion_buffer_info {
+       int ionfd;
+       int buffd;
+       unsigned int heap_type;
+       unsigned int flag_type;
+       unsigned long heap_size;
+       unsigned long buflen;
+       unsigned char *buffer;
+};
+
+
+/* This is used to fill the data into the mapped buffer */
+void write_buffer(void *buffer, unsigned long len);
+
+/* This is used to read the data from the exported buffer */
+void read_buffer(void *buffer, unsigned long len);
+
+/* This is used to create an ION buffer FD for the kernel buffer
+ * So you can export this same buffer to others in the form of FD
+ */
+int ion_export_buffer_fd(struct ion_buffer_info *ion_info);
+
+/* This is used to import or map an exported FD.
+ * So we point to same buffer without making a copy. Hence zero-copy.
+ */
+int ion_import_buffer_fd(struct ion_buffer_info *ion_info);
+
+/* This is used to close all references for the ION client */
+void ion_close_buffer_fd(struct ion_buffer_info *ion_info);
+
+/* This is used to send FD to another process using socket IPC */
+int socket_send_fd(struct socket_info *skinfo);
+
+/* This is used to receive FD from another process using socket IPC */
+int socket_receive_fd(struct socket_info *skinfo);
+
+
+#endif
diff --git a/tools/testing/selftests/android/ion/ipcsocket.c b/tools/testing/selftests/android/ion/ipcsocket.c
new file mode 100644 (file)
index 0000000..7dc5210
--- /dev/null
@@ -0,0 +1,227 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/un.h>
+#include <errno.h>
+
+#include "ipcsocket.h"
+
+
+int opensocket(int *sockfd, const char *name, int connecttype)
+{
+       int ret, temp = 1;
+
+       if (!name || strlen(name) > MAX_SOCK_NAME_LEN) {
+               fprintf(stderr, "<%s>: Invalid socket name.\n", __func__);
+               return -1;
+       }
+
+       ret = socket(PF_LOCAL, SOCK_STREAM, 0);
+       if (ret < 0) {
+               fprintf(stderr, "<%s>: Failed socket: <%s>\n",
+                       __func__, strerror(errno));
+               return ret;
+       }
+
+       *sockfd = ret;
+       if (setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR,
+               (char *)&temp, sizeof(int)) < 0) {
+               fprintf(stderr, "<%s>: Failed setsockopt: <%s>\n",
+               __func__, strerror(errno));
+               goto err;
+       }
+
+       sprintf(sock_name, "/tmp/%s", name);
+
+       if (connecttype == 1) {
+               /* This is for Server connection */
+               struct sockaddr_un skaddr;
+               int clientfd;
+               socklen_t sklen;
+
+               unlink(sock_name);
+               memset(&skaddr, 0, sizeof(skaddr));
+               skaddr.sun_family = AF_LOCAL;
+               strcpy(skaddr.sun_path, sock_name);
+
+               ret = bind(*sockfd, (struct sockaddr *)&skaddr,
+                       SUN_LEN(&skaddr));
+               if (ret < 0) {
+                       fprintf(stderr, "<%s>: Failed bind: <%s>\n",
+                       __func__, strerror(errno));
+                       goto err;
+               }
+
+               ret = listen(*sockfd, 5);
+               if (ret < 0) {
+                       fprintf(stderr, "<%s>: Failed listen: <%s>\n",
+                       __func__, strerror(errno));
+                       goto err;
+               }
+
+               memset(&skaddr, 0, sizeof(skaddr));
+               sklen = sizeof(skaddr);
+
+               ret = accept(*sockfd, (struct sockaddr *)&skaddr,
+                       (socklen_t *)&sklen);
+               if (ret < 0) {
+                       fprintf(stderr, "<%s>: Failed accept: <%s>\n",
+                       __func__, strerror(errno));
+                       goto err;
+               }
+
+               clientfd = ret;
+               *sockfd = clientfd;
+       } else {
+               /* This is for client connection */
+               struct sockaddr_un skaddr;
+
+               memset(&skaddr, 0, sizeof(skaddr));
+               skaddr.sun_family = AF_LOCAL;
+               strcpy(skaddr.sun_path, sock_name);
+
+               ret = connect(*sockfd, (struct sockaddr *)&skaddr,
+                       SUN_LEN(&skaddr));
+               if (ret < 0) {
+                       fprintf(stderr, "<%s>: Failed connect: <%s>\n",
+                       __func__, strerror(errno));
+                       goto err;
+               }
+       }
+
+       return 0;
+
+err:
+       if (*sockfd)
+               close(*sockfd);
+
+       return ret;
+}
+
+int sendtosocket(int sockfd, struct socketdata *skdata)
+{
+       int ret, buffd;
+       unsigned int len;
+       char cmsg_b[CMSG_SPACE(sizeof(int))];
+       struct cmsghdr *cmsg;
+       struct msghdr msgh;
+       struct iovec iov;
+       struct timeval timeout;
+       fd_set selFDs;
+
+       if (!skdata) {
+               fprintf(stderr, "<%s>: socketdata is NULL\n", __func__);
+               return -1;
+       }
+
+       FD_ZERO(&selFDs);
+       FD_SET(0, &selFDs);
+       FD_SET(sockfd, &selFDs);
+       timeout.tv_sec = 20;
+       timeout.tv_usec = 0;
+
+       ret = select(sockfd+1, NULL, &selFDs, NULL, &timeout);
+       if (ret < 0) {
+               fprintf(stderr, "<%s>: Failed select: <%s>\n",
+               __func__, strerror(errno));
+               return -1;
+       }
+
+       if (FD_ISSET(sockfd, &selFDs)) {
+               buffd = skdata->data;
+               len = skdata->len;
+               memset(&msgh, 0, sizeof(msgh));
+               msgh.msg_control = &cmsg_b;
+               msgh.msg_controllen = CMSG_LEN(len);
+               iov.iov_base = "OK";
+               iov.iov_len = 2;
+               msgh.msg_iov = &iov;
+               msgh.msg_iovlen = 1;
+               cmsg = CMSG_FIRSTHDR(&msgh);
+               cmsg->cmsg_level = SOL_SOCKET;
+               cmsg->cmsg_type = SCM_RIGHTS;
+               cmsg->cmsg_len = CMSG_LEN(len);
+               memcpy(CMSG_DATA(cmsg), &buffd, len);
+
+               ret = sendmsg(sockfd, &msgh, MSG_DONTWAIT);
+               if (ret < 0) {
+                       fprintf(stderr, "<%s>: Failed sendmsg: <%s>\n",
+                       __func__, strerror(errno));
+                       return -1;
+               }
+       }
+
+       return 0;
+}
+
+int receivefromsocket(int sockfd, struct socketdata *skdata)
+{
+       int ret, buffd;
+       unsigned int len = 0;
+       char cmsg_b[CMSG_SPACE(sizeof(int))];
+       struct cmsghdr *cmsg;
+       struct msghdr msgh;
+       struct iovec iov;
+       fd_set recvFDs;
+       char data[32];
+
+       if (!skdata) {
+               fprintf(stderr, "<%s>: socketdata is NULL\n", __func__);
+               return -1;
+       }
+
+       FD_ZERO(&recvFDs);
+       FD_SET(0, &recvFDs);
+       FD_SET(sockfd, &recvFDs);
+
+       ret = select(sockfd+1, &recvFDs, NULL, NULL, NULL);
+       if (ret < 0) {
+               fprintf(stderr, "<%s>: Failed select: <%s>\n",
+               __func__, strerror(errno));
+               return -1;
+       }
+
+       if (FD_ISSET(sockfd, &recvFDs)) {
+               len = sizeof(buffd);
+               memset(&msgh, 0, sizeof(msgh));
+               msgh.msg_control = &cmsg_b;
+               msgh.msg_controllen = CMSG_LEN(len);
+               iov.iov_base = data;
+               iov.iov_len = sizeof(data)-1;
+               msgh.msg_iov = &iov;
+               msgh.msg_iovlen = 1;
+               cmsg = CMSG_FIRSTHDR(&msgh);
+               cmsg->cmsg_level = SOL_SOCKET;
+               cmsg->cmsg_type = SCM_RIGHTS;
+               cmsg->cmsg_len = CMSG_LEN(len);
+
+               ret = recvmsg(sockfd, &msgh, MSG_DONTWAIT);
+               if (ret < 0) {
+                       fprintf(stderr, "<%s>: Failed recvmsg: <%s>\n",
+                       __func__, strerror(errno));
+                       return -1;
+               }
+
+               memcpy(&buffd, CMSG_DATA(cmsg), len);
+               skdata->data = buffd;
+               skdata->len = len;
+       }
+       return 0;
+}
+
+int closesocket(int sockfd, char *name)
+{
+       char sockname[MAX_SOCK_NAME_LEN];
+
+       if (sockfd)
+               close(sockfd);
+       sprintf(sockname, "/tmp/%s", name);
+       unlink(sockname);
+       shutdown(sockfd, 2);
+
+       return 0;
+}
diff --git a/tools/testing/selftests/android/ion/ipcsocket.h b/tools/testing/selftests/android/ion/ipcsocket.h
new file mode 100644 (file)
index 0000000..b3e8449
--- /dev/null
@@ -0,0 +1,35 @@
+
+#ifndef _IPCSOCKET_H
+#define _IPCSOCKET_H
+
+
+#define MAX_SOCK_NAME_LEN      64
+
+char sock_name[MAX_SOCK_NAME_LEN];
+
+/* This structure is responsible for holding the IPC data
+ * data: hold the buffer fd
+ * len: just the length of 32-bit integer fd
+ */
+struct socketdata {
+       int data;
+       unsigned int len;
+};
+
+/* This API is used to open the IPC socket connection
+ * name: implies a unique socket name in the system
+ * connecttype: implies server(0) or client(1)
+ */
+int opensocket(int *sockfd, const char *name, int connecttype);
+
+/* This is the API to send socket data over IPC socket */
+int sendtosocket(int sockfd, struct socketdata *data);
+
+/* This is the API to receive socket data over IPC socket */
+int receivefromsocket(int sockfd, struct socketdata *data);
+
+/* This is the API to close the socket connection */
+int closesocket(int sockfd, char *name);
+
+
+#endif
diff --git a/tools/testing/selftests/android/run.sh b/tools/testing/selftests/android/run.sh
new file mode 100755 (executable)
index 0000000..dd8edf2
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+(cd ion; ./ion_test.sh)
index 960d02100c26ebbf6214cde9965ba787817fd2c2..2d95e5adde726fb388b26de8e0db87343110d036 100644 (file)
@@ -19,6 +19,7 @@
 
 #define _GNU_SOURCE
 
+#include <asm/ptrace.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <sys/ptrace.h>
index e6ab090cfbf3a708eb202927df02e8e3057407c7..d4aca2ad5069bf5db35f7f32b9643cce34b88e43 100644 (file)
@@ -1,2 +1 @@
 CONFIG_NOTIFIER_ERROR_INJECTION=y
-CONFIG_CPU_NOTIFIER_ERROR_INJECT=m
index 8d5d1d2ee7c1d793405685e8266045363bcce960..67cd4597db2b78e7fb29b9121c8014afbce4b648 100644 (file)
@@ -147,7 +147,7 @@ static void exe_cp(const char *src, const char *dest)
 }
 
 #define XX_DIR_LEN 200
-static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script)
+static int check_execveat_pathmax(int root_dfd, const char *src, int is_script)
 {
        int fail = 0;
        int ii, count, len;
@@ -156,20 +156,30 @@ static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script)
 
        if (*longpath == '\0') {
                /* Create a filename close to PATH_MAX in length */
+               char *cwd = getcwd(NULL, 0);
+
+               if (!cwd) {
+                       printf("Failed to getcwd(), errno=%d (%s)\n",
+                              errno, strerror(errno));
+                       return 2;
+               }
+               strcpy(longpath, cwd);
+               strcat(longpath, "/");
                memset(longname, 'x', XX_DIR_LEN - 1);
                longname[XX_DIR_LEN - 1] = '/';
                longname[XX_DIR_LEN] = '\0';
-               count = (PATH_MAX - 3) / XX_DIR_LEN;
+               count = (PATH_MAX - 3 - strlen(cwd)) / XX_DIR_LEN;
                for (ii = 0; ii < count; ii++) {
                        strcat(longpath, longname);
                        mkdir(longpath, 0755);
                }
-               len = (PATH_MAX - 3) - (count * XX_DIR_LEN);
+               len = (PATH_MAX - 3 - strlen(cwd)) - (count * XX_DIR_LEN);
                if (len <= 0)
                        len = 1;
                memset(longname, 'y', len);
                longname[len] = '\0';
                strcat(longpath, longname);
+               free(cwd);
        }
        exe_cp(src, longpath);
 
@@ -190,7 +200,7 @@ static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script)
        }
 
        /*
-        * Execute as a long pathname relative to ".".  If this is a script,
+        * Execute as a long pathname relative to "/".  If this is a script,
         * the interpreter will launch but fail to open the script because its
         * name ("/dev/fd/5/xxx....") is bigger than PATH_MAX.
         *
@@ -200,10 +210,10 @@ static int check_execveat_pathmax(int dot_dfd, const char *src, int is_script)
         * the exit status shall be 126."), so allow either.
         */
        if (is_script)
-               fail += check_execveat_invoked_rc(dot_dfd, longpath, 0,
+               fail += check_execveat_invoked_rc(root_dfd, longpath + 1, 0,
                                                  127, 126);
        else
-               fail += check_execveat(dot_dfd, longpath, 0);
+               fail += check_execveat(root_dfd, longpath + 1, 0);
 
        return fail;
 }
@@ -218,6 +228,7 @@ static int run_tests(void)
        int subdir_dfd_ephemeral = open_or_die("subdir.ephemeral",
                                               O_DIRECTORY|O_RDONLY);
        int dot_dfd = open_or_die(".", O_DIRECTORY|O_RDONLY);
+       int root_dfd = open_or_die("/", O_DIRECTORY|O_RDONLY);
        int dot_dfd_path = open_or_die(".", O_DIRECTORY|O_RDONLY|O_PATH);
        int dot_dfd_cloexec = open_or_die(".", O_DIRECTORY|O_RDONLY|O_CLOEXEC);
        int fd = open_or_die("execveat", O_RDONLY);
@@ -353,8 +364,8 @@ static int run_tests(void)
        /* Attempt to execute relative to non-directory => ENOTDIR */
        fail += check_execveat_fail(fd, "execveat", 0, ENOTDIR);
 
-       fail += check_execveat_pathmax(dot_dfd, "execveat", 0);
-       fail += check_execveat_pathmax(dot_dfd, "script", 1);
+       fail += check_execveat_pathmax(root_dfd, "execveat", 0);
+       fail += check_execveat_pathmax(root_dfd, "script", 1);
        return fail;
 }
 
index a52a3bab532b95c277f2954209e4493061a41e4e..34a42c68ebfb81235738c0d5afc9723ebd068f21 100755 (executable)
@@ -86,6 +86,11 @@ load_fw_cancel()
 
 load_fw_custom()
 {
+       if [ ! -e "$DIR"/trigger_custom_fallback ]; then
+               echo "$0: custom fallback trigger not present, ignoring test" >&2
+               return 1
+       fi
+
        local name="$1"
        local file="$2"
 
@@ -108,11 +113,17 @@ load_fw_custom()
 
        # Wait for request to finish.
        wait
+       return 0
 }
 
 
 load_fw_custom_cancel()
 {
+       if [ ! -e "$DIR"/trigger_custom_fallback ]; then
+               echo "$0: canceling custom fallback trigger not present, ignoring test" >&2
+               return 1
+       fi
+
        local name="$1"
        local file="$2"
 
@@ -133,6 +144,7 @@ load_fw_custom_cancel()
 
        # Wait for request to finish.
        wait
+       return 0
 }
 
 load_fw_fallback_with_child()
@@ -227,20 +239,22 @@ else
        echo "$0: cancelling fallback mechanism works"
 fi
 
-load_fw_custom "$NAME" "$FW"
-if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
-       echo "$0: firmware was not loaded" >&2
-       exit 1
-else
-       echo "$0: custom fallback loading mechanism works"
+if load_fw_custom "$NAME" "$FW" ; then
+       if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
+               echo "$0: firmware was not loaded" >&2
+               exit 1
+       else
+               echo "$0: custom fallback loading mechanism works"
+       fi
 fi
 
-load_fw_custom_cancel "nope-$NAME" "$FW"
-if diff -q "$FW" /dev/test_firmware >/dev/null ; then
-       echo "$0: firmware was expected to be cancelled" >&2
-       exit 1
-else
-       echo "$0: cancelling custom fallback mechanism works"
+if load_fw_custom_cancel "nope-$NAME" "$FW" ; then
+       if diff -q "$FW" /dev/test_firmware >/dev/null ; then
+               echo "$0: firmware was expected to be cancelled" >&2
+               exit 1
+       else
+               echo "$0: cancelling custom fallback mechanism works"
+       fi
 fi
 
 set +e
index 62f2d6f54929a4260a767e06d0b08161c55b7437..b1f20fef36c77444d3de0730dfb73c223060ac56 100755 (executable)
@@ -70,9 +70,13 @@ if printf '\000' >"$DIR"/trigger_request 2> /dev/null; then
        exit 1
 fi
 
-if printf '\000' >"$DIR"/trigger_async_request 2> /dev/null; then
-       echo "$0: empty filename should not succeed (async)" >&2
-       exit 1
+if [ ! -e "$DIR"/trigger_async_request ]; then
+       echo "$0: empty filename: async trigger not present, ignoring test" >&2
+else
+       if printf '\000' >"$DIR"/trigger_async_request 2> /dev/null; then
+               echo "$0: empty filename should not succeed (async)" >&2
+               exit 1
+       fi
 fi
 
 # Request a firmware that doesn't exist, it should fail.
@@ -105,17 +109,21 @@ else
 fi
 
 # Try the asynchronous version too
-if ! echo -n "$NAME" >"$DIR"/trigger_async_request ; then
-       echo "$0: could not trigger async request" >&2
-       exit 1
-fi
-
-# Verify the contents are what we expect.
-if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
-       echo "$0: firmware was not loaded (async)" >&2
-       exit 1
+if [ ! -e "$DIR"/trigger_async_request ]; then
+       echo "$0: firmware loading: async trigger not present, ignoring test" >&2
 else
-       echo "$0: async filesystem loading works"
+       if ! echo -n "$NAME" >"$DIR"/trigger_async_request ; then
+               echo "$0: could not trigger async request" >&2
+               exit 1
+       fi
+
+       # Verify the contents are what we expect.
+       if ! diff -q "$FW" /dev/test_firmware >/dev/null ; then
+               echo "$0: firmware was not loaded (async)" >&2
+               exit 1
+       else
+               echo "$0: async filesystem loading works"
+       fi
 fi
 
 ### Batched requests tests
index 8a1c9f949fe082889aa4057ed1886c16249ef2b9..b01924c71c097c1aeb2c48c8497033266896e876 100644 (file)
@@ -1,2 +1,6 @@
 CONFIG_KPROBES=y
 CONFIG_FTRACE=y
+CONFIG_FUNCTION_PROFILER=y
+CONFIG_TRACER_SNAPSHOT=y
+CONFIG_STACK_TRACER=y
+CONFIG_HIST_TRIGGERS=y
index abc706cf7702629e8b8ce1f12d352cd362e797cf..f9a9d424c980cc932f527904b5425786cde567dc 100755 (executable)
@@ -222,7 +222,14 @@ SIG_RESULT=
 SIG_BASE=36    # Use realtime signals
 SIG_PID=$$
 
+exit_pass () {
+  exit 0
+}
+
 SIG_FAIL=$((SIG_BASE + FAIL))
+exit_fail () {
+  exit 1
+}
 trap 'SIG_RESULT=$FAIL' $SIG_FAIL
 
 SIG_UNRESOLVED=$((SIG_BASE + UNRESOLVED))
index aa51f6c17359e18de0823f125ed7239b5f29c841..0696098d6408ae13eed6e84b0160868e6b3adfde 100644 (file)
@@ -2,4 +2,4 @@
 # description: Basic event tracing check
 test -f available_events -a -f set_event -a -d events
 # check scheduler events are available
-grep -q sched available_events && exit 0 || exit $FAIL
+grep -q sched available_events && exit_pass || exit_fail
index 6ff851a7588461581ea6040987f056d2233b43b9..9daf034186f59a7215a0060af14634112ba42bfd 100644 (file)
@@ -11,7 +11,7 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 yield() {
index cc14feec6e1f2dd96a2f0aabf6ad02d45e00e069..132478b305c23ea11d042d2f2240e21d1b4eeda6 100644 (file)
@@ -13,7 +13,7 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 yield() {
index 85094904aa79b3aa2d2e720ba4bc1a6ba763a5aa..6a37a8642ee6ef7bee7326cabb7bc56c8dc77d2c 100644 (file)
@@ -11,7 +11,7 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 yield() {
index cc1cf4d30ef5d3729822a8d068c8df2e5d52e49c..4e9b6e2c02198bc82e7f2c4ddb5ddffd99408359 100644 (file)
@@ -10,7 +10,7 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 yield() {
index 45df747887e07254dd5d1e7b056b7202ccc69530..1aec99d108eb9c8dfe85d192b1673ec501177fa8 100644 (file)
@@ -28,7 +28,7 @@ do_reset() {
 fail() { # msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 disable_tracing
index 0387e22e757757894fe1a553bb6bd0a41e538a67..9f8d27ca39cf5b8807005c43b28a3bc70fde251c 100644 (file)
@@ -18,7 +18,7 @@ do_reset() {
 fail() { # msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 disable_tracing
index 78524fcc25aee94ec2414fbc53a668d7ab09fdcf..524ce24b3c22010c1908f4dbb50a8035f3087520 100644 (file)
@@ -51,7 +51,7 @@ do_reset() {
 fail() { # msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 yield() {
index 9d4afcca1e36aae049308e9faf7fcab6c05876e0..6fed4cf2db81d420e43c8c7d8b159a8e3fd3ea17 100644 (file)
@@ -27,7 +27,7 @@ do_reset() {
 fail() { # mesg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 SLEEP_TIME=".1"
@@ -48,8 +48,7 @@ test_event_enabled() {
 
     e=`cat $EVENT_ENABLE`
     if [ "$e" != $val ]; then
-       echo "Expected $val but found $e"
-       exit 1
+       fail "Expected $val but found $e"
     fi
 }
 
index fe0dc5a7ea2685d7288c15e224cd5d2e3c85d2c8..b2d5a8febfe86d1be803d0f32ea2d3b1adecaf89 100644 (file)
@@ -32,7 +32,7 @@ fail() { # mesg
     reset_tracer
     echo > set_ftrace_filter
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 echo "Testing function tracer with profiler:"
index 5ad723724adb9c72d5a94dfc373eb095e5e76943..0f3f92622e3352de7bcf7d18d7100e962e47b13b 100644 (file)
@@ -26,14 +26,14 @@ do_reset() {
 fail() { # mesg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 do_reset
 
 FILTER=set_ftrace_filter
 FUNC1="schedule"
-FUNC2="do_IRQ"
+FUNC2="do_softirq"
 
 ALL_FUNCS="#### all functions enabled ####"
 
index cdc92a371cd73f78d22c964c2afac13201108597..f6d9ac73268aece207c476a1995997e4c3895950 100644 (file)
@@ -27,7 +27,7 @@ do_reset() {
 fail() { # mesg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 SLEEP_TIME=".1"
index d7f48b55df51cb1c4e1f13f1d67b6af9272dcc96..4fa0f79144f4abbf96ea294443a4c726d6296ee1 100644 (file)
@@ -11,7 +11,7 @@ fail() { # mesg
     rmdir foo 2>/dev/null
     echo $1
     set -e
-    exit $FAIL
+    exit_fail
 }
 
 cd instances
index ddda622033664a50af8556df1d50c863f07f5866..b84651283bf3412e36e86b25ac578edbee2d8a08 100644 (file)
@@ -11,7 +11,7 @@ fail() { # mesg
     rmdir x y z 2>/dev/null
     echo $1
     set -e
-    exit $FAIL
+    exit_fail
 }
 
 cd instances
index 0e6f415c6152af1aa97f0a1e8413113c952a7c8d..bbc443a9190c9d2fa29512980850279dcdce2f4c 100644 (file)
@@ -9,7 +9,7 @@ echo > kprobe_events
 echo p:myevent _do_fork > kprobe_events
 test -d events/kprobes/myevent
 echo 1 > events/kprobes/myevent/enable
-echo > kprobe_events && exit 1 # this must fail
+echo > kprobe_events && exit_fail # this must fail
 echo 0 > events/kprobes/myevent/enable
 echo > kprobe_events # this must succeed
 clear_trace
index 679bbd23bcc3fe833f1359b7c8b5827efc4ae89d..8b43c6804fc33e384e65a7bb93df2ea2263d0790 100644 (file)
@@ -14,5 +14,5 @@ echo 1 > events/kprobes/testprobe/enable
 echo 0 > events/kprobes/testprobe/enable
 echo "-:testprobe" >> kprobe_events
 clear_trace
-test -d events/kprobes/testprobe && exit 1 || exit 0
+test -d events/kprobes/testprobe && exit_fail || exit_pass
 
index 17d33ba192f64ad1784802569af54fba5490baa4..2a1755bfc2900ef7f709a5b8e3434418d4f22d2c 100644 (file)
@@ -35,4 +35,4 @@ check_types $ARGS
 
 echo "-:testprobe" >> kprobe_events
 clear_trace
-test -d events/kprobes/testprobe && exit 1 || exit 0
+test -d events/kprobes/testprobe && exit_fail || exit_pass
index f1825bdbe3f30776e24415f1992ee203666350b1..321954683aaa9ed166406ccde15e69eed126d266 100644 (file)
@@ -14,4 +14,4 @@ echo 1 > events/kprobes/testprobe2/enable
 echo 0 > events/kprobes/testprobe2/enable
 echo '-:testprobe2' >> kprobe_events
 clear_trace
-test -d events/kprobes/testprobe2 && exit 1 || exit 0
+test -d events/kprobes/testprobe2 && exit_fail || exit_pass
index 5448f7abad5f3763b7ca06dbcc01bb416035eaeb..5c39ceb18a0d6b3efe3dd65f654b4eaa4ce322e0 100644 (file)
@@ -4,6 +4,7 @@
 # Note that all tests are run with "errexit" option.
 
 exit 0 # Return 0 if the test is passed, otherwise return !0
+# Or you can call exit_pass for passed test, and exit_fail for failed test.
 # If the test could not run because of lack of feature, call exit_unsupported
 # If the test returned unclear results, call exit_unresolved
 # If the test is a dummy, or a placeholder, call exit_untested
index 839ac4320b24e7a4ca171f7c70076b6a9d4268e6..28cc355a3a7b23181dc9fecb74f7a2cdba56e615 100644 (file)
@@ -12,7 +12,7 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 if [ ! -f set_event -o ! -d events/sched ]; then
index 66873c4b12c952503643c92ee580d9929f4623db..a48e23eb8a8be85a81324aca2aee51fbfa352ff5 100644 (file)
@@ -12,7 +12,7 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 if [ ! -f set_event -o ! -d events/sched ]; then
index 4237b32769f14552c9f0ca9ee16357c95fc52345..8da80efc44d88d741d1cab1e837ce8a4d80d8233 100644 (file)
@@ -12,7 +12,7 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 if [ ! -f set_event -o ! -d events/sched ]; then
index d24e2b8bd8633b8ec2a8344b044928d49c7f41dc..449fe9ff91a250ed6bc171f30e01d44c8a58ccde 100644 (file)
@@ -12,7 +12,7 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 if [ ! -f set_event -o ! -d events/sched ]; then
index 4c0774fff37815e20803b4f8d7acaba87af49621..c5ef8b9d02b3b8cfb8a360b0d15b332a64f0b564 100644 (file)
@@ -12,7 +12,7 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 if [ ! -f set_event -o ! -d events/sched ]; then
index 3fc6321e081f327798b08c09d7ff21bcd2693545..ed38f0050d7721c88f494b389bd1a1c63e5a58a0 100644 (file)
@@ -11,7 +11,7 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 if [ ! -f set_event -o ! -d events/sched ]; then
index 3652824f81ed6a9766e2f45ef44feee0a79c38ed..3121d795a868ce3e1ed87b02cf513c22b2cd523b 100644 (file)
@@ -11,7 +11,7 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 if [ ! -f set_event -o ! -d events/sched ]; then
index 6d9051cdf408f32449602cafb6c8c60ca708abe9..c59d9eb546daed21c889cbdc96a455aa0b149b3d 100644 (file)
@@ -11,7 +11,7 @@ do_reset() {
 fail() { #msg
     do_reset
     echo $1
-    exit $FAIL
+    exit_fail
 }
 
 if [ ! -f set_event -o ! -d events/sched ]; then
index 845e5f67b6f0245fabedc8367ecefb3ba3ad0de9..132a54f74e883963bf45a42cfc17533a306e8bd6 100644 (file)
@@ -515,7 +515,7 @@ static void mfd_assert_grow_write(int fd)
 
        buf = malloc(mfd_def_size * 8);
        if (!buf) {
-               printf("malloc(%d) failed: %m\n", mfd_def_size * 8);
+               printf("malloc(%zu) failed: %m\n", mfd_def_size * 8);
                abort();
        }
 
@@ -535,7 +535,7 @@ static void mfd_fail_grow_write(int fd)
 
        buf = malloc(mfd_def_size * 8);
        if (!buf) {
-               printf("malloc(%d) failed: %m\n", mfd_def_size * 8);
+               printf("malloc(%zu) failed: %m\n", mfd_def_size * 8);
                abort();
        }
 
index 23db11c94b59abbcc881e3c80dcf93b50d9e3abe..86636d207adf72c12403355cae88d3bfe819fd80 100644 (file)
@@ -4,10 +4,10 @@ all:
 include ../lib.mk
 
 TEST_PROGS := mem-on-off-test.sh
-override RUN_TESTS := ./mem-on-off-test.sh -r 2 || echo "selftests: memory-hotplug [FAIL]"
+override RUN_TESTS := ./mem-on-off-test.sh -r 2 && echo "selftests: memory-hotplug [PASS]" || echo "selftests: memory-hotplug [FAIL]"
 override EMIT_TESTS := echo "$(RUN_TESTS)"
 
 run_full_test:
-       @/bin/bash ./mem-on-off-test.sh || echo "memory-hotplug selftests: [FAIL]"
+       @/bin/bash ./mem-on-off-test.sh && echo "memory-hotplug selftests: [PASS]" || echo "memory-hotplug selftests: [FAIL]"
 
 clean:
index 346d83ca8069ab2a9f5c4decf26d624d289be988..5af29d3a1b0ab6b26d68a11004c5a58cde3ae484 100644 (file)
@@ -1 +1,2 @@
 seccomp_bpf
+seccomp_benchmark
index cc986621f512d949634113960f8d1c6ae46354af..2c8ac8416299fb9221ddb24ad9929a539d6f9382 100644 (file)
@@ -18,3 +18,5 @@ threadtest
 valid-adjtimex
 adjtick
 set-tz
+freq-step
+rtctest_setdate
index 8daeb7d7032c2a0b79802bb9f8674a0d0d6aeb74..2df26bd0099ccb0033f0d48bbc4d9485bb42f5da 100644 (file)
@@ -19,6 +19,19 @@ extern void *vdso_sym(const char *version, const char *name);
 extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
 extern void vdso_init_from_auxv(void *auxv);
 
+/*
+ * ARM64's vDSO exports its gettimeofday() implementation with a different
+ * name and version from other architectures, so we need to handle it as
+ * a special case.
+ */
+#if defined(__aarch64__)
+const char *version = "LINUX_2.6.39";
+const char *name = "__kernel_gettimeofday";
+#else
+const char *version = "LINUX_2.6";
+const char *name = "__vdso_gettimeofday";
+#endif
+
 int main(int argc, char **argv)
 {
        unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
@@ -31,10 +44,10 @@ int main(int argc, char **argv)
 
        /* Find gettimeofday. */
        typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
-       gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
+       gtod_t gtod = (gtod_t)vdso_sym(version, name);
 
        if (!gtod) {
-               printf("Could not find __vdso_gettimeofday\n");
+               printf("Could not find %s\n", name);
                return 1;
        }
 
@@ -45,7 +58,7 @@ int main(int argc, char **argv)
                printf("The time is %lld.%06lld\n",
                       (long long)tv.tv_sec, (long long)tv.tv_usec);
        } else {
-               printf("__vdso_gettimeofday failed\n");
+               printf("%s failed\n", name);
        }
 
        return 0;
index 142c565bb3518d0311f0049f135f7de55d336301..1ca2ee4d15b9e64dd34352c3fabf1a8d3ede45d7 100644 (file)
@@ -8,3 +8,5 @@ on-fault-limit
 transhuge-stress
 userfaultfd
 mlock-intersect-test
+mlock-random-test
+virtual_address_range