mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-28 20:44:26 +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
|
path = submodules/crosstool-ng
|
||||||
# url = https://github.com/crosstool-ng/crosstool-ng
|
# url = https://github.com/crosstool-ng/crosstool-ng
|
||||||
url = https://github.com/cirosantilli/crosstool-ng
|
url = https://github.com/cirosantilli/crosstool-ng
|
||||||
|
[submodule "submodules/dhrystone"]
|
||||||
|
path = submodules/dhrystone
|
||||||
|
url = https://github.com/cirosantilli/dhrystone
|
||||||
[submodule "submodules/gcc"]
|
[submodule "submodules/gcc"]
|
||||||
path = submodules/gcc
|
path = submodules/gcc
|
||||||
# url = git://gcc.gnu.org/git/gcc.git
|
# 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.
|
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:
|
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!
|
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:
|
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]
|
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
|
===== BST vs heap vs hashmap
|
||||||
|
|
||||||
The following benchmark setup works both:
|
The following benchmark setup works both:
|
||||||
|
|||||||
@@ -1,15 +1,21 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/times.h>
|
||||||
|
|
||||||
#include <lkmc.h>
|
#include <lkmc.h>
|
||||||
|
|
||||||
|
#define UART_DR(baseaddr) (*(unsigned int *)(baseaddr))
|
||||||
|
#define UART_FR(baseaddr) (*(((unsigned int *)(baseaddr))+6))
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
UART_FR_RXFE = 0x10,
|
UART_FR_RXFE = 0x10,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define UART_DR(baseaddr) (*(unsigned int *)(baseaddr))
|
extern char heap_low;
|
||||||
#define UART_FR(baseaddr) (*(((unsigned int *)(baseaddr))+6))
|
extern char heap_top;
|
||||||
|
|
||||||
|
char *heap_end = 0;
|
||||||
|
|
||||||
void lkmc_baremetal_on_exit_callback(int status, void *arg) {
|
void lkmc_baremetal_on_exit_callback(int status, void *arg) {
|
||||||
(void)arg;
|
(void)arg;
|
||||||
@@ -73,10 +79,15 @@ int _read(int file, char *ptr, int len) {
|
|||||||
return todo;
|
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) {
|
caddr_t _sbrk(int incr) {
|
||||||
extern char heap_low;
|
|
||||||
extern char heap_top;
|
|
||||||
char *prev_heap_end;
|
char *prev_heap_end;
|
||||||
if (heap_end == 0) {
|
if (heap_end == 0) {
|
||||||
heap_end = &heap_low;
|
heap_end = &heap_low;
|
||||||
|
|||||||
@@ -36,23 +36,6 @@ Build the baremetal examples with crosstool-NG.
|
|||||||
self.env['baremetal_build_lib_dir'],
|
self.env['baremetal_build_lib_dir'],
|
||||||
self.env['common_basename_noext'] + self.env['obj_ext']
|
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 = [
|
cc_flags = [
|
||||||
'-I', self.env['root_dir'], LF,
|
'-I', self.env['root_dir'], LF,
|
||||||
'-O{}'.format(self.env['optimization_level']), 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 [
|
for in_path, out_path in [
|
||||||
(bootloader_src, extra_obj_baremetal_bootloader),
|
(bootloader_src, extra_obj_baremetal_bootloader),
|
||||||
(self.env['common_c'], extra_obj_lkmc_common),
|
(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(
|
self._build_one(
|
||||||
in_path=in_path,
|
in_path=in_path,
|
||||||
@@ -133,7 +122,10 @@ Build the baremetal examples with crosstool-NG.
|
|||||||
self.env['baremetal_link_script'],
|
self.env['baremetal_link_script'],
|
||||||
self.env['common_h']
|
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_baremetal_bootloader': [extra_obj_baremetal_bootloader],
|
||||||
'extra_objs_lkmc_common': [extra_obj_lkmc_common],
|
'extra_objs_lkmc_common': [extra_obj_lkmc_common],
|
||||||
'in_path': in_path,
|
'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['simulator_name'] = 'qemu'
|
||||||
env['baremetal_build_dir'] = join(env['out_dir'], 'baremetal', env['arch'], env['simulator_name'], env['machine'])
|
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_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.
|
# Userland / baremetal common source.
|
||||||
env['common_basename_noext'] = env['repo_short_id']
|
env['common_basename_noext'] = env['repo_short_id']
|
||||||
@@ -958,6 +975,10 @@ Incompatible archs are skipped.
|
|||||||
env['root_dir'],
|
env['root_dir'],
|
||||||
env['common_basename_noext'] + env['header_ext']
|
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
|
# Docker
|
||||||
env['docker_build_dir'] = join(env['out_dir'], 'docker', env['arch'])
|
env['docker_build_dir'] = join(env['out_dir'], 'docker', env['arch'])
|
||||||
@@ -1022,8 +1043,10 @@ lunch aosp_{}-eng
|
|||||||
'''.format(self.env['android_arch'])
|
'''.format(self.env['android_arch'])
|
||||||
|
|
||||||
# Toolchain.
|
# Toolchain.
|
||||||
|
if env['baremetal'] and not env['_args_given']['mode']:
|
||||||
|
env['mode'] = 'baremetal'
|
||||||
if not env['_args_given']['gcc_which']:
|
if not env['_args_given']['gcc_which']:
|
||||||
if env['baremetal']:
|
if env['mode'] == 'baremetal':
|
||||||
env['gcc_which'] = 'crosstool-ng'
|
env['gcc_which'] = 'crosstool-ng'
|
||||||
if env['gcc_which'] == 'buildroot':
|
if env['gcc_which'] == 'buildroot':
|
||||||
env['toolchain_prefix'] = os.path.join(
|
env['toolchain_prefix'] = os.path.join(
|
||||||
|
|||||||
@@ -162,6 +162,15 @@ class ShellHelpers:
|
|||||||
ending = last_newline + ';'
|
ending = last_newline + ';'
|
||||||
return newline_separator.join(out) + ending
|
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(
|
def copy_dir_if_update_non_recursive(
|
||||||
self,
|
self,
|
||||||
srcdir,
|
srcdir,
|
||||||
@@ -178,12 +187,9 @@ class ShellHelpers:
|
|||||||
src = os.path.join(srcdir, basename)
|
src = os.path.join(srcdir, basename)
|
||||||
if os.path.isfile(src) or os.path.islink(src):
|
if os.path.isfile(src) or os.path.islink(src):
|
||||||
noext, ext = os.path.splitext(basename)
|
noext, ext = os.path.splitext(basename)
|
||||||
dest = os.path.join(destdir, basename)
|
if (filter_ext is None or ext == filter_ext):
|
||||||
if (
|
dest = os.path.join(destdir, basename)
|
||||||
(filter_ext is None or ext == filter_ext) and
|
self.copy_file_if_update(src, dest)
|
||||||
(not os.path.exists(dest) or os.path.getmtime(src) > os.path.getmtime(dest))
|
|
||||||
):
|
|
||||||
self.cp(src, dest)
|
|
||||||
|
|
||||||
def copy_dir_if_update(
|
def copy_dir_if_update(
|
||||||
self,
|
self,
|
||||||
|
|||||||
1
submodules/dhrystone
Submodule
1
submodules/dhrystone
Submodule
Submodule submodules/dhrystone added at fb5e01298a
Reference in New Issue
Block a user