mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
dhrystone: create nicer custom build, baremetal almost working
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -14,6 +14,9 @@
|
||||
path = submodules/crosstool-ng
|
||||
# url = https://github.com/crosstool-ng/crosstool-ng
|
||||
url = https://github.com/cirosantilli/crosstool-ng
|
||||
[submodule "submodules/dhrystone"]
|
||||
path = submodules/dhrystone
|
||||
url = https://github.com/cirosantilli/dhrystone
|
||||
[submodule "submodules/gcc"]
|
||||
path = submodules/gcc
|
||||
# url = git://gcc.gnu.org/git/gcc.git
|
||||
|
||||
52
README.adoc
52
README.adoc
@@ -3957,7 +3957,9 @@ Source: link:userland/c/getchar.c[]
|
||||
|
||||
Let's see if user mode runs considerably faster than full system or not.
|
||||
|
||||
First we build Dhrystone manually statically since dynamic linking is broken in gem5 as explained at: xref:gem5-syscall-emulation-mode[xrefstyle=full].
|
||||
First we build <<dhrystone>> manually statically since dynamic linking is broken in gem5 as explained at: xref:gem5-syscall-emulation-mode[xrefstyle=full].
|
||||
|
||||
TODO: move this section to our new custom dhrystone setup: xref:dhrystone[xrefstyle=full].
|
||||
|
||||
gem5 user mode:
|
||||
|
||||
@@ -10454,7 +10456,7 @@ gem5 however has tended towards intensive code generation in order to support al
|
||||
|
||||
OK, this is why we used gem5 in the first place, performance measurements!
|
||||
|
||||
Let's see how many cycles https://en.wikipedia.org/wiki/Dhrystone[Dhrystone], which Buildroot provides, takes for a few different input parameters.
|
||||
Let's see how many cycles <<dhrystone>>, which Buildroot provides, takes for a few different input parameters.
|
||||
|
||||
We will do that for various input parameters on full system by taking a checkpoint after the boot finishes a fast atomic CPU boot, and then we will restore in a more detailed mode and run the benchmark:
|
||||
|
||||
@@ -10937,6 +10939,52 @@ Buildroot built-in libraries, mostly under Libraries > Other:
|
||||
|
||||
There are not yet enabled, but it should be easy to so, see: xref:add-new-buildroot-packages[xrefstyle=full]
|
||||
|
||||
===== Dhrystone
|
||||
|
||||
https://en.wikipedia.org/wiki/Dhrystone
|
||||
|
||||
Created in the 80's, it is not a representative measure of performance in modern computers anymore. It has mostly been replaced by https://en.wikipedia.org/wiki/SPECint[SPEC], which is... closed source! Unbelievable.
|
||||
|
||||
<<buildroot>> has a `dhrystone` package, but because it is so interesting to us, we decided to also build it ourselves, which allows things like static and baremetal compilation more easily.
|
||||
|
||||
Build and run on QEMU <<user-mode-simulation>>:
|
||||
|
||||
....
|
||||
git submodule update --init submodules/dhrystone
|
||||
./build-dhrystone --mode userland
|
||||
./run --userland "$(./getvar userland_build_dir)/submodules/dhrystone/dhrystone"
|
||||
....
|
||||
|
||||
Build and run on gem5 use mode:
|
||||
|
||||
....
|
||||
./build-dhrystone --mode userland --static --force-rebuild
|
||||
./run --emulator gem5 --userland "$(./getvar userland_build_dir)/submodules/dhrystone/dhrystone"
|
||||
....
|
||||
|
||||
TODO automate run more nicely.
|
||||
|
||||
Build for <<baremetal>> execution and run it in baremetal QEMU:
|
||||
|
||||
....
|
||||
./build-dhrystone --arch aarch64 --mode baremetal
|
||||
./run --arch aarch64 --baremetal "$(./getvar baremetal_build_dir)/submodules/dhrystone/dhrystone"
|
||||
....
|
||||
|
||||
TODO: fix the build, just need to factor out all run arguments from link:build-baremetal[] into link:common.py[] and it should just work, no missing syscalls.
|
||||
|
||||
If you really want the Buildroot package for some reason, build it with:
|
||||
|
||||
....
|
||||
./build-buildroot --config 'BR2_PACKAGE_DHRYSTONE=y'
|
||||
....
|
||||
|
||||
and run inside the guest from `PATH` with:
|
||||
|
||||
....
|
||||
dhrystone
|
||||
....
|
||||
|
||||
===== BST vs heap vs hashmap
|
||||
|
||||
The following benchmark setup works both:
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/times.h>
|
||||
|
||||
#include <lkmc.h>
|
||||
|
||||
#define UART_DR(baseaddr) (*(unsigned int *)(baseaddr))
|
||||
#define UART_FR(baseaddr) (*(((unsigned int *)(baseaddr))+6))
|
||||
|
||||
enum {
|
||||
UART_FR_RXFE = 0x10,
|
||||
};
|
||||
|
||||
#define UART_DR(baseaddr) (*(unsigned int *)(baseaddr))
|
||||
#define UART_FR(baseaddr) (*(((unsigned int *)(baseaddr))+6))
|
||||
extern char heap_low;
|
||||
extern char heap_top;
|
||||
|
||||
char *heap_end = 0;
|
||||
|
||||
void lkmc_baremetal_on_exit_callback(int status, void *arg) {
|
||||
(void)arg;
|
||||
@@ -73,10 +79,15 @@ int _read(int file, char *ptr, int len) {
|
||||
return todo;
|
||||
}
|
||||
|
||||
char *heap_end = 0;
|
||||
/* Dummy implementation that just increments an integer. */
|
||||
_CLOCK_T_ _times_r (struct _reent *r, struct tms *ptms) {
|
||||
static long long unsigned t = 0;
|
||||
(void)r;
|
||||
(void)ptms;
|
||||
return t++;
|
||||
}
|
||||
|
||||
caddr_t _sbrk(int incr) {
|
||||
extern char heap_low;
|
||||
extern char heap_top;
|
||||
char *prev_heap_end;
|
||||
if (heap_end == 0) {
|
||||
heap_end = &heap_low;
|
||||
|
||||
@@ -36,23 +36,6 @@ Build the baremetal examples with crosstool-NG.
|
||||
self.env['baremetal_build_lib_dir'],
|
||||
self.env['common_basename_noext'] + self.env['obj_ext']
|
||||
)
|
||||
syscalls_basename_noext = 'syscalls'
|
||||
syscalls_src = os.path.join(
|
||||
self.env['baremetal_source_lib_dir'],
|
||||
syscalls_basename_noext + self.env['c_ext']
|
||||
)
|
||||
syscalls_obj = os.path.join(
|
||||
self.env['baremetal_build_lib_dir'],
|
||||
syscalls_basename_noext + self.env['obj_ext']
|
||||
)
|
||||
syscalls_asm_src = os.path.join(
|
||||
self.env['baremetal_source_lib_dir'],
|
||||
syscalls_basename_noext + '_asm' + self.env['asm_ext']
|
||||
)
|
||||
syscalls_asm_obj = os.path.join(
|
||||
self.env['baremetal_build_lib_dir'],
|
||||
syscalls_basename_noext + '_asm' + self.env['obj_ext']
|
||||
)
|
||||
cc_flags = [
|
||||
'-I', self.env['root_dir'], LF,
|
||||
'-O{}'.format(self.env['optimization_level']), LF,
|
||||
@@ -101,8 +84,14 @@ Build the baremetal examples with crosstool-NG.
|
||||
for in_path, out_path in [
|
||||
(bootloader_src, extra_obj_baremetal_bootloader),
|
||||
(self.env['common_c'], extra_obj_lkmc_common),
|
||||
(syscalls_src, syscalls_obj),
|
||||
(syscalls_asm_src, syscalls_asm_obj),
|
||||
(
|
||||
self.env['baremetal_syscalls_src'],
|
||||
self.env['baremetal_syscalls_obj']
|
||||
),
|
||||
(
|
||||
self.env['baremetal_syscalls_asm_src'],
|
||||
self.env['baremetal_syscalls_asm_obj']
|
||||
),
|
||||
]:
|
||||
self._build_one(
|
||||
in_path=in_path,
|
||||
@@ -133,7 +122,10 @@ Build the baremetal examples with crosstool-NG.
|
||||
self.env['baremetal_link_script'],
|
||||
self.env['common_h']
|
||||
],
|
||||
'extra_objs': [syscalls_obj, syscalls_asm_obj],
|
||||
'extra_objs': [
|
||||
self.env['baremetal_syscalls_obj'],
|
||||
self.env['baremetal_syscalls_asm_obj']
|
||||
],
|
||||
'extra_objs_baremetal_bootloader': [extra_obj_baremetal_bootloader],
|
||||
'extra_objs_lkmc_common': [extra_obj_lkmc_common],
|
||||
'in_path': in_path,
|
||||
|
||||
62
build-dhrystone
Executable file
62
build-dhrystone
Executable file
@@ -0,0 +1,62 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import shutil
|
||||
|
||||
import common
|
||||
import shlex
|
||||
from shell_helpers import LF
|
||||
|
||||
class Main(common.BuildCliFunction):
|
||||
def __init__(self):
|
||||
super().__init__(
|
||||
description='''\
|
||||
https://cirosantilli.com/linux-kernel-module-cheat#dhrystone
|
||||
'''
|
||||
)
|
||||
self._add_argument('--ccflags')
|
||||
self._add_argument('--force-rebuild')
|
||||
self._add_argument('--optimization-level')
|
||||
|
||||
def setup(self, env):
|
||||
self.root_relpath = os.path.join('submodules', 'dhrystone')
|
||||
|
||||
def build(self):
|
||||
build_dir = self.get_build_dir()
|
||||
cflags = ['-O{}'.format(self.env['optimization_level'])]
|
||||
extra_flags = []
|
||||
if self.env['static']:
|
||||
cflags.extend(['-static'])
|
||||
if self.env['force_rebuild']:
|
||||
extra_flags.extend(['-B', LF])
|
||||
if self.env['mode'] == 'baremetal':
|
||||
extra_objs = [
|
||||
self.env['baremetal_syscalls_obj'],
|
||||
self.env['baremetal_syscalls_asm_obj']
|
||||
]
|
||||
else:
|
||||
extra_objs = []
|
||||
ret = self.sh.run_cmd(
|
||||
[
|
||||
'make', LF,
|
||||
'-j', str(self.env['nproc']), LF,
|
||||
'-C', os.path.join(self.env['submodules_dir'], 'dhrystone'), LF,
|
||||
'CC={}'.format(self.env['gcc_path']), LF,
|
||||
'CFLAGS={}'.format(' '.join(cflags)), LF,
|
||||
'EXTRA_OBJS={}'.format(' '.join(extra_objs)), LF,
|
||||
'OUT_DIR={}'.format(build_dir), LF,
|
||||
]
|
||||
+ extra_flags
|
||||
)
|
||||
if ret == 0 and self.env['mode'] == 'userland':
|
||||
self.sh.copy_file_if_update(
|
||||
os.path.join(build_dir, 'dhrystone'),
|
||||
os.path.join(self.env['out_rootfs_overlay_lkmc_dir'], self.root_relpath),
|
||||
)
|
||||
return ret
|
||||
|
||||
def get_build_dir(self):
|
||||
return os.path.join(self.env['build_dir'], self.root_relpath)
|
||||
|
||||
if __name__ == '__main__':
|
||||
Main().cli()
|
||||
25
common.py
25
common.py
@@ -947,6 +947,23 @@ Incompatible archs are skipped.
|
||||
env['simulator_name'] = 'qemu'
|
||||
env['baremetal_build_dir'] = join(env['out_dir'], 'baremetal', env['arch'], env['simulator_name'], env['machine'])
|
||||
env['baremetal_build_lib_dir'] = join(env['baremetal_build_dir'], env['baremetal_lib_basename'])
|
||||
env['baremetal_syscalls_basename_noext'] = 'syscalls'
|
||||
env['baremetal_syscalls_src'] = os.path.join(
|
||||
env['baremetal_source_lib_dir'],
|
||||
env['baremetal_syscalls_basename_noext'] + self.env['c_ext']
|
||||
)
|
||||
env['baremetal_syscalls_obj'] = os.path.join(
|
||||
self.env['baremetal_build_lib_dir'],
|
||||
env['baremetal_syscalls_basename_noext'] + self.env['obj_ext']
|
||||
)
|
||||
env['baremetal_syscalls_asm_src'] = os.path.join(
|
||||
self.env['baremetal_source_lib_dir'],
|
||||
env['baremetal_syscalls_basename_noext'] + '_asm' + self.env['asm_ext']
|
||||
)
|
||||
env['baremetal_syscalls_asm_obj'] = os.path.join(
|
||||
self.env['baremetal_build_lib_dir'],
|
||||
env['baremetal_syscalls_basename_noext'] + '_asm' + self.env['obj_ext']
|
||||
)
|
||||
|
||||
# Userland / baremetal common source.
|
||||
env['common_basename_noext'] = env['repo_short_id']
|
||||
@@ -958,6 +975,10 @@ Incompatible archs are skipped.
|
||||
env['root_dir'],
|
||||
env['common_basename_noext'] + env['header_ext']
|
||||
)
|
||||
if env['mode'] == 'baremetal':
|
||||
env['build_dir'] = env['baremetal_build_dir']
|
||||
elif env['mode'] == 'userland':
|
||||
env['build_dir'] = env['userland_build_dir']
|
||||
|
||||
# Docker
|
||||
env['docker_build_dir'] = join(env['out_dir'], 'docker', env['arch'])
|
||||
@@ -1022,8 +1043,10 @@ lunch aosp_{}-eng
|
||||
'''.format(self.env['android_arch'])
|
||||
|
||||
# Toolchain.
|
||||
if env['baremetal'] and not env['_args_given']['mode']:
|
||||
env['mode'] = 'baremetal'
|
||||
if not env['_args_given']['gcc_which']:
|
||||
if env['baremetal']:
|
||||
if env['mode'] == 'baremetal':
|
||||
env['gcc_which'] = 'crosstool-ng'
|
||||
if env['gcc_which'] == 'buildroot':
|
||||
env['toolchain_prefix'] = os.path.join(
|
||||
|
||||
@@ -162,6 +162,15 @@ class ShellHelpers:
|
||||
ending = last_newline + ';'
|
||||
return newline_separator.join(out) + ending
|
||||
|
||||
def copy_file_if_update(self, src, dest):
|
||||
if os.path.isdir(dest):
|
||||
dest = os.path.join(dest, os.path.basename(src))
|
||||
if (
|
||||
not os.path.exists(dest) or \
|
||||
os.path.getmtime(src) > os.path.getmtime(dest)
|
||||
):
|
||||
self.cp(src, dest)
|
||||
|
||||
def copy_dir_if_update_non_recursive(
|
||||
self,
|
||||
srcdir,
|
||||
@@ -178,12 +187,9 @@ class ShellHelpers:
|
||||
src = os.path.join(srcdir, basename)
|
||||
if os.path.isfile(src) or os.path.islink(src):
|
||||
noext, ext = os.path.splitext(basename)
|
||||
if (filter_ext is None or ext == filter_ext):
|
||||
dest = os.path.join(destdir, basename)
|
||||
if (
|
||||
(filter_ext is None or ext == filter_ext) and
|
||||
(not os.path.exists(dest) or os.path.getmtime(src) > os.path.getmtime(dest))
|
||||
):
|
||||
self.cp(src, dest)
|
||||
self.copy_file_if_update(src, dest)
|
||||
|
||||
def copy_dir_if_update(
|
||||
self,
|
||||
|
||||
1
submodules/dhrystone
Submodule
1
submodules/dhrystone
Submodule
Submodule submodules/dhrystone added at fb5e01298a
Reference in New Issue
Block a user