blob: a299b20c185989e6aa9f373ba88d804a06075b44 [file] [log] [blame]
developer6d918e52023-06-27 16:54:06 +08001From d5528cc16893f1f64b07936b1e88aa023128debb Mon Sep 17 00:00:00 2001
2From: Geert Uytterhoeven <geert+renesas@glider.be>
3Date: Thu, 8 Dec 2022 15:31:28 +0100
4Subject: [PATCH] lib: add Dhrystone benchmark test
5
6When working on SoC bring-up, (a full) userspace may not be available,
7making it hard to benchmark the CPU performance of the system under
8development. Still, one may want to have a rough idea of the (relative)
9performance of one or more CPU cores, especially when working on e.g. the
10clock driver that controls the CPU core clock(s).
11
12Hence make the classical Dhrystone 2.1 benchmark available as a Linux
13kernel test module, based on[1].
14
15When built-in, this benchmark can be run without any userspace present.
16
17Parallel runs (run on multiple CPU cores) are supported, just kick the
18"run" file multiple times.
19
20Note that the actual figures depend on the configuration options that
21control compiler optimization (e.g. CONFIG_CC_OPTIMIZE_FOR_SIZE vs.
22CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE), and on the compiler options used when
23building the kernel in general. Hence numbers may differ from those
24obtained by running similar benchmarks in userspace.
25
26[1] https://github.com/qris/dhrystone-deb.git
27
28Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
29Link: https://lkml.kernel.org/r/4d07ad990740a5f1e426ce4566fb514f60ec9bdd.1670509558.git.geert+renesas@glider.be
30Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
31Cc: Arnd Bergmann <arnd@arndb.de>
32Cc: Brendan Higgins <brendanhiggins@google.com>
33Cc: David Gow <davidgow@google.com>
34[geert+renesas@glider.be: fix uninitialized use of ret]
35 Link: https://lkml.kernel.org/r/alpine.DEB.2.22.394.2212190857310.137329@ramsan.of.borg
36Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
37---
38 lib/Kconfig.debug | 35 +++++
39 lib/Makefile | 2 +
40 lib/dhry.h | 358 ++++++++++++++++++++++++++++++++++++++++++++++
41 lib/dhry_1.c | 283 ++++++++++++++++++++++++++++++++++++
42 lib/dhry_2.c | 175 ++++++++++++++++++++++
43 lib/dhry_run.c | 85 +++++++++++
44 6 files changed, 938 insertions(+)
45 create mode 100644 lib/dhry.h
46 create mode 100644 lib/dhry_1.c
47 create mode 100644 lib/dhry_2.c
48 create mode 100644 lib/dhry_run.c
49
50diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
51index 881c3f84e88a..918bda4ee120 100644
52--- a/lib/Kconfig.debug
53+++ b/lib/Kconfig.debug
54@@ -2079,6 +2079,41 @@ menuconfig RUNTIME_TESTING_MENU
55
56 if RUNTIME_TESTING_MENU
57
58+config TEST_DHRY
59+ tristate "Dhrystone benchmark test"
60+ help
61+ Enable this to include the Dhrystone 2.1 benchmark. This test
62+ calculates the number of Dhrystones per second, and the number of
63+ DMIPS (Dhrystone MIPS) obtained when the Dhrystone score is divided
64+ by 1757 (the number of Dhrystones per second obtained on the VAX
65+ 11/780, nominally a 1 MIPS machine).
66+
67+ To run the benchmark, it needs to be enabled explicitly, either from
68+ the kernel command line (when built-in), or from userspace (when
69+ built-in or modular.
70+
71+ Run once during kernel boot:
72+
73+ test_dhry.run
74+
75+ Set number of iterations from kernel command line:
76+
77+ test_dhry.iterations=<n>
78+
79+ Set number of iterations from userspace:
80+
81+ echo <n> > /sys/module/test_dhry/parameters/iterations
82+
83+ Trigger manual run from userspace:
84+
85+ echo y > /sys/module/test_dhry/parameters/run
86+
87+ If the number of iterations is <= 0, the test will devise a suitable
88+ number of iterations (test runs for at least 2s) automatically.
89+ This process takes ca. 4s.
90+
91+ If unsure, say N.
92+
93 config LKDTM
94 tristate "Linux Kernel Dump Test Tool Module"
95 depends on DEBUG_FS
96diff --git a/lib/Makefile b/lib/Makefile
97index 4d9461bfea42..06b9dcd80cda 100644
98--- a/lib/Makefile
99+++ b/lib/Makefile
100@@ -57,6 +57,8 @@ obj-$(CONFIG_TEST_HEXDUMP) += test_hexdump.o
101 obj-y += kstrtox.o
102 obj-$(CONFIG_FIND_BIT_BENCHMARK) += find_bit_benchmark.o
103 obj-$(CONFIG_TEST_BPF) += test_bpf.o
104+test_dhry-objs := dhry_1.o dhry_2.o dhry_run.o
105+obj-$(CONFIG_TEST_DHRY) += test_dhry.o
106 obj-$(CONFIG_TEST_FIRMWARE) += test_firmware.o
107 obj-$(CONFIG_TEST_BITOPS) += test_bitops.o
108 CFLAGS_test_bitops.o += -Werror
109diff --git a/lib/dhry.h b/lib/dhry.h
110new file mode 100644
111index 000000000000..e1a4db8e252c
112--- /dev/null
113+++ b/lib/dhry.h
114@@ -0,0 +1,358 @@
115+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
116+/*
117+ ****************************************************************************
118+ *
119+ * "DHRYSTONE" Benchmark Program
120+ * -----------------------------
121+ *
122+ * Version: C, Version 2.1
123+ *
124+ * File: dhry.h (part 1 of 3)
125+ *
126+ * Date: May 25, 1988
127+ *
128+ * Author: Reinhold P. Weicker
129+ * Siemens AG, AUT E 51
130+ * Postfach 3220
131+ * 8520 Erlangen
132+ * Germany (West)
133+ * Phone: [+49]-9131-7-20330
134+ * (8-17 Central European Time)
135+ * Usenet: ..!mcsun!unido!estevax!weicker
136+ *
137+ * Original Version (in Ada) published in
138+ * "Communications of the ACM" vol. 27., no. 10 (Oct. 1984),
139+ * pp. 1013 - 1030, together with the statistics
140+ * on which the distribution of statements etc. is based.
141+ *
142+ * In this C version, the following C library functions are used:
143+ * - strcpy, strcmp (inside the measurement loop)
144+ * - printf, scanf (outside the measurement loop)
145+ * In addition, Berkeley UNIX system calls "times ()" or "time ()"
146+ * are used for execution time measurement. For measurements
147+ * on other systems, these calls have to be changed.
148+ *
149+ * Collection of Results:
150+ * Reinhold Weicker (address see above) and
151+ *
152+ * Rick Richardson
153+ * PC Research. Inc.
154+ * 94 Apple Orchard Drive
155+ * Tinton Falls, NJ 07724
156+ * Phone: (201) 389-8963 (9-17 EST)
157+ * Usenet: ...!uunet!pcrat!rick
158+ *
159+ * Please send results to Rick Richardson and/or Reinhold Weicker.
160+ * Complete information should be given on hardware and software used.
161+ * Hardware information includes: Machine type, CPU, type and size
162+ * of caches; for microprocessors: clock frequency, memory speed
163+ * (number of wait states).
164+ * Software information includes: Compiler (and runtime library)
165+ * manufacturer and version, compilation switches, OS version.
166+ * The Operating System version may give an indication about the
167+ * compiler; Dhrystone itself performs no OS calls in the measurement loop.
168+ *
169+ * The complete output generated by the program should be mailed
170+ * such that at least some checks for correctness can be made.
171+ *
172+ ***************************************************************************
173+ *
174+ * History: This version C/2.1 has been made for two reasons:
175+ *
176+ * 1) There is an obvious need for a common C version of
177+ * Dhrystone, since C is at present the most popular system
178+ * programming language for the class of processors
179+ * (microcomputers, minicomputers) where Dhrystone is used most.
180+ * There should be, as far as possible, only one C version of
181+ * Dhrystone such that results can be compared without
182+ * restrictions. In the past, the C versions distributed
183+ * by Rick Richardson (Version 1.1) and by Reinhold Weicker
184+ * had small (though not significant) differences.
185+ *
186+ * 2) As far as it is possible without changes to the Dhrystone
187+ * statistics, optimizing compilers should be prevented from
188+ * removing significant statements.
189+ *
190+ * This C version has been developed in cooperation with
191+ * Rick Richardson (Tinton Falls, NJ), it incorporates many
192+ * ideas from the "Version 1.1" distributed previously by
193+ * him over the UNIX network Usenet.
194+ * I also thank Chaim Benedelac (National Semiconductor),
195+ * David Ditzel (SUN), Earl Killian and John Mashey (MIPS),
196+ * Alan Smith and Rafael Saavedra-Barrera (UC at Berkeley)
197+ * for their help with comments on earlier versions of the
198+ * benchmark.
199+ *
200+ * Changes: In the initialization part, this version follows mostly
201+ * Rick Richardson's version distributed via Usenet, not the
202+ * version distributed earlier via floppy disk by Reinhold Weicker.
203+ * As a concession to older compilers, names have been made
204+ * unique within the first 8 characters.
205+ * Inside the measurement loop, this version follows the
206+ * version previously distributed by Reinhold Weicker.
207+ *
208+ * At several places in the benchmark, code has been added,
209+ * but within the measurement loop only in branches that
210+ * are not executed. The intention is that optimizing compilers
211+ * should be prevented from moving code out of the measurement
212+ * loop, or from removing code altogether. Since the statements
213+ * that are executed within the measurement loop have NOT been
214+ * changed, the numbers defining the "Dhrystone distribution"
215+ * (distribution of statements, operand types and locality)
216+ * still hold. Except for sophisticated optimizing compilers,
217+ * execution times for this version should be the same as
218+ * for previous versions.
219+ *
220+ * Since it has proven difficult to subtract the time for the
221+ * measurement loop overhead in a correct way, the loop check
222+ * has been made a part of the benchmark. This does have
223+ * an impact - though a very minor one - on the distribution
224+ * statistics which have been updated for this version.
225+ *
226+ * All changes within the measurement loop are described
227+ * and discussed in the companion paper "Rationale for
228+ * Dhrystone version 2".
229+ *
230+ * Because of the self-imposed limitation that the order and
231+ * distribution of the executed statements should not be
232+ * changed, there are still cases where optimizing compilers
233+ * may not generate code for some statements. To a certain
234+ * degree, this is unavoidable for small synthetic benchmarks.
235+ * Users of the benchmark are advised to check code listings
236+ * whether code is generated for all statements of Dhrystone.
237+ *
238+ * Version 2.1 is identical to version 2.0 distributed via
239+ * the UNIX network Usenet in March 1988 except that it corrects
240+ * some minor deficiencies that were found by users of version 2.0.
241+ * The only change within the measurement loop is that a
242+ * non-executed "else" part was added to the "if" statement in
243+ * Func_3, and a non-executed "else" part removed from Proc_3.
244+ *
245+ ***************************************************************************
246+ *
247+ * Compilation model and measurement (IMPORTANT):
248+ *
249+ * This C version of Dhrystone consists of three files:
250+ * - dhry.h (this file, containing global definitions and comments)
251+ * - dhry_1.c (containing the code corresponding to Ada package Pack_1)
252+ * - dhry_2.c (containing the code corresponding to Ada package Pack_2)
253+ *
254+ * The following "ground rules" apply for measurements:
255+ * - Separate compilation
256+ * - No procedure merging
257+ * - Otherwise, compiler optimizations are allowed but should be indicated
258+ * - Default results are those without register declarations
259+ * See the companion paper "Rationale for Dhrystone Version 2" for a more
260+ * detailed discussion of these ground rules.
261+ *
262+ * For 16-Bit processors (e.g. 80186, 80286), times for all compilation
263+ * models ("small", "medium", "large" etc.) should be given if possible,
264+ * together with a definition of these models for the compiler system used.
265+ *
266+ **************************************************************************
267+ *
268+ * Dhrystone (C version) statistics:
269+ *
270+ * [Comment from the first distribution, updated for version 2.
271+ * Note that because of language differences, the numbers are slightly
272+ * different from the Ada version.]
273+ *
274+ * The following program contains statements of a high level programming
275+ * language (here: C) in a distribution considered representative:
276+ *
277+ * assignments 52 (51.0 %)
278+ * control statements 33 (32.4 %)
279+ * procedure, function calls 17 (16.7 %)
280+ *
281+ * 103 statements are dynamically executed. The program is balanced with
282+ * respect to the three aspects:
283+ *
284+ * - statement type
285+ * - operand type
286+ * - operand locality
287+ * operand global, local, parameter, or constant.
288+ *
289+ * The combination of these three aspects is balanced only approximately.
290+ *
291+ * 1. Statement Type:
292+ * ----------------- number
293+ *
294+ * V1 = V2 9
295+ * (incl. V1 = F(..)
296+ * V = Constant 12
297+ * Assignment, 7
298+ * with array element
299+ * Assignment, 6
300+ * with record component
301+ * --
302+ * 34 34
303+ *
304+ * X = Y +|-|"&&"|"|" Z 5
305+ * X = Y +|-|"==" Constant 6
306+ * X = X +|- 1 3
307+ * X = Y *|/ Z 2
308+ * X = Expression, 1
309+ * two operators
310+ * X = Expression, 1
311+ * three operators
312+ * --
313+ * 18 18
314+ *
315+ * if .... 14
316+ * with "else" 7
317+ * without "else" 7
318+ * executed 3
319+ * not executed 4
320+ * for ... 7 | counted every time
321+ * while ... 4 | the loop condition
322+ * do ... while 1 | is evaluated
323+ * switch ... 1
324+ * break 1
325+ * declaration with 1
326+ * initialization
327+ * --
328+ * 34 34
329+ *
330+ * P (...) procedure call 11
331+ * user procedure 10
332+ * library procedure 1
333+ * X = F (...)
334+ * function call 6
335+ * user function 5
336+ * library function 1
337+ * --
338+ * 17 17
339+ * ---
340+ * 103
341+ *
342+ * The average number of parameters in procedure or function calls
343+ * is 1.82 (not counting the function values as implicit parameters).
344+ *
345+ *
346+ * 2. Operators
347+ * ------------
348+ * number approximate
349+ * percentage
350+ *
351+ * Arithmetic 32 50.8
352+ *
353+ * + 21 33.3
354+ * - 7 11.1
355+ * * 3 4.8
356+ * / (int div) 1 1.6
357+ *
358+ * Comparison 27 42.8
359+ *
360+ * == 9 14.3
361+ * /= 4 6.3
362+ * > 1 1.6
363+ * < 3 4.8
364+ * >= 1 1.6
365+ * <= 9 14.3
366+ *
367+ * Logic 4 6.3
368+ *
369+ * && (AND-THEN) 1 1.6
370+ * | (OR) 1 1.6
371+ * ! (NOT) 2 3.2
372+ *
373+ * -- -----
374+ * 63 100.1
375+ *
376+ *
377+ * 3. Operand Type (counted once per operand reference):
378+ * ---------------
379+ * number approximate
380+ * percentage
381+ *
382+ * Integer 175 72.3 %
383+ * Character 45 18.6 %
384+ * Pointer 12 5.0 %
385+ * String30 6 2.5 %
386+ * Array 2 0.8 %
387+ * Record 2 0.8 %
388+ * --- -------
389+ * 242 100.0 %
390+ *
391+ * When there is an access path leading to the final operand (e.g. a record
392+ * component), only the final data type on the access path is counted.
393+ *
394+ *
395+ * 4. Operand Locality:
396+ * -------------------
397+ * number approximate
398+ * percentage
399+ *
400+ * local variable 114 47.1 %
401+ * global variable 22 9.1 %
402+ * parameter 45 18.6 %
403+ * value 23 9.5 %
404+ * reference 22 9.1 %
405+ * function result 6 2.5 %
406+ * constant 55 22.7 %
407+ * --- -------
408+ * 242 100.0 %
409+ *
410+ *
411+ * The program does not compute anything meaningful, but it is syntactically
412+ * and semantically correct. All variables have a value assigned to them
413+ * before they are used as a source operand.
414+ *
415+ * There has been no explicit effort to account for the effects of a
416+ * cache, or to balance the use of long or short displacements for code or
417+ * data.
418+ *
419+ ***************************************************************************
420+ */
421+
422+typedef enum {
423+ Ident_1,
424+ Ident_2,
425+ Ident_3,
426+ Ident_4,
427+ Ident_5
428+} Enumeration; /* for boolean and enumeration types in Ada, Pascal */
429+
430+/* General definitions: */
431+
432+typedef int One_Thirty;
433+typedef int One_Fifty;
434+typedef char Capital_Letter;
435+typedef int Boolean;
436+typedef char Str_30[31];
437+typedef int Arr_1_Dim[50];
438+typedef int Arr_2_Dim[50][50];
439+
440+typedef struct record {
441+ struct record *Ptr_Comp;
442+ Enumeration Discr;
443+ union {
444+ struct {
445+ Enumeration Enum_Comp;
446+ int Int_Comp;
447+ char Str_Comp[31];
448+ } var_1;
449+ struct {
450+ Enumeration E_Comp_2;
451+ char Str_2_Comp[31];
452+ } var_2;
453+ struct {
454+ char Ch_1_Comp;
455+ char Ch_2_Comp;
456+ } var_3;
457+ } variant;
458+} Rec_Type, *Rec_Pointer;
459+
460+
461+extern int Int_Glob;
462+extern char Ch_1_Glob;
463+
464+void Proc_6(Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par);
465+void Proc_7(One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val,
466+ One_Fifty *Int_Par_Ref);
467+void Proc_8(Arr_1_Dim Arr_1_Par_Ref, Arr_2_Dim Arr_2_Par_Ref,
468+ int Int_1_Par_Val, int Int_2_Par_Val);
469+Enumeration Func_1(Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val);
470+Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref);
471+
472+int dhry(int n);
473diff --git a/lib/dhry_1.c b/lib/dhry_1.c
474new file mode 100644
475index 000000000000..83247106824c
476--- /dev/null
477+++ b/lib/dhry_1.c
478@@ -0,0 +1,283 @@
479+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
480+/*
481+ ****************************************************************************
482+ *
483+ * "DHRYSTONE" Benchmark Program
484+ * -----------------------------
485+ *
486+ * Version: C, Version 2.1
487+ *
488+ * File: dhry_1.c (part 2 of 3)
489+ *
490+ * Date: May 25, 1988
491+ *
492+ * Author: Reinhold P. Weicker
493+ *
494+ ****************************************************************************
495+ */
496+
497+#include "dhry.h"
498+
499+#include <linux/ktime.h>
500+#include <linux/slab.h>
501+#include <linux/string.h>
502+
503+/* Global Variables: */
504+
505+int Int_Glob;
506+char Ch_1_Glob;
507+
508+static Rec_Pointer Ptr_Glob, Next_Ptr_Glob;
509+static Boolean Bool_Glob;
510+static char Ch_2_Glob;
511+static int Arr_1_Glob[50];
512+static int Arr_2_Glob[50][50];
513+
514+static void Proc_3(Rec_Pointer *Ptr_Ref_Par)
515+/******************/
516+/* executed once */
517+/* Ptr_Ref_Par becomes Ptr_Glob */
518+{
519+ if (Ptr_Glob) {
520+ /* then, executed */
521+ *Ptr_Ref_Par = Ptr_Glob->Ptr_Comp;
522+ }
523+ Proc_7(10, Int_Glob, &Ptr_Glob->variant.var_1.Int_Comp);
524+} /* Proc_3 */
525+
526+
527+static void Proc_1(Rec_Pointer Ptr_Val_Par)
528+/******************/
529+/* executed once */
530+{
531+ Rec_Pointer Next_Record = Ptr_Val_Par->Ptr_Comp;
532+ /* == Ptr_Glob_Next */
533+ /* Local variable, initialized with Ptr_Val_Par->Ptr_Comp, */
534+ /* corresponds to "rename" in Ada, "with" in Pascal */
535+
536+ *Ptr_Val_Par->Ptr_Comp = *Ptr_Glob;
537+ Ptr_Val_Par->variant.var_1.Int_Comp = 5;
538+ Next_Record->variant.var_1.Int_Comp =
539+ Ptr_Val_Par->variant.var_1.Int_Comp;
540+ Next_Record->Ptr_Comp = Ptr_Val_Par->Ptr_Comp;
541+ Proc_3(&Next_Record->Ptr_Comp);
542+ /* Ptr_Val_Par->Ptr_Comp->Ptr_Comp == Ptr_Glob->Ptr_Comp */
543+ if (Next_Record->Discr == Ident_1) {
544+ /* then, executed */
545+ Next_Record->variant.var_1.Int_Comp = 6;
546+ Proc_6(Ptr_Val_Par->variant.var_1.Enum_Comp,
547+ &Next_Record->variant.var_1.Enum_Comp);
548+ Next_Record->Ptr_Comp = Ptr_Glob->Ptr_Comp;
549+ Proc_7(Next_Record->variant.var_1.Int_Comp, 10,
550+ &Next_Record->variant.var_1.Int_Comp);
551+ } else {
552+ /* not executed */
553+ *Ptr_Val_Par = *Ptr_Val_Par->Ptr_Comp;
554+ }
555+} /* Proc_1 */
556+
557+
558+static void Proc_2(One_Fifty *Int_Par_Ref)
559+/******************/
560+/* executed once */
561+/* *Int_Par_Ref == 1, becomes 4 */
562+{
563+ One_Fifty Int_Loc;
564+ Enumeration Enum_Loc;
565+
566+ Int_Loc = *Int_Par_Ref + 10;
567+ do {
568+ /* executed once */
569+ if (Ch_1_Glob == 'A') {
570+ /* then, executed */
571+ Int_Loc -= 1;
572+ *Int_Par_Ref = Int_Loc - Int_Glob;
573+ Enum_Loc = Ident_1;
574+ } /* if */
575+ } while (Enum_Loc != Ident_1); /* true */
576+} /* Proc_2 */
577+
578+
579+static void Proc_4(void)
580+/*******/
581+/* executed once */
582+{
583+ Boolean Bool_Loc;
584+
585+ Bool_Loc = Ch_1_Glob == 'A';
586+ Bool_Glob = Bool_Loc | Bool_Glob;
587+ Ch_2_Glob = 'B';
588+} /* Proc_4 */
589+
590+
591+static void Proc_5(void)
592+/*******/
593+/* executed once */
594+{
595+ Ch_1_Glob = 'A';
596+ Bool_Glob = false;
597+} /* Proc_5 */
598+
599+
600+int dhry(int n)
601+/*****/
602+
603+ /* main program, corresponds to procedures */
604+ /* Main and Proc_0 in the Ada version */
605+{
606+ One_Fifty Int_1_Loc;
607+ One_Fifty Int_2_Loc;
608+ One_Fifty Int_3_Loc;
609+ char Ch_Index;
610+ Enumeration Enum_Loc;
611+ Str_30 Str_1_Loc;
612+ Str_30 Str_2_Loc;
613+ int Run_Index;
614+ int Number_Of_Runs;
615+ ktime_t Begin_Time, End_Time;
616+ u32 User_Time;
617+
618+ /* Initializations */
619+
620+ Next_Ptr_Glob = (Rec_Pointer)kzalloc(sizeof(Rec_Type), GFP_KERNEL);
621+ Ptr_Glob = (Rec_Pointer)kzalloc(sizeof(Rec_Type), GFP_KERNEL);
622+
623+ Ptr_Glob->Ptr_Comp = Next_Ptr_Glob;
624+ Ptr_Glob->Discr = Ident_1;
625+ Ptr_Glob->variant.var_1.Enum_Comp = Ident_3;
626+ Ptr_Glob->variant.var_1.Int_Comp = 40;
627+ strcpy(Ptr_Glob->variant.var_1.Str_Comp,
628+ "DHRYSTONE PROGRAM, SOME STRING");
629+ strcpy(Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
630+
631+ Arr_2_Glob[8][7] = 10;
632+ /* Was missing in published program. Without this statement, */
633+ /* Arr_2_Glob[8][7] would have an undefined value. */
634+ /* Warning: With 16-Bit processors and Number_Of_Runs > 32000, */
635+ /* overflow may occur for this array element. */
636+
637+ pr_debug("Dhrystone Benchmark, Version 2.1 (Language: C)\n");
638+
639+ Number_Of_Runs = n;
640+
641+ pr_debug("Execution starts, %d runs through Dhrystone\n",
642+ Number_Of_Runs);
643+
644+ /***************/
645+ /* Start timer */
646+ /***************/
647+
648+ Begin_Time = ktime_get();
649+
650+ for (Run_Index = 1; Run_Index <= Number_Of_Runs; ++Run_Index) {
651+ Proc_5();
652+ Proc_4();
653+ /* Ch_1_Glob == 'A', Ch_2_Glob == 'B', Bool_Glob == true */
654+ Int_1_Loc = 2;
655+ Int_2_Loc = 3;
656+ strcpy(Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
657+ Enum_Loc = Ident_2;
658+ Bool_Glob = !Func_2(Str_1_Loc, Str_2_Loc);
659+ /* Bool_Glob == 1 */
660+ while (Int_1_Loc < Int_2_Loc) {
661+ /* loop body executed once */
662+ Int_3_Loc = 5 * Int_1_Loc - Int_2_Loc;
663+ /* Int_3_Loc == 7 */
664+ Proc_7(Int_1_Loc, Int_2_Loc, &Int_3_Loc);
665+ /* Int_3_Loc == 7 */
666+ Int_1_Loc += 1;
667+ } /* while */
668+ /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
669+ Proc_8(Arr_1_Glob, Arr_2_Glob, Int_1_Loc, Int_3_Loc);
670+ /* Int_Glob == 5 */
671+ Proc_1(Ptr_Glob);
672+ for (Ch_Index = 'A'; Ch_Index <= Ch_2_Glob; ++Ch_Index) {
673+ /* loop body executed twice */
674+ if (Enum_Loc == Func_1(Ch_Index, 'C')) {
675+ /* then, not executed */
676+ Proc_6(Ident_1, &Enum_Loc);
677+ strcpy(Str_2_Loc, "DHRYSTONE PROGRAM, 3'RD STRING");
678+ Int_2_Loc = Run_Index;
679+ Int_Glob = Run_Index;
680+ }
681+ }
682+ /* Int_1_Loc == 3, Int_2_Loc == 3, Int_3_Loc == 7 */
683+ Int_2_Loc = Int_2_Loc * Int_1_Loc;
684+ Int_1_Loc = Int_2_Loc / Int_3_Loc;
685+ Int_2_Loc = 7 * (Int_2_Loc - Int_3_Loc) - Int_1_Loc;
686+ /* Int_1_Loc == 1, Int_2_Loc == 13, Int_3_Loc == 7 */
687+ Proc_2(&Int_1_Loc);
688+ /* Int_1_Loc == 5 */
689+
690+ } /* loop "for Run_Index" */
691+
692+ /**************/
693+ /* Stop timer */
694+ /**************/
695+
696+ End_Time = ktime_get();
697+
698+#define dhry_assert_int_eq(val, expected) \
699+ if (val != expected) \
700+ pr_err("%s: %d (FAIL, expected %d)\n", #val, val, \
701+ expected); \
702+ else \
703+ pr_debug("%s: %d (OK)\n", #val, val)
704+
705+#define dhry_assert_char_eq(val, expected) \
706+ if (val != expected) \
707+ pr_err("%s: %c (FAIL, expected %c)\n", #val, val, \
708+ expected); \
709+ else \
710+ pr_debug("%s: %c (OK)\n", #val, val)
711+
712+#define dhry_assert_string_eq(val, expected) \
713+ if (strcmp(val, expected)) \
714+ pr_err("%s: %s (FAIL, expected %s)\n", #val, val, \
715+ expected); \
716+ else \
717+ pr_debug("%s: %s (OK)\n", #val, val)
718+
719+ pr_debug("Execution ends\n");
720+ pr_debug("Final values of the variables used in the benchmark:\n");
721+ dhry_assert_int_eq(Int_Glob, 5);
722+ dhry_assert_int_eq(Bool_Glob, 1);
723+ dhry_assert_char_eq(Ch_1_Glob, 'A');
724+ dhry_assert_char_eq(Ch_2_Glob, 'B');
725+ dhry_assert_int_eq(Arr_1_Glob[8], 7);
726+ dhry_assert_int_eq(Arr_2_Glob[8][7], Number_Of_Runs + 10);
727+ pr_debug("Ptr_Comp: %px\n", Ptr_Glob->Ptr_Comp);
728+ dhry_assert_int_eq(Ptr_Glob->Discr, 0);
729+ dhry_assert_int_eq(Ptr_Glob->variant.var_1.Enum_Comp, 2);
730+ dhry_assert_int_eq(Ptr_Glob->variant.var_1.Int_Comp, 17);
731+ dhry_assert_string_eq(Ptr_Glob->variant.var_1.Str_Comp,
732+ "DHRYSTONE PROGRAM, SOME STRING");
733+ if (Next_Ptr_Glob->Ptr_Comp != Ptr_Glob->Ptr_Comp)
734+ pr_err("Next_Ptr_Glob->Ptr_Comp: %px (expected %px)\n",
735+ Next_Ptr_Glob->Ptr_Comp, Ptr_Glob->Ptr_Comp);
736+ else
737+ pr_debug("Next_Ptr_Glob->Ptr_Comp: %px\n",
738+ Next_Ptr_Glob->Ptr_Comp);
739+ dhry_assert_int_eq(Next_Ptr_Glob->Discr, 0);
740+ dhry_assert_int_eq(Next_Ptr_Glob->variant.var_1.Enum_Comp, 1);
741+ dhry_assert_int_eq(Next_Ptr_Glob->variant.var_1.Int_Comp, 18);
742+ dhry_assert_string_eq(Next_Ptr_Glob->variant.var_1.Str_Comp,
743+ "DHRYSTONE PROGRAM, SOME STRING");
744+ dhry_assert_int_eq(Int_1_Loc, 5);
745+ dhry_assert_int_eq(Int_2_Loc, 13);
746+ dhry_assert_int_eq(Int_3_Loc, 7);
747+ dhry_assert_int_eq(Enum_Loc, 1);
748+ dhry_assert_string_eq(Str_1_Loc, "DHRYSTONE PROGRAM, 1'ST STRING");
749+ dhry_assert_string_eq(Str_2_Loc, "DHRYSTONE PROGRAM, 2'ND STRING");
750+
751+ User_Time = ktime_to_ms(ktime_sub(End_Time, Begin_Time));
752+
753+ kfree(Ptr_Glob);
754+ kfree(Next_Ptr_Glob);
755+
756+ /* Measurements should last at least 2 seconds */
757+ if (User_Time < 2 * MSEC_PER_SEC)
758+ return -EAGAIN;
759+
760+ return div_u64(mul_u32_u32(MSEC_PER_SEC, Number_Of_Runs), User_Time);
761+}
762diff --git a/lib/dhry_2.c b/lib/dhry_2.c
763new file mode 100644
764index 000000000000..c19e661f37d3
765--- /dev/null
766+++ b/lib/dhry_2.c
767@@ -0,0 +1,175 @@
768+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
769+/*
770+ ****************************************************************************
771+ *
772+ * "DHRYSTONE" Benchmark Program
773+ * -----------------------------
774+ *
775+ * Version: C, Version 2.1
776+ *
777+ * File: dhry_2.c (part 3 of 3)
778+ *
779+ * Date: May 25, 1988
780+ *
781+ * Author: Reinhold P. Weicker
782+ *
783+ ****************************************************************************
784+ */
785+
786+#include "dhry.h"
787+
788+#include <linux/string.h>
789+
790+
791+static Boolean Func_3(Enumeration Enum_Par_Val)
792+/***************************/
793+/* executed once */
794+/* Enum_Par_Val == Ident_3 */
795+{
796+ Enumeration Enum_Loc;
797+
798+ Enum_Loc = Enum_Par_Val;
799+ if (Enum_Loc == Ident_3) {
800+ /* then, executed */
801+ return true;
802+ } else {
803+ /* not executed */
804+ return false;
805+ }
806+} /* Func_3 */
807+
808+
809+void Proc_6(Enumeration Enum_Val_Par, Enumeration *Enum_Ref_Par)
810+/*********************************/
811+/* executed once */
812+/* Enum_Val_Par == Ident_3, Enum_Ref_Par becomes Ident_2 */
813+{
814+ *Enum_Ref_Par = Enum_Val_Par;
815+ if (!Func_3(Enum_Val_Par)) {
816+ /* then, not executed */
817+ *Enum_Ref_Par = Ident_4;
818+ }
819+ switch (Enum_Val_Par) {
820+ case Ident_1:
821+ *Enum_Ref_Par = Ident_1;
822+ break;
823+ case Ident_2:
824+ if (Int_Glob > 100) {
825+ /* then */
826+ *Enum_Ref_Par = Ident_1;
827+ } else {
828+ *Enum_Ref_Par = Ident_4;
829+ }
830+ break;
831+ case Ident_3: /* executed */
832+ *Enum_Ref_Par = Ident_2;
833+ break;
834+ case Ident_4:
835+ break;
836+ case Ident_5:
837+ *Enum_Ref_Par = Ident_3;
838+ break;
839+ } /* switch */
840+} /* Proc_6 */
841+
842+
843+void Proc_7(One_Fifty Int_1_Par_Val, One_Fifty Int_2_Par_Val, One_Fifty *Int_Par_Ref)
844+/**********************************************/
845+/* executed three times */
846+/* first call: Int_1_Par_Val == 2, Int_2_Par_Val == 3, */
847+/* Int_Par_Ref becomes 7 */
848+/* second call: Int_1_Par_Val == 10, Int_2_Par_Val == 5, */
849+/* Int_Par_Ref becomes 17 */
850+/* third call: Int_1_Par_Val == 6, Int_2_Par_Val == 10, */
851+/* Int_Par_Ref becomes 18 */
852+{
853+ One_Fifty Int_Loc;
854+
855+ Int_Loc = Int_1_Par_Val + 2;
856+ *Int_Par_Ref = Int_2_Par_Val + Int_Loc;
857+} /* Proc_7 */
858+
859+
860+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)
861+/*********************************************************************/
862+/* executed once */
863+/* Int_Par_Val_1 == 3 */
864+/* Int_Par_Val_2 == 7 */
865+{
866+ One_Fifty Int_Index;
867+ One_Fifty Int_Loc;
868+
869+ Int_Loc = Int_1_Par_Val + 5;
870+ Arr_1_Par_Ref[Int_Loc] = Int_2_Par_Val;
871+ Arr_1_Par_Ref[Int_Loc+1] = Arr_1_Par_Ref[Int_Loc];
872+ Arr_1_Par_Ref[Int_Loc+30] = Int_Loc;
873+ for (Int_Index = Int_Loc; Int_Index <= Int_Loc+1; ++Int_Index)
874+ Arr_2_Par_Ref[Int_Loc][Int_Index] = Int_Loc;
875+ Arr_2_Par_Ref[Int_Loc][Int_Loc-1] += 1;
876+ Arr_2_Par_Ref[Int_Loc+20][Int_Loc] = Arr_1_Par_Ref[Int_Loc];
877+ Int_Glob = 5;
878+} /* Proc_8 */
879+
880+
881+Enumeration Func_1(Capital_Letter Ch_1_Par_Val, Capital_Letter Ch_2_Par_Val)
882+/*************************************************/
883+/* executed three times */
884+/* first call: Ch_1_Par_Val == 'H', Ch_2_Par_Val == 'R' */
885+/* second call: Ch_1_Par_Val == 'A', Ch_2_Par_Val == 'C' */
886+/* third call: Ch_1_Par_Val == 'B', Ch_2_Par_Val == 'C' */
887+{
888+ Capital_Letter Ch_1_Loc;
889+ Capital_Letter Ch_2_Loc;
890+
891+ Ch_1_Loc = Ch_1_Par_Val;
892+ Ch_2_Loc = Ch_1_Loc;
893+ if (Ch_2_Loc != Ch_2_Par_Val) {
894+ /* then, executed */
895+ return Ident_1;
896+ } else {
897+ /* not executed */
898+ Ch_1_Glob = Ch_1_Loc;
899+ return Ident_2;
900+ }
901+} /* Func_1 */
902+
903+
904+Boolean Func_2(Str_30 Str_1_Par_Ref, Str_30 Str_2_Par_Ref)
905+/*************************************************/
906+/* executed once */
907+/* Str_1_Par_Ref == "DHRYSTONE PROGRAM, 1'ST STRING" */
908+/* Str_2_Par_Ref == "DHRYSTONE PROGRAM, 2'ND STRING" */
909+{
910+ One_Thirty Int_Loc;
911+ Capital_Letter Ch_Loc;
912+
913+ Int_Loc = 2;
914+ while (Int_Loc <= 2) {
915+ /* loop body executed once */
916+ if (Func_1(Str_1_Par_Ref[Int_Loc],
917+ Str_2_Par_Ref[Int_Loc+1]) == Ident_1) {
918+ /* then, executed */
919+ Ch_Loc = 'A';
920+ Int_Loc += 1;
921+ }
922+ } /* if, while */
923+ if (Ch_Loc >= 'W' && Ch_Loc < 'Z') {
924+ /* then, not executed */
925+ Int_Loc = 7;
926+ }
927+ if (Ch_Loc == 'R') {
928+ /* then, not executed */
929+ return true;
930+ } else {
931+ /* executed */
932+ if (strcmp(Str_1_Par_Ref, Str_2_Par_Ref) > 0) {
933+ /* then, not executed */
934+ Int_Loc += 7;
935+ Int_Glob = Int_Loc;
936+ return true;
937+ } else {
938+ /* executed */
939+ return false;
940+ }
941+ } /* if Ch_Loc */
942+} /* Func_2 */
943diff --git a/lib/dhry_run.c b/lib/dhry_run.c
944new file mode 100644
945index 000000000000..f9d33efa6d09
946--- /dev/null
947+++ b/lib/dhry_run.c
948@@ -0,0 +1,85 @@
949+// SPDX-License-Identifier: GPL-2.0-only
950+/*
951+ * Dhrystone benchmark test module
952+ *
953+ * Copyright (C) 2022 Glider bv
954+ */
955+
956+#include "dhry.h"
957+
958+#include <linux/kernel.h>
959+#include <linux/module.h>
960+#include <linux/moduleparam.h>
961+#include <linux/mutex.h>
962+#include <linux/smp.h>
963+
964+#define DHRY_VAX 1757
965+
966+static int dhry_run_set(const char *val, const struct kernel_param *kp);
967+static const struct kernel_param_ops run_ops = {
968+ .flags = KERNEL_PARAM_OPS_FL_NOARG,
969+ .set = dhry_run_set,
970+};
971+static bool dhry_run;
972+module_param_cb(run, &run_ops, &dhry_run, 0200);
973+MODULE_PARM_DESC(run, "Run the test (default: false)");
974+
975+static int iterations = -1;
976+module_param(iterations, int, 0644);
977+MODULE_PARM_DESC(iterations,
978+ "Number of iterations through the benchmark (default: auto)");
979+
980+static void dhry_benchmark(void)
981+{
982+ int i, n;
983+
984+ if (iterations > 0) {
985+ n = dhry(iterations);
986+ goto report;
987+ }
988+
989+ for (i = DHRY_VAX; i > 0; i <<= 1) {
990+ n = dhry(i);
991+ if (n != -EAGAIN)
992+ break;
993+ }
994+
995+report:
996+ if (n >= 0)
997+ pr_info("CPU%u: Dhrystones per Second: %d (%d DMIPS)\n",
998+ smp_processor_id(), n, n / DHRY_VAX);
999+ else if (n == -EAGAIN)
1000+ pr_err("Please increase the number of iterations\n");
1001+ else
1002+ pr_err("Dhrystone benchmark failed error %pe\n", ERR_PTR(n));
1003+}
1004+
1005+static int dhry_run_set(const char *val, const struct kernel_param *kp)
1006+{
1007+ int ret;
1008+
1009+ if (val) {
1010+ ret = param_set_bool(val, kp);
1011+ if (ret)
1012+ return ret;
1013+ } else {
1014+ dhry_run = true;
1015+ }
1016+
1017+ if (dhry_run && system_state == SYSTEM_RUNNING)
1018+ dhry_benchmark();
1019+
1020+ return 0;
1021+}
1022+
1023+static int __init dhry_init(void)
1024+{
1025+ if (dhry_run)
1026+ dhry_benchmark();
1027+
1028+ return 0;
1029+}
1030+module_init(dhry_init);
1031+
1032+MODULE_AUTHOR("Geert Uytterhoeven <geert+renesas@glider.be>");
1033+MODULE_LICENSE("GPL");
1034--
10352.18.0
1036