* Re: [PATCH v4 00/11] kunit: create a centralized executor to dispatch all KUnit tests
From: Brendan Higgins @ 2020-06-26 21:10 UTC (permalink / raw)
To: David Gow
Cc: open list:DOCUMENTATION, catalin.marinas, jcmvbkbc, will, paulus,
open list:KERNEL SELFTEST FRAMEWORK, Frank Rowand, Anton Ivanov,
linux-arch, Richard Weinberger, rppt, Iurii Zaikin, linux-xtensa,
Kees Cook, Arnd Bergmann, Jeff Dike, linux-um, linuxppc-dev,
Shuah Khan, Linux ARM, KUnit Development, chris, monstr,
Stephen Boyd, Greg Kroah-Hartman, Linux Kernel Mailing List,
Luis Chamberlain, Alan Maguire, Andrew Morton, Logan Gunthorpe
In-Reply-To: <CABVgOSnkYfXZ1YELsXAjA0GzCQT9YWO8x+Tssw_+avkDdBB4aw@mail.gmail.com>
On Wed, Jun 24, 2020 at 6:47 PM David Gow <davidgow@google.com> wrote:
>
> Glad this is back out there: a couple of minor nitpicks below:
>
> On Thu, Jun 25, 2020 at 4:58 AM Brendan Higgins
> <brendanhiggins@google.com> wrote:
> >
> > ## TL;DR
> >
> > This patchset adds a centralized executor to dispatch tests rather than
> > relying on late_initcall to schedule each test suite separately along
> > with a couple of new features that depend on it.
> >
> > Also, sorry for the extreme delay in getting this out. Part of the delay
> > came from finding that there were actually several architectures that
> > the previous revision of this patchset didn't work on, so I went through
> > and attempted to test this patchset on every architecture - more on that
> > later.
> >
> > ## What am I trying to do?
> >
> > Conceptually, I am trying to provide a mechanism by which test suites
> > can be grouped together so that they can be reasoned about collectively.
> > The last two of three patches in this series add features which depend
> > on this:
> >
> > PATCH 8/11 Prints out a test plan[1] right before KUnit tests are run;
> > this is valuable because it makes it possible for a test
> > harness to detect whether the number of tests run matches the
> > number of tests expected to be run, ensuring that no tests
> > silently failed. The test plan includes a count of tests that
> > will run. With the centralized executor, the tests are
> > located in a single data structure and thus can be counted.
> >
>
> This appears to actually be patch 9/11.
>
> > PATCH 9/11 Add a new kernel command-line option which allows the user to
> > specify that the kernel poweroff, halt, or reboot after
> > completing all KUnit tests; this is very handy for running
> > KUnit tests on UML or a VM so that the UML/VM process exits
> > cleanly immediately after running all tests without needing a
> > special initramfs. The centralized executor provides a
> > definitive point when all tests have completed and the
> > poweroff, halt, or reboot could occur.
>
> This seems to have been merged into the above patch (9/11).
Whoops, good catch.
Fixed in v5!
> > In addition, by dispatching tests from a single location, we can
> > guarantee that all KUnit tests run after late_init is complete, which
> > was a concern during the initial KUnit patchset review (this has not
> > been a problem in practice, but resolving with certainty is nevertheless
> > desirable).
> >
> > Other use cases for this exist, but the above features should provide an
> > idea of the value that this could provide.
> >
> > ## Changes since last revision:
> > - On the last revision I got some messages from 0day that showed that
> > this patchset didn't work on several architectures, one issue that
> > this patchset addresses is that we were aligning both memory segments
> > as well as structures in the segments to specific byte boundaries
> > which was incorrect.
> > - The issue mentioned above also caused me to test on additional
> > architectures which revealed that some architectures other than UML
> > do not use the default init linker section macro that most
> > architectures use. There are now several new patches (2, 3, 4, and
> > 6).
> > - Fixed a formatting consistency issue in the kernel params
> > documentation patch (9/9).
> > - Add a brief blurb on how and when the kunit_test_suite macro works.
> >
> > ## Remaining work to be done:
> >
> > The only architecture for which I was able to get a compiler, but was
> > apparently unable to get KUnit into a section that the executor to see
> > was m68k - not sure why.
> >
> > Alan Maguire (1):
> > kunit: test: create a single centralized executor for all tests
> >
> > Brendan Higgins (10):
> > vmlinux.lds.h: add linker section for KUnit test suites
> > arch: arm64: add linker section for KUnit test suites
> > arch: microblaze: add linker section for KUnit test suites
> > arch: powerpc: add linker section for KUnit test suites
> > arch: um: add linker section for KUnit test suites
> > arch: xtensa: add linker section for KUnit test suites
> > init: main: add KUnit to kernel init
> > kunit: test: add test plan to KUnit TAP format
> > Documentation: Add kunit_shutdown to kernel-parameters.txt
> > Documentation: kunit: add a brief blurb about kunit_test_suite
> >
> > .../admin-guide/kernel-parameters.txt | 8 ++
> > Documentation/dev-tools/kunit/usage.rst | 5 ++
> > arch/arm64/kernel/vmlinux.lds.S | 3 +
> > arch/microblaze/kernel/vmlinux.lds.S | 4 +
> > arch/powerpc/kernel/vmlinux.lds.S | 4 +
> > arch/um/include/asm/common.lds.S | 4 +
> > arch/xtensa/kernel/vmlinux.lds.S | 4 +
> > include/asm-generic/vmlinux.lds.h | 8 ++
> > include/kunit/test.h | 73 ++++++++++++-----
> > init/main.c | 4 +
> > lib/kunit/Makefile | 3 +-
> > lib/kunit/executor.c | 63 +++++++++++++++
> > lib/kunit/test.c | 13 +--
> > tools/testing/kunit/kunit_kernel.py | 2 +-
> > tools/testing/kunit/kunit_parser.py | 74 +++++++++++++++---
> > .../test_is_test_passed-all_passed.log | Bin 1562 -> 1567 bytes
> > .../test_data/test_is_test_passed-crash.log | Bin 3016 -> 3021 bytes
> > .../test_data/test_is_test_passed-failure.log | Bin 1700 -> 1705 bytes
> > 18 files changed, 226 insertions(+), 46 deletions(-)
> > create mode 100644 lib/kunit/executor.c
> >
> >
> > base-commit: 4333a9b0b67bb4e8bcd91bdd80da80b0ec151162
> > prerequisite-patch-id: 2d4b5aa9fa8ada9ae04c8584b47c299a822b9455
> > prerequisite-patch-id: 582b6d9d28ce4b71628890ec832df6522ca68de0
> >
> > These patches are available for download with dependencies here:
> >
> > https://kunit-review.googlesource.com/c/linux/+/3829
> >
> > [1] https://github.com/isaacs/testanything.github.io/blob/tap14/tap-version-14-specification.md#the-plan
> > [2] https://patchwork.kernel.org/patch/11383635/
> >
> > --
> > 2.27.0.212.ge8ba1cc988-goog
> >
^ permalink raw reply
* [PATCH v5 09/12] kunit: test: add test plan to KUnit TAP format
From: Brendan Higgins @ 2020-06-26 21:09 UTC (permalink / raw)
To: jdike, richard, anton.ivanov, arnd, keescook, skhan, alan.maguire,
yzaikin, davidgow, akpm, rppt, frowand.list, catalin.marinas,
will, monstr, mpe, benh, paulus, chris, jcmvbkbc
Cc: linux-arch, linux-xtensa, linux-doc, sboyd, gregkh, linuxppc-dev,
linux-um, linux-kernel, Brendan Higgins, mcgrof, linux-kselftest,
logang, linux-arm-kernel, kunit-dev
In-Reply-To: <20200626210917.358969-1-brendanhiggins@google.com>
TAP 14 allows an optional test plan to be emitted before the start of
the start of testing[1]; this is valuable because it makes it possible
for a test harness to detect whether the number of tests run matches the
number of tests expected to be run, ensuring that no tests silently
failed.
Link[1]: https://github.com/isaacs/testanything.github.io/blob/tap14/tap-version-14-specification.md#the-plan
Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
Reviewed-by: Stephen Boyd <sboyd@kernel.org>
---
lib/kunit/executor.c | 17 ++++
lib/kunit/test.c | 11 ---
tools/testing/kunit/kunit_parser.py | 76 +++++++++++++++---
.../test_is_test_passed-all_passed.log | Bin 1562 -> 1567 bytes
.../test_data/test_is_test_passed-crash.log | Bin 3016 -> 3021 bytes
.../test_data/test_is_test_passed-failure.log | Bin 1700 -> 1705 bytes
6 files changed, 80 insertions(+), 24 deletions(-)
diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c
index 4aab7f70a88c3..a95742a4ece73 100644
--- a/lib/kunit/executor.c
+++ b/lib/kunit/executor.c
@@ -11,10 +11,27 @@ extern struct kunit_suite * const * const __kunit_suites_end[];
#if IS_BUILTIN(CONFIG_KUNIT)
+static void kunit_print_tap_header(void)
+{
+ struct kunit_suite * const * const *suites, * const *subsuite;
+ int num_of_suites = 0;
+
+ for (suites = __kunit_suites_start;
+ suites < __kunit_suites_end;
+ suites++)
+ for (subsuite = *suites; *subsuite != NULL; subsuite++)
+ num_of_suites++;
+
+ pr_info("TAP version 14\n");
+ pr_info("1..%d\n", num_of_suites);
+}
+
int kunit_run_all_tests(void)
{
struct kunit_suite * const * const *suites;
+ kunit_print_tap_header();
+
for (suites = __kunit_suites_start;
suites < __kunit_suites_end;
suites++)
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index 918dff400a9d7..b1835ccb3fce2 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -19,16 +19,6 @@ static void kunit_set_failure(struct kunit *test)
WRITE_ONCE(test->success, false);
}
-static void kunit_print_tap_version(void)
-{
- static bool kunit_has_printed_tap_version;
-
- if (!kunit_has_printed_tap_version) {
- pr_info("TAP version 14\n");
- kunit_has_printed_tap_version = true;
- }
-}
-
/*
* Append formatted message to log, size of which is limited to
* KUNIT_LOG_SIZE bytes (including null terminating byte).
@@ -68,7 +58,6 @@ EXPORT_SYMBOL_GPL(kunit_suite_num_test_cases);
static void kunit_print_subtest_start(struct kunit_suite *suite)
{
- kunit_print_tap_version();
kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "# Subtest: %s",
suite->name);
kunit_log(KERN_INFO, suite, KUNIT_SUBTEST_INDENT "1..%zd",
diff --git a/tools/testing/kunit/kunit_parser.py b/tools/testing/kunit/kunit_parser.py
index 64aac9dcd4314..6d6d94a0ee7db 100644
--- a/tools/testing/kunit/kunit_parser.py
+++ b/tools/testing/kunit/kunit_parser.py
@@ -45,10 +45,11 @@ class TestStatus(Enum):
FAILURE = auto()
TEST_CRASHED = auto()
NO_TESTS = auto()
+ FAILURE_TO_PARSE_TESTS = auto()
kunit_start_re = re.compile(r'TAP version [0-9]+$')
kunit_end_re = re.compile('(List of all partitions:|'
- 'Kernel panic - not syncing: VFS:|reboot: System halted)')
+ 'Kernel panic - not syncing: VFS:)')
def isolate_kunit_output(kernel_output):
started = False
@@ -109,7 +110,7 @@ OkNotOkResult = namedtuple('OkNotOkResult', ['is_ok','description', 'text'])
OK_NOT_OK_SUBTEST = re.compile(r'^[\s]+(ok|not ok) [0-9]+ - (.*)$')
-OK_NOT_OK_MODULE = re.compile(r'^(ok|not ok) [0-9]+ - (.*)$')
+OK_NOT_OK_MODULE = re.compile(r'^(ok|not ok) ([0-9]+) - (.*)$')
def parse_ok_not_ok_test_case(lines: List[str], test_case: TestCase) -> bool:
save_non_diagnositic(lines, test_case)
@@ -197,7 +198,9 @@ def max_status(left: TestStatus, right: TestStatus) -> TestStatus:
else:
return TestStatus.SUCCESS
-def parse_ok_not_ok_test_suite(lines: List[str], test_suite: TestSuite) -> bool:
+def parse_ok_not_ok_test_suite(lines: List[str],
+ test_suite: TestSuite,
+ expected_suite_index: int) -> bool:
consume_non_diagnositic(lines)
if not lines:
test_suite.status = TestStatus.TEST_CRASHED
@@ -210,6 +213,12 @@ def parse_ok_not_ok_test_suite(lines: List[str], test_suite: TestSuite) -> bool:
test_suite.status = TestStatus.SUCCESS
else:
test_suite.status = TestStatus.FAILURE
+ suite_index = int(match.group(2))
+ if suite_index != expected_suite_index:
+ print_with_timestamp(
+ red('[ERROR] ') + 'expected_suite_index ' +
+ str(expected_suite_index) + ', but got ' +
+ str(suite_index))
return True
else:
return False
@@ -222,7 +231,7 @@ def bubble_up_test_case_errors(test_suite: TestSuite) -> TestStatus:
max_test_case_status = bubble_up_errors(lambda x: x.status, test_suite.cases)
return max_status(max_test_case_status, test_suite.status)
-def parse_test_suite(lines: List[str]) -> TestSuite:
+def parse_test_suite(lines: List[str], expected_suite_index: int) -> TestSuite:
if not lines:
return None
consume_non_diagnositic(lines)
@@ -241,7 +250,7 @@ def parse_test_suite(lines: List[str]) -> TestSuite:
break
test_suite.cases.append(test_case)
expected_test_case_num -= 1
- if parse_ok_not_ok_test_suite(lines, test_suite):
+ if parse_ok_not_ok_test_suite(lines, test_suite, expected_suite_index):
test_suite.status = bubble_up_test_case_errors(test_suite)
return test_suite
elif not lines:
@@ -261,6 +270,17 @@ def parse_tap_header(lines: List[str]) -> bool:
else:
return False
+TEST_PLAN = re.compile(r'[0-9]+\.\.([0-9]+)')
+
+def parse_test_plan(lines: List[str]) -> int:
+ consume_non_diagnositic(lines)
+ match = TEST_PLAN.match(lines[0])
+ if match:
+ lines.pop(0)
+ return int(match.group(1))
+ else:
+ return None
+
def bubble_up_suite_errors(test_suite_list: List[TestSuite]) -> TestStatus:
return bubble_up_errors(lambda x: x.status, test_suite_list)
@@ -269,19 +289,34 @@ def parse_test_result(lines: List[str]) -> TestResult:
return TestResult(TestStatus.NO_TESTS, [], lines)
consume_non_diagnositic(lines)
if not parse_tap_header(lines):
- return None
+ return TestResult(TestStatus.NO_TESTS, [], lines)
+ expected_test_suite_num = parse_test_plan(lines)
+ if not expected_test_suite_num:
+ return TestResult(TestStatus.FAILURE_TO_PARSE_TESTS, [], lines)
test_suites = []
- test_suite = parse_test_suite(lines)
- while test_suite:
- test_suites.append(test_suite)
- test_suite = parse_test_suite(lines)
- return TestResult(bubble_up_suite_errors(test_suites), test_suites, lines)
+ for i in range(1, expected_test_suite_num + 1):
+ test_suite = parse_test_suite(lines, i)
+ if test_suite:
+ test_suites.append(test_suite)
+ else:
+ print_with_timestamp(
+ red('[ERROR] ') + ' expected ' +
+ str(expected_test_suite_num) +
+ ' test suites, but got ' + str(i - 2))
+ break
+ test_suite = parse_test_suite(lines, -1)
+ if test_suite:
+ print_with_timestamp(red('[ERROR] ') +
+ 'got unexpected test suite: ' + test_suite.name)
+ if test_suites:
+ return TestResult(bubble_up_suite_errors(test_suites), test_suites, lines)
+ else:
+ return TestResult(TestStatus.NO_TESTS, [], lines)
-def parse_run_tests(kernel_output) -> TestResult:
+def print_and_count_results(test_result: TestResult) -> None:
total_tests = 0
failed_tests = 0
crashed_tests = 0
- test_result = parse_test_result(list(isolate_kunit_output(kernel_output)))
for test_suite in test_result.suites:
if test_suite.status == TestStatus.SUCCESS:
print_suite_divider(green('[PASSED] ') + test_suite.name)
@@ -303,6 +338,21 @@ def parse_run_tests(kernel_output) -> TestResult:
print_with_timestamp(red('[FAILED] ') + test_case.name)
print_log(map(yellow, test_case.log))
print_with_timestamp('')
+ return total_tests, failed_tests, crashed_tests
+
+def parse_run_tests(kernel_output) -> TestResult:
+ total_tests = 0
+ failed_tests = 0
+ crashed_tests = 0
+ test_result = parse_test_result(list(isolate_kunit_output(kernel_output)))
+ if test_result.status == TestStatus.NO_TESTS:
+ print(red('[ERROR] ') + yellow('no tests run!'))
+ elif test_result.status == TestStatus.FAILURE_TO_PARSE_TESTS:
+ print(red('[ERROR] ') + yellow('could not parse test results!'))
+ else:
+ (total_tests,
+ failed_tests,
+ crashed_tests) = print_and_count_results(test_result)
print_with_timestamp(DIVIDER)
fmt = green if test_result.status == TestStatus.SUCCESS else red
print_with_timestamp(
diff --git a/tools/testing/kunit/test_data/test_is_test_passed-all_passed.log b/tools/testing/kunit/test_data/test_is_test_passed-all_passed.log
index 62ebc0288355c4b122ccc18ae2505f971efa57bc..bc0dc8fe35b760b1feb74ec419818dbfae1adb5c 100644
GIT binary patch
delta 28
jcmbQmGoME|#4$jjEVZaOGe1wk(1goSPtRy09}gP<dC~`u
delta 23
ecmbQwGmD2W#4$jjEVZaOGe1wk&}5@94;uhhkp{*9
diff --git a/tools/testing/kunit/test_data/test_is_test_passed-crash.log b/tools/testing/kunit/test_data/test_is_test_passed-crash.log
index 0b249870c8be417a5865bd40a24c8597bb7f5ab1..4d97f6708c4a5ad5bb2ac879e12afca6e816d83d 100644
GIT binary patch
delta 15
WcmX>hepY;fFN>j`p3z318g2k9Uj*m?
delta 10
RcmX>renNbL@5Z2NZU7lr1S$Xk
diff --git a/tools/testing/kunit/test_data/test_is_test_passed-failure.log b/tools/testing/kunit/test_data/test_is_test_passed-failure.log
index 9e89d32d5667a59d137f8adacf3a88fdb7f88baf..7a416497e3bec044eefc1535f7d84ee85703ba97 100644
GIT binary patch
delta 28
jcmZ3&yOLKp#4$jjEVZaOGe1wk(1goSPtRy0-!wJ=eKrU$
delta 23
ecmZ3<yM&i7#4$jjEVZaOGe1wk&}5_VG&TTPhX-Z=
--
2.27.0.212.ge8ba1cc988-goog
^ permalink raw reply related
* [PATCH v5 10/12] kunit: Add 'kunit_shutdown' option
From: Brendan Higgins @ 2020-06-26 21:09 UTC (permalink / raw)
To: jdike, richard, anton.ivanov, arnd, keescook, skhan, alan.maguire,
yzaikin, davidgow, akpm, rppt, frowand.list, catalin.marinas,
will, monstr, mpe, benh, paulus, chris, jcmvbkbc
Cc: linux-arch, linux-xtensa, linux-doc, sboyd, gregkh, linuxppc-dev,
linux-um, linux-kernel, Brendan Higgins, mcgrof, linux-kselftest,
logang, linux-arm-kernel, kunit-dev
In-Reply-To: <20200626210917.358969-1-brendanhiggins@google.com>
From: David Gow <davidgow@google.com>
Add a new kernel command-line option, 'kunit_shutdown', which allows the
user to specify that the kernel poweroff, halt, or reboot after
completing all KUnit tests; this is very handy for running KUnit tests
on UML or a VM so that the UML/VM process exits cleanly immediately
after running all tests without needing a special initramfs.
Signed-off-by: David Gow <davidgow@google.com>
Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
Reviewed-by: Stephen Boyd <sboyd@kernel.org>
---
lib/kunit/executor.c | 20 ++++++++++++++++++++
tools/testing/kunit/kunit_kernel.py | 2 +-
tools/testing/kunit/kunit_parser.py | 2 +-
3 files changed, 22 insertions(+), 2 deletions(-)
diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c
index a95742a4ece73..38061d456afb2 100644
--- a/lib/kunit/executor.c
+++ b/lib/kunit/executor.c
@@ -1,5 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
+#include <linux/reboot.h>
#include <kunit/test.h>
/*
@@ -11,6 +12,23 @@ extern struct kunit_suite * const * const __kunit_suites_end[];
#if IS_BUILTIN(CONFIG_KUNIT)
+static char *kunit_shutdown;
+core_param(kunit_shutdown, kunit_shutdown, charp, 0644);
+
+static void kunit_handle_shutdown(void)
+{
+ if (!kunit_shutdown)
+ return;
+
+ if (!strcmp(kunit_shutdown, "poweroff"))
+ kernel_power_off();
+ else if (!strcmp(kunit_shutdown, "halt"))
+ kernel_halt();
+ else if (!strcmp(kunit_shutdown, "reboot"))
+ kernel_restart(NULL);
+
+}
+
static void kunit_print_tap_header(void)
{
struct kunit_suite * const * const *suites, * const *subsuite;
@@ -37,6 +55,8 @@ int kunit_run_all_tests(void)
suites++)
__kunit_test_suites_init(*suites);
+ kunit_handle_shutdown();
+
return 0;
}
diff --git a/tools/testing/kunit/kunit_kernel.py b/tools/testing/kunit/kunit_kernel.py
index 63dbda2d029f6..d6a575f92317c 100644
--- a/tools/testing/kunit/kunit_kernel.py
+++ b/tools/testing/kunit/kunit_kernel.py
@@ -172,7 +172,7 @@ class LinuxSourceTree(object):
return self.validate_config(build_dir)
def run_kernel(self, args=[], build_dir='', timeout=None):
- args.extend(['mem=1G'])
+ args.extend(['mem=1G', 'kunit_shutdown=halt'])
outfile = 'test.log'
self._ops.linux_bin(args, timeout, build_dir, outfile)
subprocess.call(['stty', 'sane'])
diff --git a/tools/testing/kunit/kunit_parser.py b/tools/testing/kunit/kunit_parser.py
index 6d6d94a0ee7db..a8998a5effaad 100644
--- a/tools/testing/kunit/kunit_parser.py
+++ b/tools/testing/kunit/kunit_parser.py
@@ -49,7 +49,7 @@ class TestStatus(Enum):
kunit_start_re = re.compile(r'TAP version [0-9]+$')
kunit_end_re = re.compile('(List of all partitions:|'
- 'Kernel panic - not syncing: VFS:)')
+ 'Kernel panic - not syncing: VFS:|reboot: System halted)')
def isolate_kunit_output(kernel_output):
started = False
--
2.27.0.212.ge8ba1cc988-goog
^ permalink raw reply related
* [PATCH v5 07/12] kunit: test: create a single centralized executor for all tests
From: Brendan Higgins @ 2020-06-26 21:09 UTC (permalink / raw)
To: jdike, richard, anton.ivanov, arnd, keescook, skhan, alan.maguire,
yzaikin, davidgow, akpm, rppt, frowand.list, catalin.marinas,
will, monstr, mpe, benh, paulus, chris, jcmvbkbc
Cc: linux-arch, linux-xtensa, linux-doc, sboyd, gregkh, linuxppc-dev,
linux-um, linux-kernel, Brendan Higgins, mcgrof, linux-kselftest,
logang, linux-arm-kernel, kunit-dev
In-Reply-To: <20200626210917.358969-1-brendanhiggins@google.com>
From: Alan Maguire <alan.maguire@oracle.com>
Add a centralized executor to dispatch tests rather than relying on
late_initcall to schedule each test suite separately. Centralized
execution is for built-in tests only; modules will execute tests when
loaded.
Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
Co-developed-by: Iurii Zaikin <yzaikin@google.com>
Signed-off-by: Iurii Zaikin <yzaikin@google.com>
Co-developed-by: Brendan Higgins <brendanhiggins@google.com>
Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
Reviewed-by: Stephen Boyd <sboyd@kernel.org>
---
include/kunit/test.h | 67 +++++++++++++++++++++++++++++---------------
lib/kunit/Makefile | 3 +-
lib/kunit/executor.c | 28 ++++++++++++++++++
lib/kunit/test.c | 2 +-
4 files changed, 76 insertions(+), 24 deletions(-)
create mode 100644 lib/kunit/executor.c
diff --git a/include/kunit/test.h b/include/kunit/test.h
index 47e61e1d53370..f3e86c3953a2b 100644
--- a/include/kunit/test.h
+++ b/include/kunit/test.h
@@ -224,7 +224,7 @@ size_t kunit_suite_num_test_cases(struct kunit_suite *suite);
unsigned int kunit_test_case_num(struct kunit_suite *suite,
struct kunit_case *test_case);
-int __kunit_test_suites_init(struct kunit_suite **suites);
+int __kunit_test_suites_init(struct kunit_suite * const * const suites);
void __kunit_test_suites_exit(struct kunit_suite **suites);
@@ -237,34 +237,57 @@ void __kunit_test_suites_exit(struct kunit_suite **suites);
* Registers @suites_list with the test framework. See &struct kunit_suite for
* more information.
*
- * When builtin, KUnit tests are all run as late_initcalls; this means
- * that they cannot test anything where tests must run at a different init
- * phase. One significant restriction resulting from this is that KUnit
- * cannot reliably test anything that is initialize in the late_init phase;
- * another is that KUnit is useless to test things that need to be run in
- * an earlier init phase.
- *
- * An alternative is to build the tests as a module. Because modules
- * do not support multiple late_initcall()s, we need to initialize an
- * array of suites for a module.
- *
- * TODO(brendanhiggins@google.com): Don't run all KUnit tests as
- * late_initcalls. I have some future work planned to dispatch all KUnit
- * tests from the same place, and at the very least to do so after
- * everything else is definitely initialized.
+ * If a test suite is built-in, module_init() gets translated into
+ * an initcall which we don't want as the idea is that for builtins
+ * the executor will manage execution. So ensure we do not define
+ * module_{init|exit} functions for the builtin case when registering
+ * suites via kunit_test_suites() below.
*/
-#define kunit_test_suites(suites_list...) \
- static struct kunit_suite *suites[] = {suites_list, NULL}; \
- static int kunit_test_suites_init(void) \
+#ifdef MODULE
+#define kunit_test_suites_for_module(__suites) \
+ static int __init kunit_test_suites_init(void) \
{ \
- return __kunit_test_suites_init(suites); \
+ return __kunit_test_suites_init(__suites); \
} \
- late_initcall(kunit_test_suites_init); \
+ module_init(kunit_test_suites_init); \
+ \
static void __exit kunit_test_suites_exit(void) \
{ \
- return __kunit_test_suites_exit(suites); \
+ return __kunit_test_suites_exit(__suites); \
} \
module_exit(kunit_test_suites_exit)
+#else
+#define kunit_test_suites_for_module(__suites)
+#endif /* MODULE */
+
+#define __kunit_test_suites(unique_array, unique_suites, ...) \
+ static struct kunit_suite *unique_array[] = { __VA_ARGS__, NULL }; \
+ kunit_test_suites_for_module(unique_array); \
+ static struct kunit_suite **unique_suites \
+ __used __section(.kunit_test_suites) = unique_array
+
+/**
+ * kunit_test_suites() - used to register one or more &struct kunit_suite
+ * with KUnit.
+ *
+ * @suites: a statically allocated list of &struct kunit_suite.
+ *
+ * Registers @suites with the test framework. See &struct kunit_suite for
+ * more information.
+ *
+ * When builtin, KUnit tests are all run via executor; this is done
+ * by placing the array of struct kunit_suite * in the .kunit_test_suites
+ * ELF section.
+ *
+ * An alternative is to build the tests as a module. Because modules do not
+ * support multiple initcall()s, we need to initialize an array of suites for a
+ * module.
+ *
+ */
+#define kunit_test_suites(...) \
+ __kunit_test_suites(__UNIQUE_ID(array), \
+ __UNIQUE_ID(suites), \
+ __VA_ARGS__)
#define kunit_test_suite(suite) kunit_test_suites(&suite)
diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
index 724b94311ca36..c49f4ffb6273a 100644
--- a/lib/kunit/Makefile
+++ b/lib/kunit/Makefile
@@ -3,7 +3,8 @@ obj-$(CONFIG_KUNIT) += kunit.o
kunit-objs += test.o \
string-stream.o \
assert.o \
- try-catch.o
+ try-catch.o \
+ executor.o
ifeq ($(CONFIG_KUNIT_DEBUGFS),y)
kunit-objs += debugfs.o
diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c
new file mode 100644
index 0000000000000..7015e7328dce7
--- /dev/null
+++ b/lib/kunit/executor.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <kunit/test.h>
+
+/*
+ * These symbols point to the .kunit_test_suites section and are defined in
+ * include/asm-generic/vmlinux.lds.h, and consequently must be extern.
+ */
+extern struct kunit_suite * const * const __kunit_suites_start[];
+extern struct kunit_suite * const * const __kunit_suites_end[];
+
+#if IS_BUILTIN(CONFIG_KUNIT)
+
+static int kunit_run_all_tests(void)
+{
+ struct kunit_suite * const * const *suites;
+
+ for (suites = __kunit_suites_start;
+ suites < __kunit_suites_end;
+ suites++)
+ __kunit_test_suites_init(*suites);
+
+ return 0;
+}
+
+late_initcall(kunit_run_all_tests);
+
+#endif /* IS_BUILTIN(CONFIG_KUNIT) */
diff --git a/lib/kunit/test.c b/lib/kunit/test.c
index ccb2ffad8dcfa..918dff400a9d7 100644
--- a/lib/kunit/test.c
+++ b/lib/kunit/test.c
@@ -380,7 +380,7 @@ static void kunit_init_suite(struct kunit_suite *suite)
kunit_debugfs_create_suite(suite);
}
-int __kunit_test_suites_init(struct kunit_suite **suites)
+int __kunit_test_suites_init(struct kunit_suite * const * const suites)
{
unsigned int i;
--
2.27.0.212.ge8ba1cc988-goog
^ permalink raw reply related
* [PATCH v5 06/12] arch: xtensa: add linker section for KUnit test suites
From: Brendan Higgins @ 2020-06-26 21:09 UTC (permalink / raw)
To: jdike, richard, anton.ivanov, arnd, keescook, skhan, alan.maguire,
yzaikin, davidgow, akpm, rppt, frowand.list, catalin.marinas,
will, monstr, mpe, benh, paulus, chris, jcmvbkbc
Cc: linux-arch, linux-xtensa, linux-doc, sboyd, gregkh, linuxppc-dev,
linux-um, linux-kernel, Brendan Higgins, mcgrof, linux-kselftest,
logang, linux-arm-kernel, kunit-dev
In-Reply-To: <20200626210917.358969-1-brendanhiggins@google.com>
Add a linker section to xtensa where KUnit can put references to its
test suites. This patch is an early step in transitioning to dispatching
all KUnit tests from a centralized executor rather than having each as
its own separate late_initcall.
Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
---
arch/xtensa/kernel/vmlinux.lds.S | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S
index d23a6e38f0625..9aec4ef67d0b0 100644
--- a/arch/xtensa/kernel/vmlinux.lds.S
+++ b/arch/xtensa/kernel/vmlinux.lds.S
@@ -216,6 +216,10 @@ SECTIONS
INIT_RAM_FS
}
+ .kunit_test_suites : {
+ KUNIT_TEST_SUITES
+ }
+
PERCPU_SECTION(XCHAL_ICACHE_LINESIZE)
/* We need this dummy segment here */
--
2.27.0.212.ge8ba1cc988-goog
^ permalink raw reply related
* [PATCH v5 11/12] Documentation: Add kunit_shutdown to kernel-parameters.txt
From: Brendan Higgins @ 2020-06-26 21:09 UTC (permalink / raw)
To: jdike, richard, anton.ivanov, arnd, keescook, skhan, alan.maguire,
yzaikin, davidgow, akpm, rppt, frowand.list, catalin.marinas,
will, monstr, mpe, benh, paulus, chris, jcmvbkbc
Cc: linux-arch, linux-xtensa, linux-doc, sboyd, gregkh, linuxppc-dev,
linux-um, linux-kernel, Brendan Higgins, mcgrof, linux-kselftest,
logang, linux-arm-kernel, kunit-dev
In-Reply-To: <20200626210917.358969-1-brendanhiggins@google.com>
Add kunit_shutdown, an option to specify that the kernel shutsdown after
running KUnit tests, to the kernel-parameters.txt documentation.
Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
Reviewed-by: Stephen Boyd <sboyd@kernel.org>
---
Documentation/admin-guide/kernel-parameters.txt | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index fb95fad81c79a..e7d5eb7249e7f 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -2183,6 +2183,14 @@
0: force disabled
1: force enabled
+ kunit_shutdown=[KERNEL UNIT TESTING FRAMEWORK] Shutdown kernel after
+ running built-in tests. Tests configured as modules will
+ not be run.
+ Default: (flag not present) don't shutdown
+ poweroff: poweroff the kernel after running tests
+ halt: halt the kernel after running tests
+ reboot: reboot the kernel after running tests
+
kvm.ignore_msrs=[KVM] Ignore guest accesses to unhandled MSRs.
Default is 0 (don't ignore, but inject #GP)
--
2.27.0.212.ge8ba1cc988-goog
^ permalink raw reply related
* Re: [PATCH v5 01/12] vmlinux.lds.h: add linker section for KUnit test suites
From: Kees Cook @ 2020-06-26 21:20 UTC (permalink / raw)
To: Brendan Higgins
Cc: linux-doc, catalin.marinas, jcmvbkbc, will, paulus,
linux-kselftest, frowand.list, anton.ivanov, linux-arch, richard,
rppt, yzaikin, linux-xtensa, arnd, jdike, linux-um, linuxppc-dev,
davidgow, skhan, linux-arm-kernel, kunit-dev, chris, monstr,
sboyd, gregkh, linux-kernel, mcgrof, alan.maguire, akpm, logang
In-Reply-To: <20200626210917.358969-2-brendanhiggins@google.com>
On Fri, Jun 26, 2020 at 02:09:06PM -0700, Brendan Higgins wrote:
> Add a linker section where KUnit can put references to its test suites.
> This patch is the first step in transitioning to dispatching all KUnit
> tests from a centralized executor rather than having each as its own
> separate late_initcall.
>
> Co-developed-by: Iurii Zaikin <yzaikin@google.com>
> Signed-off-by: Iurii Zaikin <yzaikin@google.com>
> Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
> Reviewed-by: Stephen Boyd <sboyd@kernel.org>
> ---
> include/asm-generic/vmlinux.lds.h | 8 ++++++++
> 1 file changed, 8 insertions(+)
>
> diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> index db600ef218d7d..4f9b036fc9616 100644
> --- a/include/asm-generic/vmlinux.lds.h
> +++ b/include/asm-generic/vmlinux.lds.h
> @@ -881,6 +881,13 @@
> KEEP(*(.con_initcall.init)) \
> __con_initcall_end = .;
>
> +/* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */
Nit on naming:
> +#define KUNIT_TEST_SUITES \
I would call this KUNIT_TABLE to maintain the same names as other things
of this nature.
> + . = ALIGN(8); \
> + __kunit_suites_start = .; \
> + KEEP(*(.kunit_test_suites)) \
> + __kunit_suites_end = .;
> +
> #ifdef CONFIG_BLK_DEV_INITRD
> #define INIT_RAM_FS \
> . = ALIGN(4); \
> @@ -1056,6 +1063,7 @@
> INIT_CALLS \
> CON_INITCALL \
> INIT_RAM_FS \
> + KUNIT_TEST_SUITES \
> }
Nack: this must be in INIT_DATA, not in INIT_DATA_SECTION. Not all
architectures use the INIT_DATA_SECTION macro (e.g. arm64), but everything
uses INIT_DATA.
--
Kees Cook
^ permalink raw reply
* Re: [PATCH v5 02/12] arch: arm64: add linker section for KUnit test suites
From: Kees Cook @ 2020-06-26 21:20 UTC (permalink / raw)
To: Brendan Higgins
Cc: linux-doc, catalin.marinas, jcmvbkbc, will, paulus,
linux-kselftest, frowand.list, anton.ivanov, linux-arch, richard,
rppt, yzaikin, linux-xtensa, arnd, jdike, linux-um, linuxppc-dev,
davidgow, skhan, linux-arm-kernel, kunit-dev, chris, monstr,
sboyd, gregkh, linux-kernel, mcgrof, alan.maguire, akpm, logang
In-Reply-To: <20200626210917.358969-3-brendanhiggins@google.com>
On Fri, Jun 26, 2020 at 02:09:07PM -0700, Brendan Higgins wrote:
> Add a linker section to arm64 where KUnit can put references to its test
> suites. This patch is an early step in transitioning to dispatching all
> KUnit tests from a centralized executor rather than having each as its
> own separate late_initcall.
>
> Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
> ---
> arch/arm64/kernel/vmlinux.lds.S | 3 +++
> 1 file changed, 3 insertions(+)
>
> diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> index 6827da7f3aa54..a1cae9cc655d7 100644
> --- a/arch/arm64/kernel/vmlinux.lds.S
> +++ b/arch/arm64/kernel/vmlinux.lds.S
> @@ -181,6 +181,9 @@ SECTIONS
> INIT_RAM_FS
> *(.init.rodata.* .init.bss) /* from the EFI stub */
> }
> + .kunit_test_suites : {
> + KUNIT_TEST_SUITES
> + }
See my reply to 01/12. Then this patch can be dropped. :)
> .exit.data : {
> EXIT_DATA
> }
> --
> 2.27.0.212.ge8ba1cc988-goog
>
--
Kees Cook
^ permalink raw reply
* Re: [PATCH v5 01/12] vmlinux.lds.h: add linker section for KUnit test suites
From: Brendan Higgins @ 2020-06-26 21:22 UTC (permalink / raw)
To: Kees Cook
Cc: open list:DOCUMENTATION, catalin.marinas, jcmvbkbc, will, paulus,
open list:KERNEL SELFTEST FRAMEWORK, Frank Rowand, Anton Ivanov,
linux-arch, Richard Weinberger, rppt, Iurii Zaikin, linux-xtensa,
Arnd Bergmann, Jeff Dike, linux-um, linuxppc-dev, David Gow,
Shuah Khan, Linux ARM, KUnit Development, chris, monstr,
Stephen Boyd, Greg KH, Linux Kernel Mailing List,
Luis Chamberlain, Alan Maguire, Andrew Morton, Logan Gunthorpe
In-Reply-To: <202006261416.F4EAAE47E3@keescook>
On Fri, Jun 26, 2020 at 2:20 PM Kees Cook <keescook@chromium.org> wrote:
>
> On Fri, Jun 26, 2020 at 02:09:06PM -0700, Brendan Higgins wrote:
> > Add a linker section where KUnit can put references to its test suites.
> > This patch is the first step in transitioning to dispatching all KUnit
> > tests from a centralized executor rather than having each as its own
> > separate late_initcall.
> >
> > Co-developed-by: Iurii Zaikin <yzaikin@google.com>
> > Signed-off-by: Iurii Zaikin <yzaikin@google.com>
> > Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
> > Reviewed-by: Stephen Boyd <sboyd@kernel.org>
> > ---
> > include/asm-generic/vmlinux.lds.h | 8 ++++++++
> > 1 file changed, 8 insertions(+)
> >
> > diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
> > index db600ef218d7d..4f9b036fc9616 100644
> > --- a/include/asm-generic/vmlinux.lds.h
> > +++ b/include/asm-generic/vmlinux.lds.h
> > @@ -881,6 +881,13 @@
> > KEEP(*(.con_initcall.init)) \
> > __con_initcall_end = .;
> >
> > +/* Alignment must be consistent with (kunit_suite *) in include/kunit/test.h */
>
> Nit on naming:
>
> > +#define KUNIT_TEST_SUITES \
>
> I would call this KUNIT_TABLE to maintain the same names as other things
> of this nature.
>
> > + . = ALIGN(8); \
> > + __kunit_suites_start = .; \
> > + KEEP(*(.kunit_test_suites)) \
> > + __kunit_suites_end = .;
> > +
> > #ifdef CONFIG_BLK_DEV_INITRD
> > #define INIT_RAM_FS \
> > . = ALIGN(4); \
> > @@ -1056,6 +1063,7 @@
> > INIT_CALLS \
> > CON_INITCALL \
> > INIT_RAM_FS \
> > + KUNIT_TEST_SUITES \
> > }
>
> Nack: this must be in INIT_DATA, not in INIT_DATA_SECTION. Not all
> architectures use the INIT_DATA_SECTION macro (e.g. arm64), but everything
> uses INIT_DATA.
Oh, maybe that would eliminate the need for the other linkerscript
patches? That would be nice.
Alright, will fix.
^ permalink raw reply
* Re: [PATCH v5 02/12] arch: arm64: add linker section for KUnit test suites
From: Brendan Higgins @ 2020-06-26 21:23 UTC (permalink / raw)
To: Kees Cook
Cc: open list:DOCUMENTATION, catalin.marinas, jcmvbkbc, will, paulus,
open list:KERNEL SELFTEST FRAMEWORK, Frank Rowand, Anton Ivanov,
linux-arch, Richard Weinberger, rppt, Iurii Zaikin, linux-xtensa,
Arnd Bergmann, Jeff Dike, linux-um, linuxppc-dev, David Gow,
Shuah Khan, Linux ARM, KUnit Development, chris, monstr,
Stephen Boyd, Greg KH, Linux Kernel Mailing List,
Luis Chamberlain, Alan Maguire, Andrew Morton, Logan Gunthorpe
In-Reply-To: <202006261420.02E8E62@keescook>
On Fri, Jun 26, 2020 at 2:20 PM Kees Cook <keescook@chromium.org> wrote:
>
> On Fri, Jun 26, 2020 at 02:09:07PM -0700, Brendan Higgins wrote:
> > Add a linker section to arm64 where KUnit can put references to its test
> > suites. This patch is an early step in transitioning to dispatching all
> > KUnit tests from a centralized executor rather than having each as its
> > own separate late_initcall.
> >
> > Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
> > ---
> > arch/arm64/kernel/vmlinux.lds.S | 3 +++
> > 1 file changed, 3 insertions(+)
> >
> > diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S
> > index 6827da7f3aa54..a1cae9cc655d7 100644
> > --- a/arch/arm64/kernel/vmlinux.lds.S
> > +++ b/arch/arm64/kernel/vmlinux.lds.S
> > @@ -181,6 +181,9 @@ SECTIONS
> > INIT_RAM_FS
> > *(.init.rodata.* .init.bss) /* from the EFI stub */
> > }
> > + .kunit_test_suites : {
> > + KUNIT_TEST_SUITES
> > + }
>
> See my reply to 01/12. Then this patch can be dropped. :)
Sweet, presumably this one and others.
> > .exit.data : {
> > EXIT_DATA
> > }
> > --
> > 2.27.0.212.ge8ba1cc988-goog
> >
>
> --
> Kees Cook
^ permalink raw reply
* Re: [PATCH v5 07/12] kunit: test: create a single centralized executor for all tests
From: Kees Cook @ 2020-06-26 21:29 UTC (permalink / raw)
To: Brendan Higgins
Cc: linux-doc, catalin.marinas, jcmvbkbc, will, paulus,
linux-kselftest, frowand.list, anton.ivanov, linux-arch, richard,
rppt, yzaikin, linux-xtensa, arnd, jdike, linux-um, linuxppc-dev,
davidgow, skhan, linux-arm-kernel, kunit-dev, chris, monstr,
sboyd, gregkh, linux-kernel, mcgrof, alan.maguire, akpm, logang
In-Reply-To: <20200626210917.358969-8-brendanhiggins@google.com>
On Fri, Jun 26, 2020 at 02:09:12PM -0700, Brendan Higgins wrote:
> From: Alan Maguire <alan.maguire@oracle.com>
>
> Add a centralized executor to dispatch tests rather than relying on
> late_initcall to schedule each test suite separately. Centralized
> execution is for built-in tests only; modules will execute tests when
> loaded.
>
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Co-developed-by: Iurii Zaikin <yzaikin@google.com>
> Signed-off-by: Iurii Zaikin <yzaikin@google.com>
> Co-developed-by: Brendan Higgins <brendanhiggins@google.com>
> Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
> Reviewed-by: Stephen Boyd <sboyd@kernel.org>
> ---
> include/kunit/test.h | 67 +++++++++++++++++++++++++++++---------------
> lib/kunit/Makefile | 3 +-
> lib/kunit/executor.c | 28 ++++++++++++++++++
> lib/kunit/test.c | 2 +-
> 4 files changed, 76 insertions(+), 24 deletions(-)
> create mode 100644 lib/kunit/executor.c
>
> diff --git a/include/kunit/test.h b/include/kunit/test.h
> index 47e61e1d53370..f3e86c3953a2b 100644
> --- a/include/kunit/test.h
> +++ b/include/kunit/test.h
> @@ -224,7 +224,7 @@ size_t kunit_suite_num_test_cases(struct kunit_suite *suite);
> unsigned int kunit_test_case_num(struct kunit_suite *suite,
> struct kunit_case *test_case);
>
> -int __kunit_test_suites_init(struct kunit_suite **suites);
> +int __kunit_test_suites_init(struct kunit_suite * const * const suites);
>
> void __kunit_test_suites_exit(struct kunit_suite **suites);
>
> @@ -237,34 +237,57 @@ void __kunit_test_suites_exit(struct kunit_suite **suites);
> * Registers @suites_list with the test framework. See &struct kunit_suite for
> * more information.
> *
> - * When builtin, KUnit tests are all run as late_initcalls; this means
> - * that they cannot test anything where tests must run at a different init
> - * phase. One significant restriction resulting from this is that KUnit
> - * cannot reliably test anything that is initialize in the late_init phase;
> - * another is that KUnit is useless to test things that need to be run in
> - * an earlier init phase.
> - *
> - * An alternative is to build the tests as a module. Because modules
> - * do not support multiple late_initcall()s, we need to initialize an
> - * array of suites for a module.
> - *
> - * TODO(brendanhiggins@google.com): Don't run all KUnit tests as
> - * late_initcalls. I have some future work planned to dispatch all KUnit
> - * tests from the same place, and at the very least to do so after
> - * everything else is definitely initialized.
> + * If a test suite is built-in, module_init() gets translated into
> + * an initcall which we don't want as the idea is that for builtins
> + * the executor will manage execution. So ensure we do not define
> + * module_{init|exit} functions for the builtin case when registering
> + * suites via kunit_test_suites() below.
> */
> -#define kunit_test_suites(suites_list...) \
> - static struct kunit_suite *suites[] = {suites_list, NULL}; \
> - static int kunit_test_suites_init(void) \
> +#ifdef MODULE
> +#define kunit_test_suites_for_module(__suites) \
> + static int __init kunit_test_suites_init(void) \
> { \
> - return __kunit_test_suites_init(suites); \
> + return __kunit_test_suites_init(__suites); \
> } \
> - late_initcall(kunit_test_suites_init); \
> + module_init(kunit_test_suites_init); \
> + \
> static void __exit kunit_test_suites_exit(void) \
> { \
> - return __kunit_test_suites_exit(suites); \
> + return __kunit_test_suites_exit(__suites); \
> } \
> module_exit(kunit_test_suites_exit)
> +#else
> +#define kunit_test_suites_for_module(__suites)
> +#endif /* MODULE */
> +
> +#define __kunit_test_suites(unique_array, unique_suites, ...) \
> + static struct kunit_suite *unique_array[] = { __VA_ARGS__, NULL }; \
> + kunit_test_suites_for_module(unique_array); \
> + static struct kunit_suite **unique_suites \
> + __used __section(.kunit_test_suites) = unique_array
> +
> +/**
> + * kunit_test_suites() - used to register one or more &struct kunit_suite
> + * with KUnit.
> + *
> + * @suites: a statically allocated list of &struct kunit_suite.
> + *
> + * Registers @suites with the test framework. See &struct kunit_suite for
> + * more information.
> + *
> + * When builtin, KUnit tests are all run via executor; this is done
> + * by placing the array of struct kunit_suite * in the .kunit_test_suites
> + * ELF section.
> + *
> + * An alternative is to build the tests as a module. Because modules do not
> + * support multiple initcall()s, we need to initialize an array of suites for a
> + * module.
> + *
> + */
> +#define kunit_test_suites(...) \
> + __kunit_test_suites(__UNIQUE_ID(array), \
> + __UNIQUE_ID(suites), \
> + __VA_ARGS__)
>
> #define kunit_test_suite(suite) kunit_test_suites(&suite)
>
> diff --git a/lib/kunit/Makefile b/lib/kunit/Makefile
> index 724b94311ca36..c49f4ffb6273a 100644
> --- a/lib/kunit/Makefile
> +++ b/lib/kunit/Makefile
> @@ -3,7 +3,8 @@ obj-$(CONFIG_KUNIT) += kunit.o
> kunit-objs += test.o \
> string-stream.o \
> assert.o \
> - try-catch.o
> + try-catch.o \
> + executor.o
>
> ifeq ($(CONFIG_KUNIT_DEBUGFS),y)
> kunit-objs += debugfs.o
> diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c
> new file mode 100644
> index 0000000000000..7015e7328dce7
> --- /dev/null
> +++ b/lib/kunit/executor.c
> @@ -0,0 +1,28 @@
> +// SPDX-License-Identifier: GPL-2.0
> +
> +#include <kunit/test.h>
> +
> +/*
> + * These symbols point to the .kunit_test_suites section and are defined in
> + * include/asm-generic/vmlinux.lds.h, and consequently must be extern.
> + */
> +extern struct kunit_suite * const * const __kunit_suites_start[];
> +extern struct kunit_suite * const * const __kunit_suites_end[];
I would expect these to be in include/asm-generic/sections.h but I guess
it's not required.
Reviewed-by: Kees Cook <keescook@chromium.org>
--
Kees Cook
^ permalink raw reply
* Re: [PATCH v5 06/12] arch: xtensa: add linker section for KUnit test suites
From: Kees Cook @ 2020-06-26 21:30 UTC (permalink / raw)
To: Brendan Higgins
Cc: linux-doc, catalin.marinas, jcmvbkbc, will, paulus,
linux-kselftest, frowand.list, anton.ivanov, linux-arch, richard,
rppt, yzaikin, linux-xtensa, arnd, jdike, linux-um, linuxppc-dev,
davidgow, skhan, linux-arm-kernel, kunit-dev, chris, monstr,
sboyd, gregkh, linux-kernel, mcgrof, alan.maguire, akpm, logang
In-Reply-To: <20200626210917.358969-7-brendanhiggins@google.com>
On Fri, Jun 26, 2020 at 02:09:11PM -0700, Brendan Higgins wrote:
> Add a linker section to xtensa where KUnit can put references to its
> test suites. This patch is an early step in transitioning to dispatching
> all KUnit tests from a centralized executor rather than having each as
> its own separate late_initcall.
>
> Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
> ---
> arch/xtensa/kernel/vmlinux.lds.S | 4 ++++
If you ever find yourself modifying multiple arch linker scripts for a
series, something has gone wrong. ;)
--
Kees Cook
^ permalink raw reply
* Re: [PATCH v5 08/12] init: main: add KUnit to kernel init
From: Kees Cook @ 2020-06-26 21:33 UTC (permalink / raw)
To: Brendan Higgins
Cc: linux-doc, catalin.marinas, jcmvbkbc, will, paulus,
linux-kselftest, frowand.list, anton.ivanov, linux-arch, richard,
rppt, yzaikin, linux-xtensa, arnd, jdike, linux-um, linuxppc-dev,
davidgow, skhan, linux-arm-kernel, kunit-dev, chris, monstr,
sboyd, gregkh, linux-kernel, mcgrof, alan.maguire, akpm, logang
In-Reply-To: <20200626210917.358969-9-brendanhiggins@google.com>
On Fri, Jun 26, 2020 at 02:09:13PM -0700, Brendan Higgins wrote:
> Remove KUnit from init calls entirely, instead call directly from
> kernel_init().
>
> Co-developed-by: Alan Maguire <alan.maguire@oracle.com>
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
> Reviewed-by: Stephen Boyd <sboyd@kernel.org>
Reviewed-by: Kees Cook <keescook@chromium.org>
--
Kees Cook
^ permalink raw reply
* Re: [PATCH v5 09/12] kunit: test: add test plan to KUnit TAP format
From: Kees Cook @ 2020-06-26 21:35 UTC (permalink / raw)
To: Brendan Higgins
Cc: linux-doc, catalin.marinas, jcmvbkbc, will, paulus,
linux-kselftest, frowand.list, anton.ivanov, linux-arch, richard,
rppt, yzaikin, linux-xtensa, arnd, jdike, linux-um, linuxppc-dev,
davidgow, skhan, linux-arm-kernel, kunit-dev, chris, monstr,
sboyd, gregkh, linux-kernel, mcgrof, alan.maguire, akpm, logang
In-Reply-To: <20200626210917.358969-10-brendanhiggins@google.com>
On Fri, Jun 26, 2020 at 02:09:14PM -0700, Brendan Higgins wrote:
> TAP 14 allows an optional test plan to be emitted before the start of
> the start of testing[1]; this is valuable because it makes it possible
> for a test harness to detect whether the number of tests run matches the
> number of tests expected to be run, ensuring that no tests silently
> failed.
>
> Link[1]: https://github.com/isaacs/testanything.github.io/blob/tap14/tap-version-14-specification.md#the-plan
> Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
> Reviewed-by: Stephen Boyd <sboyd@kernel.org>
Look good, except...
> diff --git a/tools/testing/kunit/test_data/test_is_test_passed-all_passed.log b/tools/testing/kunit/test_data/test_is_test_passed-all_passed.log
> index 62ebc0288355c4b122ccc18ae2505f971efa57bc..bc0dc8fe35b760b1feb74ec419818dbfae1adb5c 100644
> GIT binary patch
> delta 28
> jcmbQmGoME|#4$jjEVZaOGe1wk(1goSPtRy09}gP<dC~`u
>
> delta 23
> ecmbQwGmD2W#4$jjEVZaOGe1wk&}5@94;uhhkp{*9
>
> diff --git a/tools/testing/kunit/test_data/test_is_test_passed-crash.log b/tools/testing/kunit/test_data/test_is_test_passed-crash.log
> index 0b249870c8be417a5865bd40a24c8597bb7f5ab1..4d97f6708c4a5ad5bb2ac879e12afca6e816d83d 100644
> GIT binary patch
> delta 15
> WcmX>hepY;fFN>j`p3z318g2k9Uj*m?
>
> delta 10
> RcmX>renNbL@5Z2NZU7lr1S$Xk
>
> diff --git a/tools/testing/kunit/test_data/test_is_test_passed-failure.log b/tools/testing/kunit/test_data/test_is_test_passed-failure.log
> index 9e89d32d5667a59d137f8adacf3a88fdb7f88baf..7a416497e3bec044eefc1535f7d84ee85703ba97 100644
> GIT binary patch
> delta 28
> jcmZ3&yOLKp#4$jjEVZaOGe1wk(1goSPtRy0-!wJ=eKrU$
>
> delta 23
> ecmZ3<yM&i7#4$jjEVZaOGe1wk&}5_VG&TTPhX-Z=
What is happening here?? Those logs appear as text to me. Why did git
freak out?
--
Kees Cook
^ permalink raw reply
* Re: [PATCH v5 10/12] kunit: Add 'kunit_shutdown' option
From: Kees Cook @ 2020-06-26 21:40 UTC (permalink / raw)
To: Brendan Higgins
Cc: linux-doc, catalin.marinas, jcmvbkbc, will, paulus,
linux-kselftest, frowand.list, anton.ivanov, linux-arch, richard,
rppt, yzaikin, linux-xtensa, arnd, jdike, linux-um, linuxppc-dev,
davidgow, skhan, linux-arm-kernel, kunit-dev, chris, monstr,
sboyd, gregkh, linux-kernel, mcgrof, alan.maguire, akpm, logang
In-Reply-To: <20200626210917.358969-11-brendanhiggins@google.com>
On Fri, Jun 26, 2020 at 02:09:15PM -0700, Brendan Higgins wrote:
> From: David Gow <davidgow@google.com>
>
> Add a new kernel command-line option, 'kunit_shutdown', which allows the
> user to specify that the kernel poweroff, halt, or reboot after
> completing all KUnit tests; this is very handy for running KUnit tests
> on UML or a VM so that the UML/VM process exits cleanly immediately
> after running all tests without needing a special initramfs.
>
> Signed-off-by: David Gow <davidgow@google.com>
> Signed-off-by: Brendan Higgins <brendanhiggins@google.com>
> Reviewed-by: Stephen Boyd <sboyd@kernel.org>
> ---
> lib/kunit/executor.c | 20 ++++++++++++++++++++
> tools/testing/kunit/kunit_kernel.py | 2 +-
> tools/testing/kunit/kunit_parser.py | 2 +-
> 3 files changed, 22 insertions(+), 2 deletions(-)
>
> diff --git a/lib/kunit/executor.c b/lib/kunit/executor.c
> index a95742a4ece73..38061d456afb2 100644
> --- a/lib/kunit/executor.c
> +++ b/lib/kunit/executor.c
> @@ -1,5 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0
>
> +#include <linux/reboot.h>
> #include <kunit/test.h>
>
> /*
> @@ -11,6 +12,23 @@ extern struct kunit_suite * const * const __kunit_suites_end[];
>
> #if IS_BUILTIN(CONFIG_KUNIT)
>
> +static char *kunit_shutdown;
> +core_param(kunit_shutdown, kunit_shutdown, charp, 0644);
> +
> +static void kunit_handle_shutdown(void)
> +{
> + if (!kunit_shutdown)
> + return;
> +
> + if (!strcmp(kunit_shutdown, "poweroff"))
> + kernel_power_off();
> + else if (!strcmp(kunit_shutdown, "halt"))
> + kernel_halt();
> + else if (!strcmp(kunit_shutdown, "reboot"))
> + kernel_restart(NULL);
> +
> +}
If you have patches that do something just before the initrd, and then
you add more patches to shut down immediately after an initrd, people
may ask you to just use an initrd instead of filling the kernel with
these changes...
I mean, I get it, but it's not hard to make an initrd that poke a sysctl
to start the tests...
In fact, you don't even need a initrd to poke sysctls these days.
--
Kees Cook
^ permalink raw reply
* Re: [PATCH v5 00/12] kunit: create a centralized executor to dispatch all KUnit tests
From: Kees Cook @ 2020-06-26 21:52 UTC (permalink / raw)
To: Brendan Higgins
Cc: linux-doc, catalin.marinas, jcmvbkbc, will, paulus,
linux-kselftest, frowand.list, anton.ivanov, linux-arch, richard,
rppt, yzaikin, linux-xtensa, arnd, jdike, linux-um, linuxppc-dev,
davidgow, skhan, linux-arm-kernel, kunit-dev, chris, monstr,
sboyd, gregkh, linux-kernel, mcgrof, alan.maguire, akpm, logang
In-Reply-To: <20200626210917.358969-1-brendanhiggins@google.com>
On Fri, Jun 26, 2020 at 02:09:05PM -0700, Brendan Higgins wrote:
> This patchset adds a centralized executor to dispatch tests rather than
> relying on late_initcall to schedule each test suite separately along
> with a couple of new features that depend on it.
So, the new section looks fine to me (modulo the INIT_DATA change). The
plumbing to start the tests, though, I think is redundant. Why not just
add a sysctl that starts all known tests?
That way you don't need the plumbing into init/main.c, and you can have
a mode where builtin tests can be started on a fully booted system too.
i.e. boot with "sysctl.kernel.kunit=start" or when fully booted with
"echo start > /proc/sys/kernel/kunit"
And instead of the kunit-specific halt/reboot stuff, how about moving
/proc/sysrq-trigger into /proc/sys instead? Then you (or anything) could
do:
sysctl.kernel.kunit=start sysctl.kernel.sysrq-trigger=b
--
Kees Cook
^ permalink raw reply
* [PATCH 16/26] mm/powerpc: Use general page fault accounting
From: Peter Xu @ 2020-06-26 22:36 UTC (permalink / raw)
To: linux-mm, linux-kernel
Cc: Andrea Arcangeli, Linus Torvalds, linuxppc-dev, Peter Xu,
Paul Mackerras, Andrew Morton, Will Deacon, Gerald Schaefer
In-Reply-To: <20200626223130.199227-1-peterx@redhat.com>
Use the general page fault accounting by passing regs into handle_mm_fault().
CC: Michael Ellerman <mpe@ellerman.id.au>
CC: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Paul Mackerras <paulus@samba.org>
CC: linuxppc-dev@lists.ozlabs.org
Signed-off-by: Peter Xu <peterx@redhat.com>
---
arch/powerpc/mm/fault.c | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 992b10c3761c..e325d13efaf5 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -563,7 +563,7 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
* make sure we exit gracefully rather than endlessly redo
* the fault.
*/
- fault = handle_mm_fault(vma, address, flags, NULL);
+ fault = handle_mm_fault(vma, address, flags, regs);
#ifdef CONFIG_PPC_MEM_KEYS
/*
@@ -604,14 +604,9 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
/*
* Major/minor page fault accounting.
*/
- if (major) {
- current->maj_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MAJ, 1, regs, address);
+ if (major)
cmo_account_page_fault();
- } else {
- current->min_flt++;
- perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS_MIN, 1, regs, address);
- }
+
return 0;
}
NOKPROBE_SYMBOL(__do_page_fault);
--
2.26.2
^ permalink raw reply related
* Re: [PATCH 16/17] arch: remove HAVE_COPY_THREAD_TLS
From: Greentime Hu @ 2020-06-27 3:06 UTC (permalink / raw)
To: Christian Brauner
Cc: Rich Felker, linux-sh, Peter Zijlstra, Catalin Marinas,
Heiko Carstens, linux-mips, James E.J. Bottomley, Guo Ren,
linux-csky, sparclinux, linux-hexagon, linux-riscv, Vincent Chen,
Will Deacon, Thomas Gleixner, Anton Ivanov, Jonas Bonn,
linux-s390, linux-ia64, linux-c6x-dev, Brian Cain, linux-xtensa,
Helge Deller, x86, Russell King, Ley Foon Tan, Mike Rapoport,
Christian Borntraeger, Ingo Molnar, Geert Uytterhoeven,
linux-parisc, Mark Salter, Matt Turner, linux-snps-arc,
uclinux-h8-devel, Fenghua Yu, Albert Ou, Kees Cook, Vasily Gorbik,
Jeff Dike, linux-alpha, linux-um, linuxppc-dev, Aurelien Jacquiot,
linux-m68k, Thomas Bogendoerfer, Ivan Kokshaysky, Al Viro,
Paul Walmsley, Stafford Horne, Stefan Kristiansson, Guan Xuetao,
linux-arm-kernel, Richard Henderson, Michal Simek, Tony Luck,
Yoshinori Sato, Nick Hu, Vineet Gupta, Linux Kernel Mailing List,
openrisc, Palmer Dabbelt, Richard Weinberger, Paul Mackerras,
Linus Torvalds, David S. Miller
In-Reply-To: <20200622234326.906346-17-christian.brauner@ubuntu.com>
Christian Brauner <christian.brauner@ubuntu.com> 於 2020年6月23日 週二 上午7:46寫道:
>
> All architectures support copy_thread_tls() now, so remove the legacy
> copy_thread() function and the HAVE_COPY_THREAD_TLS config option. Everyone
> uses the same process creation calling convention based on
> copy_thread_tls() and struct kernel_clone_args. This will make it easier to
> maintain the core process creation code under kernel/, simplifies the
> callpaths and makes the identical for all architectures.
>
> Cc: Richard Henderson <rth@twiddle.net>
> Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
> Cc: Matt Turner <mattst88@gmail.com>
> Cc: Vineet Gupta <vgupta@synopsys.com>
> Cc: Russell King <linux@armlinux.org.uk>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will@kernel.org>
> Cc: Mark Salter <msalter@redhat.com>
> Cc: Aurelien Jacquiot <jacquiot.aurelien@gmail.com>
> Cc: Guo Ren <guoren@kernel.org>
> Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
> Cc: Brian Cain <bcain@codeaurora.org>
> Cc: Tony Luck <tony.luck@intel.com>
> Cc: Fenghua Yu <fenghua.yu@intel.com>
> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> Cc: Michal Simek <monstr@monstr.eu>
> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
> Cc: Nick Hu <nickhu@andestech.com>
> Cc: Greentime Hu <green.hu@gmail.com>
> Cc: Vincent Chen <deanbo422@gmail.com>
> Cc: Ley Foon Tan <ley.foon.tan@intel.com>
> Cc: Jonas Bonn <jonas@southpole.se>
> Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
> Cc: Stafford Horne <shorne@gmail.com>
> Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
> Cc: Helge Deller <deller@gmx.de>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Paul Walmsley <paul.walmsley@sifive.com>
> Cc: Palmer Dabbelt <palmer@dabbelt.com>
> Cc: Albert Ou <aou@eecs.berkeley.edu>
> Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
> Cc: Vasily Gorbik <gor@linux.ibm.com>
> Cc: Christian Borntraeger <borntraeger@de.ibm.com>
> Cc: Rich Felker <dalias@libc.org>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Jeff Dike <jdike@addtoit.com>
> Cc: Richard Weinberger <richard@nod.at>
> Cc: Anton Ivanov <anton.ivanov@cambridgegreys.com>
> Cc: Guan Xuetao <gxt@pku.edu.cn>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: x86@kernel.org
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Kees Cook <keescook@chromium.org>
> Cc: Mike Rapoport <rppt@linux.ibm.com>
> Cc: "Matthew Wilcox
> Cc: Al Viro <viro@zeniv.linux.org.uk>
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-alpha@vger.kernel.org
> Cc: linux-snps-arc@lists.infradead.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-c6x-dev@linux-c6x.org
> Cc: linux-csky@vger.kernel.org
> Cc: uclinux-h8-devel@lists.sourceforge.jp
> Cc: linux-hexagon@vger.kernel.org
> Cc: linux-ia64@vger.kernel.org
> Cc: linux-m68k@lists.linux-m68k.org
> Cc: linux-mips@vger.kernel.org
> Cc: openrisc@lists.librecores.org
> Cc: linux-parisc@vger.kernel.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-riscv@lists.infradead.org
> Cc: linux-s390@vger.kernel.org
> Cc: linux-sh@vger.kernel.org
> Cc: sparclinux@vger.kernel.org
> Cc: linux-um@lists.infradead.org
> Cc: linux-xtensa@linux-xtensa.org
> Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
> [...]
> diff --git a/arch/nds32/Kconfig b/arch/nds32/Kconfig
> index 7b6eaca81cce..e30298e99e1b 100644
> --- a/arch/nds32/Kconfig
> +++ b/arch/nds32/Kconfig
> @@ -48,7 +48,6 @@ config NDS32
> select HAVE_FUNCTION_GRAPH_TRACER
> select HAVE_FTRACE_MCOUNT_RECORD
> select HAVE_DYNAMIC_FTRACE
> - select HAVE_COPY_THREAD_TLS
> help
> Andes(nds32) Linux support.
Hi Christian, Thank you.
Acked-by: Greentime Hu <green.hu@gmail.com>
^ permalink raw reply
* Re: [PATCH 17/17] arch: rename copy_thread_tls() back to copy_thread()
From: Greentime Hu @ 2020-06-27 3:10 UTC (permalink / raw)
To: Christian Brauner
Cc: Rich Felker, linux-sh, Peter Zijlstra (Intel), Catalin Marinas,
linux-mips, James E.J. Bottomley, Max Filippov, Guo Ren,
Matthew Wilcox (Oracle), H. Peter Anvin, sparclinux,
linux-hexagon, linux-riscv, Vincent Chen, Will Deacon,
Thomas Gleixner, Anton Ivanov, Jonas Bonn, linux-s390, linux-ia64,
linux-c6x-dev, Brian Cain, linux-xtensa, Helge Deller, x86,
Russell King, Ley Foon Tan, Christian Borntraeger, Ingo Molnar,
Geert Uytterhoeven, linux-parisc, Mark Salter, linux-csky,
Matt Turner, linux-snps-arc, uclinux-h8-devel, Fenghua Yu,
Albert Ou, Kees Cook, Jeff Dike, linux-alpha, linux-um,
linuxppc-dev, Aurelien Jacquiot, linux-m68k, Thomas Bogendoerfer,
Ivan Kokshaysky, Al Viro, Paul Walmsley, Stafford Horne,
Stefan Kristiansson, Guan Xuetao, linux-arm-kernel,
Richard Henderson, Chris Zankel, Michal Simek, Tony Luck,
Yoshinori Sato, Nick Hu, Vineet Gupta, Linux Kernel Mailing List,
openrisc, Palmer Dabbelt, Richard Weinberger, Paul Mackerras,
Linus Torvalds, David S. Miller
In-Reply-To: <20200622234326.906346-18-christian.brauner@ubuntu.com>
Christian Brauner <christian.brauner@ubuntu.com> 於 2020年6月23日 週二 上午7:58寫道:
>
> Now that HAVE_COPY_THREAD_TLS has been removed, rename copy_thread_tls()
> back simply copy_thread(). It's a simpler name, and doesn't imply that only
> tls is copied here. This finishes an outstanding chunk of internal process
> creation work since we've added clone3().
>
> Cc: Richard Henderson <rth@twiddle.net>
> Cc: Ivan Kokshaysky <ink@jurassic.park.msu.ru>
> Cc: Matt Turner <mattst88@gmail.com>
> Cc: Vineet Gupta <vgupta@synopsys.com>
> Cc: Russell King <linux@armlinux.org.uk>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will@kernel.org>
> Cc: Mark Salter <msalter@redhat.com>
> Cc: Aurelien Jacquiot <jacquiot.aurelien@gmail.com>
> Cc: Guo Ren <guoren@kernel.org>
> Cc: Yoshinori Sato <ysato@users.sourceforge.jp>
> Cc: Brian Cain <bcain@codeaurora.org>
> Cc: Tony Luck <tony.luck@intel.com>
> Cc: Fenghua Yu <fenghua.yu@intel.com>
> Cc: Geert Uytterhoeven <geert@linux-m68k.org>
> Cc: Michal Simek <monstr@monstr.eu>
> Cc: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
> Cc: Nick Hu <nickhu@andestech.com>
> Cc: Greentime Hu <green.hu@gmail.com>
> Cc: Vincent Chen <deanbo422@gmail.com>
> Cc: Ley Foon Tan <ley.foon.tan@intel.com>
> Cc: Jonas Bonn <jonas@southpole.se>
> Cc: Stefan Kristiansson <stefan.kristiansson@saunalahti.fi>
> Cc: Stafford Horne <shorne@gmail.com>
> Cc: "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
> Cc: Helge Deller <deller@gmx.de>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Paul Walmsley <paul.walmsley@sifive.com>
> Cc: Palmer Dabbelt <palmer@dabbelt.com>
> Cc: Albert Ou <aou@eecs.berkeley.edu>
> Cc: Christian Borntraeger <borntraeger@de.ibm.com>
> Cc: Rich Felker <dalias@libc.org>
> Cc: "David S. Miller" <davem@davemloft.net>
> Cc: Jeff Dike <jdike@addtoit.com>
> Cc: Richard Weinberger <richard@nod.at>
> Cc: Anton Ivanov <anton.ivanov@cambridgegreys.com>
> Cc: Guan Xuetao <gxt@pku.edu.cn>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: x86@kernel.org
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Chris Zankel <chris@zankel.net>
> Cc: Max Filippov <jcmvbkbc@gmail.com>
> Cc: Kees Cook <keescook@chromium.org>
> Cc: "Peter Zijlstra (Intel)" <peterz@infradead.org>
> Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>
> Cc: Al Viro <viro@zeniv.linux.org.uk>
> Cc: linux-alpha@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-snps-arc@lists.infradead.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linux-c6x-dev@linux-c6x.org
> Cc: linux-csky@vger.kernel.org
> Cc: uclinux-h8-devel@lists.sourceforge.jp
> Cc: linux-hexagon@vger.kernel.org
> Cc: linux-ia64@vger.kernel.org
> Cc: linux-m68k@lists.linux-m68k.org
> Cc: linux-mips@vger.kernel.org
> Cc: openrisc@lists.librecores.org
> Cc: linux-parisc@vger.kernel.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-riscv@lists.infradead.org
> Cc: linux-s390@vger.kernel.org
> Cc: linux-sh@vger.kernel.org
> Cc: sparclinux@vger.kernel.org
> Cc: linux-um@lists.infradead.org
> Cc: linux-xtensa@linux-xtensa.org
> Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
> ---
> arch/alpha/kernel/process.c | 2 +-
> arch/arc/kernel/process.c | 2 +-
> arch/arm/kernel/process.c | 2 +-
> arch/arm64/kernel/process.c | 2 +-
> arch/c6x/kernel/process.c | 2 +-
> arch/csky/kernel/process.c | 2 +-
> arch/h8300/kernel/process.c | 2 +-
> arch/hexagon/kernel/process.c | 2 +-
> arch/ia64/kernel/process.c | 4 ++--
> arch/m68k/kernel/process.c | 2 +-
> arch/microblaze/kernel/process.c | 2 +-
> arch/mips/kernel/process.c | 2 +-
> arch/nds32/kernel/process.c | 2 +-
> arch/nios2/kernel/process.c | 2 +-
> arch/openrisc/kernel/process.c | 4 ++--
> arch/parisc/kernel/process.c | 2 +-
> arch/powerpc/kernel/process.c | 2 +-
> arch/riscv/kernel/process.c | 2 +-
> arch/s390/kernel/process.c | 2 +-
> arch/sh/kernel/process_32.c | 2 +-
> arch/sparc/kernel/process.c | 6 +++---
> arch/sparc/kernel/process_32.c | 2 +-
> arch/sparc/kernel/process_64.c | 2 +-
> arch/um/kernel/process.c | 2 +-
> arch/unicore32/kernel/process.c | 2 +-
> arch/x86/kernel/process.c | 2 +-
> arch/x86/kernel/unwind_frame.c | 2 +-
> arch/xtensa/kernel/process.c | 2 +-
> include/linux/sched/task.h | 2 +-
> kernel/fork.c | 2 +-
> 30 files changed, 34 insertions(+), 34 deletions(-)
>
> [...]
> diff --git a/arch/nds32/kernel/process.c b/arch/nds32/kernel/process.c
> index 7dbb1bf64165..1020e2c6dcd8 100644
> --- a/arch/nds32/kernel/process.c
> +++ b/arch/nds32/kernel/process.c
> @@ -149,7 +149,7 @@ void flush_thread(void)
> DEFINE_PER_CPU(struct task_struct *, __entry_task);
>
> asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
> -int copy_thread_tls(unsigned long clone_flags, unsigned long stack_start,
> +int copy_thread(unsigned long clone_flags, unsigned long stack_start,
> unsigned long stk_sz, struct task_struct *p,
> unsigned long tls)
> {
Hi Christian, Thank you.
Acked-by: Greentime Hu <green.hu@gmail.com>
^ permalink raw reply
* Re: [PATCH 01/11] kexec_file: allow archs to handle special regions while locating memory hole
From: Christophe Leroy @ 2020-06-27 6:30 UTC (permalink / raw)
To: Hari Bathini, Michael Ellerman, Andrew Morton
Cc: Pingfan Liu, Kexec-ml, Petr Tesarik, Mahesh J Salgaonkar,
Sourabh Jain, lkml, linuxppc-dev, Mimi Zohar,
Thiago Jung Bauermann, Dave Young, Vivek Goyal, Eric Biederman
In-Reply-To: <159319828304.16351.6990340111766605842.stgit@hbathini.in.ibm.com>
Le 26/06/2020 à 21:04, Hari Bathini a écrit :
> Some archs can have special memory regions, within the given memory
> range, which can't be used for the buffer in a kexec segment. As
> kexec_add_buffer() function is being called from generic code as well,
> add weak arch_kexec_add_buffer definition for archs to override & take
> care of special regions before trying to locate a memory hole.
>
> Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
> ---
> include/linux/kexec.h | 5 +++++
> kernel/kexec_file.c | 37 +++++++++++++++++++++++++++++++++----
> 2 files changed, 38 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/kexec.h b/include/linux/kexec.h
> index 1776eb2..1237682 100644
> --- a/include/linux/kexec.h
> +++ b/include/linux/kexec.h
> @@ -195,6 +195,11 @@ int __weak arch_kexec_apply_relocations(struct purgatory_info *pi,
> const Elf_Shdr *relsec,
> const Elf_Shdr *symtab);
>
> +extern int arch_kexec_add_buffer(struct kexec_buf *kbuf);
> +
extern keywork is useless here, please remove (checkpatch also complains
about it usually).
> +/* arch_kexec_add_buffer calls this when it is ready */
> +extern int __kexec_add_buffer(struct kexec_buf *kbuf);
> +
same
> extern int kexec_add_buffer(struct kexec_buf *kbuf);
> int kexec_locate_mem_hole(struct kexec_buf *kbuf);
>
> diff --git a/kernel/kexec_file.c b/kernel/kexec_file.c
> index bb05fd5..a0b4f7f 100644
> --- a/kernel/kexec_file.c
> +++ b/kernel/kexec_file.c
> @@ -669,10 +669,6 @@ int kexec_locate_mem_hole(struct kexec_buf *kbuf)
> */
> int kexec_add_buffer(struct kexec_buf *kbuf)
> {
> -
> - struct kexec_segment *ksegment;
> - int ret;
> -
> /* Currently adding segment this way is allowed only in file mode */
> if (!kbuf->image->file_mode)
> return -EINVAL;
> @@ -696,6 +692,25 @@ int kexec_add_buffer(struct kexec_buf *kbuf)
> kbuf->memsz = ALIGN(kbuf->memsz, PAGE_SIZE);
> kbuf->buf_align = max(kbuf->buf_align, PAGE_SIZE);
>
> + return arch_kexec_add_buffer(kbuf);
> +}
> +
> +/**
> + * __kexec_add_buffer - arch_kexec_add_buffer would call this function after
> + * updating kbuf, to place a buffer in a kexec segment.
> + * @kbuf: Buffer contents and memory parameters.
> + *
> + * This function assumes that kexec_mutex is held.
> + * On successful return, @kbuf->mem will have the physical address of
> + * the buffer in memory.
> + *
> + * Return: 0 on success, negative errno on error.
> + */
> +int __kexec_add_buffer(struct kexec_buf *kbuf)
> +{
> + struct kexec_segment *ksegment;
> + int ret;
> +
> /* Walk the RAM ranges and allocate a suitable range for the buffer */
> ret = kexec_locate_mem_hole(kbuf);
> if (ret)
> @@ -711,6 +726,20 @@ int kexec_add_buffer(struct kexec_buf *kbuf)
> return 0;
> }
>
> +/**
> + * arch_kexec_add_buffer - Some archs have memory regions within the given
> + * range that can't be used to place a kexec segment.
> + * Such archs can override this function to take care
> + * of them before trying to locate the memory hole.
> + * @kbuf: Buffer contents and memory parameters.
> + *
> + * Return: 0 on success, negative errno on error.
> + */
> +int __weak arch_kexec_add_buffer(struct kexec_buf *kbuf)
> +{
> + return __kexec_add_buffer(kbuf);
> +}
> +
> /* Calculate and store the digest of segments */
> static int kexec_calculate_store_digests(struct kimage *image)
> {
>
Christophe
^ permalink raw reply
* Re: [PATCH 02/11] powerpc/kexec_file: mark PPC64 specific code
From: Christophe Leroy @ 2020-06-27 6:42 UTC (permalink / raw)
To: Hari Bathini, Michael Ellerman, Andrew Morton
Cc: Pingfan Liu, Kexec-ml, Petr Tesarik, Mahesh J Salgaonkar,
Sourabh Jain, lkml, linuxppc-dev, Mimi Zohar,
Thiago Jung Bauermann, Dave Young, Vivek Goyal, Eric Biederman
In-Reply-To: <159319829236.16351.3935863082429593906.stgit@hbathini.in.ibm.com>
Le 26/06/2020 à 21:04, Hari Bathini a écrit :
> Some of the kexec_file_load code isn't PPC64 specific. Move PPC64
> specific code from kexec/file_load.c to kexec/file_load_64.c. Also,
> rename purgatory/trampoline.S to purgatory/trampoline_64.S in the
> same spirit.
At the time being, CONFIG_KEXEC_FILE depends on PPC64.
Are you planning to make it work on PPC32 as well ?
Otherwise I don't understand the purpose of this patch.
Also, what is being done in this patch seems to go far beyond what you
describe above. It is propably worth splitting in several patches with
proper explanation.
Christophe
>
> Signed-off-by: Hari Bathini <hbathini@linux.ibm.com>
> ---
> arch/powerpc/include/asm/kexec.h | 11 +++
> arch/powerpc/kexec/Makefile | 2 -
> arch/powerpc/kexec/elf_64.c | 7 +-
> arch/powerpc/kexec/file_load.c | 37 ++--------
> arch/powerpc/kexec/file_load_64.c | 108 ++++++++++++++++++++++++++++++
> arch/powerpc/purgatory/Makefile | 4 +
> arch/powerpc/purgatory/trampoline.S | 117 --------------------------------
> arch/powerpc/purgatory/trampoline_64.S | 117 ++++++++++++++++++++++++++++++++
> 8 files changed, 248 insertions(+), 155 deletions(-)
> create mode 100644 arch/powerpc/kexec/file_load_64.c
> delete mode 100644 arch/powerpc/purgatory/trampoline.S
> create mode 100644 arch/powerpc/purgatory/trampoline_64.S
>
> diff --git a/arch/powerpc/include/asm/kexec.h b/arch/powerpc/include/asm/kexec.h
> index c684768..7008ea1 100644
> --- a/arch/powerpc/include/asm/kexec.h
> +++ b/arch/powerpc/include/asm/kexec.h
> @@ -114,8 +114,17 @@ int setup_purgatory(struct kimage *image, const void *slave_code,
> unsigned long fdt_load_addr);
> int setup_new_fdt(const struct kimage *image, void *fdt,
> unsigned long initrd_load_addr, unsigned long initrd_len,
> - const char *cmdline);
> + const char *cmdline, int *node);
> int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size);
> +
> +#ifdef CONFIG_PPC64
> +int setup_purgatory_ppc64(struct kimage *image, const void *slave_code,
> + const void *fdt, unsigned long kernel_load_addr,
> + unsigned long fdt_load_addr);
> +int setup_new_fdt_ppc64(const struct kimage *image, void *fdt,
> + unsigned long initrd_load_addr,
> + unsigned long initrd_len, const char *cmdline);
> +#endif /* CONFIG_PPC64 */
> #endif /* CONFIG_KEXEC_FILE */
>
> #else /* !CONFIG_KEXEC_CORE */
> diff --git a/arch/powerpc/kexec/Makefile b/arch/powerpc/kexec/Makefile
> index 86380c6..67c3553 100644
> --- a/arch/powerpc/kexec/Makefile
> +++ b/arch/powerpc/kexec/Makefile
> @@ -7,7 +7,7 @@ obj-y += core.o crash.o core_$(BITS).o
>
> obj-$(CONFIG_PPC32) += relocate_32.o
>
> -obj-$(CONFIG_KEXEC_FILE) += file_load.o elf_$(BITS).o
> +obj-$(CONFIG_KEXEC_FILE) += file_load.o file_load_$(BITS).o elf_$(BITS).o
>
> ifdef CONFIG_HAVE_IMA_KEXEC
> ifdef CONFIG_IMA
> diff --git a/arch/powerpc/kexec/elf_64.c b/arch/powerpc/kexec/elf_64.c
> index 3072fd6..23ad04c 100644
> --- a/arch/powerpc/kexec/elf_64.c
> +++ b/arch/powerpc/kexec/elf_64.c
> @@ -88,7 +88,8 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
> goto out;
> }
>
> - ret = setup_new_fdt(image, fdt, initrd_load_addr, initrd_len, cmdline);
> + ret = setup_new_fdt_ppc64(image, fdt, initrd_load_addr,
> + initrd_len, cmdline);
> if (ret)
> goto out;
>
> @@ -107,8 +108,8 @@ static void *elf64_load(struct kimage *image, char *kernel_buf,
> pr_debug("Loaded device tree at 0x%lx\n", fdt_load_addr);
>
> slave_code = elf_info.buffer + elf_info.proghdrs[0].p_offset;
> - ret = setup_purgatory(image, slave_code, fdt, kernel_load_addr,
> - fdt_load_addr);
> + ret = setup_purgatory_ppc64(image, slave_code, fdt, kernel_load_addr,
> + fdt_load_addr);
> if (ret)
> pr_err("Error setting up the purgatory.\n");
>
> diff --git a/arch/powerpc/kexec/file_load.c b/arch/powerpc/kexec/file_load.c
> index 143c917..99a2c4d 100644
> --- a/arch/powerpc/kexec/file_load.c
> +++ b/arch/powerpc/kexec/file_load.c
> @@ -1,6 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0-only
> /*
> - * ppc64 code to implement the kexec_file_load syscall
> + * powerpc code to implement the kexec_file_load syscall
> *
> * Copyright (C) 2004 Adam Litke (agl@us.ibm.com)
> * Copyright (C) 2004 IBM Corp.
> @@ -16,26 +16,10 @@
>
> #include <linux/slab.h>
> #include <linux/kexec.h>
> -#include <linux/of_fdt.h>
> #include <linux/libfdt.h>
> #include <asm/ima.h>
>
> -#define SLAVE_CODE_SIZE 256
> -
> -const struct kexec_file_ops * const kexec_file_loaders[] = {
> - &kexec_elf64_ops,
> - NULL
> -};
> -
> -int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
> - unsigned long buf_len)
> -{
> - /* We don't support crash kernels yet. */
> - if (image->type == KEXEC_TYPE_CRASH)
> - return -EOPNOTSUPP;
> -
> - return kexec_image_probe_default(image, buf, buf_len);
> -}
> +#define SLAVE_CODE_SIZE 256 /* First 0x100 bytes */
>
> /**
> * setup_purgatory - initialize the purgatory's global variables
> @@ -127,24 +111,17 @@ int delete_fdt_mem_rsv(void *fdt, unsigned long start, unsigned long size)
> * @initrd_len: Size of the next initrd, or 0 if there will be none.
> * @cmdline: Command line for the next kernel, or NULL if there will
> * be none.
> + * @chosen_node: Set this output parameter to chosen_node.
> *
> * Return: 0 on success, or negative errno on error.
> */
> int setup_new_fdt(const struct kimage *image, void *fdt,
> unsigned long initrd_load_addr, unsigned long initrd_len,
> - const char *cmdline)
> + const char *cmdline, int *node)
> {
> int ret, chosen_node;
> const void *prop;
>
> - /* Remove memory reservation for the current device tree. */
> - ret = delete_fdt_mem_rsv(fdt, __pa(initial_boot_params),
> - fdt_totalsize(initial_boot_params));
> - if (ret == 0)
> - pr_debug("Removed old device tree reservation.\n");
> - else if (ret != -ENOENT)
> - return ret;
> -
> chosen_node = fdt_path_offset(fdt, "/chosen");
> if (chosen_node == -FDT_ERR_NOTFOUND) {
> chosen_node = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"),
> @@ -157,6 +134,8 @@ int setup_new_fdt(const struct kimage *image, void *fdt,
> pr_err("Malformed device tree: error reading /chosen.\n");
> return -EINVAL;
> }
> + if (node)
> + *node = chosen_node;
>
> /* Did we boot using an initrd? */
> prop = fdt_getprop(fdt, chosen_node, "linux,initrd-start", NULL);
> @@ -242,10 +221,6 @@ int setup_new_fdt(const struct kimage *image, void *fdt,
> return ret;
> }
>
> - ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
> - if (ret)
> - goto err;
> -
> return 0;
>
> err:
> diff --git a/arch/powerpc/kexec/file_load_64.c b/arch/powerpc/kexec/file_load_64.c
> new file mode 100644
> index 0000000..e6bff960
> --- /dev/null
> +++ b/arch/powerpc/kexec/file_load_64.c
> @@ -0,0 +1,108 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * ppc64 code to implement the kexec_file_load syscall
> + *
> + * Copyright (C) 2004 Adam Litke (agl@us.ibm.com)
> + * Copyright (C) 2004 IBM Corp.
> + * Copyright (C) 2004,2005 Milton D Miller II, IBM Corporation
> + * Copyright (C) 2005 R Sharada (sharada@in.ibm.com)
> + * Copyright (C) 2006 Mohan Kumar M (mohan@in.ibm.com)
> + * Copyright (C) 2020 IBM Corporation
> + *
> + * Based on kexec-tools' kexec-ppc64.c, kexec-elf-rel-ppc64.c, fs2dt.c.
> + * Heavily modified for the kernel by
> + * Hari Bathini <hbathini@linux.ibm.com>.
> + */
> +
> +#include <linux/kexec.h>
> +#include <linux/of_fdt.h>
> +#include <linux/libfdt.h>
> +
> +const struct kexec_file_ops * const kexec_file_loaders[] = {
> + &kexec_elf64_ops,
> + NULL
> +};
> +
> +/**
> + * setup_purgatory_ppc64 - initialize PPC64 specific purgatory's global
> + * variables and call setup_purgatory() to initialize
> + * common global variable.
> + * @image: kexec image.
> + * @slave_code: Slave code for the purgatory.
> + * @fdt: Flattened device tree for the next kernel.
> + * @kernel_load_addr: Address where the kernel is loaded.
> + * @fdt_load_addr: Address where the flattened device tree is loaded.
> + *
> + * Returns 0 on success, negative errno on error.
> + */
> +int setup_purgatory_ppc64(struct kimage *image, const void *slave_code,
> + const void *fdt, unsigned long kernel_load_addr,
> + unsigned long fdt_load_addr)
> +{
> + int ret;
> +
> + ret = setup_purgatory(image, slave_code, fdt, kernel_load_addr,
> + fdt_load_addr);
> + if (ret)
> + pr_err("Failed to setup purgatory symbols");
> + return ret;
> +}
> +
> +/**
> + * setup_new_fdt_ppc64 - Update the flattend device-tree of the kernel
> + * being loaded.
> + * @image: kexec image being loaded.
> + * @fdt: Flattened device tree for the next kernel.
> + * @initrd_load_addr: Address where the next initrd will be loaded.
> + * @initrd_len: Size of the next initrd, or 0 if there will be none.
> + * @cmdline: Command line for the next kernel, or NULL if there will
> + * be none.
> + *
> + * Returns 0 on success, negative errno on error.
> + */
> +int setup_new_fdt_ppc64(const struct kimage *image, void *fdt,
> + unsigned long initrd_load_addr,
> + unsigned long initrd_len, const char *cmdline)
> +{
> + int chosen_node, ret;
> +
> + /* Remove memory reservation for the current device tree. */
> + ret = delete_fdt_mem_rsv(fdt, __pa(initial_boot_params),
> + fdt_totalsize(initial_boot_params));
> + if (ret == 0)
> + pr_debug("Removed old device tree reservation.\n");
> + else if (ret != -ENOENT) {
> + pr_err("Failed to remove old device-tree reservation.\n");
> + return ret;
> + }
> +
> + ret = setup_new_fdt(image, fdt, initrd_load_addr, initrd_len,
> + cmdline, &chosen_node);
> + if (ret)
> + return ret;
> +
> + ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0);
> + if (ret)
> + pr_err("Failed to update device-tree with linux,booted-from-kexec\n");
> +
> + return ret;
> +}
> +
> +/**
> + * arch_kexec_kernel_image_probe - Does additional handling needed to setup
> + * kexec segments.
> + * @image: kexec image being loaded.
> + * @buf: Buffer pointing to elf data.
> + * @buf_len: Length of the buffer.
> + *
> + * Returns 0 on success, negative errno on error.
> + */
> +int arch_kexec_kernel_image_probe(struct kimage *image, void *buf,
> + unsigned long buf_len)
> +{
> + /* We don't support crash kernels yet. */
> + if (image->type == KEXEC_TYPE_CRASH)
> + return -EOPNOTSUPP;
> +
> + return kexec_image_probe_default(image, buf, buf_len);
> +}
> diff --git a/arch/powerpc/purgatory/Makefile b/arch/powerpc/purgatory/Makefile
> index 7c6d8b1..348f5958 100644
> --- a/arch/powerpc/purgatory/Makefile
> +++ b/arch/powerpc/purgatory/Makefile
> @@ -2,11 +2,11 @@
>
> KASAN_SANITIZE := n
>
> -targets += trampoline.o purgatory.ro kexec-purgatory.c
> +targets += trampoline_$(BITS).o purgatory.ro kexec-purgatory.c
>
> LDFLAGS_purgatory.ro := -e purgatory_start -r --no-undefined
>
> -$(obj)/purgatory.ro: $(obj)/trampoline.o FORCE
> +$(obj)/purgatory.ro: $(obj)/trampoline_$(BITS).o FORCE
> $(call if_changed,ld)
>
> quiet_cmd_bin2c = BIN2C $@
> diff --git a/arch/powerpc/purgatory/trampoline.S b/arch/powerpc/purgatory/trampoline.S
> deleted file mode 100644
> index a5a83c3..0000000
> --- a/arch/powerpc/purgatory/trampoline.S
> +++ /dev/null
> @@ -1,117 +0,0 @@
> -/* SPDX-License-Identifier: GPL-2.0-only */
> -/*
> - * kexec trampoline
> - *
> - * Based on code taken from kexec-tools and kexec-lite.
> - *
> - * Copyright (C) 2004 - 2005, Milton D Miller II, IBM Corporation
> - * Copyright (C) 2006, Mohan Kumar M, IBM Corporation
> - * Copyright (C) 2013, Anton Blanchard, IBM Corporation
> - */
> -
> -#include <asm/asm-compat.h>
> -
> - .machine ppc64
> - .balign 256
> - .globl purgatory_start
> -purgatory_start:
> - b master
> -
> - /* ABI: possible run_at_load flag at 0x5c */
> - .org purgatory_start + 0x5c
> - .globl run_at_load
> -run_at_load:
> - .long 0
> - .size run_at_load, . - run_at_load
> -
> - /* ABI: slaves start at 60 with r3=phys */
> - .org purgatory_start + 0x60
> -slave:
> - b .
> - /* ABI: end of copied region */
> - .org purgatory_start + 0x100
> - .size purgatory_start, . - purgatory_start
> -
> -/*
> - * The above 0x100 bytes at purgatory_start are replaced with the
> - * code from the kernel (or next stage) by setup_purgatory().
> - */
> -
> -master:
> - or %r1,%r1,%r1 /* low priority to let other threads catchup */
> - isync
> - mr %r17,%r3 /* save cpu id to r17 */
> - mr %r15,%r4 /* save physical address in reg15 */
> -
> - or %r3,%r3,%r3 /* ok now to high priority, lets boot */
> - lis %r6,0x1
> - mtctr %r6 /* delay a bit for slaves to catch up */
> - bdnz . /* before we overwrite 0-100 again */
> -
> - bl 0f /* Work out where we're running */
> -0: mflr %r18
> -
> - /* load device-tree address */
> - ld %r3, (dt_offset - 0b)(%r18)
> - mr %r16,%r3 /* save dt address in reg16 */
> - li %r4,20
> - LWZX_BE %r6,%r3,%r4 /* fetch __be32 version number at byte 20 */
> - cmpwi %cr0,%r6,2 /* v2 or later? */
> - blt 1f
> - li %r4,28
> - STWX_BE %r17,%r3,%r4 /* Store my cpu as __be32 at byte 28 */
> -1:
> - /* load the kernel address */
> - ld %r4,(kernel - 0b)(%r18)
> -
> - /* load the run_at_load flag */
> - /* possibly patched by kexec */
> - ld %r6,(run_at_load - 0b)(%r18)
> - /* and patch it into the kernel */
> - stw %r6,(0x5c)(%r4)
> -
> - mr %r3,%r16 /* restore dt address */
> -
> - li %r5,0 /* r5 will be 0 for kernel */
> -
> - mfmsr %r11
> - andi. %r10,%r11,1 /* test MSR_LE */
> - bne .Little_endian
> -
> - mtctr %r4 /* prepare branch to */
> - bctr /* start kernel */
> -
> -.Little_endian:
> - mtsrr0 %r4 /* prepare branch to */
> -
> - clrrdi %r11,%r11,1 /* clear MSR_LE */
> - mtsrr1 %r11
> -
> - rfid /* update MSR and start kernel */
> -
> -
> - .balign 8
> - .globl kernel
> -kernel:
> - .8byte 0x0
> - .size kernel, . - kernel
> -
> - .balign 8
> - .globl dt_offset
> -dt_offset:
> - .8byte 0x0
> - .size dt_offset, . - dt_offset
> -
> -
> - .data
> - .balign 8
> -.globl purgatory_sha256_digest
> -purgatory_sha256_digest:
> - .skip 32
> - .size purgatory_sha256_digest, . - purgatory_sha256_digest
> -
> - .balign 8
> -.globl purgatory_sha_regions
> -purgatory_sha_regions:
> - .skip 8 * 2 * 16
> - .size purgatory_sha_regions, . - purgatory_sha_regions
> diff --git a/arch/powerpc/purgatory/trampoline_64.S b/arch/powerpc/purgatory/trampoline_64.S
> new file mode 100644
> index 0000000..a5a83c3
> --- /dev/null
> +++ b/arch/powerpc/purgatory/trampoline_64.S
> @@ -0,0 +1,117 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * kexec trampoline
> + *
> + * Based on code taken from kexec-tools and kexec-lite.
> + *
> + * Copyright (C) 2004 - 2005, Milton D Miller II, IBM Corporation
> + * Copyright (C) 2006, Mohan Kumar M, IBM Corporation
> + * Copyright (C) 2013, Anton Blanchard, IBM Corporation
> + */
> +
> +#include <asm/asm-compat.h>
> +
> + .machine ppc64
> + .balign 256
> + .globl purgatory_start
> +purgatory_start:
> + b master
> +
> + /* ABI: possible run_at_load flag at 0x5c */
> + .org purgatory_start + 0x5c
> + .globl run_at_load
> +run_at_load:
> + .long 0
> + .size run_at_load, . - run_at_load
> +
> + /* ABI: slaves start at 60 with r3=phys */
> + .org purgatory_start + 0x60
> +slave:
> + b .
> + /* ABI: end of copied region */
> + .org purgatory_start + 0x100
> + .size purgatory_start, . - purgatory_start
> +
> +/*
> + * The above 0x100 bytes at purgatory_start are replaced with the
> + * code from the kernel (or next stage) by setup_purgatory().
> + */
> +
> +master:
> + or %r1,%r1,%r1 /* low priority to let other threads catchup */
> + isync
> + mr %r17,%r3 /* save cpu id to r17 */
> + mr %r15,%r4 /* save physical address in reg15 */
> +
> + or %r3,%r3,%r3 /* ok now to high priority, lets boot */
> + lis %r6,0x1
> + mtctr %r6 /* delay a bit for slaves to catch up */
> + bdnz . /* before we overwrite 0-100 again */
> +
> + bl 0f /* Work out where we're running */
> +0: mflr %r18
> +
> + /* load device-tree address */
> + ld %r3, (dt_offset - 0b)(%r18)
> + mr %r16,%r3 /* save dt address in reg16 */
> + li %r4,20
> + LWZX_BE %r6,%r3,%r4 /* fetch __be32 version number at byte 20 */
> + cmpwi %cr0,%r6,2 /* v2 or later? */
> + blt 1f
> + li %r4,28
> + STWX_BE %r17,%r3,%r4 /* Store my cpu as __be32 at byte 28 */
> +1:
> + /* load the kernel address */
> + ld %r4,(kernel - 0b)(%r18)
> +
> + /* load the run_at_load flag */
> + /* possibly patched by kexec */
> + ld %r6,(run_at_load - 0b)(%r18)
> + /* and patch it into the kernel */
> + stw %r6,(0x5c)(%r4)
> +
> + mr %r3,%r16 /* restore dt address */
> +
> + li %r5,0 /* r5 will be 0 for kernel */
> +
> + mfmsr %r11
> + andi. %r10,%r11,1 /* test MSR_LE */
> + bne .Little_endian
> +
> + mtctr %r4 /* prepare branch to */
> + bctr /* start kernel */
> +
> +.Little_endian:
> + mtsrr0 %r4 /* prepare branch to */
> +
> + clrrdi %r11,%r11,1 /* clear MSR_LE */
> + mtsrr1 %r11
> +
> + rfid /* update MSR and start kernel */
> +
> +
> + .balign 8
> + .globl kernel
> +kernel:
> + .8byte 0x0
> + .size kernel, . - kernel
> +
> + .balign 8
> + .globl dt_offset
> +dt_offset:
> + .8byte 0x0
> + .size dt_offset, . - dt_offset
> +
> +
> + .data
> + .balign 8
> +.globl purgatory_sha256_digest
> +purgatory_sha256_digest:
> + .skip 32
> + .size purgatory_sha256_digest, . - purgatory_sha256_digest
> +
> + .balign 8
> +.globl purgatory_sha_regions
> +purgatory_sha_regions:
> + .skip 8 * 2 * 16
> + .size purgatory_sha_regions, . - purgatory_sha_regions
>
^ permalink raw reply
* [PATCH 1/2] powerpc/mm/book3s54/pkeys: make pkey access check work on execute_only_key
From: Aneesh Kumar K.V @ 2020-06-27 7:01 UTC (permalink / raw)
To: linuxppc-dev, mpe; +Cc: Aneesh Kumar K.V, Jan Stancek
pkey_access_permitted() should not check for pkey is available in UAMOR or not.
The kernel needs to do that check only while allocating keys. This also makes
sure execute_only_key which is marked as non-manageable via UAMOR gives the
right access check return w.r.t pkey_access_permitted().
This fix the page fault loop when using PROT_EXEC as below
addr = mmap(0, page_sz, PROT_EXEC, MAP_FILE | MAP_PRIVATE, fildes, 0);
x = *addr);
Fixes: c46241a370a6 ("powerpc/pkeys: Check vma before returning key fault error to the user")
Reported-by: Jan Stancek <jstancek@redhat.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
---
arch/powerpc/mm/book3s64/pkeys.c | 3 ---
1 file changed, 3 deletions(-)
diff --git a/arch/powerpc/mm/book3s64/pkeys.c b/arch/powerpc/mm/book3s64/pkeys.c
index 1199fc2bfaec..ca5fcb4bff32 100644
--- a/arch/powerpc/mm/book3s64/pkeys.c
+++ b/arch/powerpc/mm/book3s64/pkeys.c
@@ -353,9 +353,6 @@ static bool pkey_access_permitted(int pkey, bool write, bool execute)
int pkey_shift;
u64 amr;
- if (!is_pkey_enabled(pkey))
- return true;
-
pkey_shift = pkeyshift(pkey);
if (execute && !(read_iamr() & (IAMR_EX_BIT << pkey_shift)))
return true;
--
2.26.2
^ permalink raw reply related
* [PATCH 2/2] powerpc/mm/books64/pkeys: Rename is_pkey_enabled()
From: Aneesh Kumar K.V @ 2020-06-27 7:01 UTC (permalink / raw)
To: linuxppc-dev, mpe; +Cc: Aneesh Kumar K.V
In-Reply-To: <20200627070147.297535-1-aneesh.kumar@linux.ibm.com>
Rename is_pkey_enabled() to is_pkey_masked() to better indicates that
this check is to make sure the key is available for userspace usage. For it to
be made available both the bits in UAMOR should be set to 1 (0b11).
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
---
arch/powerpc/mm/book3s64/pkeys.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/arch/powerpc/mm/book3s64/pkeys.c b/arch/powerpc/mm/book3s64/pkeys.c
index ca5fcb4bff32..70d760ade922 100644
--- a/arch/powerpc/mm/book3s64/pkeys.c
+++ b/arch/powerpc/mm/book3s64/pkeys.c
@@ -206,18 +206,16 @@ static inline void write_uamor(u64 value)
mtspr(SPRN_UAMOR, value);
}
-static bool is_pkey_enabled(int pkey)
+static bool is_pkey_masked(int pkey)
{
u64 uamor = read_uamor();
u64 pkey_bits = 0x3ul << pkeyshift(pkey);
u64 uamor_pkey_bits = (uamor & pkey_bits);
/*
- * Both the bits in UAMOR corresponding to the key should be set or
- * reset.
+ * Both the bits in UAMOR corresponding to the key should be set
*/
- WARN_ON(uamor_pkey_bits && (uamor_pkey_bits != pkey_bits));
- return !!(uamor_pkey_bits);
+ return (uamor_pkey_bits != pkey_bits);
}
static inline void init_amr(int pkey, u8 init_bits)
@@ -246,7 +244,7 @@ int __arch_set_user_pkey_access(struct task_struct *tsk, int pkey,
u64 new_amr_bits = 0x0ul;
u64 new_iamr_bits = 0x0ul;
- if (!is_pkey_enabled(pkey))
+ if (is_pkey_masked(pkey))
return -EINVAL;
if (init_val & PKEY_DISABLE_EXECUTE) {
--
2.26.2
^ permalink raw reply related
* Re: [PATCH V3 2/4] mm/debug_vm_pgtable: Add tests validating advanced arch page table helpers
From: Christophe Leroy @ 2020-06-27 7:18 UTC (permalink / raw)
To: Anshuman Khandual, linux-mm
Cc: Heiko Carstens, Paul Mackerras, H. Peter Anvin, linux-riscv,
Will Deacon, linux-arch, linux-s390, x86, Mike Rapoport,
Christian Borntraeger, Ingo Molnar, linux-arm-kernel, ziy,
Catalin Marinas, linux-snps-arc, Vasily Gorbik, Borislav Petkov,
Paul Walmsley, Kirill A . Shutemov, Thomas Gleixner,
gerald.schaefer, christophe.leroy, Vineet Gupta, linux-kernel,
Palmer Dabbelt, Andrew Morton, linuxppc-dev
In-Reply-To: <1592192277-8421-3-git-send-email-anshuman.khandual@arm.com>
Le 15/06/2020 à 05:37, Anshuman Khandual a écrit :
> This adds new tests validating for these following arch advanced page table
> helpers. These tests create and test specific mapping types at various page
> table levels.
>
> 1. pxxp_set_wrprotect()
> 2. pxxp_get_and_clear()
> 3. pxxp_set_access_flags()
> 4. pxxp_get_and_clear_full()
> 5. pxxp_test_and_clear_young()
> 6. pxx_leaf()
> 7. pxx_set_huge()
> 8. pxx_(clear|mk)_savedwrite()
> 9. huge_pxxp_xxx()
>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Mike Rapoport <rppt@linux.ibm.com>
> Cc: Vineet Gupta <vgupta@synopsys.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will@kernel.org>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
> Cc: Vasily Gorbik <gor@linux.ibm.com>
> Cc: Christian Borntraeger <borntraeger@de.ibm.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Kirill A. Shutemov <kirill@shutemov.name>
> Cc: Paul Walmsley <paul.walmsley@sifive.com>
> Cc: Palmer Dabbelt <palmer@dabbelt.com>
> Cc: linux-snps-arc@lists.infradead.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-s390@vger.kernel.org
> Cc: linux-riscv@lists.infradead.org
> Cc: x86@kernel.org
> Cc: linux-mm@kvack.org
> Cc: linux-arch@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Suggested-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
> ---
> mm/debug_vm_pgtable.c | 306 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 306 insertions(+)
>
> diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
> index ffa163d4c63c..e3f9f8317a98 100644
> --- a/mm/debug_vm_pgtable.c
> +++ b/mm/debug_vm_pgtable.c
> @@ -21,6 +21,7 @@
> #include <linux/module.h>
> #include <linux/pfn_t.h>
> #include <linux/printk.h>
> +#include <linux/pgtable.h>
> #include <linux/random.h>
> #include <linux/spinlock.h>
> #include <linux/swap.h>
> @@ -28,6 +29,7 @@
> #include <linux/start_kernel.h>
> #include <linux/sched/mm.h>
> #include <asm/pgalloc.h>
> +#include <asm/tlbflush.h>
>
> #define VMFLAGS (VM_READ|VM_WRITE|VM_EXEC)
>
> @@ -55,6 +57,54 @@ static void __init pte_basic_tests(unsigned long pfn, pgprot_t prot)
> WARN_ON(pte_write(pte_wrprotect(pte_mkwrite(pte))));
> }
>
> +static void __init pte_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma, pte_t *ptep,
> + unsigned long pfn, unsigned long vaddr, pgprot_t prot)
> +{
> + pte_t pte = pfn_pte(pfn, prot);
> +
> + pte = pfn_pte(pfn, prot);
> + set_pte_at(mm, vaddr, ptep, pte);
> + ptep_set_wrprotect(mm, vaddr, ptep);
> + pte = READ_ONCE(*ptep);
same
> + WARN_ON(pte_write(pte));
> +
> + pte = pfn_pte(pfn, prot);
> + set_pte_at(mm, vaddr, ptep, pte);
> + ptep_get_and_clear(mm, vaddr, ptep);
> + pte = READ_ONCE(*ptep);
same
> + WARN_ON(!pte_none(pte));
> +
> + pte = pfn_pte(pfn, prot);
> + pte = pte_wrprotect(pte);
> + pte = pte_mkclean(pte);
> + set_pte_at(mm, vaddr, ptep, pte);
> + pte = pte_mkwrite(pte);
> + pte = pte_mkdirty(pte);
> + ptep_set_access_flags(vma, vaddr, ptep, pte, 1);
> + pte = READ_ONCE(*ptep);
same
> + WARN_ON(!(pte_write(pte) && pte_dirty(pte)));
> +
> + pte = pfn_pte(pfn, prot);
> + set_pte_at(mm, vaddr, ptep, pte);
> + ptep_get_and_clear_full(mm, vaddr, ptep, 1);
> + pte = READ_ONCE(*ptep);
same
> + WARN_ON(!pte_none(pte));
> +
> + pte = pte_mkyoung(pte);
> + set_pte_at(mm, vaddr, ptep, pte);
> + ptep_test_and_clear_young(vma, vaddr, ptep);
> + pte = READ_ONCE(*ptep);
same
> + WARN_ON(pte_young(pte));
> +}
> +
> +static void __init pte_savedwrite_tests(unsigned long pfn, pgprot_t prot)
> +{
> + pte_t pte = pfn_pte(pfn, prot);
> +
> + WARN_ON(!pte_savedwrite(pte_mk_savedwrite(pte_clear_savedwrite(pte))));
> + WARN_ON(pte_savedwrite(pte_clear_savedwrite(pte_mk_savedwrite(pte))));
> +}
> #ifdef CONFIG_TRANSPARENT_HUGEPAGE
> static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot)
> {
> @@ -77,6 +127,89 @@ static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot)
> WARN_ON(!pmd_bad(pmd_mkhuge(pmd)));
> }
>
> +static void __init pmd_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma, pmd_t *pmdp,
> + unsigned long pfn, unsigned long vaddr, pgprot_t prot)
> +{
> + pmd_t pmd = pfn_pmd(pfn, prot);
> +
> + if (!has_transparent_hugepage())
> + return;
> +
> + /* Align the address wrt HPAGE_PMD_SIZE */
> + vaddr = (vaddr & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE;
> +
> + pmd = pfn_pmd(pfn, prot);
> + set_pmd_at(mm, vaddr, pmdp, pmd);
> + pmdp_set_wrprotect(mm, vaddr, pmdp);
> + pmd = READ_ONCE(*pmdp);
> + WARN_ON(pmd_write(pmd));
> +
> + pmd = pfn_pmd(pfn, prot);
> + set_pmd_at(mm, vaddr, pmdp, pmd);
> + pmdp_huge_get_and_clear(mm, vaddr, pmdp);
> + pmd = READ_ONCE(*pmdp);
> + WARN_ON(!pmd_none(pmd));
> +
> + pmd = pfn_pmd(pfn, prot);
> + pmd = pmd_wrprotect(pmd);
> + pmd = pmd_mkclean(pmd);
> + set_pmd_at(mm, vaddr, pmdp, pmd);
> + pmd = pmd_mkwrite(pmd);
> + pmd = pmd_mkdirty(pmd);
> + pmdp_set_access_flags(vma, vaddr, pmdp, pmd, 1);
> + pmd = READ_ONCE(*pmdp);
> + WARN_ON(!(pmd_write(pmd) && pmd_dirty(pmd)));
> +
> + pmd = pmd_mkhuge(pfn_pmd(pfn, prot));
> + set_pmd_at(mm, vaddr, pmdp, pmd);
> + pmdp_huge_get_and_clear_full(vma, vaddr, pmdp, 1);
> + pmd = READ_ONCE(*pmdp);
> + WARN_ON(!pmd_none(pmd));
> +
> + pmd = pmd_mkyoung(pmd);
> + set_pmd_at(mm, vaddr, pmdp, pmd);
> + pmdp_test_and_clear_young(vma, vaddr, pmdp);
> + pmd = READ_ONCE(*pmdp);
> + WARN_ON(pmd_young(pmd));
> +}
> +
> +static void __init pmd_leaf_tests(unsigned long pfn, pgprot_t prot)
> +{
> + pmd_t pmd = pfn_pmd(pfn, prot);
> +
> + /*
> + * PMD based THP is a leaf entry.
> + */
> + pmd = pmd_mkhuge(pmd);
> + WARN_ON(!pmd_leaf(pmd));
> +}
> +
> +static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
> +{
> + pmd_t pmd;
> +
> + if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMAP))
> + return;
> + /*
> + * X86 defined pmd_set_huge() verifies that the given
> + * PMD is not a populated non-leaf entry.
> + */
> + WRITE_ONCE(*pmdp, __pmd(0));
> + WARN_ON(!pmd_set_huge(pmdp, __pfn_to_phys(pfn), prot));
> + WARN_ON(!pmd_clear_huge(pmdp));
> + pmd = READ_ONCE(*pmdp);
> + WARN_ON(!pmd_none(pmd));
> +}
> +
> +static void __init pmd_savedwrite_tests(unsigned long pfn, pgprot_t prot)
> +{
> + pmd_t pmd = pfn_pmd(pfn, prot);
> +
> + WARN_ON(!pmd_savedwrite(pmd_mk_savedwrite(pmd_clear_savedwrite(pmd))));
> + WARN_ON(pmd_savedwrite(pmd_clear_savedwrite(pmd_mk_savedwrite(pmd))));
> +}
> +
> #ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
> static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot)
> {
> @@ -100,12 +233,115 @@ static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot)
> */
> WARN_ON(!pud_bad(pud_mkhuge(pud)));
> }
> +
> +static void pud_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma, pud_t *pudp,
> + unsigned long pfn, unsigned long vaddr, pgprot_t prot)
> +{
> + pud_t pud = pfn_pud(pfn, prot);
> +
> + if (!has_transparent_hugepage())
> + return;
> +
> + /* Align the address wrt HPAGE_PUD_SIZE */
> + vaddr = (vaddr & HPAGE_PUD_MASK) + HPAGE_PUD_SIZE;
> +
> + set_pud_at(mm, vaddr, pudp, pud);
> + pudp_set_wrprotect(mm, vaddr, pudp);
> + pud = READ_ONCE(*pudp);
> + WARN_ON(pud_write(pud));
> +
> +#ifndef __PAGETABLE_PMD_FOLDED
> + pud = pfn_pud(pfn, prot);
> + set_pud_at(mm, vaddr, pudp, pud);
> + pudp_huge_get_and_clear(mm, vaddr, pudp);
> + pud = READ_ONCE(*pudp);
> + WARN_ON(!pud_none(pud));
> +
> + pud = pfn_pud(pfn, prot);
> + set_pud_at(mm, vaddr, pudp, pud);
> + pudp_huge_get_and_clear_full(mm, vaddr, pudp, 1);
> + pud = READ_ONCE(*pudp);
> + WARN_ON(!pud_none(pud));
> +#endif /* __PAGETABLE_PMD_FOLDED */
> + pud = pfn_pud(pfn, prot);
> + pud = pud_wrprotect(pud);
> + pud = pud_mkclean(pud);
> + set_pud_at(mm, vaddr, pudp, pud);
> + pud = pud_mkwrite(pud);
> + pud = pud_mkdirty(pud);
> + pudp_set_access_flags(vma, vaddr, pudp, pud, 1);
> + pud = READ_ONCE(*pudp);
> + WARN_ON(!(pud_write(pud) && pud_dirty(pud)));
> +
> + pud = pud_mkyoung(pud);
> + set_pud_at(mm, vaddr, pudp, pud);
> + pudp_test_and_clear_young(vma, vaddr, pudp);
> + pud = READ_ONCE(*pudp);
> + WARN_ON(pud_young(pud));
> +}
> +
> +static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot)
> +{
> + pud_t pud = pfn_pud(pfn, prot);
> +
> + /*
> + * PUD based THP is a leaf entry.
> + */
> + pud = pud_mkhuge(pud);
> + WARN_ON(!pud_leaf(pud));
> +}
> +
> +static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
> +{
> + pud_t pud;
> +
> + if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMAP))
> + return;
> + /*
> + * X86 defined pud_set_huge() verifies that the given
> + * PUD is not a populated non-leaf entry.
> + */
> + WRITE_ONCE(*pudp, __pud(0));
> + WARN_ON(!pud_set_huge(pudp, __pfn_to_phys(pfn), prot));
> + WARN_ON(!pud_clear_huge(pudp));
> + pud = READ_ONCE(*pudp);
> + WARN_ON(!pud_none(pud));
> +}
> #else /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
> static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot) { }
> +static void pud_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma, pud_t *pudp,
> + unsigned long pfn, unsigned long vaddr, pgprot_t prot)
> +{
> +}
> +static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot) { }
> +static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
> +{
> +}
> #endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
> #else /* !CONFIG_TRANSPARENT_HUGEPAGE */
> static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) { }
> static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot) { }
> +static void __init pmd_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma, pmd_t *pmdp,
> + unsigned long pfn, unsigned long vaddr, pgprot_t prot)
> +{
> +}
> +static void __init pud_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma, pud_t *pudp,
> + unsigned long pfn, unsigned long vaddr, pgprot_t prot)
> +{
> +}
> +static void __init pmd_leaf_tests(unsigned long pfn, pgprot_t prot) { }
> +static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot) { }
> +static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
> +{
> +}
> +static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
> +{
> +}
> +static void __init pmd_savedwrite_tests(unsigned long pfn, pgprot_t prot) { }
> #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
>
> static void __init p4d_basic_tests(unsigned long pfn, pgprot_t prot)
> @@ -495,8 +731,56 @@ static void __init hugetlb_basic_tests(unsigned long pfn, pgprot_t prot)
> WARN_ON(!pte_huge(pte_mkhuge(pte)));
> #endif /* CONFIG_ARCH_WANT_GENERAL_HUGETLB */
> }
> +
> +static void __init hugetlb_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma,
> + pte_t *ptep, unsigned long pfn,
> + unsigned long vaddr, pgprot_t prot)
> +{
> + struct page *page = pfn_to_page(pfn);
> + pte_t pte = READ_ONCE(*ptep);
Remplace with ptep_get() to avoid build failure on powerpc 8xx.
> + unsigned long paddr = (__pfn_to_phys(pfn) | RANDOM_ORVALUE) & PMD_MASK;
> +
> + pte = pte_mkhuge(mk_pte(pfn_to_page(PHYS_PFN(paddr)), prot));
> + set_huge_pte_at(mm, vaddr, ptep, pte);
> + barrier();
> + WARN_ON(!pte_same(pte, huge_ptep_get(ptep)));
> + huge_pte_clear(mm, vaddr, ptep, PMD_SIZE);
> + pte = huge_ptep_get(ptep);
> + WARN_ON(!huge_pte_none(pte));
> +
> + pte = mk_huge_pte(page, prot);
> + set_huge_pte_at(mm, vaddr, ptep, pte);
> + barrier();
> + huge_ptep_set_wrprotect(mm, vaddr, ptep);
> + pte = huge_ptep_get(ptep);
> + WARN_ON(huge_pte_write(pte));
> +
> + pte = mk_huge_pte(page, prot);
> + set_huge_pte_at(mm, vaddr, ptep, pte);
> + barrier();
> + huge_ptep_get_and_clear(mm, vaddr, ptep);
> + pte = huge_ptep_get(ptep);
> + WARN_ON(!huge_pte_none(pte));
> +
> + pte = mk_huge_pte(page, prot);
> + pte = huge_pte_wrprotect(pte);
> + set_huge_pte_at(mm, vaddr, ptep, pte);
> + barrier();
> + pte = huge_pte_mkwrite(pte);
> + pte = huge_pte_mkdirty(pte);
> + huge_ptep_set_access_flags(vma, vaddr, ptep, pte, 1);
> + pte = huge_ptep_get(ptep);
> + WARN_ON(!(huge_pte_write(pte) && huge_pte_dirty(pte)));
> +}
> #else /* !CONFIG_HUGETLB_PAGE */
> static void __init hugetlb_basic_tests(unsigned long pfn, pgprot_t prot) { }
> +static void __init hugetlb_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma,
> + pte_t *ptep, unsigned long pfn,
> + unsigned long vaddr, pgprot_t prot)
> +{
> +}
> #endif /* CONFIG_HUGETLB_PAGE */
>
> #ifdef CONFIG_TRANSPARENT_HUGEPAGE
> @@ -568,6 +852,7 @@ static unsigned long __init get_random_vaddr(void)
>
> static int __init debug_vm_pgtable(void)
> {
> + struct vm_area_struct *vma;
> struct mm_struct *mm;
> pgd_t *pgdp;
> p4d_t *p4dp, *saved_p4dp;
> @@ -596,6 +881,12 @@ static int __init debug_vm_pgtable(void)
> */
> protnone = __P000;
>
> + vma = vm_area_alloc(mm);
> + if (!vma) {
> + pr_err("vma allocation failed\n");
> + return 1;
> + }
> +
> /*
> * PFN for mapping at PTE level is determined from a standard kernel
> * text symbol. But pfns for higher page table levels are derived by
> @@ -644,6 +935,20 @@ static int __init debug_vm_pgtable(void)
> p4d_clear_tests(mm, p4dp);
> pgd_clear_tests(mm, pgdp);
>
> + pte_advanced_tests(mm, vma, ptep, pte_aligned, vaddr, prot);
> + pmd_advanced_tests(mm, vma, pmdp, pmd_aligned, vaddr, prot);
> + pud_advanced_tests(mm, vma, pudp, pud_aligned, vaddr, prot);
> + hugetlb_advanced_tests(mm, vma, ptep, pte_aligned, vaddr, prot);
> +
> + pmd_leaf_tests(pmd_aligned, prot);
> + pud_leaf_tests(pud_aligned, prot);
> +
> + pmd_huge_tests(pmdp, pmd_aligned, prot);
> + pud_huge_tests(pudp, pud_aligned, prot);
> +
> + pte_savedwrite_tests(pte_aligned, prot);
> + pmd_savedwrite_tests(pmd_aligned, prot);
> +
> pte_unmap_unlock(ptep, ptl);
>
> pmd_populate_tests(mm, pmdp, saved_ptep);
> @@ -678,6 +983,7 @@ static int __init debug_vm_pgtable(void)
> pmd_free(mm, saved_pmdp);
> pte_free(mm, saved_ptep);
>
> + vm_area_free(vma);
> mm_dec_nr_puds(mm);
> mm_dec_nr_pmds(mm);
> mm_dec_nr_ptes(mm);
>
Christophe
^ permalink raw reply
* Re: [PATCH V3 2/4] mm/debug_vm_pgtable: Add tests validating advanced arch page table helpers
From: Christophe Leroy @ 2020-06-27 7:26 UTC (permalink / raw)
To: Anshuman Khandual, linux-mm
Cc: Heiko Carstens, Paul Mackerras, H. Peter Anvin, linux-riscv,
Will Deacon, linux-arch, linux-s390, x86, Mike Rapoport,
Christian Borntraeger, Ingo Molnar, gerald.schaefer, ziy,
Catalin Marinas, linux-snps-arc, Vasily Gorbik, Borislav Petkov,
Paul Walmsley, Kirill A . Shutemov, Thomas Gleixner,
linux-arm-kernel, Vineet Gupta, linux-kernel, Palmer Dabbelt,
Andrew Morton, linuxppc-dev
In-Reply-To: <1592192277-8421-3-git-send-email-anshuman.khandual@arm.com>
Le 15/06/2020 à 05:37, Anshuman Khandual a écrit :
> This adds new tests validating for these following arch advanced page table
> helpers. These tests create and test specific mapping types at various page
> table levels.
>
> 1. pxxp_set_wrprotect()
> 2. pxxp_get_and_clear()
> 3. pxxp_set_access_flags()
> 4. pxxp_get_and_clear_full()
> 5. pxxp_test_and_clear_young()
> 6. pxx_leaf()
> 7. pxx_set_huge()
> 8. pxx_(clear|mk)_savedwrite()
> 9. huge_pxxp_xxx()
>
> Cc: Andrew Morton <akpm@linux-foundation.org>
> Cc: Mike Rapoport <rppt@linux.ibm.com>
> Cc: Vineet Gupta <vgupta@synopsys.com>
> Cc: Catalin Marinas <catalin.marinas@arm.com>
> Cc: Will Deacon <will@kernel.org>
> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> Cc: Paul Mackerras <paulus@samba.org>
> Cc: Michael Ellerman <mpe@ellerman.id.au>
> Cc: Heiko Carstens <heiko.carstens@de.ibm.com>
> Cc: Vasily Gorbik <gor@linux.ibm.com>
> Cc: Christian Borntraeger <borntraeger@de.ibm.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Borislav Petkov <bp@alien8.de>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: Kirill A. Shutemov <kirill@shutemov.name>
> Cc: Paul Walmsley <paul.walmsley@sifive.com>
> Cc: Palmer Dabbelt <palmer@dabbelt.com>
> Cc: linux-snps-arc@lists.infradead.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-s390@vger.kernel.org
> Cc: linux-riscv@lists.infradead.org
> Cc: x86@kernel.org
> Cc: linux-mm@kvack.org
> Cc: linux-arch@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> Suggested-by: Catalin Marinas <catalin.marinas@arm.com>
> Signed-off-by: Anshuman Khandual <anshuman.khandual@arm.com>
> ---
> mm/debug_vm_pgtable.c | 306 ++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 306 insertions(+)
>
> diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
> index ffa163d4c63c..e3f9f8317a98 100644
> --- a/mm/debug_vm_pgtable.c
> +++ b/mm/debug_vm_pgtable.c
> @@ -21,6 +21,7 @@
> #include <linux/module.h>
> #include <linux/pfn_t.h>
> #include <linux/printk.h>
> +#include <linux/pgtable.h>
> #include <linux/random.h>
> #include <linux/spinlock.h>
> #include <linux/swap.h>
> @@ -28,6 +29,7 @@
> #include <linux/start_kernel.h>
> #include <linux/sched/mm.h>
> #include <asm/pgalloc.h>
> +#include <asm/tlbflush.h>
>
> #define VMFLAGS (VM_READ|VM_WRITE|VM_EXEC)
>
> @@ -55,6 +57,54 @@ static void __init pte_basic_tests(unsigned long pfn, pgprot_t prot)
> WARN_ON(pte_write(pte_wrprotect(pte_mkwrite(pte))));
> }
>
> +static void __init pte_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma, pte_t *ptep,
> + unsigned long pfn, unsigned long vaddr, pgprot_t prot)
Align args properly.
> +{
> + pte_t pte = pfn_pte(pfn, prot);
> +
> + pte = pfn_pte(pfn, prot);
> + set_pte_at(mm, vaddr, ptep, pte);
> + ptep_set_wrprotect(mm, vaddr, ptep);
> + pte = READ_ONCE(*ptep);
> + WARN_ON(pte_write(pte));
> +
> + pte = pfn_pte(pfn, prot);
> + set_pte_at(mm, vaddr, ptep, pte);
> + ptep_get_and_clear(mm, vaddr, ptep);
> + pte = READ_ONCE(*ptep);
> + WARN_ON(!pte_none(pte));
> +
> + pte = pfn_pte(pfn, prot);
> + pte = pte_wrprotect(pte);
> + pte = pte_mkclean(pte);
> + set_pte_at(mm, vaddr, ptep, pte);
> + pte = pte_mkwrite(pte);
> + pte = pte_mkdirty(pte);
> + ptep_set_access_flags(vma, vaddr, ptep, pte, 1);
> + pte = READ_ONCE(*ptep);
> + WARN_ON(!(pte_write(pte) && pte_dirty(pte)));
> +
> + pte = pfn_pte(pfn, prot);
> + set_pte_at(mm, vaddr, ptep, pte);
> + ptep_get_and_clear_full(mm, vaddr, ptep, 1);
> + pte = READ_ONCE(*ptep);
> + WARN_ON(!pte_none(pte));
> +
> + pte = pte_mkyoung(pte);
> + set_pte_at(mm, vaddr, ptep, pte);
> + ptep_test_and_clear_young(vma, vaddr, ptep);
> + pte = READ_ONCE(*ptep);
> + WARN_ON(pte_young(pte));
> +}
> +
> +static void __init pte_savedwrite_tests(unsigned long pfn, pgprot_t prot)
> +{
> + pte_t pte = pfn_pte(pfn, prot);
> +
> + WARN_ON(!pte_savedwrite(pte_mk_savedwrite(pte_clear_savedwrite(pte))));
> + WARN_ON(pte_savedwrite(pte_clear_savedwrite(pte_mk_savedwrite(pte))));
> +}
> #ifdef CONFIG_TRANSPARENT_HUGEPAGE
> static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot)
> {
> @@ -77,6 +127,89 @@ static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot)
> WARN_ON(!pmd_bad(pmd_mkhuge(pmd)));
> }
>
> +static void __init pmd_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma, pmd_t *pmdp,
> + unsigned long pfn, unsigned long vaddr, pgprot_t prot)
Align args properly
> +{
> + pmd_t pmd = pfn_pmd(pfn, prot);
> +
> + if (!has_transparent_hugepage())
> + return;
> +
> + /* Align the address wrt HPAGE_PMD_SIZE */
> + vaddr = (vaddr & HPAGE_PMD_MASK) + HPAGE_PMD_SIZE;
> +
> + pmd = pfn_pmd(pfn, prot);
> + set_pmd_at(mm, vaddr, pmdp, pmd);
> + pmdp_set_wrprotect(mm, vaddr, pmdp);
> + pmd = READ_ONCE(*pmdp);
> + WARN_ON(pmd_write(pmd));
> +
> + pmd = pfn_pmd(pfn, prot);
> + set_pmd_at(mm, vaddr, pmdp, pmd);
> + pmdp_huge_get_and_clear(mm, vaddr, pmdp);
> + pmd = READ_ONCE(*pmdp);
> + WARN_ON(!pmd_none(pmd));
> +
> + pmd = pfn_pmd(pfn, prot);
> + pmd = pmd_wrprotect(pmd);
> + pmd = pmd_mkclean(pmd);
> + set_pmd_at(mm, vaddr, pmdp, pmd);
> + pmd = pmd_mkwrite(pmd);
> + pmd = pmd_mkdirty(pmd);
> + pmdp_set_access_flags(vma, vaddr, pmdp, pmd, 1);
> + pmd = READ_ONCE(*pmdp);
> + WARN_ON(!(pmd_write(pmd) && pmd_dirty(pmd)));
> +
> + pmd = pmd_mkhuge(pfn_pmd(pfn, prot));
> + set_pmd_at(mm, vaddr, pmdp, pmd);
> + pmdp_huge_get_and_clear_full(vma, vaddr, pmdp, 1);
> + pmd = READ_ONCE(*pmdp);
> + WARN_ON(!pmd_none(pmd));
> +
> + pmd = pmd_mkyoung(pmd);
> + set_pmd_at(mm, vaddr, pmdp, pmd);
> + pmdp_test_and_clear_young(vma, vaddr, pmdp);
> + pmd = READ_ONCE(*pmdp);
> + WARN_ON(pmd_young(pmd));
> +}
> +
> +static void __init pmd_leaf_tests(unsigned long pfn, pgprot_t prot)
> +{
> + pmd_t pmd = pfn_pmd(pfn, prot);
> +
> + /*
> + * PMD based THP is a leaf entry.
> + */
> + pmd = pmd_mkhuge(pmd);
> + WARN_ON(!pmd_leaf(pmd));
> +}
> +
> +static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
> +{
> + pmd_t pmd;
> +
> + if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMAP))
> + return;
> + /*
> + * X86 defined pmd_set_huge() verifies that the given
> + * PMD is not a populated non-leaf entry.
> + */
> + WRITE_ONCE(*pmdp, __pmd(0));
> + WARN_ON(!pmd_set_huge(pmdp, __pfn_to_phys(pfn), prot));
> + WARN_ON(!pmd_clear_huge(pmdp));
> + pmd = READ_ONCE(*pmdp);
> + WARN_ON(!pmd_none(pmd));
> +}
> +
> +static void __init pmd_savedwrite_tests(unsigned long pfn, pgprot_t prot)
> +{
> + pmd_t pmd = pfn_pmd(pfn, prot);
> +
> + WARN_ON(!pmd_savedwrite(pmd_mk_savedwrite(pmd_clear_savedwrite(pmd))));
> + WARN_ON(pmd_savedwrite(pmd_clear_savedwrite(pmd_mk_savedwrite(pmd))));
> +}
> +
> #ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD
> static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot)
> {
> @@ -100,12 +233,115 @@ static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot)
> */
> WARN_ON(!pud_bad(pud_mkhuge(pud)));
> }
> +
> +static void pud_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma, pud_t *pudp,
> + unsigned long pfn, unsigned long vaddr, pgprot_t prot)
Align args properly
> +{
> + pud_t pud = pfn_pud(pfn, prot);
> +
> + if (!has_transparent_hugepage())
> + return;
> +
> + /* Align the address wrt HPAGE_PUD_SIZE */
> + vaddr = (vaddr & HPAGE_PUD_MASK) + HPAGE_PUD_SIZE;
> +
> + set_pud_at(mm, vaddr, pudp, pud);
> + pudp_set_wrprotect(mm, vaddr, pudp);
> + pud = READ_ONCE(*pudp);
> + WARN_ON(pud_write(pud));
> +
> +#ifndef __PAGETABLE_PMD_FOLDED
> + pud = pfn_pud(pfn, prot);
> + set_pud_at(mm, vaddr, pudp, pud);
> + pudp_huge_get_and_clear(mm, vaddr, pudp);
> + pud = READ_ONCE(*pudp);
> + WARN_ON(!pud_none(pud));
> +
> + pud = pfn_pud(pfn, prot);
> + set_pud_at(mm, vaddr, pudp, pud);
> + pudp_huge_get_and_clear_full(mm, vaddr, pudp, 1);
> + pud = READ_ONCE(*pudp);
> + WARN_ON(!pud_none(pud));
> +#endif /* __PAGETABLE_PMD_FOLDED */
> + pud = pfn_pud(pfn, prot);
> + pud = pud_wrprotect(pud);
> + pud = pud_mkclean(pud);
> + set_pud_at(mm, vaddr, pudp, pud);
> + pud = pud_mkwrite(pud);
> + pud = pud_mkdirty(pud);
> + pudp_set_access_flags(vma, vaddr, pudp, pud, 1);
> + pud = READ_ONCE(*pudp);
> + WARN_ON(!(pud_write(pud) && pud_dirty(pud)));
> +
> + pud = pud_mkyoung(pud);
> + set_pud_at(mm, vaddr, pudp, pud);
> + pudp_test_and_clear_young(vma, vaddr, pudp);
> + pud = READ_ONCE(*pudp);
> + WARN_ON(pud_young(pud));
> +}
> +
> +static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot)
> +{
> + pud_t pud = pfn_pud(pfn, prot);
> +
> + /*
> + * PUD based THP is a leaf entry.
> + */
> + pud = pud_mkhuge(pud);
> + WARN_ON(!pud_leaf(pud));
> +}
> +
> +static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
> +{
> + pud_t pud;
> +
> + if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMAP))
> + return;
> + /*
> + * X86 defined pud_set_huge() verifies that the given
> + * PUD is not a populated non-leaf entry.
> + */
> + WRITE_ONCE(*pudp, __pud(0));
> + WARN_ON(!pud_set_huge(pudp, __pfn_to_phys(pfn), prot));
> + WARN_ON(!pud_clear_huge(pudp));
> + pud = READ_ONCE(*pudp);
> + WARN_ON(!pud_none(pud));
> +}
> #else /* !CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
> static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot) { }
> +static void pud_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma, pud_t *pudp,
> + unsigned long pfn, unsigned long vaddr, pgprot_t prot)
Align args properly
> +{
> +}
> +static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot) { }
> +static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
> +{
> +}
> #endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */
> #else /* !CONFIG_TRANSPARENT_HUGEPAGE */
> static void __init pmd_basic_tests(unsigned long pfn, pgprot_t prot) { }
> static void __init pud_basic_tests(unsigned long pfn, pgprot_t prot) { }
> +static void __init pmd_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma, pmd_t *pmdp,
> + unsigned long pfn, unsigned long vaddr, pgprot_t prot)
Align args properly
> +{
> +}
> +static void __init pud_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma, pud_t *pudp,
> + unsigned long pfn, unsigned long vaddr, pgprot_t prot)
Align args properly
> +{
> +}
> +static void __init pmd_leaf_tests(unsigned long pfn, pgprot_t prot) { }
> +static void __init pud_leaf_tests(unsigned long pfn, pgprot_t prot) { }
> +static void __init pmd_huge_tests(pmd_t *pmdp, unsigned long pfn, pgprot_t prot)
> +{
> +}
> +static void __init pud_huge_tests(pud_t *pudp, unsigned long pfn, pgprot_t prot)
> +{
> +}
> +static void __init pmd_savedwrite_tests(unsigned long pfn, pgprot_t prot) { }
> #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
>
> static void __init p4d_basic_tests(unsigned long pfn, pgprot_t prot)
> @@ -495,8 +731,56 @@ static void __init hugetlb_basic_tests(unsigned long pfn, pgprot_t prot)
> WARN_ON(!pte_huge(pte_mkhuge(pte)));
> #endif /* CONFIG_ARCH_WANT_GENERAL_HUGETLB */
> }
> +
> +static void __init hugetlb_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma,
> + pte_t *ptep, unsigned long pfn,
> + unsigned long vaddr, pgprot_t prot)
> +{
> + struct page *page = pfn_to_page(pfn);
> + pte_t pte = READ_ONCE(*ptep);
> + unsigned long paddr = (__pfn_to_phys(pfn) | RANDOM_ORVALUE) & PMD_MASK;
> +
> + pte = pte_mkhuge(mk_pte(pfn_to_page(PHYS_PFN(paddr)), prot));
> + set_huge_pte_at(mm, vaddr, ptep, pte);
> + barrier();
> + WARN_ON(!pte_same(pte, huge_ptep_get(ptep)));
> + huge_pte_clear(mm, vaddr, ptep, PMD_SIZE);
> + pte = huge_ptep_get(ptep);
> + WARN_ON(!huge_pte_none(pte));
> +
> + pte = mk_huge_pte(page, prot);
> + set_huge_pte_at(mm, vaddr, ptep, pte);
> + barrier();
> + huge_ptep_set_wrprotect(mm, vaddr, ptep);
> + pte = huge_ptep_get(ptep);
> + WARN_ON(huge_pte_write(pte));
> +
> + pte = mk_huge_pte(page, prot);
> + set_huge_pte_at(mm, vaddr, ptep, pte);
> + barrier();
> + huge_ptep_get_and_clear(mm, vaddr, ptep);
> + pte = huge_ptep_get(ptep);
> + WARN_ON(!huge_pte_none(pte));
> +
> + pte = mk_huge_pte(page, prot);
> + pte = huge_pte_wrprotect(pte);
> + set_huge_pte_at(mm, vaddr, ptep, pte);
> + barrier();
> + pte = huge_pte_mkwrite(pte);
> + pte = huge_pte_mkdirty(pte);
> + huge_ptep_set_access_flags(vma, vaddr, ptep, pte, 1);
> + pte = huge_ptep_get(ptep);
> + WARN_ON(!(huge_pte_write(pte) && huge_pte_dirty(pte)));
> +}
> #else /* !CONFIG_HUGETLB_PAGE */
> static void __init hugetlb_basic_tests(unsigned long pfn, pgprot_t prot) { }
> +static void __init hugetlb_advanced_tests(struct mm_struct *mm,
> + struct vm_area_struct *vma,
> + pte_t *ptep, unsigned long pfn,
> + unsigned long vaddr, pgprot_t prot)
> +{
> +}
> #endif /* CONFIG_HUGETLB_PAGE */
>
> #ifdef CONFIG_TRANSPARENT_HUGEPAGE
> @@ -568,6 +852,7 @@ static unsigned long __init get_random_vaddr(void)
>
> static int __init debug_vm_pgtable(void)
> {
> + struct vm_area_struct *vma;
> struct mm_struct *mm;
> pgd_t *pgdp;
> p4d_t *p4dp, *saved_p4dp;
> @@ -596,6 +881,12 @@ static int __init debug_vm_pgtable(void)
> */
> protnone = __P000;
>
> + vma = vm_area_alloc(mm);
> + if (!vma) {
> + pr_err("vma allocation failed\n");
> + return 1;
> + }
> +
> /*
> * PFN for mapping at PTE level is determined from a standard kernel
> * text symbol. But pfns for higher page table levels are derived by
> @@ -644,6 +935,20 @@ static int __init debug_vm_pgtable(void)
> p4d_clear_tests(mm, p4dp);
> pgd_clear_tests(mm, pgdp);
>
> + pte_advanced_tests(mm, vma, ptep, pte_aligned, vaddr, prot);
> + pmd_advanced_tests(mm, vma, pmdp, pmd_aligned, vaddr, prot);
> + pud_advanced_tests(mm, vma, pudp, pud_aligned, vaddr, prot);
> + hugetlb_advanced_tests(mm, vma, ptep, pte_aligned, vaddr, prot);
> +
> + pmd_leaf_tests(pmd_aligned, prot);
> + pud_leaf_tests(pud_aligned, prot);
> +
> + pmd_huge_tests(pmdp, pmd_aligned, prot);
> + pud_huge_tests(pudp, pud_aligned, prot);
> +
> + pte_savedwrite_tests(pte_aligned, prot);
> + pmd_savedwrite_tests(pmd_aligned, prot);
> +
> pte_unmap_unlock(ptep, ptl);
>
> pmd_populate_tests(mm, pmdp, saved_ptep);
> @@ -678,6 +983,7 @@ static int __init debug_vm_pgtable(void)
> pmd_free(mm, saved_pmdp);
> pte_free(mm, saved_ptep);
>
> + vm_area_free(vma);
> mm_dec_nr_puds(mm);
> mm_dec_nr_pmds(mm);
> mm_dec_nr_ptes(mm);
>
Christophe
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox