[][kernel][mt7988][backport dhrystone from kernel 6.4]

[Description]
Add backport dhrystone from kernel 6.4 to backport-5.4.

[Release-log]
N/A

Change-Id: I0cf90c7bc11002da820e7c2aa6a261df2dfb0747
Reviewed-on: https://gerrit.mediatek.inc/c/openwrt/feeds/mtk_openwrt_feeds/+/7672020
diff --git a/target/linux/generic/backport-5.4/999-1900-lib-add-Dhrystone-benchmark-test.patch b/target/linux/generic/backport-5.4/999-1900-lib-add-Dhrystone-benchmark-test.patch
new file mode 100644
index 0000000..a299b20
--- /dev/null
+++ b/target/linux/generic/backport-5.4/999-1900-lib-add-Dhrystone-benchmark-test.patch
@@ -0,0 +1,1036 @@
+From d5528cc16893f1f64b07936b1e88aa023128debb Mon Sep 17 00:00:00 2001
+From: Geert Uytterhoeven <geert+renesas@glider.be>
+Date: Thu, 8 Dec 2022 15:31:28 +0100
+Subject: [PATCH] lib: add Dhrystone benchmark test
+
+When working on SoC bring-up, (a full) userspace may not be available,
+making it hard to benchmark the CPU performance of the system under
+development.  Still, one may want to have a rough idea of the (relative)
+performance of one or more CPU cores, especially when working on e.g.  the
+clock driver that controls the CPU core clock(s).
+
+Hence make the classical Dhrystone 2.1 benchmark available as a Linux
+kernel test module, based on[1].
+
+When built-in, this benchmark can be run without any userspace present.
+
+Parallel runs (run on multiple CPU cores) are supported, just kick the
+"run" file multiple times.
+
+Note that the actual figures depend on the configuration options that
+control compiler optimization (e.g.  CONFIG_CC_OPTIMIZE_FOR_SIZE vs.
+CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE), and on the compiler options used when
+building the kernel in general.  Hence numbers may differ from those
+obtained by running similar benchmarks in userspace.
+
+[1] https://github.com/qris/dhrystone-deb.git
+
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Link: https://lkml.kernel.org/r/4d07ad990740a5f1e426ce4566fb514f60ec9bdd.1670509558.git.geert+renesas@glider.be
+Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
+Cc: Arnd Bergmann <arnd@arndb.de>
+Cc: Brendan Higgins <brendanhiggins@google.com>
+Cc: David Gow <davidgow@google.com>
+[geert+renesas@glider.be: fix uninitialized use of ret]
+ Link: https://lkml.kernel.org/r/alpine.DEB.2.22.394.2212190857310.137329@ramsan.of.borg
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+---
+ lib/Kconfig.debug |  35 +++++
+ lib/Makefile      |   2 +
+ lib/dhry.h        | 358 ++++++++++++++++++++++++++++++++++++++++++++++
+ lib/dhry_1.c      | 283 ++++++++++++++++++++++++++++++++++++
+ lib/dhry_2.c      | 175 ++++++++++++++++++++++
+ lib/dhry_run.c    |  85 +++++++++++
+ 6 files changed, 938 insertions(+)
+ create mode 100644 lib/dhry.h
+ create mode 100644 lib/dhry_1.c
+ create mode 100644 lib/dhry_2.c
+ create mode 100644 lib/dhry_run.c
+
+diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
+index 881c3f84e88a..918bda4ee120 100644
+--- a/lib/Kconfig.debug
++++ b/lib/Kconfig.debug
+@@ -2079,6 +2079,41 @@ menuconfig RUNTIME_TESTING_MENU
+ 
+ if RUNTIME_TESTING_MENU
+ 
++config TEST_DHRY
++	tristate "Dhrystone benchmark test"
++	help
++	  Enable this to include the Dhrystone 2.1 benchmark.  This test
++	  calculates the number of Dhrystones per second, and the number of
++	  DMIPS (Dhrystone MIPS) obtained when the Dhrystone score is divided
++	  by 1757 (the number of Dhrystones per second obtained on the VAX
++	  11/780, nominally a 1 MIPS machine).
++
++	  To run the benchmark, it needs to be enabled explicitly, either from
++	  the kernel command line (when built-in), or from userspace (when
++	  built-in or modular.
++
++	  Run once during kernel boot:
++
++	      test_dhry.run
++
++	  Set number of iterations from kernel command line:
++
++	      test_dhry.iterations=<n>
++
++	  Set number of iterations from userspace:
++
++	      echo <n> > /sys/module/test_dhry/parameters/iterations
++
++	  Trigger manual run from userspace:
++
++	      echo y > /sys/module/test_dhry/parameters/run
++
++	  If the number of iterations is <= 0, the test will devise a suitable
++	  number of iterations (test runs for at least 2s) automatically.
++	  This process takes ca. 4s.
++
++	  If unsure, say N.
++
+ config LKDTM
+ 	tristate "Linux Kernel Dump Test Tool Module"
+ 	depends on DEBUG_FS
+diff --git a/lib/Makefile b/lib/Makefile
+index 4d9461bfea42..06b9dcd80cda 100644
+--- a/lib/Makefile
++++ b/lib/Makefile
+@@ -57,6 +57,8 @@ obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o
+ obj-y += kstrtox.o
+ obj-$(CONFIG_FIND_BIT_BENCHMARK) += find_bit_benchmark.o
+ obj-$(CONFIG_TEST_BPF) += test_bpf.o
++test_dhry-objs := dhry_1.o dhry_2.o dhry_run.o
++obj-$(CONFIG_TEST_DHRY) += test_dhry.o
+ obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
+ obj-$(CONFIG_TEST_BITOPS) += test_bitops.o
+ CFLAGS_test_bitops.o += -Werror
+diff --git a/lib/dhry.h b/lib/dhry.h
+new file mode 100644
+index 000000000000..e1a4db8e252c
+--- /dev/null
++++ b/lib/dhry.h
+@@ -0,0 +1,358 @@
++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
++/*
++ ****************************************************************************
++ *
++ *                   "DHRYSTONE" Benchmark Program
++ *                   -----------------------------
++ *
++ *  Version:    C, Version 2.1
++ *
++ *  File:       dhry.h (part 1 of 3)
++ *
++ *  Date:       May 25, 1988
++ *
++ *  Author:     Reinhold P. Weicker
++ *                      Siemens AG, AUT E 51
++ *                      Postfach 3220
++ *                      8520 Erlangen
++ *                      Germany (West)
++ *                              Phone:  [+49]-9131-7-20330
++ *                                      (8-17 Central European Time)
++ *                              Usenet: ..!mcsun!unido!estevax!weicker
++ *
++ *              Original Version (in Ada) published in
++ *              "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
++ *              pp. 1013 - 1030, together with the statistics
++ *              on which the distribution of statements etc. is based.
++ *
++ *              In this C version, the following C library functions are used:
++ *              - strcpy, strcmp (inside the measurement loop)
++ *              - printf, scanf (outside the measurement loop)
++ *              In addition, Berkeley UNIX system calls "times ()" or "time ()"
++ *              are used for execution time measurement. For measurements
++ *              on other systems, these calls have to be changed.
++ *
++ *  Collection of Results:
++ *              Reinhold Weicker (address see above) and
++ *
++ *              Rick Richardson
++ *              PC Research. Inc.
++ *              94 Apple Orchard Drive
++ *              Tinton Falls, NJ 07724
++ *                      Phone:  (201) 389-8963 (9-17 EST)
++ *                      Usenet: ...!uunet!pcrat!rick
++ *
++ *      Please send results to Rick Richardson and/or Reinhold Weicker.
++ *      Complete information should be given on hardware and software used.
++ *      Hardware information includes: Machine type, CPU, type and size
++ *      of caches; for microprocessors: clock frequency, memory speed
++ *      (number of wait states).
++ *      Software information includes: Compiler (and runtime library)
++ *      manufacturer and version, compilation switches, OS version.
++ *      The Operating System version may give an indication about the
++ *      compiler; Dhrystone itself performs no OS calls in the measurement loop.
++ *
++ *      The complete output generated by the program should be mailed
++ *      such that at least some checks for correctness can be made.
++ *
++ ***************************************************************************
++ *
++ *  History:    This version C/2.1 has been made for two reasons:
++ *
++ *              1) There is an obvious need for a common C version of
++ *              Dhrystone, since C is at present the most popular system
++ *              programming language for the class of processors
++ *              (microcomputers, minicomputers) where Dhrystone is used most.
++ *              There should be, as far as possible, only one C version of
++ *              Dhrystone such that results can be compared without
++ *              restrictions. In the past, the C versions distributed
++ *              by Rick Richardson (Version 1.1) and by Reinhold Weicker
++ *              had small (though not significant) differences.
++ *
++ *              2) As far as it is possible without changes to the Dhrystone
++ *              statistics, optimizing compilers should be prevented from
++ *              removing significant statements.
++ *
++ *              This C version has been developed in cooperation with
++ *              Rick Richardson (Tinton Falls, NJ), it incorporates many
++ *              ideas from the "Version 1.1" distributed previously by
++ *              him over the UNIX network Usenet.
++ *              I also thank Chaim Benedelac (National Semiconductor),
++ *              David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
++ *              Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
++ *              for their help with comments on earlier versions of the
++ *              benchmark.
++ *
++ *  Changes:    In the initialization part, this version follows mostly
++ *              Rick Richardson's version distributed via Usenet, not the
++ *              version distributed earlier via floppy disk by Reinhold Weicker.
++ *              As a concession to older compilers, names have been made
++ *              unique within the first 8 characters.
++ *              Inside the measurement loop, this version follows the
++ *              version previously distributed by Reinhold Weicker.
++ *
++ *              At several places in the benchmark, code has been added,
++ *              but within the measurement loop only in branches that
++ *              are not executed. The intention is that optimizing compilers
++ *              should be prevented from moving code out of the measurement
++ *              loop, or from removing code altogether. Since the statements
++ *              that are executed within the measurement loop have NOT been
++ *              changed, the numbers defining the "Dhrystone distribution"
++ *              (distribution of statements, operand types and locality)
++ *              still hold. Except for sophisticated optimizing compilers,
++ *              execution times for this version should be the same as
++ *              for previous versions.
++ *
++ *              Since it has proven difficult to subtract the time for the
++ *              measurement loop overhead in a correct way, the loop check
++ *              has been made a part of the benchmark. This does have
++ *              an impact - though a very minor one - on the distribution
++ *              statistics which have been updated for this version.
++ *
++ *              All changes within the measurement loop are described
++ *              and discussed in the companion paper "Rationale for
++ *              Dhrystone version 2".
++ *
++ *              Because of the self-imposed limitation that the order and
++ *              distribution of the executed statements should not be
++ *              changed, there are still cases where optimizing compilers
++ *              may not generate code for some statements. To a certain
++ *              degree, this is unavoidable for small synthetic benchmarks.
++ *              Users of the benchmark are advised to check code listings
++ *              whether code is generated for all statements of Dhrystone.
++ *
++ *              Version 2.1 is identical to version 2.0 distributed via
++ *              the UNIX network Usenet in March 1988 except that it corrects
++ *              some minor deficiencies that were found by users of version 2.0.
++ *              The only change within the measurement loop is that a
++ *              non-executed "else" part was added to the "if" statement in
++ *              Func_3, and a non-executed "else" part removed from Proc_3.
++ *
++ ***************************************************************************
++ *
++ *  Compilation model and measurement (IMPORTANT):
++ *
++ *  This C version of Dhrystone consists of three files:
++ *  - dhry.h (this file, containing global definitions and comments)
++ *  - dhry_1.c (containing the code corresponding to Ada package Pack_1)
++ *  - dhry_2.c (containing the code corresponding to Ada package Pack_2)
++ *
++ *  The following "ground rules" apply for measurements:
++ *  - Separate compilation
++ *  - No procedure merging
++ *  - Otherwise, compiler optimizations are allowed but should be indicated
++ *  - Default results are those without register declarations
++ *  See the companion paper "Rationale for Dhrystone Version 2" for a more
++ *  detailed discussion of these ground rules.
++ *
++ *  For 16-Bit processors (e.g. 80186, 80286), times for all compilation
++ *  models ("small", "medium", "large" etc.) should be given if possible,
++ *  together with a definition of these models for the compiler system used.
++ *
++ **************************************************************************
++ *
++ *  Dhrystone (C version) statistics:
++ *
++ *  [Comment from the first distribution, updated for version 2.
++ *   Note that because of language differences, the numbers are slightly
++ *   different from the Ada version.]
++ *
++ *  The following program contains statements of a high level programming
++ *  language (here: C) in a distribution considered representative:
++ *
++ *    assignments                  52 (51.0 %)
++ *    control statements           33 (32.4 %)
++ *    procedure, function calls    17 (16.7 %)
++ *
++ *  103 statements are dynamically executed. The program is balanced with
++ *  respect to the three aspects:
++ *
++ *    - statement type
++ *    - operand type
++ *    - operand locality
++ *         operand global, local, parameter, or constant.
++ *
++ *  The combination of these three aspects is balanced only approximately.
++ *
++ *  1. Statement Type:
++ *  -----------------             number
++ *
++ *     V1 = V2                     9
++ *       (incl. V1 = F(..)
++ *     V = Constant               12
++ *     Assignment,                 7
++ *       with array element
++ *     Assignment,                 6
++ *       with record component
++ *                                --
++ *                                34       34
++ *
++ *     X = Y +|-|"&&"|"|" Z        5
++ *     X = Y +|-|"==" Constant     6
++ *     X = X +|- 1                 3
++ *     X = Y *|/ Z                 2
++ *     X = Expression,             1
++ *           two operators
++ *     X = Expression,             1
++ *           three operators
++ *                                --
++ *                                18       18
++ *
++ *     if ....                    14
++ *       with "else"      7
++ *       without "else"   7
++ *           executed        3
++ *           not executed    4
++ *     for ...                     7  |  counted every time
++ *     while ...                   4  |  the loop condition
++ *     do ... while                1  |  is evaluated
++ *     switch ...                  1
++ *     break                       1
++ *     declaration with            1
++ *       initialization
++ *                                --
++ *                                34       34
++ *
++ *     P (...)  procedure call    11
++ *       user procedure      10
++ *       library procedure    1
++ *     X = F (...)
++ *             function  call      6
++ *       user function        5
++ *       library function     1
++ *                                --
++ *                                17       17
++ *                                        ---
++ *                                        103
++ *
++ *    The average number of parameters in procedure or function calls
++ *    is 1.82 (not counting the function values as implicit parameters).
++ *
++ *
++ *  2. Operators
++ *  ------------
++ *                          number    approximate
++ *                                    percentage
++ *
++ *    Arithmetic             32          50.8
++ *
++ *       +                     21          33.3
++ *       -                      7          11.1
++ *       *                      3           4.8
++ *       / (int div)            1           1.6
++ *
++ *    Comparison             27           42.8
++ *
++ *       ==                     9           14.3
++ *       /=                     4            6.3
++ *       >                      1            1.6
++ *       <                      3            4.8
++ *       >=                     1            1.6
++ *       <=                     9           14.3
++ *
++ *    Logic                   4            6.3
++ *
++ *       && (AND-THEN)          1            1.6
++ *       |  (OR)                1            1.6
++ *       !  (NOT)               2            3.2
++ *
++ *                           --          -----
++ *                           63          100.1
++ *
++ *
++ *  3. Operand Type (counted once per operand reference):
++ *  ---------------
++ *                          number    approximate
++ *                                    percentage
++ *
++ *     Integer               175        72.3 %
++ *     Character              45        18.6 %
++ *     Pointer                12         5.0 %
++ *     String30                6         2.5 %
++ *     Array                   2         0.8 %
++ *     Record                  2         0.8 %
++ *                           ---       -------
++ *                           242       100.0 %
++ *
++ *  When there is an access path leading to the final operand (e.g. a record
++ *  component), only the final data type on the access path is counted.
++ *
++ *
++ *  4. Operand Locality:
++ *  -------------------
++ *                                number    approximate
++ *                                          percentage
++ *
++ *     local variable              114        47.1 %
++ *     global variable              22         9.1 %
++ *     parameter                    45        18.6 %
++ *        value                        23         9.5 %
++ *        reference                    22         9.1 %
++ *     function result               6         2.5 %
++ *     constant                     55        22.7 %
++ *                                 ---       -------
++ *                                 242       100.0 %
++ *
++ *
++ *  The program does not compute anything meaningful, but it is syntactically
++ *  and semantically correct. All variables have a value assigned to them
++ *  before they are used as a source operand.
++ *
++ *  There has been no explicit effort to account for the effects of a
++ *  cache, or to balance the use of long or short displacements for code or
++ *  data.
++ *
++ ***************************************************************************
++ */
++
++typedef enum {
++	Ident_1,
++	Ident_2,
++	Ident_3,
++	Ident_4,
++	Ident_5
++} Enumeration;	/* for boolean and enumeration types in Ada, Pascal */
++
++/* General definitions: */
++
++typedef int One_Thirty;
++typedef int One_Fifty;
++typedef char Capital_Letter;
++typedef int Boolean;
++typedef char Str_30[31];
++typedef int Arr_1_Dim[50];
++typedef int Arr_2_Dim[50][50];
++
++typedef struct record {
++	struct record *Ptr_Comp;
++	Enumeration    Discr;
++	union {
++		struct {
++			Enumeration Enum_Comp;
++			int Int_Comp;
++			char Str_Comp[31];
++		} var_1;
++		struct {
++			Enumeration E_Comp_2;
++			char Str_2_Comp[31];
++		} var_2;
++		struct {
++			char Ch_1_Comp;
++			char Ch_2_Comp;
++		} var_3;
++	} variant;
++} Rec_Type, *Rec_Pointer;
++
++
++extern int Int_Glob;
++extern char Ch_1_Glob;
++
++void Proc_6(Enumeration  Enum_Val_Par, Enumeration *Enum_Ref_Par);
++void Proc_7(One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val,
++	    One_Fifty *Int_Par_Ref);
++void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref,
++	    int Int_1_Par_Val, int Int_2_Par_Val);
++Enumeration Func_1(Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val);
++Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref);
++
++int dhry(int n);
+diff --git a/lib/dhry_1.c b/lib/dhry_1.c
+new file mode 100644
+index 000000000000..83247106824c
+--- /dev/null
++++ b/lib/dhry_1.c
+@@ -0,0 +1,283 @@
++// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++/*
++ ****************************************************************************
++ *
++ *                   "DHRYSTONE" Benchmark Program
++ *                   -----------------------------
++ *
++ *  Version:    C, Version 2.1
++ *
++ *  File:       dhry_1.c (part 2 of 3)
++ *
++ *  Date:       May 25, 1988
++ *
++ *  Author:     Reinhold P. Weicker
++ *
++ ****************************************************************************
++ */
++
++#include "dhry.h"
++
++#include <linux/ktime.h>
++#include <linux/slab.h>
++#include <linux/string.h>
++
++/* Global Variables: */
++
++int Int_Glob;
++char Ch_1_Glob;
++
++static Rec_Pointer Ptr_Glob, Next_Ptr_Glob;
++static Boolean Bool_Glob;
++static char Ch_2_Glob;
++static int Arr_1_Glob[50];
++static int Arr_2_Glob[50][50];
++
++static void Proc_3(Rec_Pointer *Ptr_Ref_Par)
++/******************/
++/* executed once */
++/* Ptr_Ref_Par becomes Ptr_Glob */
++{
++	if (Ptr_Glob) {
++		/* then, executed */
++		*Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
++	}
++	Proc_7(10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
++} /* Proc_3 */
++
++
++static void Proc_1(Rec_Pointer Ptr_Val_Par)
++/******************/
++/* executed once */
++{
++	Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
++						/* == Ptr_Glob_Next */
++	/* Local variable, initialized with Ptr_Val_Par->Ptr_Comp,    */
++	/* corresponds to "rename" in Ada, "with" in Pascal           */
++
++	*Ptr_Val_Par->Ptr_Comp = *Ptr_Glob;
++	Ptr_Val_Par->variant.var_1.Int_Comp = 5;
++	Next_Record->variant.var_1.Int_Comp =
++		Ptr_Val_Par->variant.var_1.Int_Comp;
++	Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
++	Proc_3(&Next_Record->Ptr_Comp);
++	/* Ptr_Val_Par->Ptr_Comp->Ptr_Comp == Ptr_Glob->Ptr_Comp */
++	if (Next_Record->Discr == Ident_1) {
++		/* then, executed */
++		Next_Record->variant.var_1.Int_Comp = 6;
++		Proc_6(Ptr_Val_Par->variant.var_1.Enum_Comp,
++		       &Next_Record->variant.var_1.Enum_Comp);
++		Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
++		Proc_7(Next_Record->variant.var_1.Int_Comp, 10,
++		       &Next_Record->variant.var_1.Int_Comp);
++	} else {
++		/* not executed */
++		*Ptr_Val_Par = *Ptr_Val_Par->Ptr_Comp;
++	}
++} /* Proc_1 */
++
++
++static void Proc_2(One_Fifty *Int_Par_Ref)
++/******************/
++/* executed once */
++/* *Int_Par_Ref == 1, becomes 4 */
++{
++	One_Fifty  Int_Loc;
++	Enumeration   Enum_Loc;
++
++	Int_Loc = *Int_Par_Ref + 10;
++	do {
++		/* executed once */
++		if (Ch_1_Glob == 'A') {
++			/* then, executed */
++			Int_Loc -= 1;
++			*Int_Par_Ref = Int_Loc - Int_Glob;
++			Enum_Loc = Ident_1;
++		} /* if */
++	} while (Enum_Loc != Ident_1); /* true */
++} /* Proc_2 */
++
++
++static void Proc_4(void)
++/*******/
++/* executed once */
++{
++	Boolean Bool_Loc;
++
++	Bool_Loc = Ch_1_Glob == 'A';
++	Bool_Glob = Bool_Loc | Bool_Glob;
++	Ch_2_Glob = 'B';
++} /* Proc_4 */
++
++
++static void Proc_5(void)
++/*******/
++/* executed once */
++{
++	Ch_1_Glob = 'A';
++	Bool_Glob = false;
++} /* Proc_5 */
++
++
++int dhry(int n)
++/*****/
++
++  /* main program, corresponds to procedures        */
++  /* Main and Proc_0 in the Ada version             */
++{
++	One_Fifty Int_1_Loc;
++	One_Fifty Int_2_Loc;
++	One_Fifty Int_3_Loc;
++	char Ch_Index;
++	Enumeration Enum_Loc;
++	Str_30 Str_1_Loc;
++	Str_30 Str_2_Loc;
++	int Run_Index;
++	int Number_Of_Runs;
++	ktime_t Begin_Time, End_Time;
++	u32 User_Time;
++
++	/* Initializations */
++
++	Next_Ptr_Glob = (Rec_Pointer)kzalloc(sizeof(Rec_Type), GFP_KERNEL);
++	Ptr_Glob = (Rec_Pointer)kzalloc(sizeof(Rec_Type), GFP_KERNEL);
++
++	Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
++	Ptr_Glob->Discr = Ident_1;
++	Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
++	Ptr_Glob->variant.var_1.Int_Comp = 40;
++	strcpy(Ptr_Glob->variant.var_1.Str_Comp,
++	       "DHRYSTONE PROGRAM, SOME STRING");
++	strcpy(Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
++
++	Arr_2_Glob[8][7] = 10;
++	/* Was missing in published program. Without this statement,    */
++	/* Arr_2_Glob[8][7] would have an undefined value.             */
++	/* Warning: With 16-Bit processors and Number_Of_Runs > 32000,  */
++	/* overflow may occur for this array element.                   */
++
++	pr_debug("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
++
++	Number_Of_Runs = n;
++
++	pr_debug("Execution starts, %d runs through Dhrystone\n",
++		 Number_Of_Runs);
++
++	/***************/
++	/* Start timer */
++	/***************/
++
++	Begin_Time = ktime_get();
++
++	for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) {
++		Proc_5();
++		Proc_4();
++		/* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
++		Int_1_Loc = 2;
++		Int_2_Loc = 3;
++		strcpy(Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
++		Enum_Loc = Ident_2;
++		Bool_Glob = !Func_2(Str_1_Loc, Str_2_Loc);
++		/* Bool_Glob == 1 */
++		while (Int_1_Loc < Int_2_Loc) {
++			/* loop body executed once */
++			Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
++			/* Int_3_Loc == 7 */
++			Proc_7(Int_1_Loc, Int_2_Loc, &Int_3_Loc);
++			/* Int_3_Loc == 7 */
++			Int_1_Loc += 1;
++		} /* while */
++		/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
++		Proc_8(Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
++		/* Int_Glob == 5 */
++		Proc_1(Ptr_Glob);
++		for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) {
++			/* loop body executed twice */
++			if (Enum_Loc == Func_1(Ch_Index, 'C')) {
++				/* then, not executed */
++				Proc_6(Ident_1, &Enum_Loc);
++				strcpy(Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
++				Int_2_Loc = Run_Index;
++				Int_Glob = Run_Index;
++			}
++		}
++		/* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
++		Int_2_Loc = Int_2_Loc * Int_1_Loc;
++		Int_1_Loc = Int_2_Loc / Int_3_Loc;
++		Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
++		/* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
++		Proc_2(&Int_1_Loc);
++		/* Int_1_Loc == 5 */
++
++	} /* loop "for Run_Index" */
++
++	/**************/
++	/* Stop timer */
++	/**************/
++
++	End_Time = ktime_get();
++
++#define dhry_assert_int_eq(val, expected)				\
++	if (val != expected)						\
++		pr_err("%s: %d (FAIL, expected %d)\n", #val, val,	\
++		       expected);					\
++	else								\
++		pr_debug("%s: %d (OK)\n", #val, val)
++
++#define dhry_assert_char_eq(val, expected)				\
++	if (val != expected)						\
++		pr_err("%s: %c (FAIL, expected %c)\n", #val, val,	\
++		       expected);					\
++	else								\
++		pr_debug("%s: %c (OK)\n", #val, val)
++
++#define dhry_assert_string_eq(val, expected)				\
++	if (strcmp(val, expected))					\
++		pr_err("%s: %s (FAIL, expected %s)\n", #val, val,	\
++		       expected);					\
++	else								\
++		pr_debug("%s: %s (OK)\n", #val, val)
++
++	pr_debug("Execution ends\n");
++	pr_debug("Final values of the variables used in the benchmark:\n");
++	dhry_assert_int_eq(Int_Glob, 5);
++	dhry_assert_int_eq(Bool_Glob, 1);
++	dhry_assert_char_eq(Ch_1_Glob, 'A');
++	dhry_assert_char_eq(Ch_2_Glob, 'B');
++	dhry_assert_int_eq(Arr_1_Glob[8], 7);
++	dhry_assert_int_eq(Arr_2_Glob[8][7], Number_Of_Runs + 10);
++	pr_debug("Ptr_Comp: %px\n", Ptr_Glob->Ptr_Comp);
++	dhry_assert_int_eq(Ptr_Glob->Discr, 0);
++	dhry_assert_int_eq(Ptr_Glob->variant.var_1.Enum_Comp, 2);
++	dhry_assert_int_eq(Ptr_Glob->variant.var_1.Int_Comp, 17);
++	dhry_assert_string_eq(Ptr_Glob->variant.var_1.Str_Comp,
++			      "DHRYSTONE PROGRAM, SOME STRING");
++	if (Next_Ptr_Glob->Ptr_Comp != Ptr_Glob->Ptr_Comp)
++		pr_err("Next_Ptr_Glob->Ptr_Comp: %px (expected %px)\n",
++		       Next_Ptr_Glob->Ptr_Comp, Ptr_Glob->Ptr_Comp);
++	else
++		pr_debug("Next_Ptr_Glob->Ptr_Comp: %px\n",
++			 Next_Ptr_Glob->Ptr_Comp);
++	dhry_assert_int_eq(Next_Ptr_Glob->Discr, 0);
++	dhry_assert_int_eq(Next_Ptr_Glob->variant.var_1.Enum_Comp, 1);
++	dhry_assert_int_eq(Next_Ptr_Glob->variant.var_1.Int_Comp, 18);
++	dhry_assert_string_eq(Next_Ptr_Glob->variant.var_1.Str_Comp,
++			      "DHRYSTONE PROGRAM, SOME STRING");
++	dhry_assert_int_eq(Int_1_Loc, 5);
++	dhry_assert_int_eq(Int_2_Loc, 13);
++	dhry_assert_int_eq(Int_3_Loc, 7);
++	dhry_assert_int_eq(Enum_Loc, 1);
++	dhry_assert_string_eq(Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
++	dhry_assert_string_eq(Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
++
++	User_Time = ktime_to_ms(ktime_sub(End_Time, Begin_Time));
++
++	kfree(Ptr_Glob);
++	kfree(Next_Ptr_Glob);
++
++	/* Measurements should last at least 2 seconds */
++	if (User_Time < 2 * MSEC_PER_SEC)
++		return -EAGAIN;
++
++	return div_u64(mul_u32_u32(MSEC_PER_SEC, Number_Of_Runs), User_Time);
++}
+diff --git a/lib/dhry_2.c b/lib/dhry_2.c
+new file mode 100644
+index 000000000000..c19e661f37d3
+--- /dev/null
++++ b/lib/dhry_2.c
+@@ -0,0 +1,175 @@
++// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
++/*
++ ****************************************************************************
++ *
++ *                   "DHRYSTONE" Benchmark Program
++ *                   -----------------------------
++ *
++ *  Version:    C, Version 2.1
++ *
++ *  File:       dhry_2.c (part 3 of 3)
++ *
++ *  Date:       May 25, 1988
++ *
++ *  Author:     Reinhold P. Weicker
++ *
++ ****************************************************************************
++ */
++
++#include "dhry.h"
++
++#include <linux/string.h>
++
++
++static Boolean Func_3(Enumeration Enum_Par_Val)
++/***************************/
++/* executed once        */
++/* Enum_Par_Val == Ident_3 */
++{
++	Enumeration Enum_Loc;
++
++	Enum_Loc = Enum_Par_Val;
++	if (Enum_Loc == Ident_3) {
++		/* then, executed */
++		return true;
++	} else {
++		/* not executed */
++		return false;
++	}
++} /* Func_3 */
++
++
++void Proc_6(Enumeration  Enum_Val_Par, Enumeration *Enum_Ref_Par)
++/*********************************/
++/* executed once */
++/* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
++{
++	*Enum_Ref_Par = Enum_Val_Par;
++	if (!Func_3(Enum_Val_Par)) {
++		/* then, not executed */
++		*Enum_Ref_Par = Ident_4;
++	}
++	switch (Enum_Val_Par) {
++	case Ident_1:
++		*Enum_Ref_Par = Ident_1;
++		break;
++	case Ident_2:
++		if (Int_Glob > 100) {
++			/* then */
++			*Enum_Ref_Par = Ident_1;
++		} else {
++			*Enum_Ref_Par = Ident_4;
++		}
++		break;
++	case Ident_3: /* executed */
++		*Enum_Ref_Par = Ident_2;
++		break;
++	case Ident_4:
++		break;
++	case Ident_5:
++		*Enum_Ref_Par = Ident_3;
++		break;
++	} /* switch */
++} /* Proc_6 */
++
++
++void Proc_7(One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref)
++/**********************************************/
++/* executed three times                                      */
++/* first call:      Int_1_Par_Val == 2, Int_2_Par_Val == 3,  */
++/*                  Int_Par_Ref becomes 7                    */
++/* second call:     Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
++/*                  Int_Par_Ref becomes 17                   */
++/* third call:      Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
++/*                  Int_Par_Ref becomes 18                   */
++{
++	One_Fifty Int_Loc;
++
++	Int_Loc = Int_1_Par_Val + 2;
++	*Int_Par_Ref = Int_2_Par_Val + Int_Loc;
++} /* Proc_7 */
++
++
++void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref, int Int_1_Par_Val, int Int_2_Par_Val)
++/*********************************************************************/
++/* executed once      */
++/* Int_Par_Val_1 == 3 */
++/* Int_Par_Val_2 == 7 */
++{
++	One_Fifty Int_Index;
++	One_Fifty Int_Loc;
++
++	Int_Loc = Int_1_Par_Val + 5;
++	Arr_1_Par_Ref[Int_Loc] = Int_2_Par_Val;
++	Arr_1_Par_Ref[Int_Loc+1] = Arr_1_Par_Ref[Int_Loc];
++	Arr_1_Par_Ref[Int_Loc+30] = Int_Loc;
++	for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
++		Arr_2_Par_Ref[Int_Loc][Int_Index] = Int_Loc;
++	Arr_2_Par_Ref[Int_Loc][Int_Loc-1] += 1;
++	Arr_2_Par_Ref[Int_Loc+20][Int_Loc] = Arr_1_Par_Ref[Int_Loc];
++	Int_Glob = 5;
++} /* Proc_8 */
++
++
++Enumeration Func_1(Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val)
++/*************************************************/
++/* executed three times                                         */
++/* first call:      Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R'    */
++/* second call:     Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C'    */
++/* third call:      Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C'    */
++{
++	Capital_Letter Ch_1_Loc;
++	Capital_Letter Ch_2_Loc;
++
++	Ch_1_Loc = Ch_1_Par_Val;
++	Ch_2_Loc = Ch_1_Loc;
++	if (Ch_2_Loc != Ch_2_Par_Val) {
++		/* then, executed */
++		return Ident_1;
++	} else {
++		/* not executed */
++		Ch_1_Glob = Ch_1_Loc;
++		return Ident_2;
++	}
++} /* Func_1 */
++
++
++Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref)
++/*************************************************/
++/* executed once */
++/* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
++/* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
++{
++	One_Thirty Int_Loc;
++	Capital_Letter Ch_Loc;
++
++	Int_Loc = 2;
++	while (Int_Loc <= 2) {
++		/* loop body executed once */
++		if (Func_1(Str_1_Par_Ref[Int_Loc],
++			   Str_2_Par_Ref[Int_Loc+1]) == Ident_1) {
++			/* then, executed */
++			Ch_Loc = 'A';
++			Int_Loc += 1;
++		}
++	} /* if, while */
++	if (Ch_Loc >= 'W' && Ch_Loc < 'Z') {
++		/* then, not executed */
++		Int_Loc = 7;
++	}
++	if (Ch_Loc == 'R') {
++		/* then, not executed */
++		return true;
++	} else {
++		/* executed */
++		if (strcmp(Str_1_Par_Ref, Str_2_Par_Ref) > 0) {
++			/* then, not executed */
++			Int_Loc += 7;
++			Int_Glob = Int_Loc;
++			return true;
++		} else {
++			/* executed */
++			return false;
++		}
++	} /* if Ch_Loc */
++} /* Func_2 */
+diff --git a/lib/dhry_run.c b/lib/dhry_run.c
+new file mode 100644
+index 000000000000..f9d33efa6d09
+--- /dev/null
++++ b/lib/dhry_run.c
+@@ -0,0 +1,85 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Dhrystone benchmark test module
++ *
++ * Copyright (C) 2022 Glider bv
++ */
++
++#include "dhry.h"
++
++#include <linux/kernel.h>
++#include <linux/module.h>
++#include <linux/moduleparam.h>
++#include <linux/mutex.h>
++#include <linux/smp.h>
++
++#define DHRY_VAX	1757
++
++static int dhry_run_set(const char *val, const struct kernel_param *kp);
++static const struct kernel_param_ops run_ops = {
++	.flags = KERNEL_PARAM_OPS_FL_NOARG,
++	.set = dhry_run_set,
++};
++static bool dhry_run;
++module_param_cb(run, &run_ops, &dhry_run, 0200);
++MODULE_PARM_DESC(run, "Run the test (default: false)");
++
++static int iterations = -1;
++module_param(iterations, int, 0644);
++MODULE_PARM_DESC(iterations,
++		"Number of iterations through the benchmark (default: auto)");
++
++static void dhry_benchmark(void)
++{
++	int i, n;
++
++	if (iterations > 0) {
++		n = dhry(iterations);
++		goto report;
++	}
++
++	for (i = DHRY_VAX; i > 0; i <<= 1) {
++		n = dhry(i);
++		if (n != -EAGAIN)
++			break;
++	}
++
++report:
++	if (n >= 0)
++		pr_info("CPU%u: Dhrystones per Second: %d (%d DMIPS)\n",
++			smp_processor_id(), n, n / DHRY_VAX);
++	else if (n == -EAGAIN)
++		pr_err("Please increase the number of iterations\n");
++	else
++		pr_err("Dhrystone benchmark failed error %pe\n", ERR_PTR(n));
++}
++
++static int dhry_run_set(const char *val, const struct kernel_param *kp)
++{
++	int ret;
++
++	if (val) {
++		ret = param_set_bool(val, kp);
++		if (ret)
++			return ret;
++	} else {
++		dhry_run = true;
++	}
++
++	if (dhry_run && system_state == SYSTEM_RUNNING)
++		dhry_benchmark();
++
++	return 0;
++}
++
++static int __init dhry_init(void)
++{
++	if (dhry_run)
++		dhry_benchmark();
++
++	return 0;
++}
++module_init(dhry_init);
++
++MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>");
++MODULE_LICENSE("GPL");
+-- 
+2.18.0
+