Commit f4b39746 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'linux-kselftest-5.5-rc4' of...

Merge tag 'linux-kselftest-5.5-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull Kselftest fixes from Shuah Khan:

 - rseq build failures fixes related to glibc 2.30 compatibility from
   Mathieu Desnoyers

 - Kunit fixes and cleanups from SeongJae Park

 - Fixes to filesystems/epoll, firmware, and livepatch build failures
   and skip handling.

* tag 'linux-kselftest-5.5-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
  rseq/selftests: Clarify rseq_prepare_unload() helper requirements
  rseq/selftests: Fix: Namespace gettid() for compatibility with glibc 2.30
  rseq/selftests: Turn off timeout setting
  kunit/kunit_tool_test: Test '--build_dir' option run
  kunit: Rename 'kunitconfig' to '.kunitconfig'
  kunit: Place 'test.log' under the 'build_dir'
  kunit: Create default config in '--build_dir'
  kunit: Remove duplicated defconfig creation
  docs/kunit/start: Use in-tree 'kunit_defconfig'
  selftests: livepatch: Fix it to do root uid check and skip
  selftests: firmware: Fix it to do root uid check and skip
  selftests: filesystems/epoll: fix build error
parents 1413c361 2a1f40ad
...@@ -24,19 +24,16 @@ The wrapper can be run with: ...@@ -24,19 +24,16 @@ The wrapper can be run with:
For more information on this wrapper (also called kunit_tool) checkout the For more information on this wrapper (also called kunit_tool) checkout the
:doc:`kunit-tool` page. :doc:`kunit-tool` page.
Creating a kunitconfig Creating a .kunitconfig
====================== =======================
The Python script is a thin wrapper around Kbuild. As such, it needs to be The Python script is a thin wrapper around Kbuild. As such, it needs to be
configured with a ``kunitconfig`` file. This file essentially contains the configured with a ``.kunitconfig`` file. This file essentially contains the
regular Kernel config, with the specific test targets as well. regular Kernel config, with the specific test targets as well.
.. code-block:: bash .. code-block:: bash
git clone -b master https://kunit.googlesource.com/kunitconfig $PATH_TO_KUNITCONFIG_REPO
cd $PATH_TO_LINUX_REPO cd $PATH_TO_LINUX_REPO
ln -s $PATH_TO_KUNIT_CONFIG_REPO/kunitconfig kunitconfig cp arch/um/configs/kunit_defconfig .kunitconfig
You may want to add kunitconfig to your local gitignore.
Verifying KUnit Works Verifying KUnit Works
--------------------- ---------------------
...@@ -151,7 +148,7 @@ and the following to ``drivers/misc/Makefile``: ...@@ -151,7 +148,7 @@ and the following to ``drivers/misc/Makefile``:
obj-$(CONFIG_MISC_EXAMPLE_TEST) += example-test.o obj-$(CONFIG_MISC_EXAMPLE_TEST) += example-test.o
Now add it to your ``kunitconfig``: Now add it to your ``.kunitconfig``:
.. code-block:: none .. code-block:: none
......
...@@ -31,15 +31,12 @@ class KunitStatus(Enum): ...@@ -31,15 +31,12 @@ class KunitStatus(Enum):
TEST_FAILURE = auto() TEST_FAILURE = auto()
def create_default_kunitconfig(): def create_default_kunitconfig():
if not os.path.exists(kunit_kernel.KUNITCONFIG_PATH): if not os.path.exists(kunit_kernel.kunitconfig_path):
shutil.copyfile('arch/um/configs/kunit_defconfig', shutil.copyfile('arch/um/configs/kunit_defconfig',
kunit_kernel.KUNITCONFIG_PATH) kunit_kernel.kunitconfig_path)
def run_tests(linux: kunit_kernel.LinuxSourceTree, def run_tests(linux: kunit_kernel.LinuxSourceTree,
request: KunitRequest) -> KunitResult: request: KunitRequest) -> KunitResult:
if request.defconfig:
create_default_kunitconfig()
config_start = time.time() config_start = time.time()
success = linux.build_reconfig(request.build_dir) success = linux.build_reconfig(request.build_dir)
config_end = time.time() config_end = time.time()
...@@ -108,15 +105,22 @@ def main(argv, linux=None): ...@@ -108,15 +105,22 @@ def main(argv, linux=None):
run_parser.add_argument('--build_dir', run_parser.add_argument('--build_dir',
help='As in the make command, it specifies the build ' help='As in the make command, it specifies the build '
'directory.', 'directory.',
type=str, default=None, metavar='build_dir') type=str, default='', metavar='build_dir')
run_parser.add_argument('--defconfig', run_parser.add_argument('--defconfig',
help='Uses a default kunitconfig.', help='Uses a default .kunitconfig.',
action='store_true') action='store_true')
cli_args = parser.parse_args(argv) cli_args = parser.parse_args(argv)
if cli_args.subcommand == 'run': if cli_args.subcommand == 'run':
if cli_args.build_dir:
if not os.path.exists(cli_args.build_dir):
os.mkdir(cli_args.build_dir)
kunit_kernel.kunitconfig_path = os.path.join(
cli_args.build_dir,
kunit_kernel.kunitconfig_path)
if cli_args.defconfig: if cli_args.defconfig:
create_default_kunitconfig() create_default_kunitconfig()
......
...@@ -14,7 +14,7 @@ import os ...@@ -14,7 +14,7 @@ import os
import kunit_config import kunit_config
KCONFIG_PATH = '.config' KCONFIG_PATH = '.config'
KUNITCONFIG_PATH = 'kunitconfig' kunitconfig_path = '.kunitconfig'
class ConfigError(Exception): class ConfigError(Exception):
"""Represents an error trying to configure the Linux kernel.""" """Represents an error trying to configure the Linux kernel."""
...@@ -82,7 +82,7 @@ class LinuxSourceTree(object): ...@@ -82,7 +82,7 @@ class LinuxSourceTree(object):
def __init__(self): def __init__(self):
self._kconfig = kunit_config.Kconfig() self._kconfig = kunit_config.Kconfig()
self._kconfig.read_from_file(KUNITCONFIG_PATH) self._kconfig.read_from_file(kunitconfig_path)
self._ops = LinuxSourceTreeOperations() self._ops = LinuxSourceTreeOperations()
def clean(self): def clean(self):
...@@ -111,7 +111,7 @@ class LinuxSourceTree(object): ...@@ -111,7 +111,7 @@ class LinuxSourceTree(object):
return True return True
def build_reconfig(self, build_dir): def build_reconfig(self, build_dir):
"""Creates a new .config if it is not a subset of the kunitconfig.""" """Creates a new .config if it is not a subset of the .kunitconfig."""
kconfig_path = get_kconfig_path(build_dir) kconfig_path = get_kconfig_path(build_dir)
if os.path.exists(kconfig_path): if os.path.exists(kconfig_path):
existing_kconfig = kunit_config.Kconfig() existing_kconfig = kunit_config.Kconfig()
...@@ -140,10 +140,10 @@ class LinuxSourceTree(object): ...@@ -140,10 +140,10 @@ class LinuxSourceTree(object):
return False return False
return True return True
def run_kernel(self, args=[], timeout=None, build_dir=None): def run_kernel(self, args=[], timeout=None, build_dir=''):
args.extend(['mem=256M']) args.extend(['mem=256M'])
process = self._ops.linux_bin(args, timeout, build_dir) process = self._ops.linux_bin(args, timeout, build_dir)
with open('test.log', 'w') as f: with open(os.path.join(build_dir, 'test.log'), 'w') as f:
for line in process.stdout: for line in process.stdout:
f.write(line.rstrip().decode('ascii') + '\n') f.write(line.rstrip().decode('ascii') + '\n')
yield line.rstrip().decode('ascii') yield line.rstrip().decode('ascii')
...@@ -174,6 +174,7 @@ class KUnitMainTest(unittest.TestCase): ...@@ -174,6 +174,7 @@ class KUnitMainTest(unittest.TestCase):
kunit.main(['run'], self.linux_source_mock) kunit.main(['run'], self.linux_source_mock)
assert self.linux_source_mock.build_reconfig.call_count == 1 assert self.linux_source_mock.build_reconfig.call_count == 1
assert self.linux_source_mock.run_kernel.call_count == 1 assert self.linux_source_mock.run_kernel.call_count == 1
self.linux_source_mock.run_kernel.assert_called_once_with(build_dir='', timeout=300)
self.print_mock.assert_any_call(StrContains('Testing complete.')) self.print_mock.assert_any_call(StrContains('Testing complete.'))
def test_run_passes_args_fail(self): def test_run_passes_args_fail(self):
...@@ -199,7 +200,14 @@ class KUnitMainTest(unittest.TestCase): ...@@ -199,7 +200,14 @@ class KUnitMainTest(unittest.TestCase):
timeout = 3453 timeout = 3453
kunit.main(['run', '--timeout', str(timeout)], self.linux_source_mock) kunit.main(['run', '--timeout', str(timeout)], self.linux_source_mock)
assert self.linux_source_mock.build_reconfig.call_count == 1 assert self.linux_source_mock.build_reconfig.call_count == 1
self.linux_source_mock.run_kernel.assert_called_once_with(build_dir=None, timeout=timeout) self.linux_source_mock.run_kernel.assert_called_once_with(build_dir='', timeout=timeout)
self.print_mock.assert_any_call(StrContains('Testing complete.'))
def test_run_builddir(self):
build_dir = '.kunit'
kunit.main(['run', '--build_dir', build_dir], self.linux_source_mock)
assert self.linux_source_mock.build_reconfig.call_count == 1
self.linux_source_mock.run_kernel.assert_called_once_with(build_dir=build_dir, timeout=300)
self.print_mock.assert_any_call(StrContains('Testing complete.')) self.print_mock.assert_any_call(StrContains('Testing complete.'))
if __name__ == '__main__': if __name__ == '__main__':
......
# SPDX-License-Identifier: GPL-2.0 # SPDX-License-Identifier: GPL-2.0
CFLAGS += -I../../../../../usr/include/ CFLAGS += -I../../../../../usr/include/
LDFLAGS += -lpthread LDLIBS += -lpthread
TEST_GEN_PROGS := epoll_wakeup_test TEST_GEN_PROGS := epoll_wakeup_test
include ../../lib.mk include ../../lib.mk
...@@ -34,6 +34,12 @@ test_modprobe() ...@@ -34,6 +34,12 @@ test_modprobe()
check_mods() check_mods()
{ {
local uid=$(id -u)
if [ $uid -ne 0 ]; then
echo "skip all tests: must be run as root" >&2
exit $ksft_skip
fi
trap "test_modprobe" EXIT trap "test_modprobe" EXIT
if [ ! -d $DIR ]; then if [ ! -d $DIR ]; then
modprobe test_firmware modprobe test_firmware
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
MAX_RETRIES=600 MAX_RETRIES=600
RETRY_INTERVAL=".1" # seconds RETRY_INTERVAL=".1" # seconds
# Kselftest framework requirement - SKIP code is 4
ksft_skip=4
# log(msg) - write message to kernel log # log(msg) - write message to kernel log
# msg - insightful words # msg - insightful words
function log() { function log() {
...@@ -18,7 +21,16 @@ function log() { ...@@ -18,7 +21,16 @@ function log() {
function skip() { function skip() {
log "SKIP: $1" log "SKIP: $1"
echo "SKIP: $1" >&2 echo "SKIP: $1" >&2
exit 4 exit $ksft_skip
}
# root test
function is_root() {
uid=$(id -u)
if [ $uid -ne 0 ]; then
echo "skip all tests: must be run as root" >&2
exit $ksft_skip
fi
} }
# die(msg) - game over, man # die(msg) - game over, man
...@@ -62,6 +74,7 @@ function set_ftrace_enabled() { ...@@ -62,6 +74,7 @@ function set_ftrace_enabled() {
# for verbose livepatching output and turn on # for verbose livepatching output and turn on
# the ftrace_enabled sysctl. # the ftrace_enabled sysctl.
function setup_config() { function setup_config() {
is_root
push_config push_config
set_dynamic_debug set_dynamic_debug
set_ftrace_enabled 1 set_ftrace_enabled 1
......
...@@ -8,8 +8,7 @@ MOD_LIVEPATCH=test_klp_state ...@@ -8,8 +8,7 @@ MOD_LIVEPATCH=test_klp_state
MOD_LIVEPATCH2=test_klp_state2 MOD_LIVEPATCH2=test_klp_state2
MOD_LIVEPATCH3=test_klp_state3 MOD_LIVEPATCH3=test_klp_state3
set_dynamic_debug setup_config
# TEST: Loading and removing a module that modifies the system state # TEST: Loading and removing a module that modifies the system state
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
#include <errno.h> #include <errno.h>
#include <stddef.h> #include <stddef.h>
static inline pid_t gettid(void) static inline pid_t rseq_gettid(void)
{ {
return syscall(__NR_gettid); return syscall(__NR_gettid);
} }
...@@ -373,11 +373,12 @@ void *test_percpu_spinlock_thread(void *arg) ...@@ -373,11 +373,12 @@ void *test_percpu_spinlock_thread(void *arg)
rseq_percpu_unlock(&data->lock, cpu); rseq_percpu_unlock(&data->lock, cpu);
#ifndef BENCHMARK #ifndef BENCHMARK
if (i != 0 && !(i % (reps / 10))) if (i != 0 && !(i % (reps / 10)))
printf_verbose("tid %d: count %lld\n", (int) gettid(), i); printf_verbose("tid %d: count %lld\n",
(int) rseq_gettid(), i);
#endif #endif
} }
printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n", printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n",
(int) gettid(), nr_abort, signals_delivered); (int) rseq_gettid(), nr_abort, signals_delivered);
if (!opt_disable_rseq && thread_data->reg && if (!opt_disable_rseq && thread_data->reg &&
rseq_unregister_current_thread()) rseq_unregister_current_thread())
abort(); abort();
...@@ -454,11 +455,12 @@ void *test_percpu_inc_thread(void *arg) ...@@ -454,11 +455,12 @@ void *test_percpu_inc_thread(void *arg)
} while (rseq_unlikely(ret)); } while (rseq_unlikely(ret));
#ifndef BENCHMARK #ifndef BENCHMARK
if (i != 0 && !(i % (reps / 10))) if (i != 0 && !(i % (reps / 10)))
printf_verbose("tid %d: count %lld\n", (int) gettid(), i); printf_verbose("tid %d: count %lld\n",
(int) rseq_gettid(), i);
#endif #endif
} }
printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n", printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n",
(int) gettid(), nr_abort, signals_delivered); (int) rseq_gettid(), nr_abort, signals_delivered);
if (!opt_disable_rseq && thread_data->reg && if (!opt_disable_rseq && thread_data->reg &&
rseq_unregister_current_thread()) rseq_unregister_current_thread())
abort(); abort();
...@@ -605,7 +607,7 @@ void *test_percpu_list_thread(void *arg) ...@@ -605,7 +607,7 @@ void *test_percpu_list_thread(void *arg)
} }
printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n", printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n",
(int) gettid(), nr_abort, signals_delivered); (int) rseq_gettid(), nr_abort, signals_delivered);
if (!opt_disable_rseq && rseq_unregister_current_thread()) if (!opt_disable_rseq && rseq_unregister_current_thread())
abort(); abort();
...@@ -796,7 +798,7 @@ void *test_percpu_buffer_thread(void *arg) ...@@ -796,7 +798,7 @@ void *test_percpu_buffer_thread(void *arg)
} }
printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n", printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n",
(int) gettid(), nr_abort, signals_delivered); (int) rseq_gettid(), nr_abort, signals_delivered);
if (!opt_disable_rseq && rseq_unregister_current_thread()) if (!opt_disable_rseq && rseq_unregister_current_thread())
abort(); abort();
...@@ -1011,7 +1013,7 @@ void *test_percpu_memcpy_buffer_thread(void *arg) ...@@ -1011,7 +1013,7 @@ void *test_percpu_memcpy_buffer_thread(void *arg)
} }
printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n", printf_verbose("tid %d: number of rseq abort: %d, signals delivered: %u\n",
(int) gettid(), nr_abort, signals_delivered); (int) rseq_gettid(), nr_abort, signals_delivered);
if (!opt_disable_rseq && rseq_unregister_current_thread()) if (!opt_disable_rseq && rseq_unregister_current_thread())
abort(); abort();
......
...@@ -149,11 +149,13 @@ static inline void rseq_clear_rseq_cs(void) ...@@ -149,11 +149,13 @@ static inline void rseq_clear_rseq_cs(void)
/* /*
* rseq_prepare_unload() should be invoked by each thread executing a rseq * rseq_prepare_unload() should be invoked by each thread executing a rseq
* critical section at least once between their last critical section and * critical section at least once between their last critical section and
* library unload of the library defining the rseq critical section * library unload of the library defining the rseq critical section (struct
* (struct rseq_cs). This also applies to use of rseq in code generated by * rseq_cs) or the code referred to by the struct rseq_cs start_ip and
* JIT: rseq_prepare_unload() should be invoked at least once by each * post_commit_offset fields. This also applies to use of rseq in code
* thread executing a rseq critical section before reclaim of the memory * generated by JIT: rseq_prepare_unload() should be invoked at least once by
* holding the struct rseq_cs. * each thread executing a rseq critical section before reclaim of the memory
* holding the struct rseq_cs or reclaim of the code pointed to by struct
* rseq_cs start_ip and post_commit_offset fields.
*/ */
static inline void rseq_prepare_unload(void) static inline void rseq_prepare_unload(void)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment