added my Recipes
This commit is contained in:
@@ -0,0 +1,145 @@
|
||||
SUMMARY = "Kernel selftest for Linux"
|
||||
DESCRIPTION = "Kernel selftest for Linux"
|
||||
LICENSE = "GPL-2.0-only"
|
||||
|
||||
LIC_FILES_CHKSUM = "file://../COPYING;md5=bbea815ee2795b2f4230826c0c6b8814"
|
||||
|
||||
DEPENDS = "rsync-native llvm-native"
|
||||
|
||||
# for musl libc
|
||||
SRC_URI:append:libc-musl = "\
|
||||
file://userfaultfd.patch \
|
||||
"
|
||||
SRC_URI += "file://run-ptest \
|
||||
file://COPYING \
|
||||
"
|
||||
|
||||
# now we just test bpf and vm
|
||||
# we will append other kernel selftest in the future
|
||||
# bpf was added in 4.10 with: https://github.com/torvalds/linux/commit/5aa5bd14c5f8660c64ceedf14a549781be47e53d
|
||||
# if you have older kernel than that you need to remove it from PACKAGECONFIG
|
||||
PACKAGECONFIG ??= "firmware"
|
||||
PACKAGECONFIG:remove:x86 = "bpf"
|
||||
PACKAGECONFIG:remove:arm = "bpf vm"
|
||||
# host ptrace.h is used to compile BPF target but mips ptrace.h is needed
|
||||
# progs/loop1.c:21:9: error: incomplete definition of type 'struct user_pt_regs'
|
||||
# m = PT_REGS_RC(ctx);
|
||||
# vm tests need libhugetlbfs starting 5.8+ (https://lkml.org/lkml/2020/4/22/1654)
|
||||
PACKAGECONFIG:remove:qemumips = "bpf vm"
|
||||
|
||||
# riscv does not support libhugetlbfs yet
|
||||
PACKAGECONFIG:remove:riscv64 = "vm"
|
||||
PACKAGECONFIG:remove:riscv32 = "vm"
|
||||
|
||||
PACKAGECONFIG[bpf] = ",,elfutils libcap libcap-ng rsync-native,"
|
||||
PACKAGECONFIG[firmware] = ",,libcap, bash"
|
||||
PACKAGECONFIG[vm] = ",,libcap libhugetlbfs,libgcc bash"
|
||||
|
||||
do_patch[depends] += "virtual/kernel:do_shared_workdir"
|
||||
|
||||
inherit linux-kernel-base kernel-arch ptest
|
||||
|
||||
S = "${WORKDIR}/${BP}"
|
||||
|
||||
TEST_LIST = "\
|
||||
${@bb.utils.filter('PACKAGECONFIG', 'bpf firmware vm', d)} \
|
||||
rtc \
|
||||
"
|
||||
|
||||
EXTRA_OEMAKE = '\
|
||||
CROSS_COMPILE=${TARGET_PREFIX} \
|
||||
ARCH=${ARCH} \
|
||||
CC="${CC}" \
|
||||
CLANG="clang -fno-stack-protector -target ${TARGET_ARCH} ${TOOLCHAIN_OPTIONS}" \
|
||||
AR="${AR}" \
|
||||
LD="${LD}" \
|
||||
DESTDIR="${D}" \
|
||||
MACHINE="${ARCH}" \
|
||||
'
|
||||
|
||||
KERNEL_SELFTEST_SRC ?= "Makefile \
|
||||
include \
|
||||
kernel \
|
||||
lib \
|
||||
tools \
|
||||
scripts \
|
||||
arch \
|
||||
LICENSES \
|
||||
"
|
||||
|
||||
do_compile() {
|
||||
if [ ${@bb.utils.contains('PACKAGECONFIG', 'bpf', 'True', 'False', d)} = 'True' ]; then
|
||||
if [ ${@bb.utils.contains('DEPENDS', 'clang-native', 'True', 'False', d)} = 'False' ]; then
|
||||
bbwarn "clang >= 6.0 with bpf support is needed with kernel 4.18+ so
|
||||
either install it and add it to HOSTTOOLS, or add clang-native from meta-clang to dependency"
|
||||
fi
|
||||
fi
|
||||
|
||||
for i in ${TEST_LIST}
|
||||
do
|
||||
oe_runmake -C ${S}/tools/testing/selftests/${i}
|
||||
done
|
||||
}
|
||||
|
||||
do_install() {
|
||||
for i in ${TEST_LIST}
|
||||
do
|
||||
oe_runmake -C ${S}/tools/testing/selftests/${i} INSTALL_PATH=${D}/usr/kernel-selftest/${i} install
|
||||
# Install kselftest-list.txt that required by kselftest runner.
|
||||
oe_runmake -s --no-print-directory COLLECTION=${i} -C ${S}/tools/testing/selftests/${i} emit_tests \
|
||||
>> ${D}/usr/kernel-selftest/kselftest-list.txt
|
||||
done
|
||||
# Install kselftest runner.
|
||||
install -m 0755 ${S}/tools/testing/selftests/run_kselftest.sh ${D}/usr/kernel-selftest/
|
||||
cp -R --no-dereference --preserve=mode,links -v ${S}/tools/testing/selftests/kselftest ${D}/usr/kernel-selftest/
|
||||
if [ -e ${D}/usr/kernel-selftest/bpf/test_offload.py ]; then
|
||||
sed -i -e '1s,#!.*python3,#! /usr/bin/env python3,' ${D}/usr/kernel-selftest/bpf/test_offload.py
|
||||
fi
|
||||
chown root:root -R ${D}/usr/kernel-selftest
|
||||
}
|
||||
|
||||
do_configure() {
|
||||
install -D -m 0644 ${WORKDIR}/COPYING ${S}/COPYING
|
||||
}
|
||||
|
||||
do_patch[prefuncs] += "copy_kselftest_source_from_kernel remove_unrelated"
|
||||
python copy_kselftest_source_from_kernel() {
|
||||
sources = (d.getVar("KERNEL_SELFTEST_SRC") or "").split()
|
||||
src_dir = d.getVar("STAGING_KERNEL_DIR")
|
||||
dest_dir = d.getVar("S")
|
||||
bb.utils.mkdirhier(dest_dir)
|
||||
for s in sources:
|
||||
src = oe.path.join(src_dir, s)
|
||||
dest = oe.path.join(dest_dir, s)
|
||||
if os.path.isdir(src):
|
||||
oe.path.copytree(src, dest)
|
||||
else:
|
||||
bb.utils.copyfile(src, dest)
|
||||
}
|
||||
|
||||
remove_unrelated() {
|
||||
if ${@bb.utils.contains('PACKAGECONFIG','bpf','true','false',d)} ; then
|
||||
test -f ${S}/tools/testing/selftests/bpf/Makefile && \
|
||||
sed -i -e 's/test_pkt_access.*$/\\/' \
|
||||
-e 's/test_pkt_md_access.*$/\\/' \
|
||||
-e 's/sockmap_verdict_prog.*$/\\/' \
|
||||
${S}/tools/testing/selftests/bpf/Makefile || \
|
||||
bberror "Your kernel is probably older than 4.10 and doesn't have tools/testing/selftests/bpf/Makefile file from https://github.com/torvalds/linux/commit/5aa5bd14c5f8660c64ceedf14a549781be47e53d, disable bpf PACKAGECONFIG"
|
||||
fi
|
||||
}
|
||||
|
||||
PACKAGE_ARCH = "${MACHINE_ARCH}"
|
||||
|
||||
INHIBIT_PACKAGE_DEBUG_SPLIT="1"
|
||||
FILES:${PN} += "/usr/kernel-selftest"
|
||||
|
||||
RDEPENDS:${PN} += "python3 perl"
|
||||
# tools/testing/selftests/vm/Makefile doesn't respect LDFLAGS and tools/testing/selftests/Makefile explicitly overrides to empty
|
||||
INSANE_SKIP:${PN} += "ldflags"
|
||||
|
||||
SECURITY_CFLAGS = ""
|
||||
COMPATIBLE_HOST:libc-musl = 'null'
|
||||
|
||||
# It has native clang/llvm dependency, poky distro is reluctant to include them as deps
|
||||
# this helps with world builds on AB
|
||||
EXCLUDE_FROM_WORLD = "1"
|
||||
@@ -0,0 +1,18 @@
|
||||
The Linux Kernel is provided under:
|
||||
|
||||
SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
|
||||
|
||||
Being under the terms of the GNU General Public License version 2 only,
|
||||
according with:
|
||||
|
||||
LICENSES/preferred/GPL-2.0
|
||||
|
||||
With an explicit syscall exception, as stated at:
|
||||
|
||||
LICENSES/exceptions/Linux-syscall-note
|
||||
|
||||
In addition, other licenses may also apply. Please see:
|
||||
|
||||
Documentation/process/license-rules.rst
|
||||
|
||||
for more details.
|
||||
@@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
export PATH=$PATH:/usr/kernel-selftest/bpf
|
||||
|
||||
# test_align
|
||||
test_align | grep "12 pass" &> /dev/null
|
||||
if [ $? == 0 ]; then
|
||||
echo "[PASS]: test_align"
|
||||
else
|
||||
echo "[FAIL]: test_align"
|
||||
fi
|
||||
|
||||
@@ -0,0 +1,322 @@
|
||||
From c7b375747cffb627d02543d946b28525455d7d46 Mon Sep 17 00:00:00 2001
|
||||
From: "Hongzhi.Song" <hongzhi.song@windriver.com>
|
||||
Date: Fri, 13 Jul 2018 06:06:19 -0700
|
||||
Subject: [PATCH] vm: add some funtions to support musl libc
|
||||
|
||||
Signed-off-by: Hongzhi.Song <hongzhi.song@windriver.com>
|
||||
---
|
||||
tools/testing/selftests/vm/userfaultfd.c | 298 +++++++++++++++++++++++++++++++
|
||||
1 file changed, 298 insertions(+)
|
||||
|
||||
diff --git a/tools/testing/selftests/vm/userfaultfd.c b/tools/testing/selftests/vm/userfaultfd.c
|
||||
index de2f9ec..dc73021 100644
|
||||
--- a/tools/testing/selftests/vm/userfaultfd.c
|
||||
+++ b/tools/testing/selftests/vm/userfaultfd.c
|
||||
@@ -71,6 +71,304 @@
|
||||
|
||||
#ifdef __NR_userfaultfd
|
||||
|
||||
+/* Linear congruential. */
|
||||
+#define TYPE_0 0
|
||||
+#define BREAK_0 8
|
||||
+#define DEG_0 0
|
||||
+#define SEP_0 0
|
||||
+
|
||||
+/* x**7 + x**3 + 1. */
|
||||
+#define TYPE_1 1
|
||||
+#define BREAK_1 32
|
||||
+#define DEG_1 7
|
||||
+#define SEP_1 3
|
||||
+
|
||||
+/* x**15 + x + 1. */
|
||||
+#define TYPE_2 2
|
||||
+#define BREAK_2 64
|
||||
+#define DEG_2 15
|
||||
+#define SEP_2 1
|
||||
+
|
||||
+/* x**31 + x**3 + 1. */
|
||||
+#define TYPE_3 3
|
||||
+#define BREAK_3 128
|
||||
+#define DEG_3 31
|
||||
+#define SEP_3 3
|
||||
+
|
||||
+/* x**63 + x + 1. */
|
||||
+#define TYPE_4 4
|
||||
+#define BREAK_4 256
|
||||
+#define DEG_4 63
|
||||
+#define SEP_4 1
|
||||
+
|
||||
+/* Array versions of the above information to make code run faster.
|
||||
+ Relies on fact that TYPE_i == i. */
|
||||
+
|
||||
+#define MAX_TYPES 5 /* Max number of types above. */
|
||||
+
|
||||
+#define __set_errno(val) (errno = (val))
|
||||
+
|
||||
+struct random_data
|
||||
+ {
|
||||
+ int32_t *fptr; /* Front pointer. */
|
||||
+ int32_t *rptr; /* Rear pointer. */
|
||||
+ int32_t *state; /* Array of state values. */
|
||||
+ int rand_type; /* Type of random number generator. */
|
||||
+ int rand_deg; /* Degree of random number generator. */
|
||||
+ int rand_sep; /* Distance between front and rear. */
|
||||
+ int32_t *end_ptr; /* Pointer behind state table. */
|
||||
+ };
|
||||
+
|
||||
+struct random_poly_info
|
||||
+{
|
||||
+ int seps[MAX_TYPES];
|
||||
+ int degrees[MAX_TYPES];
|
||||
+};
|
||||
+
|
||||
+static const struct random_poly_info random_poly_info =
|
||||
+{
|
||||
+ { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 },
|
||||
+ { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 }
|
||||
+};
|
||||
+
|
||||
+/* If we are using the trivial TYPE_0 R.N.G., just do the old linear
|
||||
+ congruential bit. Otherwise, we do our fancy trinomial stuff, which is the
|
||||
+ same in all the other cases due to all the global variables that have been
|
||||
+ set up. The basic operation is to add the number at the rear pointer into
|
||||
+ the one at the front pointer. Then both pointers are advanced to the next
|
||||
+ location cyclically in the table. The value returned is the sum generated,
|
||||
+ reduced to 31 bits by throwing away the "least random" low bit.
|
||||
+ Note: The code takes advantage of the fact that both the front and
|
||||
+ rear pointers can't wrap on the same call by not testing the rear
|
||||
+ pointer if the front one has wrapped. Returns a 31-bit random number. */
|
||||
+
|
||||
+int random_r (struct random_data *buf, int32_t *result)
|
||||
+{
|
||||
+ int32_t *state;
|
||||
+
|
||||
+ if (buf == NULL || result == NULL)
|
||||
+ goto fail;
|
||||
+
|
||||
+ state = buf->state;
|
||||
+
|
||||
+ if (buf->rand_type == TYPE_0)
|
||||
+ {
|
||||
+ int32_t val = ((state[0] * 1103515245U) + 12345U) & 0x7fffffff;
|
||||
+ state[0] = val;
|
||||
+ *result = val;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ int32_t *fptr = buf->fptr;
|
||||
+ int32_t *rptr = buf->rptr;
|
||||
+ int32_t *end_ptr = buf->end_ptr;
|
||||
+ uint32_t val;
|
||||
+
|
||||
+ val = *fptr += (uint32_t) *rptr;
|
||||
+ /* Chucking least random bit. */
|
||||
+ *result = val >> 1;
|
||||
+ ++fptr;
|
||||
+ if (fptr >= end_ptr)
|
||||
+ {
|
||||
+ fptr = state;
|
||||
+ ++rptr;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ ++rptr;
|
||||
+ if (rptr >= end_ptr)
|
||||
+ rptr = state;
|
||||
+ }
|
||||
+ buf->fptr = fptr;
|
||||
+ buf->rptr = rptr;
|
||||
+ }
|
||||
+ return 0;
|
||||
+
|
||||
+ fail:
|
||||
+ __set_errno (EINVAL);
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+/* Initialize the random number generator based on the given seed. If the
|
||||
+ type is the trivial no-state-information type, just remember the seed.
|
||||
+ Otherwise, initializes state[] based on the given "seed" via a linear
|
||||
+ congruential generator. Then, the pointers are set to known locations
|
||||
+ that are exactly rand_sep places apart. Lastly, it cycles the state
|
||||
+ information a given number of times to get rid of any initial dependencies
|
||||
+ introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
|
||||
+ for default usage relies on values produced by this routine. */
|
||||
+int srandom_r (unsigned int seed, struct random_data *buf)
|
||||
+{
|
||||
+ int type;
|
||||
+ int32_t *state;
|
||||
+ long int i;
|
||||
+ int32_t word;
|
||||
+ int32_t *dst;
|
||||
+ int kc;
|
||||
+
|
||||
+ if (buf == NULL)
|
||||
+ goto fail;
|
||||
+ type = buf->rand_type;
|
||||
+ if ((unsigned int) type >= MAX_TYPES)
|
||||
+ goto fail;
|
||||
+
|
||||
+ state = buf->state;
|
||||
+ /* We must make sure the seed is not 0. Take arbitrarily 1 in this case. */
|
||||
+ if (seed == 0)
|
||||
+ seed = 1;
|
||||
+ state[0] = seed;
|
||||
+ if (type == TYPE_0)
|
||||
+ goto done;
|
||||
+
|
||||
+ dst = state;
|
||||
+ word = seed;
|
||||
+ kc = buf->rand_deg;
|
||||
+ for (i = 1; i < kc; ++i)
|
||||
+ {
|
||||
+ /* This does:
|
||||
+ state[i] = (16807 * state[i - 1]) % 2147483647;
|
||||
+ but avoids overflowing 31 bits. */
|
||||
+ long int hi = word / 127773;
|
||||
+ long int lo = word % 127773;
|
||||
+ word = 16807 * lo - 2836 * hi;
|
||||
+ if (word < 0)
|
||||
+ word += 2147483647;
|
||||
+ *++dst = word;
|
||||
+ }
|
||||
+
|
||||
+ buf->fptr = &state[buf->rand_sep];
|
||||
+ buf->rptr = &state[0];
|
||||
+ kc *= 10;
|
||||
+ while (--kc >= 0)
|
||||
+ {
|
||||
+ int32_t discard;
|
||||
+ (void) random_r (buf, &discard);
|
||||
+ }
|
||||
+
|
||||
+ done:
|
||||
+ return 0;
|
||||
+
|
||||
+ fail:
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+/* Initialize the state information in the given array of N bytes for
|
||||
+ future random number generation. Based on the number of bytes we
|
||||
+ are given, and the break values for the different R.N.G.'s, we choose
|
||||
+ the best (largest) one we can and set things up for it. srandom is
|
||||
+ then called to initialize the state information. Note that on return
|
||||
+ from srandom, we set state[-1] to be the type multiplexed with the current
|
||||
+ value of the rear pointer; this is so successive calls to initstate won't
|
||||
+ lose this information and will be able to restart with setstate.
|
||||
+ Note: The first thing we do is save the current state, if any, just like
|
||||
+ setstate so that it doesn't matter when initstate is called.
|
||||
+ Returns 0 on success, non-zero on failure. */
|
||||
+int initstate_r (unsigned int seed, char *arg_state, size_t n,
|
||||
+ struct random_data *buf)
|
||||
+{
|
||||
+ if (buf == NULL)
|
||||
+ goto fail;
|
||||
+
|
||||
+ int32_t *old_state = buf->state;
|
||||
+ if (old_state != NULL)
|
||||
+ {
|
||||
+ int old_type = buf->rand_type;
|
||||
+ if (old_type == TYPE_0)
|
||||
+ old_state[-1] = TYPE_0;
|
||||
+ else
|
||||
+ old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type;
|
||||
+ }
|
||||
+
|
||||
+ int type;
|
||||
+ if (n >= BREAK_3)
|
||||
+ type = n < BREAK_4 ? TYPE_3 : TYPE_4;
|
||||
+ else if (n < BREAK_1)
|
||||
+ {
|
||||
+ if (n < BREAK_0)
|
||||
+ goto fail;
|
||||
+
|
||||
+ type = TYPE_0;
|
||||
+ }
|
||||
+ else
|
||||
+ type = n < BREAK_2 ? TYPE_1 : TYPE_2;
|
||||
+
|
||||
+ int degree = random_poly_info.degrees[type];
|
||||
+ int separation = random_poly_info.seps[type];
|
||||
+
|
||||
+ buf->rand_type = type;
|
||||
+ buf->rand_sep = separation;
|
||||
+ buf->rand_deg = degree;
|
||||
+ int32_t *state = &((int32_t *) arg_state)[1]; /* First location. */
|
||||
+ /* Must set END_PTR before srandom. */
|
||||
+ buf->end_ptr = &state[degree];
|
||||
+
|
||||
+ buf->state = state;
|
||||
+
|
||||
+ srandom_r (seed, buf);
|
||||
+
|
||||
+ state[-1] = TYPE_0;
|
||||
+ if (type != TYPE_0)
|
||||
+ state[-1] = (buf->rptr - state) * MAX_TYPES + type;
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+ fail:
|
||||
+ __set_errno (EINVAL);
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
+/* Restore the state from the given state array.
|
||||
+ Note: It is important that we also remember the locations of the pointers
|
||||
+ in the current state information, and restore the locations of the pointers
|
||||
+ from the old state information. This is done by multiplexing the pointer
|
||||
+ location into the zeroth word of the state information. Note that due
|
||||
+ to the order in which things are done, it is OK to call setstate with the
|
||||
+ same state as the current state
|
||||
+ Returns 0 on success, non-zero on failure. */
|
||||
+int setstate_r (char *arg_state, struct random_data *buf)
|
||||
+{
|
||||
+ int32_t *new_state = 1 + (int32_t *) arg_state;
|
||||
+ int type;
|
||||
+ int old_type;
|
||||
+ int32_t *old_state;
|
||||
+ int degree;
|
||||
+ int separation;
|
||||
+
|
||||
+ if (arg_state == NULL || buf == NULL)
|
||||
+ goto fail;
|
||||
+
|
||||
+ old_type = buf->rand_type;
|
||||
+ old_state = buf->state;
|
||||
+ if (old_type == TYPE_0)
|
||||
+ old_state[-1] = TYPE_0;
|
||||
+ else
|
||||
+ old_state[-1] = (MAX_TYPES * (buf->rptr - old_state)) + old_type;
|
||||
+
|
||||
+ type = new_state[-1] % MAX_TYPES;
|
||||
+ if (type < TYPE_0 || type > TYPE_4)
|
||||
+ goto fail;
|
||||
+
|
||||
+ buf->rand_deg = degree = random_poly_info.degrees[type];
|
||||
+ buf->rand_sep = separation = random_poly_info.seps[type];
|
||||
+ buf->rand_type = type;
|
||||
+
|
||||
+ if (type != TYPE_0)
|
||||
+ {
|
||||
+ int rear = new_state[-1] / MAX_TYPES;
|
||||
+ buf->rptr = &new_state[rear];
|
||||
+ buf->fptr = &new_state[(rear + separation) % degree];
|
||||
+ }
|
||||
+ buf->state = new_state;
|
||||
+ /* Set end_ptr too. */
|
||||
+ buf->end_ptr = &new_state[degree];
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+ fail:
|
||||
+ __set_errno (EINVAL);
|
||||
+ return -1;
|
||||
+}
|
||||
+
|
||||
static unsigned long nr_cpus, nr_pages, nr_pages_per_cpu, page_size;
|
||||
|
||||
#define BOUNCE_RANDOM (1<<0)
|
||||
--
|
||||
2.11.0
|
||||
|
||||
Reference in New Issue
Block a user