mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-13 20:12:26 +00:00
lkmc v2-rc
Unsquashed version at v2-rc-unsquashed, but that cannot be merged as it breaks bisects at several points. All bugs will not bisect to this humongous change. It all started with a conversion of the Bash scripts to Python, mainly because I couldn't stand not being able to properly use --options for run which has a million options. Then since that required a full testing, I decided to do all the refactorings that I had in mind at once, and so I did and it became v2-rc. This is the largest patch I have ever done! OMG a few weeks of extra time. I'm never writing a Bash script for anything that starts getting big again. Some of the features are: * separate build-qemu and build-gem5 commands * common: convert scripts to python. Add --option for everything * rename build to build-buildroot now that we are splitting all the build commands, Linux kernel to follow * move all git submodules to submodules/ and all buildroot packages to packages/ * refactor the out/ structure. Keep projects on toplevel, because guest projects separate archs and host ones don't, making a toplevel arch wrong * do-release: rename to just release https://stackoverflow.com/questions/16174992/cant-get-argparse-to-read-quoted-string-with-dashes-in-it * run: add --terminal and explain gem5 pdb * just track the lvimrc * store CLI kernel config fragment inside buildlroot to avoid conflicts * gem5: document m5 initparam * readme: make a bunch of things awesomer * readme: fix broken refs * parsec-benchmark: update to 75d55ac446a43c47efb1044844a108c6c330184c Could not fetch otherwise. * gem5: M5_OVERRIDE_PY_SOURCE
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@ -11,3 +11,7 @@ gitignore*
|
||||
/images-*.zip
|
||||
/out
|
||||
/out.*
|
||||
|
||||
# Python trash.
|
||||
*.pyc
|
||||
__pycache__
|
||||
|
||||
24
.gitmodules
vendored
24
.gitmodules
vendored
@ -1,16 +1,20 @@
|
||||
[submodule "buildroot"]
|
||||
path = buildroot
|
||||
[submodule "submodules/buildroot"]
|
||||
path = submodules/buildroot
|
||||
url = https://github.com/cirosantilli/buildroot
|
||||
ignore = dirty
|
||||
[submodule "qemu"]
|
||||
path = qemu
|
||||
[submodule "submodules/qemu"]
|
||||
path = submodules/qemu
|
||||
url = https://github.com/cirosantilli/qemu
|
||||
[submodule "linux"]
|
||||
path = linux
|
||||
# The true upstream does not accept git submodule update --init --depth 1
|
||||
# git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git
|
||||
# But git clone --branch --depth 1 worked weirdly:
|
||||
# https://unix.stackexchange.com/questions/338578/linux-kernel-source-code-size-difference
|
||||
[submodule "submodules/linux"]
|
||||
path = submodules/linux
|
||||
url = https://github.com/cirosantilli/linux
|
||||
[submodule "gem5/gem5"]
|
||||
path = gem5/gem5
|
||||
[submodule "submodules/gem5"]
|
||||
path = submodules/gem5
|
||||
url = https://gem5.googlesource.com/public/gem5
|
||||
[submodule "parsec-benchmark/parsec-benchmark"]
|
||||
path = parsec-benchmark/parsec-benchmark
|
||||
[submodule "submodules/parsec-benchmark"]
|
||||
path = submodules/parsec-benchmark
|
||||
url = https://github.com/cirosantilli/parsec-benchmark
|
||||
|
||||
9
.lvimrc
Normal file
9
.lvimrc
Normal file
@ -0,0 +1,9 @@
|
||||
" Use this automatically with:
|
||||
"
|
||||
" Plugin 'embear/vim-localvimrc'
|
||||
" let g:localvimrc_ask = 0
|
||||
" let g:localvimrc_sandbox = 0
|
||||
|
||||
if &filetype ==# 'c' || &filetype ==# 'cpp'
|
||||
setlocal noexpandtab
|
||||
endif
|
||||
@ -21,5 +21,6 @@ script: |
|
||||
# The following packages have unmet dependencies:
|
||||
# libsdl2-dev : Depends: libegl1-mesa-dev
|
||||
# Depends: libgles2-mesa-dev
|
||||
bash -x ./build-qemu -j 16 -S |& awk 'NR % 1000 == 0'
|
||||
bash -x ./build -j 16 -S |& awk 'NR % 1000 == 0'
|
||||
bash -x ./run -e 'init=/poweroff.out'
|
||||
|
||||
4299
README.adoc
4299
README.adoc
File diff suppressed because it is too large
Load Diff
124
bench-all
124
bench-all
@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common"
|
||||
set -x
|
||||
bench_build=false
|
||||
bench_buildroot_baseline=false
|
||||
set -eux
|
||||
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
|
||||
bench_all=false
|
||||
bench_buildroot_build=false
|
||||
bench_buildroot_baseline_build=false
|
||||
bench_gem5_build=false
|
||||
bench_linux_boot=false
|
||||
default_arch=x86_64
|
||||
@ -10,19 +11,16 @@ update_repo=false
|
||||
while getopts Aa:Bbglu OPT; do
|
||||
case "$OPT" in
|
||||
A)
|
||||
bench_build=true
|
||||
bench_buildroot_baseline=true
|
||||
bench_gem5_build=true
|
||||
bench_linux_boot=true
|
||||
bench_all=true
|
||||
;;
|
||||
a)
|
||||
default_arch="$OPTARG"
|
||||
;;
|
||||
b)
|
||||
bench_build=true
|
||||
bench_buildroot_build=true
|
||||
;;
|
||||
B)
|
||||
bench_buildroot_baseline=true
|
||||
bench_buildroot_baseline_build=true
|
||||
;;
|
||||
g)
|
||||
bench_gem5_build=true
|
||||
@ -40,9 +38,24 @@ while getopts Aa:Bbglu OPT; do
|
||||
done
|
||||
shift "$(($OPTIND - 1))"
|
||||
comment="${1:-}"
|
||||
if \
|
||||
! "$bench_buildroot_build" && \
|
||||
! "$bench_buildroot_baseline_build" && \
|
||||
! "$bench_gem5_build" && \
|
||||
! "$bench_linux_boot" \
|
||||
; then
|
||||
bench_all=true
|
||||
fi
|
||||
if "$bench_all"; then
|
||||
bench_buildroot_build=true
|
||||
bench_buildroot_baseline_build=true
|
||||
bench_gem5_build=true
|
||||
bench_linux_boot=true
|
||||
fi
|
||||
getvar="${root_dir}/getvar"
|
||||
|
||||
# Create output directory.
|
||||
benchmark_repo="${common_root_dir}/../linux-kernel-module-cheat-regression"
|
||||
benchmark_repo="${root_dir}/../linux-kernel-module-cheat-regression"
|
||||
mkdir -p "$benchmark_repo"
|
||||
last_dir="$(ls "$benchmark_repo" | grep -E '^[0-9]' | tail -n 1)"
|
||||
if [ -n "$last_dir" ]; then
|
||||
@ -51,62 +64,61 @@ else
|
||||
seq_id=0
|
||||
fi
|
||||
seq_id="$(printf '%0.4d' "$seq_id")"
|
||||
dir_basename="${seq_id}_${common_sha}"
|
||||
dir_basename="${seq_id}_$("$getvar" sha)"
|
||||
new_dir="${benchmark_repo}/${dir_basename}"
|
||||
mkdir "$new_dir"
|
||||
|
||||
if "$bench_build"; then
|
||||
common_arch="$default_arch"
|
||||
common_suffix=bench
|
||||
common_setup
|
||||
rm -rf "$common_out_arch_dir"
|
||||
./build -a "$common_arch" -B 'BR2_CCACHE=n' -s "$common_suffix"
|
||||
cp "${common_build_dir}/build-time.log" "${new_dir}/build-time-${common_arch}.log"
|
||||
rm -rf "$common_out_arch_dir"
|
||||
do_bench_buildroot_build() (
|
||||
arch="$default_arch"
|
||||
build_id=bench
|
||||
if [ "${1:-}" = baseline ]; then
|
||||
baseline=--baseline
|
||||
baseline_suffix=-baseline
|
||||
else
|
||||
baseline=
|
||||
baseline_suffix=
|
||||
fi
|
||||
common_build_dir="$("$getvar" --arch "$arch" --buildroot-build-id "$build_id" build_dir)"
|
||||
common_images_dir="$("$getvar" --arch "$arch" --buildroot-build-id "$build_id" images_dir)"
|
||||
"${root_dir}/build-buildroot" --arch "$arch" $baseline --buildroot-build-id "$build_id" --clean
|
||||
"${root_dir}/build-buildroot" --arch "$arch" $baseline --buildroot-build-id "$build_id" --no-all -- source
|
||||
"${root_dir}/build-buildroot" --arch "$arch" $baseline --buildroot-build-id "$build_id"
|
||||
cp "${common_build_dir}/build-time.log" "${new_dir}/buildroot-build-time-${baseline_suffix}${arch}.log"
|
||||
wc -c "${images_dir}/"* > "${new_dir}/buildroot-image-size-${baseline_suffix}${arch}.log"
|
||||
"${root_dir}/build-buildroot" --arch "$arch" $baseline --buildroot-build-id "$build_id" --clean
|
||||
)
|
||||
|
||||
if "$bench_buildroot_build"; then
|
||||
do_bench_buildroot_build
|
||||
fi
|
||||
|
||||
if "$bench_buildroot_baseline"; then
|
||||
cd "${common_root_dir}/buildroot"
|
||||
git clean -xdf
|
||||
make "qemu_${default_arch}_defconfig"
|
||||
printf '
|
||||
BR2_CCACHE=y
|
||||
BR2_TARGET_ROOTFS_CPIO=y
|
||||
BR2_TARGET_ROOTFS_EXT2=n
|
||||
' >>.config
|
||||
make olddefconfig
|
||||
make source
|
||||
time env -u LD_LIBRARY_PATH make BR2_JLEVEL="$(nproc)"
|
||||
cp output/build/build-time.log "${new_dir}/baseline-build-time-${default_arch}.log"
|
||||
wc -c output/images/* > "${new_dir}/baseline-image-size-${default_arch}.log"
|
||||
git clean -xdf
|
||||
if "$bench_buildroot_baseline_build"; then
|
||||
do_bench_buildroot_build baseline
|
||||
fi
|
||||
|
||||
if "$bench_gem5_build"; then
|
||||
arches='x86_64 arm'
|
||||
for common_arch in $arches; do
|
||||
common_setup
|
||||
cd "${common_gem5_src_dir}"
|
||||
git clean -xdf
|
||||
results_file="${common_gem5_out_dir}/bench-build.txt"
|
||||
gem5_outdir="${common_out_dir}/bench_build"
|
||||
rm -fr "$results_file" "${gem5_outdir}"
|
||||
# TODO understand better: --foreground required otherwise we cannot
|
||||
# kill the build with Ctrl+C if something goes wrong, can be minimized to:
|
||||
# bash -c "eval 'timeout 5 sleep 3'"
|
||||
common_bench_cmd "timeout --foreground 900 ../build -a '$common_arch' -o '${gem5_outdir}'" "$results_file"
|
||||
cp "$results_file" "${new_dir}/gem5-bench-build-${common_arch}.txt"
|
||||
cd "${common_root_dir}/gem5/gem5"
|
||||
git clean -xdf
|
||||
rm -fr "${gem5_outdir}"
|
||||
done
|
||||
common_arch="$default_arch"
|
||||
gem5_build_id=bench-build
|
||||
common_gem5_build_dir="$("$getvar" --arch "$common_arch" --gem5-build-id "$gem5_build_id" gem5_out_dir)"
|
||||
common_gem5_src_dir="$("$getvar" --arch "$common_arch" --gem5-build-id "$gem5_build_id" gem5_src_dir)"
|
||||
results_file="${common_gem5_build_dir}/bench-build.txt"
|
||||
git -C "${common_gem5_src_dir}" clean -xdf
|
||||
rm -f "$results_file"
|
||||
"${root_dir}/build-gem5" --arch "$common_arch" --clean --gem5-build-id "$gem5_build_id"
|
||||
# TODO understand better: --foreground required otherwise we cannot
|
||||
# kill the build with Ctrl+C if something goes wrong, can be minimized to:
|
||||
# bash -c "eval 'timeout 5 sleep 3'"
|
||||
"${root_dir}/bench-cmd" "timeout --foreground 900 ./build-gem5 --arch '$common_arch' --gem5-build-id '$gem5_build_id'" "$results_file"
|
||||
cp "$results_file" "${new_dir}/gem5-bench-build-${common_arch}.txt"
|
||||
git -C "${common_gem5_src_dir}" clean -xdf
|
||||
"${root_dir}/build-gem5" --arch "$common_arch" --clean --gem5-build-id "$gem5_build_id"
|
||||
fi
|
||||
|
||||
if "$bench_linux_boot"; then
|
||||
cd "${common_root_dir}"
|
||||
./build-all
|
||||
./bench-boot
|
||||
cp "$common_bench_boot" "$new_dir"
|
||||
cd "${root_dir}"
|
||||
"${root_dir}/build-all"
|
||||
"${root_dir}/bench-boot" -t 3
|
||||
cp "$(${root_dir}/getvar bench_boot)" "$new_dir"
|
||||
fi
|
||||
|
||||
if "$update_repo"; then
|
||||
|
||||
84
bench-boot
84
bench-boot
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common"
|
||||
set -eu
|
||||
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
|
||||
test_size=1
|
||||
OPTIND=1
|
||||
while getopts t: OPT; do
|
||||
@ -16,56 +17,83 @@ while getopts t: OPT; do
|
||||
esac
|
||||
done
|
||||
shift "$(($OPTIND - 1))"
|
||||
extra_args="$*"
|
||||
|
||||
if [ $# -gt 1 ]; then
|
||||
extra_args=" $*"
|
||||
else
|
||||
extra_args=
|
||||
fi
|
||||
getvar="${root_dir}/getvar"
|
||||
common_bench_boot="$("$getvar" bench_boot)"
|
||||
caches='--caches --l2cache --l1d_size=1024kB --l1i_size=1024kB --l2_size=1024kB --l3_size=1024kB'
|
||||
|
||||
bench() (
|
||||
common_bench_cmd "./run -a ${1} ${extra_args}" "$common_bench_boot"
|
||||
echo >> "$common_bench_boot"
|
||||
"${root_dir}/bench-cmd" "./run --arch ${1}${extra_args}" "$common_bench_boot"
|
||||
)
|
||||
|
||||
gem5_insts() (
|
||||
printf "instructions $(./gem5-stat -a "$1" sim_insts)\n" >> "$common_bench_boot"
|
||||
printf "instructions $(./gem5-stat --arch "$1" sim_insts)\n" >> "$common_bench_boot"
|
||||
)
|
||||
|
||||
qemu_insts() (
|
||||
common_arch="$1"
|
||||
./qemu-trace2txt -a "$common_arch"
|
||||
common_setup
|
||||
printf "instructions $(wc -l "${common_trace_txt_file}" | cut -d' ' -f1)\n" >> "$common_bench_boot"
|
||||
./qemu-trace2txt --arch "$common_arch"
|
||||
common_qemu_trace_txt_file="$("$getvar" --arch "$common_arch" qemu_trace_txt_file)"
|
||||
printf "instructions $(wc -l "${common_qemu_trace_txt_file}" | cut -d' ' -f1)\n" >> "$common_bench_boot"
|
||||
)
|
||||
|
||||
newline() (
|
||||
echo >> "$common_bench_boot"
|
||||
)
|
||||
|
||||
rm -f "${common_bench_boot}"
|
||||
|
||||
arch=x86_64
|
||||
bench "$arch -E '/poweroff.out'"
|
||||
bench "$arch -E '/poweroff.out' -K"
|
||||
bench "${arch} --eval '/poweroff.out'"
|
||||
newline
|
||||
bench "${arch} --eval '/poweroff.out' --kvm"
|
||||
newline
|
||||
if [ "$test_size" -ge 2 ]; then
|
||||
bench "$arch -E '/poweroff.out' -T exec_tb"
|
||||
bench "${arch} --eval '/poweroff.out' --trace exec_tb"
|
||||
qemu_insts "$arch"
|
||||
fi
|
||||
if [ "$test_size" -ge 2 ]; then
|
||||
bench "$arch -E 'm5 exit' -g"
|
||||
newline
|
||||
bench "$arch --eval 'm5 exit' --gem5"
|
||||
gem5_insts "$arch"
|
||||
newline
|
||||
fi
|
||||
#bench "$arch -E 'm5 exit' -g -- --cpu-type=DerivO3CPU ${caches}"
|
||||
#bench "$arch --eval 'm5 exit' --gem5 -- --cpu-type=DerivO3CPU ${caches}"
|
||||
#gem5_insts "$arch"
|
||||
#newline
|
||||
|
||||
arch=arm
|
||||
bench "$arch -E '/poweroff.out'"
|
||||
bench "$arch --eval '/poweroff.out'"
|
||||
newline
|
||||
if [ "$test_size" -ge 2 ]; then
|
||||
bench "$arch -E '/poweroff.out' -T exec_tb"
|
||||
bench "$arch --eval '/poweroff.out' --trace exec_tb"
|
||||
qemu_insts "$arch"
|
||||
newline
|
||||
#bench "$arch --eval 'm5 exit' --gem5"
|
||||
#gem5_insts "$arch"
|
||||
#newline
|
||||
fi
|
||||
#bench "$arch -E 'm5 exit' -g"
|
||||
#gem5_insts "$arch"
|
||||
#bench "$arch -E 'm5 exit' -g -- --cpu-type=HPI ${caches}"
|
||||
#gem5_insts "$arch"
|
||||
#if [ "$test_size" -ge 3 ]; then
|
||||
# bench "$arch --eval 'm5 exit' --gem5 -- --cpu-type=HPI ${caches}"
|
||||
# gem5_insts "$arch"
|
||||
# newline
|
||||
#fi
|
||||
|
||||
arch=aarch64
|
||||
bench "$arch -E '/poweroff.out'"
|
||||
bench "$arch --eval '/poweroff.out'"
|
||||
newline
|
||||
if [ "$test_size" -ge 2 ]; then
|
||||
bench "$arch -E '/poweroff.out' -T exec_tb"
|
||||
bench "$arch --eval '/poweroff.out' --trace exec_tb"
|
||||
qemu_insts "$arch"
|
||||
newline
|
||||
bench "$arch --eval 'm5 exit' --gem5"
|
||||
gem5_insts "$arch"
|
||||
newline
|
||||
fi
|
||||
if [ "$test_size" -ge 3 ]; then
|
||||
bench "$arch --eval 'm5 exit' --gem5 -- --cpu-type=HPI ${caches}"
|
||||
gem5_insts "$arch"
|
||||
newline
|
||||
fi
|
||||
#bench "$arch -E 'm5 exit' -g"
|
||||
#gem5_insts "$arch"
|
||||
#bench "$arch -E 'm5 exit' -g -- --cpu-type=HPI ${caches}"
|
||||
#gem5_insts "$arch"
|
||||
|
||||
17
bench-cmd
Executable file
17
bench-cmd
Executable file
@ -0,0 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
# Benchmark a command as a string and output results
|
||||
# to a file with format:
|
||||
#
|
||||
# cmd <command run>
|
||||
# time <time in seconds to finish>
|
||||
# exit_status <exit status>
|
||||
set -eu
|
||||
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
|
||||
# Command to benchmark
|
||||
cmd="$1"
|
||||
shift
|
||||
# Where to append write results to. Default: /dev/null.
|
||||
results_file="${1:-/dev/null}"
|
||||
printf 'cmd ' >> "$results_file"
|
||||
env time --append -f 'time %e' --output="$results_file" "${root_dir}/eeval" -a "$cmd" "$results_file"
|
||||
printf "exit_status $?\n" >> "$results_file"
|
||||
34
bisect-linux-boot-gem5
Executable file
34
bisect-linux-boot-gem5
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import imp
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
|
||||
import common
|
||||
build = imp.load_source('build', os.path.join(common.root_dir, 'build'))
|
||||
run = imp.load_source('run', os.path.join(common.root_dir, 'run'))
|
||||
|
||||
parser = common.get_argparse(
|
||||
argparse_args={
|
||||
'description': '''Bisect the Linux kernel on gem5 boots.
|
||||
|
||||
More information at: https://github.com/cirosantilli/linux-kernel-module-cheat#bisection
|
||||
'''},
|
||||
default_args={
|
||||
'gem5': True,
|
||||
'linux_build_id': 'bisect',
|
||||
},
|
||||
)
|
||||
args = common.setup(parser)
|
||||
# We need a clean rebuild because rebuilds at different revisions:
|
||||
# - may fail
|
||||
# - may not actually rebuild all files, e.g. on header changes
|
||||
common.rmrf(common.linux_variant_dir)
|
||||
assert build.main(args) == 0
|
||||
status = run.main(args, {
|
||||
'eval': 'm5 exit',
|
||||
})
|
||||
if status == 125 or status == 127:
|
||||
status = 1
|
||||
sys.exit(status)
|
||||
6
bisect-qemu-linux-boot
Executable file
6
bisect-qemu-linux-boot
Executable file
@ -0,0 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
git submodule update
|
||||
cd ..
|
||||
./build-qemu --arch arm -Q bisect
|
||||
./run --arch arm -E '/poweroff.out' -Q bisect
|
||||
6
br2/qemu
6
br2/qemu
@ -1,6 +0,0 @@
|
||||
BR2_PACKAGE_HOST_QEMU=y
|
||||
# False because otherwise we need the host to be as recent as guest, and the build fails with:
|
||||
# package/qemu/qemu.mk:110: *** "Refusing to build qemu-user: target Linux version newer than host's.". Stop.
|
||||
BR2_PACKAGE_HOST_QEMU_LINUX_USER_MODE=n
|
||||
BR2_PACKAGE_HOST_QEMU_SYSTEM_MODE=y
|
||||
BR2_PACKAGE_HOST_QEMU_VDE2=y
|
||||
28
bst-vs-heap
28
bst-vs-heap
@ -1,11 +1,17 @@
|
||||
#!/usr/bin/env bash
|
||||
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common"
|
||||
while getopts "${common_getopts_flags}" OPT; do
|
||||
case "$OPT" in
|
||||
?)
|
||||
common_getopts_case "$OPT"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift "$(($OPTIND - 1))"
|
||||
"${common_root_dir}/gem5-stat" -a "$common_arch" | awk 'NR % 2 { printf "%d %s ", NR/2, $0; next; } 1'
|
||||
#!/usr/bin/env python3
|
||||
import common
|
||||
parser = common.get_argparse(
|
||||
argparse_args={'description':'Convert a BST vs heap stat file into a gnuplot input'}
|
||||
)
|
||||
args = common.setup(parser)
|
||||
stats = common.get_stats()
|
||||
it = iter(stats)
|
||||
i = 1
|
||||
for stat in it:
|
||||
try:
|
||||
next_stat = next(it)
|
||||
except StopIteration:
|
||||
# Automatic dumpstats at end may lead to odd number of stats.
|
||||
break
|
||||
print('{} {} {}'.format(i, stat, next_stat))
|
||||
i += 1
|
||||
|
||||
223
build
223
build
@ -1,223 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common"
|
||||
mkdir -p "${common_out_dir}"
|
||||
br2_cli_file="${common_out_dir}/br2_cli"
|
||||
rm -f "$br2_cli_file"
|
||||
touch "$br2_cli_file"
|
||||
kernel_config_fragment_cli_file="${common_out_dir}/kernel_config_fragment_cli"
|
||||
kernel_config_fragment_cli_file_tmp="${kernel_config_fragment_cli_file}_tmp"
|
||||
rm -f "$kernel_config_fragment_cli_file_tmp"
|
||||
touch "$kernel_config_fragment_cli_file_tmp"
|
||||
configure=true
|
||||
config_fragments="${common_root_dir}/br2/default"
|
||||
extra_make_args=
|
||||
j="$(nproc)"
|
||||
linux_reconfigure=false
|
||||
linux_kernel_custom_config_file=
|
||||
kernel_config_fragments=
|
||||
post_script_args=
|
||||
qemu_sdl='--enable-sdl --with-sdlabi=2.0'
|
||||
v=0
|
||||
while getopts "B:b:C:c:fGj:hIiK:klp:qSs:v${common_getopts_flags}" OPT; do
|
||||
case "$OPT" in
|
||||
B)
|
||||
echo "$OPTARG" >> "$br2_cli_file"
|
||||
;;
|
||||
b)
|
||||
config_fragments="${config_fragments} $(common_abspath "${OPTARG}")"
|
||||
;;
|
||||
C)
|
||||
echo "$OPTARG" >> "$kernel_config_fragment_cli_file_tmp"
|
||||
;;
|
||||
c)
|
||||
kernel_config_fragments="${kernel_config_fragments} $(common_abspath "${OPTARG}")"
|
||||
;;
|
||||
f)
|
||||
configure=false
|
||||
;;
|
||||
h)
|
||||
echo "https://github.com/cirosantilli/linux-kernel-module-cheat#build" 2>&1
|
||||
exit
|
||||
;;
|
||||
I)
|
||||
echo "
|
||||
BR2_TARGET_ROOTFS_CPIO=n
|
||||
BR2_TARGET_ROOTFS_EXT2=n
|
||||
BR2_TARGET_ROOTFS_INITRAMFS=y
|
||||
" >> "$br2_cli_file"
|
||||
;;
|
||||
i)
|
||||
echo "
|
||||
BR2_TARGET_ROOTFS_CPIO=y
|
||||
BR2_TARGET_ROOTFS_EXT2=n
|
||||
BR2_TARGET_ROOTFS_INITRAMFS=n
|
||||
" >> "$br2_cli_file"
|
||||
;;
|
||||
j)
|
||||
j="$OPTARG"
|
||||
;;
|
||||
K)
|
||||
linux_kernel_custom_config_file="$(common_abspath "${OPTARG}")"
|
||||
;;
|
||||
k)
|
||||
extra_make_args="${extra_make_args} kernel_module-reconfigure \\
|
||||
"
|
||||
;;
|
||||
l)
|
||||
linux_reconfigure=true
|
||||
extra_make_args="${extra_make_args} linux-reconfigure \\
|
||||
"
|
||||
;;
|
||||
p)
|
||||
post_script_args="$OPTARG"
|
||||
;;
|
||||
q)
|
||||
extra_make_args="${extra_make_args} host-qemu-reconfigure \\
|
||||
"
|
||||
;;
|
||||
S)
|
||||
qemu_sdl=
|
||||
;;
|
||||
v)
|
||||
v=1
|
||||
;;
|
||||
?)
|
||||
common_getopts_case "$OPT"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift $(($OPTIND - 1))
|
||||
if "$common_gem5"; then
|
||||
extra_make_args="${extra_make_args} gem5-reconfigure \\
|
||||
"
|
||||
fi
|
||||
extra_make_args="${extra_make_args} $@"
|
||||
common_setup
|
||||
config_file="${common_buildroot_out_dir}/.config"
|
||||
case "$common_arch" in
|
||||
x86_64)
|
||||
defconfig=qemu_x86_64_defconfig
|
||||
;;
|
||||
arm)
|
||||
defconfig=qemu_arm_vexpress_defconfig
|
||||
;;
|
||||
aarch64)
|
||||
defconfig=qemu_aarch64_virt_defconfig
|
||||
;;
|
||||
mips64)
|
||||
defconfig=qemu_mips64r6_malta_defconfig
|
||||
;;
|
||||
esac
|
||||
config_fragments="${config_fragments} ${common_root_dir}/br2/qemu ${br2_cli_file}"
|
||||
|
||||
time {
|
||||
# Configure.
|
||||
if "$configure"; then
|
||||
if ! cmp "${kernel_config_fragment_cli_file}" "${kernel_config_fragment_cli_file_tmp}"; then
|
||||
# Only copy if modified, otherwise the kernel always rebuilds.
|
||||
cp "${kernel_config_fragment_cli_file_tmp}" "${kernel_config_fragment_cli_file}"
|
||||
fi
|
||||
cd "${common_buildroot_dir}"
|
||||
for p in $(find "${common_root_dir}/patches/buildroot/" -maxdepth 1 -name '*.patch' -print); do
|
||||
patch -N -r - -p 1 < "$p" || :
|
||||
done
|
||||
br2_external='../kernel_module:../gem5:../parsec-benchmark'
|
||||
packages_dir="${common_root_dir}/packages"
|
||||
for package_dir in "${packages_dir}"/*/; do
|
||||
br2_external="${br2_external}:../packages/$(basename "${package_dir}")"
|
||||
done
|
||||
make O="$common_buildroot_out_dir" BR2_EXTERNAL="$br2_external" "$defconfig"
|
||||
# TODO Can't get rid of these for now.
|
||||
# http://stackoverflow.com/questions/44078245/is-it-possible-to-use-config-fragments-with-buildroots-config
|
||||
for config_fragment in $config_fragments; do
|
||||
cat "$config_fragment" >> "$config_file"
|
||||
done
|
||||
printf "
|
||||
BR2_JLEVEL=${j}
|
||||
BR2_DL_DIR=\"${common_dir}/dl\"
|
||||
BR2_ROOTFS_POST_SCRIPT_ARGS=\"${post_script_args}\"
|
||||
" >> "$config_file"
|
||||
if "$common_gem5"; then
|
||||
printf "BR2_PACKAGE_GEM5=y\n" >> "${config_file}"
|
||||
fi
|
||||
kernel_config_fragment_dir=../kernel_config_fragment
|
||||
if [ -n "$linux_kernel_custom_config_file" ]; then
|
||||
if [ -f "$linux_kernel_custom_config_file" ]; then
|
||||
printf "BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y\nBR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=\"${linux_kernel_custom_config_file}\"\n" >> "$config_file"
|
||||
if "${linux_reconfigure}"; then
|
||||
touch "${linux_kernel_custom_config_file}"
|
||||
fi
|
||||
else
|
||||
echo "error: -K: file does not exist: ${linux_kernel_custom_config_file}" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
default_config_fragments=
|
||||
else
|
||||
default_config_fragments="${kernel_config_fragment_dir}/min ${kernel_config_fragment_dir}/default ${kernel_config_fragment_dir}/display"
|
||||
fi
|
||||
printf "BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES=\"${default_config_fragments} ${kernel_config_fragments} ${kernel_config_fragment_cli_file}\"\n" >> "$config_file"
|
||||
if "${linux_reconfigure}"; then
|
||||
# https://stackoverflow.com/questions/49260466/why-when-i-change-br2-linux-kernel-custom-config-file-and-run-make-linux-reconfi
|
||||
touch "${kernel_config_fragment_dir}/min"
|
||||
fi
|
||||
if [ "$common_arch" = 'mips64' ]; then
|
||||
# Workaround for: https://bugs.busybox.net/show_bug.cgi?id=10276
|
||||
sed -Ei 's/^BR2_PACKAGE_LINUX_TOOLS_GPIO/BR2_PACKAGE_LINUX_TOOLS_GPIO=n/' "$config_file"
|
||||
fi
|
||||
make O="$common_buildroot_out_dir" olddefconfig
|
||||
fi
|
||||
echo 'config time:'
|
||||
}
|
||||
echo
|
||||
|
||||
common_mkdir
|
||||
|
||||
# Manage Linux kernel and QEMU variants.
|
||||
symlink_buildroot_variant() (
|
||||
custom_dir="$1"
|
||||
variant_dir="$2"
|
||||
if [ -h "$custom_dir" ]; then
|
||||
rm "$custom_dir"
|
||||
elif [ -d "$custom_dir" ]; then
|
||||
# Migration for existing builds.
|
||||
mv "$custom_dir" "$variant_dir"
|
||||
fi
|
||||
mkdir -p "$variant_dir"
|
||||
ln -s "$variant_dir" "$custom_dir"
|
||||
)
|
||||
symlink_buildroot_variant "$common_linux_custom_dir" "$common_linux_variant_dir"
|
||||
symlink_buildroot_variant "$common_qemu_custom_dir" "$common_qemu_variant_dir"
|
||||
# TODO: this breaks the build. But then I noticed that it wouldn't make sense,
|
||||
# because this is a guest tool, and we don't have image variants yet. Some other day maybe.
|
||||
#symlink_buildroot_variant "$common_qemu_guest_custom_dir" "$common_qemu_guest_variant_dir"
|
||||
|
||||
# Manage gem5 variants.
|
||||
if "$common_gem5"; then
|
||||
if [ ! -e "${common_gem5_src_dir}/.git" ]; then
|
||||
git -C "$common_gem5_default_src_dir" worktree add -b "wt/${common_gem5_variant}" "${common_gem5_src_dir}"
|
||||
fi
|
||||
fi
|
||||
|
||||
cd "$common_buildroot_dir"
|
||||
# HOST_QEMU_OPTS is a hack that happens to work because the QEMU package luckly uses += at all times.
|
||||
# It shouldn't be necessary in the first place: https://bugs.busybox.net/show_bug.cgi?id=9936
|
||||
#
|
||||
# Even if were an autotools package, there is no general way currently to pass extra configs to it:
|
||||
# https://stackoverflow.com/questions/44341188/how-to-pass-extra-custom-configure-autotools-options-to-a-buildroot-package/44341225#44341225
|
||||
#
|
||||
# BR2_ options may be given on the command line here, and they do have direct "define" effects.
|
||||
# But this is generally bad, as it skips the Kconfig mechanism, e.g. it does not set defaults properly.
|
||||
cmd="time \\
|
||||
env \\
|
||||
-u LD_LIBRARY_PATH \\
|
||||
make \\
|
||||
O='${common_buildroot_out_dir}' \\
|
||||
HOST_QEMU_OPTS='--enable-debug --enable-trace-backends=simple ${qemu_sdl}' \\
|
||||
GEM5_LKMC_GEM5_BUILD_TYPE="$common_gem5_build_type" \\
|
||||
GEM5_LKMC_OUTDIR="$common_gem5_out_dir" \\
|
||||
GEM5_LKMC_SRCDIR="$common_gem5_src_dir" \\
|
||||
V='${v}' \\
|
||||
${extra_make_args} \
|
||||
all \\
|
||||
"
|
||||
"${common_root_dir}/eeval" "$cmd" "${common_out_arch_dir}/build.sh"
|
||||
10
build-all
10
build-all
@ -1,18 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eu
|
||||
archs='x86_64 arm aarch64'
|
||||
gem5=-g
|
||||
gem5=true
|
||||
while getopts A:G OPT; do
|
||||
case "$OPT" in
|
||||
A)
|
||||
archs="$OPTARG"
|
||||
;;
|
||||
G)
|
||||
gem5=
|
||||
gem5=false
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift "$(($OPTIND - 1))"
|
||||
for arch in $archs; do
|
||||
./build -a "$arch" -klq $gem5 "$@"
|
||||
./build-qemu --arch "$arch"
|
||||
./build --arch "$arch" --kernel-modules -l "$@"
|
||||
if "$gem5"; then
|
||||
./build-gem5 --arch "$arch"
|
||||
fi
|
||||
done
|
||||
|
||||
324
build-buildroot
Executable file
324
build-buildroot
Executable file
@ -0,0 +1,324 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import multiprocessing
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import re
|
||||
|
||||
import common
|
||||
|
||||
defaults = {
|
||||
'baseline': False,
|
||||
'buildroot_bare_kernel': False,
|
||||
'buildroot_config': [],
|
||||
'buildroot_config_fragment': [],
|
||||
'initramfs': False,
|
||||
'initrd': False,
|
||||
'kernel_config': [],
|
||||
'kernel_config_fragment': [],
|
||||
'kernel_custom_config_file': None,
|
||||
'kernel_modules': False,
|
||||
'linux_reconfigure': False,
|
||||
'no_all': False,
|
||||
'nproc': None,
|
||||
'skip_configure': False,
|
||||
'verbose': False,
|
||||
'extra_make_args': [],
|
||||
}
|
||||
|
||||
def get_argparse():
|
||||
parser = common.get_argparse(argparse_args={'description':'Run Linux on an emulator'})
|
||||
common.add_build_arguments(parser)
|
||||
parser.add_argument(
|
||||
'-B', '--buildroot-config', default=defaults['buildroot_config'], action='append',
|
||||
help='''Add a single Buildroot config to the current build.
|
||||
Example value: 'BR2_TARGET_ROOTFS_EXT2_SIZE="512M"'.
|
||||
Can be used multiple times to add multiple configs.
|
||||
Takes precedence over any Buildroot config files.
|
||||
'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'-b', '--buildroot-config-fragment', default=defaults['buildroot_config_fragment'], action='append',
|
||||
help='''Also use the given Buildroot configuration fragment file.
|
||||
Pass multiple times to use multiple fragment files.'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'--baseline', default=defaults['baseline'], action='store_true',
|
||||
help='''Do a default-ish Buildroot defconfig build, without any of our extra options.
|
||||
Mostly to track how much slower we are than a basic build.'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'-C', '--kernel-config', default=defaults['kernel_config'], action='append',
|
||||
help='''Add a single kernel config configs to the current build.
|
||||
Example value: 'CONFIG_FORTIFY_SOURCE=y'.
|
||||
Can be used multiple times to add multiple configs.
|
||||
Takes precedence over any Buildroot config files.
|
||||
'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'-c', '--kernel-config-fragment', default=defaults['kernel_config_fragment'], action='append',
|
||||
help='''Also use the given kernel configuration fragment file.
|
||||
Pass multiple times to use multiple fragment files.'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'-I', '--initramfs', default=defaults['initramfs'], action='store_true',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-i', '--initrd', default=defaults['initrd'], action='store_true',
|
||||
)
|
||||
parser.add_argument(
|
||||
'-j', '--nproc', default=defaults['nproc'], type=int,
|
||||
help='Number of processors to use for the build. Default: all.'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-K', '--kernel-custom-config-file', default=defaults['kernel_custom_config_file'],
|
||||
help='''Ignore all default kernel configurations and use this file instead.
|
||||
Still uses options explicitly passed with `-C` and `-c` on top of it.'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'-k', '--kernel-modules', default=defaults['kernel_modules'], action='store_true',
|
||||
help='Reconfigure and rebuild the kernel modules'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-l', '--linux-reconfigure', default=defaults['linux_reconfigure'], action='store_true',
|
||||
help='''Reconfigure and rebuild the Linux kernel.
|
||||
Touches kernel configuration files to overcome:
|
||||
https://stackoverflow.com/questions/49260466/why-when-i-change-br2-linux-kernel-custom-config-file-and-run-make-linux-reconfi'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'--no-all', default=defaults['no_all'], action='store_true',
|
||||
help='''Don't build the all target which normally gets build by default.
|
||||
That target builds the root filesystem and all its dependencies.'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'--skip-configure', default=defaults['skip_configure'], action='store_true',
|
||||
help='''Skip the Buildroot configuration. Saves a few seconds,
|
||||
but requires you to know what you are doing :-)'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'-v', '--verbose', default=defaults['verbose'], action='store_true',
|
||||
help='Do a verbose build'
|
||||
)
|
||||
parser.add_argument(
|
||||
'extra_make_args', default=defaults['extra_make_args'], metavar='extra-make-args', nargs='*',
|
||||
help='''Extra arguments to be passed to the Buildroot make,
|
||||
usually extra Buildroot targets.'''
|
||||
)
|
||||
return parser
|
||||
|
||||
def main(args, extra_args=None):
|
||||
global defaults
|
||||
args = common.resolve_args(defaults, args, extra_args)
|
||||
if args.clean:
|
||||
common.rmrf(common.buildroot_build_dir)
|
||||
else:
|
||||
os.makedirs(common.out_dir, exist_ok=True)
|
||||
extra_make_args = args.extra_make_args.copy()
|
||||
if args.kernel_modules:
|
||||
extra_make_args.append('kernel_modules-reconfigure')
|
||||
if args.linux_reconfigure:
|
||||
extra_make_args.append('linux-reconfigure')
|
||||
if args.gem5:
|
||||
extra_make_args.append('gem5-reconfigure')
|
||||
if args.nproc is None:
|
||||
nproc = multiprocessing.cpu_count()
|
||||
else:
|
||||
nproc = args.nproc
|
||||
if args.arch == 'x86_64':
|
||||
defconfig = 'qemu_x86_64_defconfig'
|
||||
elif args.arch == 'arm':
|
||||
defconfig = 'qemu_arm_vexpress_defconfig'
|
||||
elif args.arch == 'aarch64':
|
||||
defconfig = 'qemu_aarch64_virt_defconfig'
|
||||
|
||||
# Configure.
|
||||
if not args.skip_configure:
|
||||
# Initial make configure.
|
||||
# TODO port and test.
|
||||
#cd "${common_buildroot_src_dir}"
|
||||
#for p in $(find "${common_root_dir}/patches/buildroot/" -maxdepth 1 -name '*.patch' -print); do
|
||||
# patch -N -r - -p 1 < "$p" || :
|
||||
#done
|
||||
br2_external_dirs = []
|
||||
packages_dir = os.path.join(common.root_dir, 'packages')
|
||||
for package_dir in os.listdir(packages_dir):
|
||||
package_dir_abs = os.path.join(packages_dir, package_dir)
|
||||
if os.path.isdir(package_dir_abs):
|
||||
br2_external_dirs.append(path_relative_to_buildroot(package_dir_abs))
|
||||
br2_external_str = ':'.join(br2_external_dirs)
|
||||
subprocess.check_call(
|
||||
[
|
||||
'make',
|
||||
'O={}'.format(common.buildroot_build_dir),
|
||||
'BR2_EXTERNAL={}'.format(br2_external_str),
|
||||
defconfig,
|
||||
],
|
||||
cwd=common.buildroot_src_dir,
|
||||
)
|
||||
buildroot_configs = args.buildroot_config
|
||||
buildroot_configs.extend([
|
||||
'BR2_JLEVEL={}'.format(nproc),
|
||||
'BR2_DL_DIR="{}"'.format(common.dl_dir),
|
||||
])
|
||||
write_configs(buildroot_configs)
|
||||
if not args.baseline:
|
||||
buildroot_configs.extend([
|
||||
'BR2_GLOBAL_PATCH_DIR="{}"'.format(
|
||||
path_relative_to_buildroot(os.path.join(common.root_dir, 'patches', 'global'))),
|
||||
'BR2_PACKAGE_BUSYBOX_CONFIG_FRAGMENT_FILES="{}"'.format(
|
||||
path_relative_to_buildroot(os.path.join(common.root_dir, 'busybox_config_fragment'))),
|
||||
'BR2_PACKAGE_OVERRIDE_FILE="{}"'.format(
|
||||
path_relative_to_buildroot(os.path.join(common.root_dir, 'buildroot_override'))),
|
||||
'BR2_ROOTFS_OVERLAY="{}"'.format(
|
||||
path_relative_to_buildroot(os.path.join(common.root_dir, 'rootfs_overlay'))),
|
||||
'BR2_ROOTFS_POST_BUILD_SCRIPT="{}"'.format(
|
||||
path_relative_to_buildroot(os.path.join(common.root_dir, 'rootfs_post_build_script'))),
|
||||
'BR2_ROOTFS_USERS_TABLES="{}"'.format(
|
||||
path_relative_to_buildroot(os.path.join(common.root_dir, 'user_table'))),
|
||||
])
|
||||
if args.gem5:
|
||||
buildroot_configs.append('BR2_PACKAGE_GEM5=y')
|
||||
if args.initramfs:
|
||||
buildroot_configs.extend([
|
||||
'BR2_TARGET_ROOTFS_CPIO=n',
|
||||
'BR2_TARGET_ROOTFS_EXT2=n',
|
||||
'BR2_TARGET_ROOTFS_INITRAMFS=y',
|
||||
])
|
||||
if args.initrd:
|
||||
buildroot_configs.extend([
|
||||
'BR2_TARGET_ROOTFS_CPIO=y',
|
||||
'BR2_TARGET_ROOTFS_EXT2=n'
|
||||
'BR2_TARGET_ROOTFS_INITRAMFS=n',
|
||||
])
|
||||
buildroot_config_fragments = [
|
||||
os.path.join(common.root_dir, 'buildroot_config', 'default')
|
||||
] + args.buildroot_config_fragment
|
||||
|
||||
# Decide kernel configuration.
|
||||
kernel_config_fragments = []
|
||||
if True:
|
||||
# CLI kernel configurations.
|
||||
kernel_config_fragment_cli_path = os.path.join(common.buildroot_build_dir, 'lkmc_kernel_config_fragment_cli')
|
||||
kernel_config_cli_str = '\n'.join(args.kernel_config)
|
||||
do_write = False
|
||||
if os.path.exists(kernel_config_fragment_cli_path):
|
||||
with open(kernel_config_fragment_cli_path, 'r') as kernel_config_fragment_cli_file:
|
||||
kernel_config_cli_str_old = kernel_config_fragment_cli_file.read()
|
||||
if kernel_config_cli_str != kernel_config_cli_str_old:
|
||||
do_write = True
|
||||
else:
|
||||
do_write = True
|
||||
if do_write:
|
||||
# Only update if modified, otherwise Buildroot tries to
|
||||
# rebuilds the kernel every time, which takes a few seconds.
|
||||
# even when the kernel has already been built.
|
||||
with open(kernel_config_fragment_cli_path, 'w') as kernel_config_fragment_cli_file:
|
||||
kernel_config_fragment_cli_file.write(kernel_config_cli_str)
|
||||
kernel_config_fragments.append(os.path.join(kernel_config_fragment_cli_path))
|
||||
if True:
|
||||
# Kernel configuration fragments.
|
||||
if args.kernel_custom_config_file is not None:
|
||||
if os.path.exists(args.kernel_custom_config_file):
|
||||
buildroot_configs.extend([
|
||||
'BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y',
|
||||
'BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE=\"{}\"'.format(args.kernel_custom_config_file),
|
||||
])
|
||||
if args.linux_reconfigure:
|
||||
pathlib.Path(args.kernel_custom_config_file).touch()
|
||||
else:
|
||||
raise Exception('Kernel config fragment file does not exist: {}'.format(args.kernel_custom_config_file))
|
||||
default_kernel_config_fragments = []
|
||||
else:
|
||||
kernel_config_fragment_dir = os.path.join(common.root_dir, 'kernel_config')
|
||||
default_kernel_config_fragments = ['min', 'default']
|
||||
if args.linux_reconfigure:
|
||||
# https://stackoverflow.com/questions/49260466/why-when-i-change-br2-linux-kernel-custom-config-file-and-run-make-linux-reconfi
|
||||
pathlib.Path(os.path.join(kernel_config_fragment_dir, 'min')).touch()
|
||||
for i, default_kernel_config_fragment in enumerate(default_kernel_config_fragments):
|
||||
default_kernel_config_fragments[i] = os.path.join(kernel_config_fragment_dir, default_kernel_config_fragment)
|
||||
kernel_config_fragments.extend(default_kernel_config_fragments)
|
||||
for i, frag in enumerate(kernel_config_fragments):
|
||||
kernel_config_fragments[i] = path_relative_to_buildroot(frag)
|
||||
buildroot_kernel_config_fragment_str = 'BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="{}"'.format(' '.join(kernel_config_fragments))
|
||||
buildroot_configs.append(buildroot_kernel_config_fragment_str)
|
||||
write_configs(buildroot_configs, buildroot_config_fragments)
|
||||
subprocess.check_call(
|
||||
[
|
||||
'make',
|
||||
'O={}'.format(common.buildroot_build_dir),
|
||||
'olddefconfig',
|
||||
],
|
||||
cwd=common.buildroot_src_dir,
|
||||
)
|
||||
|
||||
# Manage Linux kernel and QEMU variants.
|
||||
def symlink_buildroot_variant(custom_dir, variant_dir):
|
||||
if os.path.islink(custom_dir):
|
||||
os.unlink(custom_dir)
|
||||
elif os.path.isdir(custom_dir):
|
||||
# Migration for existing builds.
|
||||
shutil.move(custom_dir, variant_dir)
|
||||
os.makedirs(variant_dir, exist_ok=True)
|
||||
os.symlink(variant_dir, custom_dir)
|
||||
symlink_buildroot_variant(common.linux_build_dir, common.linux_variant_dir)
|
||||
|
||||
# Do the actual build.
|
||||
common.mkdir()
|
||||
if not args.no_all:
|
||||
extra_make_args.append('all')
|
||||
assert common.run_cmd(
|
||||
[
|
||||
'make',
|
||||
'LKMC_GEM5_SRCDIR="{}"'.format(common.gem5_src_dir),
|
||||
'LKMC_PARSEC_BENCHMARK_SRCDIR="{}"'.format(common.parsec_benchmark_src_dir),
|
||||
'O={}'.format(common.buildroot_build_dir),
|
||||
'V={}'.format(int(args.verbose)),
|
||||
] +
|
||||
extra_make_args
|
||||
,
|
||||
out_file=os.path.join(common.buildroot_build_dir, 'lkmc.log'),
|
||||
delete_env=['LD_LIBRARY_PATH'],
|
||||
cwd=common.buildroot_src_dir,
|
||||
) == 0
|
||||
|
||||
# Create the qcow2 from ext2. This is optional, because gem5
|
||||
# does not need the qcow2.
|
||||
if os.path.exists(common.qemu_img_executable) and os.path.exists(common.ext2_file):
|
||||
assert common.run_cmd([
|
||||
common.qemu_img_executable,
|
||||
'-T', 'pr_manager_run,file=/dev/null',
|
||||
'convert',
|
||||
'-f', 'raw',
|
||||
'-O', 'qcow2',
|
||||
common.ext2_file,
|
||||
common.qcow2_file,
|
||||
]) == 0
|
||||
|
||||
return 0
|
||||
|
||||
def path_relative_to_buildroot(abspath):
|
||||
return os.path.relpath(abspath, common.buildroot_src_dir)
|
||||
|
||||
def write_configs(buildroot_configs, buildroot_config_fragments=None):
|
||||
"""
|
||||
Write extra configs into the Buildroot config file.
|
||||
TODO Can't get rid of these for now with nice fragments:
|
||||
http://stackoverflow.com/questions/44078245/is-it-possible-to-use-config-fragments-with-buildroots-config
|
||||
"""
|
||||
if buildroot_config_fragments is None:
|
||||
buildroot_config_fragments = []
|
||||
with open(common.buildroot_config_file, 'a') as br2_config_file:
|
||||
for buildroot_config_fragment in buildroot_config_fragments:
|
||||
with open(buildroot_config_fragment, 'r') as br2_config_fragment:
|
||||
for line in br2_config_fragment:
|
||||
br2_config_file.write(line)
|
||||
for buildroot_config in buildroot_configs:
|
||||
br2_config_file.write(buildroot_config + '\n')
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = get_argparse()
|
||||
args = common.setup(parser)
|
||||
sys.exit(main(args))
|
||||
83
build-gem5
Executable file
83
build-gem5
Executable file
@ -0,0 +1,83 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import glob
|
||||
import multiprocessing
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
import subprocess
|
||||
|
||||
import common
|
||||
|
||||
parser = common.get_argparse()
|
||||
common.add_build_arguments(parser)
|
||||
parser.add_argument(
|
||||
'extra_scons_args',
|
||||
default=[],
|
||||
metavar='extra-scons-args',
|
||||
nargs='*'
|
||||
)
|
||||
args = common.setup(parser)
|
||||
binaries_dir = os.path.join(common.gem5_system_dir, 'binaries')
|
||||
disks_dir = os.path.join(common.gem5_system_dir, 'disks')
|
||||
if args.clean:
|
||||
common.rmrf(common.gem5_build_dir)
|
||||
else:
|
||||
os.makedirs(binaries_dir, exist_ok=True)
|
||||
os.makedirs(disks_dir, exist_ok=True)
|
||||
if not os.path.exists(os.path.join(common.gem5_src_dir, '.git')):
|
||||
subprocess.check_call([
|
||||
'git',
|
||||
'-C', common.gem5_default_src_dir,
|
||||
'worktree', 'add',
|
||||
'-b', os.path.join('wt', args.gem5_build_id),
|
||||
common.gem5_src_dir
|
||||
])
|
||||
if args.arch == 'x86_64':
|
||||
dummy_img_path = os.path.join(disks_dir, 'linux-bigswap2.img')
|
||||
with open(dummy_img_path, 'wb') as dummy_img_file:
|
||||
zeroes = b'\x00' * (2 ** 16)
|
||||
for i in range(2 ** 10):
|
||||
dummy_img_file.write(zeroes)
|
||||
subprocess.check_call(['mkswap', dummy_img_path])
|
||||
with open(os.path.join(binaries_dir, 'x86_64-vmlinux-2.6.22.9'), 'w'):
|
||||
# This file must always be present, despite --kernel overriding that default and selecting the kernel.
|
||||
# I'm not even joking. No one has ever built x86 gem5 without the magic dist dir present.
|
||||
pass
|
||||
elif args.arch == 'arm' or args.arch == 'aarch64':
|
||||
gem5_system_src_dir = os.path.join(common.gem5_src_dir, 'system')
|
||||
|
||||
# dtb
|
||||
dt_src_dir = os.path.join(gem5_system_src_dir, 'arm', 'dt')
|
||||
dt_build_dir = os.path.join(common.gem5_system_dir, 'arm', 'dt')
|
||||
subprocess.check_call(['make', '-C', dt_src_dir])
|
||||
os.makedirs(dt_build_dir, exist_ok=True)
|
||||
for dt in glob.glob(os.path.join(dt_src_dir, '*.dtb')):
|
||||
shutil.copy2(dt, dt_build_dir)
|
||||
|
||||
# Bootloader 32.
|
||||
bootloader32_dir = os.path.join(gem5_system_src_dir, 'arm', 'simple_bootloader')
|
||||
# TODO use the buildroot cross compiler here, and remove the dependencies from configure.
|
||||
subprocess.check_call(['make', '-C', bootloader32_dir])
|
||||
# bootloader
|
||||
shutil.copy2(os.path.join(bootloader32_dir, 'boot_emm.arm'), binaries_dir)
|
||||
|
||||
# Bootloader 64.
|
||||
bootloader64_dir = os.path.join(gem5_system_src_dir, 'arm', 'aarch64_bootloader')
|
||||
# TODO cross_compile is ignored because the make does not use CC...
|
||||
subprocess.check_call(['make', '-C', bootloader64_dir])
|
||||
shutil.copy2(os.path.join(bootloader64_dir, 'boot_emm.arm64'), binaries_dir)
|
||||
assert common.run_cmd([
|
||||
'scons',
|
||||
# TODO factor with build.
|
||||
'-j', str(multiprocessing.cpu_count()),
|
||||
'--ignore-style',
|
||||
common.gem5_executable
|
||||
] +
|
||||
args.extra_scons_args,
|
||||
cwd=common.gem5_src_dir,
|
||||
extra_env={'PATH': '/usr/lib/ccache:' + os.environ['PATH']},
|
||||
) == 0
|
||||
term_src_dir = os.path.join(common.gem5_src_dir, 'util/term')
|
||||
subprocess.check_call(['make', '-C', term_src_dir])
|
||||
shutil.copy2(os.path.join(term_src_dir, 'm5term'), common.gem5_m5term)
|
||||
41
build-qemu
Executable file
41
build-qemu
Executable file
@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import multiprocessing
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
import common
|
||||
|
||||
parser = common.get_argparse()
|
||||
common.add_build_arguments(parser)
|
||||
parser.add_argument(
|
||||
'extra_config_args',
|
||||
default=[],
|
||||
metavar='extra-config-args',
|
||||
nargs='*'
|
||||
)
|
||||
args = common.setup(parser)
|
||||
if args.clean:
|
||||
common.rmrf(common.qemu_build_dir)
|
||||
else:
|
||||
os.makedirs(common.qemu_build_dir, exist_ok=True)
|
||||
subprocess.check_call(
|
||||
[
|
||||
os.path.join(common.qemu_src_dir, 'configure'),
|
||||
'--enable-debug',
|
||||
'--enable-trace-backends=simple',
|
||||
'--target-list={}-softmmu'.format(args.arch),
|
||||
'--enable-sdl',
|
||||
'--with-sdlabi=2.0',
|
||||
] +
|
||||
args.extra_config_args,
|
||||
cwd=common.qemu_build_dir
|
||||
)
|
||||
subprocess.check_call(
|
||||
[
|
||||
'make',
|
||||
# TODO factor with build.
|
||||
'-j', str(multiprocessing.cpu_count()),
|
||||
],
|
||||
cwd=common.qemu_build_dir
|
||||
)
|
||||
@ -1,6 +1,17 @@
|
||||
# Custom packages
|
||||
BR2_PACKAGE_KERNEL_MODULE=y
|
||||
BR2_SAMPLE_PACKAGE=y
|
||||
# Toolchain options.
|
||||
# Enable as much visibility as possible.
|
||||
BR2_CCACHE=y
|
||||
BR2_CCACHE_USE_BASEDIR=n
|
||||
BR2_DEBUG_3=y
|
||||
BR2_ENABLE_DEBUG=y
|
||||
BR2_GCC_ENABLE_GRAPHITE=y
|
||||
BR2_GCC_ENABLE_LTO=y
|
||||
BR2_GCC_ENABLE_OPENMP=y
|
||||
BR2_OPTIMIZE_0=y
|
||||
BR2_PTHREAD_DEBUG=y
|
||||
BR2_TOOLCHAIN_BUILDROOT_CXX=y
|
||||
BR2_TOOLCHAIN_BUILDROOT_FORTRAN=y
|
||||
BR2_TOOLCHAIN_BUILDROOT_WCHAR=y
|
||||
|
||||
# Rootfs
|
||||
BR2_TARGET_ROOTFS_CPIO=n
|
||||
@ -8,43 +19,6 @@ BR2_TARGET_ROOTFS_EXT2=y
|
||||
BR2_TARGET_ROOTFS_INITRAMFS=n
|
||||
BR2_TARGET_ROOTFS_EXT2_SIZE="512M"
|
||||
|
||||
# We were tempted to do this to disable S40network neatly,
|
||||
# but that package also creates extra configuration files
|
||||
# such as /etc/network/interfaces which we need. So we just
|
||||
# remove the init.d file for now.
|
||||
#BR2_PACKAGE_IFUPDOWN_SCRIPTS=n
|
||||
|
||||
# Misc
|
||||
BR2_CCACHE=y
|
||||
# Otherwise our precious debug would break!
|
||||
BR2_CCACHE_USE_BASEDIR=n
|
||||
BR2_GCC_ENABLE_GRAPHITE=y
|
||||
BR2_GCC_ENABLE_LTO=y
|
||||
BR2_GCC_ENABLE_OPENMP=y
|
||||
BR2_GLOBAL_PATCH_DIR="../patches/global"
|
||||
BR2_PACKAGE_BUSYBOX_CONFIG_FRAGMENT_FILES="../busybox_config_fragment"
|
||||
BR2_PACKAGE_DHRYSTONE=y
|
||||
BR2_PACKAGE_FILE=y
|
||||
BR2_PACKAGE_OVERRIDE_FILE="../buildroot_override"
|
||||
BR2_PACKAGE_PCIUTILS=y
|
||||
# For qemu-ga on guest. TODO: do something with it, and document it.
|
||||
# Maybe: https://superuser.com/questions/930588/how-to-pass-commands-noninteractively-to-running-qemu-from-the-guest-qmp-via-te
|
||||
BR2_PACKAGE_QEMU=y
|
||||
BR2_PACKAGE_STRACE=y
|
||||
BR2_ROOTFS_OVERLAY="../rootfs_overlay"
|
||||
BR2_ROOTFS_POST_BUILD_SCRIPT="../rootfs_post_build_script"
|
||||
BR2_ROOTFS_POST_IMAGE_SCRIPT="../rootfs_post_image_script"
|
||||
BR2_ROOTFS_USERS_TABLES="../user_table"
|
||||
BR2_TOOLCHAIN_BUILDROOT_CXX=y
|
||||
BR2_TOOLCHAIN_BUILDROOT_FORTRAN=y
|
||||
BR2_TOOLCHAIN_BUILDROOT_WCHAR=y
|
||||
|
||||
# lscpu: TODO not installing?
|
||||
BR2_PACKAGE_UTIL_LINUX=y
|
||||
BR2_PACKAGE_UTIL_LINUX_BINARIES=y
|
||||
# taskset
|
||||
BR2_PACKAGE_UTIL_LINUX_SCHEDUTILS=y
|
||||
|
||||
# Host GDB
|
||||
BR2_GDB_VERSION="7.11.1"
|
||||
BR2_GDB_VERSION_7_10=n
|
||||
@ -55,12 +29,32 @@ BR2_PACKAGE_HOST_GDB_PYTHON=y
|
||||
BR2_PACKAGE_HOST_GDB_SIM=y
|
||||
BR2_PACKAGE_HOST_GDB_TUI=y
|
||||
|
||||
# Custom packages
|
||||
# Keepding those in because we control them fully
|
||||
# and know for sure that are small.
|
||||
BR2_PACKAGE_KERNEL_MODULES=y
|
||||
BR2_SAMPLE_PACKAGE=y
|
||||
|
||||
# We were tempted to do this to disable S40network neatly,
|
||||
# but that package also creates extra configuration files
|
||||
# such as /etc/network/interfaces which we need. So we just
|
||||
# remove the init.d file for now.
|
||||
#BR2_PACKAGE_IFUPDOWN_SCRIPTS=n
|
||||
|
||||
# misc packages
|
||||
BR2_PACKAGE_DHRYSTONE=y
|
||||
BR2_PACKAGE_FILE=y
|
||||
BR2_PACKAGE_PCIUTILS=y
|
||||
BR2_PACKAGE_STRACE=y
|
||||
|
||||
# lscpu: TODO not installing?
|
||||
BR2_PACKAGE_UTIL_LINUX=y
|
||||
BR2_PACKAGE_UTIL_LINUX_BINARIES=y
|
||||
# taskset
|
||||
BR2_PACKAGE_UTIL_LINUX_SCHEDUTILS=y
|
||||
|
||||
# gdbserver
|
||||
BR2_DEBUG_3=y
|
||||
BR2_ENABLE_DEBUG=y
|
||||
BR2_OPTIMIZE_0=y
|
||||
BR2_PACKAGE_GDB=y
|
||||
BR2_PTHREAD_DEBUG=y
|
||||
|
||||
# ftrace
|
||||
BR2_PACKAGE_TRACE_CMD=y
|
||||
@ -1,5 +1,2 @@
|
||||
HOST_QEMU_OVERRIDE_SRCDIR = ../qemu
|
||||
LINUX_OVERRIDE_SRCDIR = ../linux
|
||||
PARSEC_BENCHMARK_OVERRIDE_SRCDIR = ../parsec-benchmark/parsec-benchmark
|
||||
QEMU_OVERRIDE_SRCDIR = ../qemu
|
||||
# UCLIBC_OVERRIDE_SRCDIR = ../uclibc-ng
|
||||
LINUX_OVERRIDE_SRCDIR = ../../submodules/linux
|
||||
QEMU_OVERRIDE_SRCDIR = ../../submodules/qemu
|
||||
|
||||
204
common
204
common
@ -1,204 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -eu
|
||||
|
||||
common_abspath() (
|
||||
echo "$(cd "$(dirname "$1")"; pwd)/$(basename "$1")"
|
||||
)
|
||||
|
||||
# Benchmark a command.
|
||||
#
|
||||
# $1: command to benchmark
|
||||
# $2: where to append write results to. Default: /dev/null.
|
||||
#
|
||||
# Result format:
|
||||
#
|
||||
# cmd <command run>
|
||||
# time <time in seconds to finish>
|
||||
# exit_status <exit status>
|
||||
common_bench_cmd() (
|
||||
cmd="$1"
|
||||
results_file="${2:-/dev/null}"
|
||||
printf 'cmd ' >> "$results_file"
|
||||
env time --append -f 'time %e' --output="$results_file" "${common_root_dir}/eeval" -a "$cmd" "$results_file"
|
||||
printf "exit_status $?\n" >> "$results_file"
|
||||
)
|
||||
|
||||
|
||||
# Handle options common across multiple scripts.
|
||||
common_getopts_case() {
|
||||
case "$1" in
|
||||
a)
|
||||
common_arch="$OPTARG"
|
||||
;;
|
||||
g)
|
||||
common_gem5=true
|
||||
;;
|
||||
L)
|
||||
common_linux_variant="$OPTARG"
|
||||
;;
|
||||
M)
|
||||
common_gem5_variant="$OPTARG"
|
||||
;;
|
||||
N)
|
||||
common_gem5_worktree="$OPTARG"
|
||||
;;
|
||||
n)
|
||||
common_run_id="$OPTARG"
|
||||
;;
|
||||
Q)
|
||||
common_qemu_variant="$OPTARG"
|
||||
;;
|
||||
s)
|
||||
common_suffix="$OPTARG"
|
||||
;;
|
||||
t)
|
||||
common_gem5_build_type="$OPTARG"
|
||||
;;
|
||||
?)
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
}
|
||||
common_getopts_flags='a:gL:M:N:n:Q:s:t:'
|
||||
|
||||
# Setup several variables and do other initialization common to most scripts.
|
||||
# Typically done after getting inputs from the command line arguments.
|
||||
common_setup() {
|
||||
case "$common_arch" in
|
||||
a|arm)
|
||||
common_arch=arm
|
||||
common_gem5_arch=ARM
|
||||
;;
|
||||
A|aarch64)
|
||||
common_arch=aarch64
|
||||
common_gem5_arch=ARM
|
||||
;;
|
||||
m|mips64)
|
||||
common_arch=mips64
|
||||
;;
|
||||
x|x86_64)
|
||||
common_arch=x86_64
|
||||
common_gem5_arch=X86
|
||||
;;
|
||||
*)
|
||||
printf "unknown arch: ${common_arch}\n" 1>&2
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
common_buildroot_dir="${common_root_dir}/buildroot"
|
||||
common_arch_dir="$common_arch"
|
||||
if [ -n "$common_suffix" ]; then
|
||||
common_arch_dir="${common_arch_dir}-${common_suffix}"
|
||||
fi
|
||||
common_out_arch_dir="${common_out_dir}/${common_arch_dir}"
|
||||
common_buildroot_out_dir="${common_out_arch_dir}/buildroot"
|
||||
common_build_dir="${common_buildroot_out_dir}/build"
|
||||
common_linux_custom_dir="${common_build_dir}/linux-custom"
|
||||
common_linux_variant_dir="${common_linux_custom_dir}.${common_linux_variant}"
|
||||
common_vmlinux="${common_linux_variant_dir}/vmlinux"
|
||||
common_qemu_custom_dir="${common_build_dir}/host-qemu-custom"
|
||||
common_qemu_guest_variant_dir="${common_qemu_custom_dir}.${common_qemu_variant}"
|
||||
common_qemu_variant_dir="${common_qemu_custom_dir}.${common_qemu_variant}"
|
||||
common_qemu_exec="${common_qemu_variant_dir}/${common_arch}-softmmu/qemu-system-${common_arch}"
|
||||
common_qemu_guest_custom_dir="${common_build_dir}/qemu-custom"
|
||||
common_host_dir="${common_buildroot_out_dir}/host"
|
||||
common_images_dir="${common_buildroot_out_dir}/images"
|
||||
common_qcow2_file="${common_images_dir}/rootfs.ext2.qcow2"
|
||||
common_staging_dir="${common_buildroot_out_dir}/staging"
|
||||
common_target_dir="${common_buildroot_out_dir}/target"
|
||||
common_gem5_run_dir="${common_out_arch_dir}/gem5/${common_run_id}"
|
||||
common_m5out_dir="${common_gem5_run_dir}/m5out"
|
||||
common_trace_txt_file="${common_m5out_dir}/trace.txt"
|
||||
common_gem5_termout_file="${common_gem5_run_dir}/termout.txt"
|
||||
common_qemu_run_dir="${common_out_arch_dir}/qemu/${common_run_id}"
|
||||
common_qemu_termout_file="${common_qemu_run_dir}/termout.txt"
|
||||
common_qemu_rrfile="${common_qemu_run_dir}/rrfile"
|
||||
common_gem5_out_dir="${common_dir}/gem5/${common_gem5_variant}"
|
||||
common_gem5_m5term="${common_gem5_out_dir}/m5term"
|
||||
common_gem5_build_dir="${common_gem5_out_dir}/build"
|
||||
common_gem5_exec="${common_gem5_build_dir}/${common_gem5_arch}/gem5.${common_gem5_build_type}"
|
||||
common_gem5_system_dir="${common_gem5_out_dir}/system"
|
||||
if [ -n "$common_gem5_worktree" ]; then
|
||||
common_gem5_src_dir="${common_gem5_non_default_src_root_dir}/${common_gem5_worktree}"
|
||||
else
|
||||
common_gem5_src_dir="$common_gem5_default_src_dir"
|
||||
fi
|
||||
if "$common_gem5"; then
|
||||
common_exec="$common_gem5_exec"
|
||||
common_run_dir="$common_gem5_run_dir"
|
||||
common_termout_file="$common_gem5_termout_file"
|
||||
else
|
||||
common_exec="$common_qemu_exec"
|
||||
common_run_dir="$common_qemu_run_dir"
|
||||
common_termout_file="$common_qemu_termout_file"
|
||||
fi
|
||||
case "$common_arch" in
|
||||
arm)
|
||||
common_linux_image=arch/arm/boot/zImage
|
||||
;;
|
||||
aarch64)
|
||||
common_linux_image=arch/arm64/boot/Image
|
||||
;;
|
||||
mips64)
|
||||
common_linux_image=vmlinux
|
||||
;;
|
||||
x86_64)
|
||||
common_linux_image=arch/x86/boot/bzImage
|
||||
;;
|
||||
esac
|
||||
common_linux_image="${common_linux_variant_dir}/${common_linux_image}"
|
||||
|
||||
# Ports.
|
||||
common_run_id_number="$(echo "$common_run_id" | cut -d . -f 2)"
|
||||
if "$common_gem5"; then
|
||||
common_gem5_telnet_port="$((3456 + $common_run_id_number))"
|
||||
common_gdb_port="$((7000 + $common_run_id_number))"
|
||||
else
|
||||
common_qemu_base_port="$((45454 + 10 * $common_run_id_number))"
|
||||
common_qemu_monitor_port="$(($common_qemu_base_port + 0))"
|
||||
common_qemu_hostfwd_generic_port="$(($common_qemu_base_port + 1))"
|
||||
common_qemu_hostfwd_ssh_port="$(($common_qemu_base_port + 2))"
|
||||
common_qemu_gdb_port="$(($common_qemu_base_port + 3))"
|
||||
common_gdb_port="$common_qemu_gdb_port"
|
||||
fi
|
||||
}
|
||||
|
||||
common_mkdir() (
|
||||
mkdir -p \
|
||||
"$common_build_dir" \
|
||||
"$common_gem5_out_dir" \
|
||||
"$common_gem5_run_dir" \
|
||||
"$common_qemu_run_dir" \
|
||||
"$common_9p_dir" \
|
||||
;
|
||||
)
|
||||
|
||||
# Default paths.
|
||||
common_root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
common_data_dir="${common_root_dir}/data"
|
||||
common_9p_dir="${common_data_dir}/9p"
|
||||
common_gem5_non_default_src_root_dir="${common_data_dir}/gem5"
|
||||
common_gem5_readfile_file="${common_data_dir}/readfile"
|
||||
common_gem5_default_src_dir="${common_root_dir}/gem5/gem5"
|
||||
common_out_dir="${common_root_dir}/out"
|
||||
common_bench_boot="${common_out_dir}/bench-boot.txt"
|
||||
common_dir="${common_out_dir}/common"
|
||||
|
||||
# Other default variables.
|
||||
common_arch=x86_64
|
||||
common_gem5=false
|
||||
common_gem5_build_type=opt
|
||||
common_gem5_cpt_pref='^cpt\.'
|
||||
common_gem5_variant=default
|
||||
common_gem5_worktree=
|
||||
common_linux_variant=default
|
||||
common_qemu_variant=default
|
||||
common_run_id=0
|
||||
common_sha="$(git log -1 --format="%H")"
|
||||
common_suffix=
|
||||
|
||||
f="${common_data_dir}/config"
|
||||
if [ -f "$f" ]; then
|
||||
. "$f"
|
||||
fi
|
||||
395
common.py
Normal file
395
common.py
Normal file
@ -0,0 +1,395 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import base64
|
||||
import copy
|
||||
import glob
|
||||
import imp
|
||||
import os
|
||||
import re
|
||||
import shlex
|
||||
import shutil
|
||||
import signal
|
||||
import stat
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
this = sys.modules[__name__]
|
||||
|
||||
# Default paths.
|
||||
root_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
data_dir = os.path.join(root_dir, 'data')
|
||||
p9_dir = os.path.join(data_dir, '9p')
|
||||
gem5_non_default_src_root_dir = os.path.join(data_dir, 'gem5')
|
||||
out_dir = os.path.join(root_dir, 'out')
|
||||
bench_boot = os.path.join(out_dir, 'bench-boot.txt')
|
||||
dl_dir = os.path.join(out_dir, 'dl')
|
||||
submodules_dir = os.path.join(root_dir, 'submodules')
|
||||
buildroot_src_dir = os.path.join(submodules_dir, 'buildroot')
|
||||
gem5_default_src_dir = os.path.join(submodules_dir, 'gem5')
|
||||
linux_src_dir = os.path.join(submodules_dir, 'linux')
|
||||
qemu_src_dir = os.path.join(submodules_dir, 'qemu')
|
||||
parsec_benchmark_src_dir = os.path.join(submodules_dir, 'parsec-benchmark')
|
||||
|
||||
# Other default variables.
|
||||
arch_map = {
|
||||
'a': 'arm',
|
||||
'A': 'aarch64',
|
||||
'x': 'x86_64',
|
||||
}
|
||||
arches = [arch_map[k] for k in arch_map]
|
||||
gem5_cpt_prefix = '^cpt\.'
|
||||
sha = subprocess.check_output(['git', '-C', root_dir, 'log', '-1', '--format=%H']).decode().rstrip()
|
||||
config_file = os.path.join(data_dir, 'config')
|
||||
if os.path.exists(config_file):
|
||||
config = imp.load_source('config', config_file)
|
||||
configs = {x:getattr(config, x) for x in dir(config) if not x.startswith('__')}
|
||||
|
||||
def base64_encode(string):
|
||||
return base64.b64encode(string.encode()).decode()
|
||||
|
||||
def gem_list_checkpoint_dirs():
|
||||
'''
|
||||
List checkpoint directory, oldest first.
|
||||
'''
|
||||
global this
|
||||
prefix_re = re.compile(this.gem5_cpt_prefix)
|
||||
files = list(filter(lambda x: os.path.isdir(os.path.join(this.m5out_dir, x)) and prefix_re.search(x), os.listdir(this.m5out_dir)))
|
||||
files.sort(key=lambda x: os.path.getmtime(os.path.join(this.m5out_dir, x)))
|
||||
return files
|
||||
|
||||
def get_argparse(default_args=None, argparse_args=None):
|
||||
'''
|
||||
Return an argument parser with common arguments set.
|
||||
|
||||
:type default_args: Dict[str,str]
|
||||
:type argparse_args: Dict
|
||||
'''
|
||||
global this
|
||||
if default_args is None:
|
||||
default_args = {}
|
||||
if argparse_args is None:
|
||||
argparse_args = {}
|
||||
arch_choices = []
|
||||
for key in this.arch_map:
|
||||
arch_choices.append(key)
|
||||
arch_choices.append(this.arch_map[key])
|
||||
default_build_id = 'default'
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawTextHelpFormatter,
|
||||
**argparse_args
|
||||
)
|
||||
parser.add_argument(
|
||||
'-a', '--arch', choices=arch_choices, default='x86_64',
|
||||
help='CPU architecture. Default: %(default)s'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-g', '--gem5', default=False, action='store_true',
|
||||
help='Use gem5 instead of QEMU'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-L', '--linux-build-id', default=default_build_id,
|
||||
help='Linux build ID. Allows you to keep multiple separate Linux builds. Default: %(default)s'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-M', '--gem5-build-id', default=default_build_id,
|
||||
help='gem5 build ID. Allows you to keep multiple separate gem5 builds. Default: %(default)s'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-N', '--gem5-worktree',
|
||||
help='''\
|
||||
gem5 git worktree to use for build and Python scripts at runtime. Automatically
|
||||
create a new git worktree with the given id if one does not exist. If not
|
||||
given, just use the submodule source.
|
||||
'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'-n', '--run-id', default='0',
|
||||
help='''\
|
||||
ID for run outputs such as gem5's m5out. Allows you to do multiple runs,
|
||||
and then inspect separate outputs later in different output directories.
|
||||
Default: %(default)s
|
||||
'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'--port-offset', type=int,
|
||||
help='''\
|
||||
Increase the ports to be used such as for GDB by an offset to run multiple
|
||||
instances in parallel.
|
||||
Default: the run ID (-n) if that is an integer, otherwise 0.
|
||||
'''
|
||||
)
|
||||
parser.add_argument(
|
||||
'-Q', '--qemu-build-id', default=default_build_id,
|
||||
help='QEMU build ID. Allows you to keep multiple separate QEMU builds. Default: %(default)s'
|
||||
)
|
||||
parser.add_argument(
|
||||
'--buildroot-build-id',
|
||||
default=default_build_id,
|
||||
help='Buildroot build ID. Allows you to keep multiple separate gem5 builds. Default: %(default)s'
|
||||
)
|
||||
parser.add_argument(
|
||||
'-t', '--gem5-build-type', default='opt',
|
||||
help='gem5 build type, most often used for "debug" builds. Default: %(default)s'
|
||||
)
|
||||
if hasattr(this, 'configs'):
|
||||
defaults = this.configs.copy()
|
||||
else:
|
||||
defaults = {}
|
||||
defaults.update(default_args)
|
||||
# A bit ugly as it actually changes the defaults shown on --help, but we can't do any better
|
||||
# because it is impossible to check if arguments were given or not...
|
||||
# - https://stackoverflow.com/questions/30487767/check-if-argparse-optional-argument-is-set-or-not
|
||||
# - https://stackoverflow.com/questions/3609852/which-is-the-best-way-to-allow-configuration-options-be-overridden-at-the-comman
|
||||
parser.set_defaults(**defaults)
|
||||
return parser
|
||||
|
||||
def add_build_arguments(parser):
|
||||
parser.add_argument(
|
||||
'--clean',
|
||||
help='Clean the build instead of building.',
|
||||
action='store_true',
|
||||
)
|
||||
|
||||
def get_elf_entry(elf_file_path):
|
||||
global this
|
||||
readelf_header = subprocess.check_output([
|
||||
this.get_toolchain_tool('readelf'),
|
||||
'-h',
|
||||
elf_file_path
|
||||
])
|
||||
for line in readelf_header.decode().split('\n'):
|
||||
split = line.split()
|
||||
if line.startswith(' Entry point address:'):
|
||||
addr = line.split()[-1]
|
||||
break
|
||||
return int(addr, 0)
|
||||
|
||||
def get_stats(stat_re=None, stats_file=None):
|
||||
global this
|
||||
if stat_re is None:
|
||||
stat_re = '^system.cpu[0-9]*.numCycles$'
|
||||
if stats_file is None:
|
||||
stats_file = this.stats_file
|
||||
stat_re = re.compile(stat_re)
|
||||
ret = []
|
||||
with open(stats_file, 'r') as statfile:
|
||||
for line in statfile:
|
||||
if line[0] != '-':
|
||||
cols = line.split()
|
||||
if len(cols) > 1 and stat_re.search(cols[0]):
|
||||
ret.append(cols[1])
|
||||
return ret
|
||||
|
||||
def get_toolchain_tool(tool):
|
||||
global this
|
||||
return glob.glob(os.path.join(this.host_bin_dir, '*-buildroot-*-{}'.format(tool)))[0]
|
||||
|
||||
def log_error(msg):
|
||||
print('error: {}'.format(msg), file=sys.stderr)
|
||||
|
||||
def print_cmd(cmd, cmd_file=None, extra_env=None):
|
||||
'''
|
||||
Format a command given as a list of strings so that it can
|
||||
be viewed nicely and executed by bash directly and print it to stdout.
|
||||
|
||||
Optionally save the command to cmd_file file, and add extra_env
|
||||
environment variables to the command generated.
|
||||
'''
|
||||
newline_separator = ' \\\n'
|
||||
out = []
|
||||
for key in extra_env:
|
||||
out.extend(['{}={}'.format(shlex.quote(key), shlex.quote(extra_env[key])), newline_separator])
|
||||
for arg in cmd:
|
||||
out.extend([shlex.quote(arg), newline_separator])
|
||||
out = ''.join(out)
|
||||
print(out)
|
||||
if cmd_file is not None:
|
||||
with open(cmd_file, 'w') as f:
|
||||
f.write('#!/usr/bin/env bash\n')
|
||||
f.write(out)
|
||||
st = os.stat(cmd_file)
|
||||
os.chmod(cmd_file, st.st_mode | stat.S_IXUSR)
|
||||
|
||||
def resolve_args(defaults, args, extra_args):
|
||||
if extra_args is None:
|
||||
extra_args = {}
|
||||
argcopy = copy.copy(args)
|
||||
argcopy.__dict__ = dict(list(defaults.items()) + list(argcopy.__dict__.items()) + list(extra_args.items()))
|
||||
return argcopy
|
||||
|
||||
def rmrf(path):
|
||||
if os.path.exists(path):
|
||||
shutil.rmtree(path)
|
||||
|
||||
def run_cmd(
|
||||
cmd,
|
||||
cmd_file=None,
|
||||
out_file=None,
|
||||
show_stdout=True,
|
||||
show_cmd=True,
|
||||
extra_env=None,
|
||||
delete_env=None,
|
||||
**kwargs
|
||||
):
|
||||
'''
|
||||
Run a command. Write the command to stdout before running it.
|
||||
|
||||
Wait until the command finishes execution.
|
||||
|
||||
:param cmd: command to run
|
||||
:type cmd: List[str]
|
||||
|
||||
:param cmd_file: if not None, write the command to be run to that file
|
||||
:type cmd_file: str
|
||||
|
||||
:param out_file: if not None, write the stdout and stderr of the command the file
|
||||
:type out_file: str
|
||||
|
||||
:param show_stdout: wether to show stdout and stderr on the terminal or not
|
||||
:type show_stdout: bool
|
||||
|
||||
:param extra_env: extra environment variables to add when running the command
|
||||
:type extra_env: Dict[str,str]
|
||||
'''
|
||||
if out_file is not None:
|
||||
stdout = subprocess.PIPE
|
||||
stderr = subprocess.STDOUT
|
||||
else:
|
||||
if show_stdout:
|
||||
stdout = None
|
||||
stderr = None
|
||||
else:
|
||||
stdout = subprocess.DEVNULL
|
||||
stderr = subprocess.DEVNULL
|
||||
if extra_env is None:
|
||||
extra_env = {}
|
||||
if delete_env is None:
|
||||
delete_env = []
|
||||
env = os.environ.copy()
|
||||
env.update(extra_env)
|
||||
for key in delete_env:
|
||||
del env[key]
|
||||
if show_cmd:
|
||||
print_cmd(cmd, cmd_file, extra_env=extra_env)
|
||||
# Otherwise Ctrl + C gives:
|
||||
# - ugly Python stack trace for gem5 (QEMU takes over terminal and is fine).
|
||||
# - kills Python, and that then kills GDB: https://stackoverflow.com/questions/19807134/does-python-always-raise-an-exception-if-you-do-ctrlc-when-a-subprocess-is-exec
|
||||
signal.signal(signal.SIGINT, signal.SIG_IGN)
|
||||
# https://stackoverflow.com/questions/15535240/python-popen-write-to-stdout-and-log-file-simultaneously/52090802#52090802
|
||||
with subprocess.Popen(cmd, stdout=stdout, stderr=stderr, env=env, **kwargs) as proc:
|
||||
if out_file is not None:
|
||||
with open(out_file, 'bw') as logfile:
|
||||
while True:
|
||||
byte = proc.stdout.read(1)
|
||||
if byte:
|
||||
if show_stdout:
|
||||
sys.stdout.buffer.write(byte)
|
||||
sys.stdout.flush()
|
||||
logfile.write(byte)
|
||||
else:
|
||||
break
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
return proc.returncode
|
||||
|
||||
def setup(parser, **extra_args):
|
||||
'''
|
||||
Parse the command line arguments, and setup several variables based on them.
|
||||
Typically done after getting inputs from the command line arguments.
|
||||
'''
|
||||
global this
|
||||
args = parser.parse_args()
|
||||
if args.arch in this.arch_map:
|
||||
args.arch = this.arch_map[args.arch]
|
||||
if args.arch == 'arm':
|
||||
this.armv = 7
|
||||
this.gem5_arch = 'ARM'
|
||||
elif args.arch == 'aarch64':
|
||||
this.armv = 8
|
||||
this.gem5_arch = 'ARM'
|
||||
elif args.arch == 'x86_64':
|
||||
this.gem5_arch = 'X86'
|
||||
this.buildroot_build_dir = os.path.join(this.out_dir, 'buildroot', args.arch, args.buildroot_build_id)
|
||||
this.buildroot_config_file = os.path.join(this.buildroot_build_dir, '.config')
|
||||
this.build_dir = os.path.join(this.buildroot_build_dir, 'build')
|
||||
this.linux_build_dir = os.path.join(this.build_dir, 'linux-custom')
|
||||
this.linux_variant_dir = '{}.{}'.format(this.linux_build_dir, args.linux_build_id)
|
||||
this.vmlinux = os.path.join(this.linux_variant_dir, "vmlinux")
|
||||
this.qemu_build_dir = os.path.join(this.out_dir, 'qemu', args.qemu_build_id)
|
||||
this.qemu_executable = os.path.join(this.qemu_build_dir, '{}-softmmu'.format(args.arch), 'qemu-system-{}'.format(args.arch))
|
||||
this.qemu_img_executable = os.path.join(this.qemu_build_dir, 'qemu-img')
|
||||
this.qemu_guest_build_dir = os.path.join(this.build_dir, 'qemu-custom')
|
||||
this.host_dir = os.path.join(this.buildroot_build_dir, 'host')
|
||||
this.host_bin_dir = os.path.join(this.host_dir, 'usr', 'bin')
|
||||
this.images_dir = os.path.join(this.buildroot_build_dir, 'images')
|
||||
this.ext2_file = os.path.join(this.images_dir, 'rootfs.ext2')
|
||||
this.qcow2_file = os.path.join(this.images_dir, 'rootfs.ext2.qcow2')
|
||||
this.staging_dir = os.path.join(this.buildroot_build_dir, 'staging')
|
||||
this.target_dir = os.path.join(this.buildroot_build_dir, 'target')
|
||||
this.run_dir_base = os.path.join(this.out_dir, 'run')
|
||||
this.gem5_run_dir = os.path.join(this.run_dir_base, 'gem5', args.arch, str(args.run_id))
|
||||
this.m5out_dir = os.path.join(this.gem5_run_dir, 'm5out')
|
||||
this.stats_file = os.path.join(this.m5out_dir, 'stats.txt')
|
||||
this.trace_txt_file = os.path.join(this.m5out_dir, 'trace.txt')
|
||||
this.gem5_readfile = os.path.join(this.gem5_run_dir, 'readfile')
|
||||
this.gem5_termout_file = os.path.join(this.gem5_run_dir, 'termout.txt')
|
||||
this.qemu_run_dir = os.path.join(this.run_dir_base, 'qemu', args.arch, str(args.run_id))
|
||||
this.qemu_trace_basename = 'trace.bin'
|
||||
this.qemu_trace_file = os.path.join(this.qemu_run_dir, 'trace.bin')
|
||||
this.qemu_trace_txt_file = os.path.join(this.qemu_run_dir, 'trace.txt')
|
||||
this.qemu_termout_file = os.path.join(this.qemu_run_dir, 'termout.txt')
|
||||
this.qemu_rrfile = os.path.join(this.qemu_run_dir, 'rrfile')
|
||||
this.gem5_build_dir = os.path.join(this.out_dir, 'gem5', args.gem5_build_id)
|
||||
this.gem5_m5term = os.path.join(this.gem5_build_dir, 'm5term')
|
||||
this.gem5_build_build_dir = os.path.join(this.gem5_build_dir, 'build')
|
||||
this.gem5_executable = os.path.join(this.gem5_build_build_dir, gem5_arch, 'gem5.{}'.format(args.gem5_build_type))
|
||||
this.gem5_system_dir = os.path.join(this.gem5_build_dir, 'system')
|
||||
if args.gem5_worktree is not None:
|
||||
this.gem5_src_dir = os.path.join(this.gem5_non_default_src_root_dir, args.gem5_worktree)
|
||||
else:
|
||||
this.gem5_src_dir = this.gem5_default_src_dir
|
||||
if args.gem5:
|
||||
this.executable = this.gem5_executable
|
||||
this.run_dir = this.gem5_run_dir
|
||||
this.termout_file = this.gem5_termout_file
|
||||
else:
|
||||
this.executable = this.qemu_executable
|
||||
this.run_dir = this.qemu_run_dir
|
||||
this.termout_file = this.qemu_termout_file
|
||||
this.gem5_config_dir = os.path.join(this.gem5_src_dir, 'configs')
|
||||
this.gem5_se_file = os.path.join(this.gem5_config_dir, 'example', 'se.py')
|
||||
this.gem5_fs_file = os.path.join(this.gem5_config_dir, 'example', 'fs.py')
|
||||
this.run_cmd_file = os.path.join(this.run_dir, 'run.sh')
|
||||
if args.arch == 'arm':
|
||||
this.linux_image = os.path.join('arch', 'arm', 'boot', 'zImage')
|
||||
elif args.arch == 'aarch64':
|
||||
this.linux_image = os.path.join('arch', 'arm64', 'boot', 'Image')
|
||||
elif args.arch == 'x86_64':
|
||||
this.linux_image = os.path.join('arch', 'x86', 'boot', 'bzImage')
|
||||
this.linux_image = os.path.join(this.linux_variant_dir, linux_image)
|
||||
|
||||
# Ports.
|
||||
if args.port_offset is None:
|
||||
try:
|
||||
args.port_offset = int(args.run_id)
|
||||
except ValueError:
|
||||
args.port_offset = 0
|
||||
if args.gem5:
|
||||
this.gem5_telnet_port = 3456 + args.port_offset
|
||||
this.gdb_port = 7000 + args.port_offset
|
||||
else:
|
||||
this.qemu_base_port = 45454 + 10 * args.port_offset
|
||||
this.qemu_monitor_port = this.qemu_base_port + 0
|
||||
this.qemu_hostfwd_generic_port = this.qemu_base_port + 1
|
||||
this.qemu_hostfwd_ssh_port = this.qemu_base_port + 2
|
||||
this.qemu_gdb_port = this.qemu_base_port + 3
|
||||
this.gdb_port = this.qemu_gdb_port
|
||||
return args
|
||||
|
||||
def mkdir():
|
||||
global this
|
||||
os.makedirs(this.build_dir, exist_ok=True)
|
||||
os.makedirs(this.gem5_build_dir, exist_ok=True)
|
||||
os.makedirs(this.gem5_run_dir, exist_ok=True)
|
||||
os.makedirs(this.qemu_run_dir, exist_ok=True)
|
||||
os.makedirs(this.p9_dir, exist_ok=True)
|
||||
@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env bash
|
||||
common_arch=aarch64
|
||||
common_gem5=true
|
||||
#!/usr/bin/env python
|
||||
arch = 'aarch64'
|
||||
gem5 = True
|
||||
run_id = 'asdf'
|
||||
|
||||
14
configure
vendored
14
configure
vendored
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
set -e
|
||||
set -eu
|
||||
interactive_pkgs=libsdl2-dev
|
||||
gem5=false
|
||||
qemu=true
|
||||
@ -11,7 +11,7 @@ while getopts gpqt OPT; do
|
||||
gem5=true
|
||||
;;
|
||||
p)
|
||||
submodules="$submodules parsec-benchmark/parsec-benchmark"
|
||||
submodules="${submodules} parsec-benchmark"
|
||||
;;
|
||||
q)
|
||||
qemu=false
|
||||
@ -100,11 +100,12 @@ fi
|
||||
## Submodules
|
||||
|
||||
if "$qemu"; then
|
||||
submodules="$submodules qemu"
|
||||
submodules="${submodules} qemu"
|
||||
fi
|
||||
if "$gem5"; then
|
||||
submodules="$submodules gem5/gem5"
|
||||
submodules="${submodules} gem5"
|
||||
fi
|
||||
submodules="$(for submodule in ${submodules}; do printf "submodules/${submodule} "; done)"
|
||||
(
|
||||
set -e
|
||||
# Shallow cloning saves a considerable amount of time, specially because of the linux kernel.
|
||||
@ -113,10 +114,9 @@ fi
|
||||
# In particular:
|
||||
# - `shallow = true` on the submodule has no effect for the non default educational branches of our submodules
|
||||
# - QEMU's submodules point to commits that are neither under branches nor tags, and so `--shallow-submodules` fails
|
||||
git submodule update --depth 1 $gitjobs --init -- $submodules
|
||||
git submodule update --depth 1 $gitjobs --init -- ${submodules}
|
||||
if "$qemu"; then
|
||||
cd qemu
|
||||
git submodule update --init --recursive
|
||||
git -C submodules/qemu submodule update --init --recursive
|
||||
fi
|
||||
) &
|
||||
# https://unix.stackexchange.com/questions/65532/why-does-set-e-not-work-inside-subshells-with-parenthesis-followed-by-an-or
|
||||
|
||||
3
eeval
3
eeval
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
# echo and eval
|
||||
# echo a command and eval it.
|
||||
# Can also print the command to a file.
|
||||
set -e
|
||||
a=
|
||||
while getopts a OPT; do
|
||||
|
||||
@ -1,72 +1,72 @@
|
||||
#!/usr/bin/env bash
|
||||
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common"
|
||||
common_gem5=true
|
||||
set -eu
|
||||
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
|
||||
generate_checkpoints=true
|
||||
while getopts "C${common_getopts_flags}" OPT; do
|
||||
while getopts "C" OPT; do
|
||||
case "$OPT" in
|
||||
C)
|
||||
generate_checkpoints=false
|
||||
;;
|
||||
?)
|
||||
common_getopts_case "$OPT"
|
||||
exit 2;
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift "$(($OPTIND - 1))"
|
||||
common_setup
|
||||
common_opts="--gem5 $@"
|
||||
|
||||
# Vars
|
||||
cmd="./run -a ${common_arch} -g"
|
||||
cmd="./run ${common_opts}"
|
||||
cache_small='--caches --l2cache --l1d_size=1024 --l1i_size=1024 --l2_size=1024 --l3_size=1024 '
|
||||
cache_large='--caches --l2cache --l1d_size=1024kB --l1i_size=1024kB --l2_size=1024kB --l3_size=1024kB'
|
||||
results_file="${common_gem5_run_dir}/bench-cache.txt"
|
||||
results_file="$(${root_dir}/getvar ${common_opts} run_dir)/bench-cache.txt"
|
||||
|
||||
bench() (
|
||||
common_bench_cmd "$1" "$results_file"
|
||||
"${root_dir}/bench-cmd" "$1"
|
||||
{
|
||||
printf 'cycles '
|
||||
./gem5-stat -a "$common_arch"
|
||||
./gem5-stat ${common_opts}
|
||||
printf 'instructions '
|
||||
./gem5-stat -a "$common_arch" sim_insts
|
||||
./gem5-stat ${common_opts} sim_insts
|
||||
# RESTORE_INVESTIGATION
|
||||
#cycles_switch="$(./gem5-stat -a "$common_arch" system.switch_cpus.numCycles)"
|
||||
#cycles_switch="$(./gem5-stat ${common_opts} system.switch_cpus.numCycles)"
|
||||
#if [ -n "$cycles_switch" ]; then
|
||||
# printf "cycles_switch ${cycles_switch}\n"
|
||||
#fi
|
||||
printf "\n"
|
||||
} >> "$results_file"
|
||||
)
|
||||
|
||||
bench-all() (
|
||||
bench "${cmd} -l 1 -- ${cache_small} --cpu-type=HPI --restore-with-cpu=HPI"
|
||||
bench "${cmd} -l 1 -- ${cache_large} --cpu-type=HPI --restore-with-cpu=HPI"
|
||||
bench "${cmd} --gem5-readfile \"$1\" --gem5-restore 1 -- ${cache_small} --cpu-type=HPI --restore-with-cpu=HPI"
|
||||
bench "${cmd} --gem5-readfile \"$1\" --gem5-restore 1 -- ${cache_large} --cpu-type=HPI --restore-with-cpu=HPI"
|
||||
# RESTORE_INVESTIGATION
|
||||
# These were mostly to investigate what happens on restore:
|
||||
# https://stackoverflow.com/questions/49011096/how-to-switch-cpu-models-in-gem5-after-restoring-a-checkpoint-and-then-observe-t
|
||||
#bench "${cmd} -l 1"
|
||||
#bench "${cmd} -l 1 -- ${cache_small}"
|
||||
#bench "${cmd} -l 1 -- ${cache_large}"
|
||||
#bench "${cmd} -l 2 -- ${cache_small}"
|
||||
#bench "${cmd} -l 3 -- ${cache_large}"
|
||||
#bench "${cmd} -l 4 -- ${cache_small} --cpu-type=HPI"
|
||||
#bench "${cmd} -l 5 -- ${cache_large} --cpu-type=HPI"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 1"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 1 -- ${cache_small}"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 1 -- ${cache_large}"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 2 -- ${cache_small}"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 3 -- ${cache_large}"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 4 -- ${cache_small} --cpu-type=HPI"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 5 -- ${cache_large} --cpu-type=HPI"
|
||||
## Restore from At-- omicSimpleCPU to HPI.
|
||||
#bench "${cmd} -l 2 -- ${cache_small} --cpu-type=HPI --restore-with-cpu=HPI"
|
||||
#bench "${cmd} -l 3 -- ${cache_large} --cpu-type=HPI --restore-with-cpu=HPI"
|
||||
#bench "${cmd} -l 2 -- ${cache_small} --restore-with-cpu=HPI"
|
||||
#bench "${cmd} -l 3 -- ${cache_large} --restore-with-cpu=HPI"
|
||||
#bench "${cmd} -l 2 -- ${cache_small} --cpu-type=HPI"
|
||||
#bench "${cmd} -l 3 -- ${cache_large} --cpu-type=HPI"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 2 -- ${cache_small} --cpu-type=HPI --restore-with-cpu=HPI"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 3 -- ${cache_large} --cpu-type=HPI --restore-with-cpu=HPI"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 2 -- ${cache_small} --restore-with-cpu=HPI"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 3 -- ${cache_large} --restore-with-cpu=HPI"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 2 -- ${cache_small} --cpu-type=HPI"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 3 -- ${cache_large} --cpu-type=HPI"
|
||||
## Restore HPI with different cache sizes and see if it is used.
|
||||
#bench "${cmd} -l 4 -- ${cache_large} --cpu-type=HPI"
|
||||
#bench "${cmd} -l 5 -- ${cache_small} --cpu-type=HPI"
|
||||
#bench "${cmd} -l 2 -- ${cache_large} --cpu-type=HPI"
|
||||
#bench "${cmd} -l 3 -- ${cache_small} --cpu-type=HPI"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 4 -- ${cache_large} --cpu-type=HPI"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 5 -- ${cache_small} --cpu-type=HPI"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 2 -- ${cache_large} --cpu-type=HPI"
|
||||
#bench "${cmd} --gem5-readfile '$1' --gem5-restore 3 -- ${cache_small} --cpu-type=HPI"
|
||||
)
|
||||
|
||||
|
||||
if "$generate_checkpoints"; then
|
||||
# Create the checkpoints after the kernel boot.
|
||||
printf 'm5 exit' > "${common_gem5_readfile_file}"
|
||||
cpt_cmd="-E '/gem5.sh'"
|
||||
# RESTORE_INVESTIGATION
|
||||
## 5
|
||||
@ -84,8 +84,5 @@ fi
|
||||
# Restore and run benchmarks.
|
||||
rm -f "$results_file"
|
||||
for n in 1000 10000 100000; do
|
||||
printf "n ${n}\n" >> "$results_file"
|
||||
printf "dhrystone ${n}" > "${common_gem5_readfile_file}"
|
||||
bench-all
|
||||
printf "\n" >> "$results_file"
|
||||
bench-all "dhrystone ${n}"
|
||||
done
|
||||
|
||||
26
gem5-bench-dhrystone
Executable file
26
gem5-bench-dhrystone
Executable file
@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# https://github.com/cirosantilli/linux-kernel-module-cheat/tree/58de3f7243016c052ad080f82dd757d61878219b#gem5-run-benchmark
|
||||
|
||||
set -eu
|
||||
root_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)"
|
||||
outfile="${root_dir}/out/gem5-bench-dhrystone.txt"
|
||||
arch=aarch64
|
||||
cmd="./run -a '$arch' --gem5 --eval-busybox '/gem5.sh'"
|
||||
|
||||
# These cache sizes roughly match the ARM Cortex A75
|
||||
# https://en.wikipedia.org/wiki/ARM_Cortex-A75
|
||||
restore='-l 1 -- --cpu-type=HPI --restore-with-cpu=HPI --caches --l2cache --l1d_size=128kB --l1i_size=1024kB --l2_size=256kB'
|
||||
|
||||
# Generate a checkpoint after Linux boots, using the faster and less detailed CPU.
|
||||
# The boot takes a while, be patient young Padawan.
|
||||
eval "$cmd"
|
||||
|
||||
printf 'n cycles\n' > "$outfile"
|
||||
for n in 1000 10000 100000; do
|
||||
# Restore the most recent checkpoint taken with the more detailed and slower HPI CPU,
|
||||
# and run the benchmark with different parameters. We skip the boot completely, saving time!
|
||||
eval "${cmd} --gem5-readfile 'dhrystone ${n}' ${restore}" &>/dev/null
|
||||
printf "${n} " >> "$outfile"
|
||||
./gem5-stat -a "$arch" >> "$outfile"
|
||||
done
|
||||
26
gem5-shell
26
gem5-shell
@ -1,13 +1,13 @@
|
||||
#!/usr/bin/env bash
|
||||
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common"
|
||||
common_gem5=true
|
||||
while getopts "${common_getopts_flags}" OPT; do
|
||||
case "$OPT" in
|
||||
?)
|
||||
common_getopts_case "$OPT"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift "$(($OPTIND - 1))"
|
||||
common_setup
|
||||
"${common_gem5_m5term}" localhost "$common_gem5_telnet_port"
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
import common
|
||||
|
||||
parser = common.get_argparse(
|
||||
default_args={'gem5':True},
|
||||
argparse_args={'description':'Connect a terminal to a running gem5 instance'}
|
||||
)
|
||||
args = common.setup(parser)
|
||||
sys.exit(common.run_cmd([str(common.gem5_m5term), 'localhost', str(common.gem5_telnet_port)]))
|
||||
|
||||
39
gem5-stat
39
gem5-stat
@ -1,25 +1,14 @@
|
||||
#!/usr/bin/env bash
|
||||
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common"
|
||||
common_gem5=true
|
||||
while getopts "h${common_getopts_flags}" OPT; do
|
||||
case "$OPT" in
|
||||
h)
|
||||
printf "\
|
||||
usage: $0 [-a arch] [stat=system.cpu.numCycles]
|
||||
Get the value for a gem5 stat from the stats.txt file.
|
||||
" 1>&2
|
||||
exit
|
||||
;;
|
||||
?)
|
||||
common_getopts_case "$OPT"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift "$(($OPTIND - 1))"
|
||||
if [ $# -gt 0 ]; then
|
||||
stat="$1"
|
||||
else
|
||||
stat=system.cpu[0-9]*.numCycles
|
||||
fi
|
||||
common_setup
|
||||
awk "/^$stat /{ print \$2 }" "${common_m5out_dir}/stats.txt"
|
||||
#!/usr/bin/env python3
|
||||
import common
|
||||
parser = common.get_argparse(
|
||||
argparse_args={'description':'Get the value of a gem5 stat from the stats.txt file.'}
|
||||
)
|
||||
parser.add_argument(
|
||||
'stat',
|
||||
default=None,
|
||||
help='Python regexp matching the full stat name of interest',
|
||||
nargs='?',
|
||||
)
|
||||
args = common.setup(parser)
|
||||
stats = common.get_stats(args.stat)
|
||||
print('\n'.join(stats))
|
||||
|
||||
@ -1,7 +0,0 @@
|
||||
config BR2_PACKAGE_GEM5
|
||||
bool "gem5"
|
||||
help
|
||||
gem5 system simulator. Only builds the m5 guest instrumentation
|
||||
tool for now, not the simulator itself.
|
||||
|
||||
http://gem5.org
|
||||
61
gem5/build
61
gem5/build
@ -1,61 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
set -eux
|
||||
arch=x86_64
|
||||
build_type=opt
|
||||
cross_compile=
|
||||
j=
|
||||
outdir="$(pwd)"
|
||||
while getopts a:c:j:o:t: OPT; do
|
||||
case "$OPT" in
|
||||
a)
|
||||
arch="$OPTARG"
|
||||
;;
|
||||
c)
|
||||
cross_compile="CROSS_COMPILE=$OPTARG"
|
||||
;;
|
||||
j)
|
||||
j="$OPTARG"
|
||||
;;
|
||||
o)
|
||||
outdir="$OPTARG"
|
||||
;;
|
||||
t)
|
||||
build_type="$OPTARG"
|
||||
;;
|
||||
?)
|
||||
exit 2
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift "$(($OPTIND - 1))"
|
||||
if [ -z "$j" ]; then
|
||||
j="$(nproc)"
|
||||
fi
|
||||
system_dir="${outdir}/system"
|
||||
binaries_dir="${system_dir}/binaries"
|
||||
disks_dir="${system_dir}/disks"
|
||||
mkdir -p "$binaries_dir" "$disks_dir"
|
||||
export PATH="/usr/lib/ccache:${PATH}"
|
||||
if [ "$arch" = x86_64 ]; then
|
||||
scons -j "$j" --ignore-style "${outdir}/build/X86/gem5.${build_type}"
|
||||
f="${disks_dir}/linux-bigswap2.img"
|
||||
dd if=/dev/zero of="$f" bs=1024 count=65536
|
||||
mkswap "$f"
|
||||
# This file must always be present, despite --kernel overriding that default and selecting the kernel.
|
||||
# I'm not even joking. No one has ever built x86 gem5 without the magic dist dir present.
|
||||
touch "${binaries_dir}/x86_64-vmlinux-2.6.22.9"
|
||||
elif [ "$arch" = arm ] || [ "$arch" = aarch64 ]; then
|
||||
scons -j "$j" --ignore-style "${outdir}/build/ARM/gem5.${build_type}"
|
||||
make -C ./system/arm/dt/
|
||||
mkdir -p "${system_dir}/arm/dt"
|
||||
# || true in case they are the same directory.
|
||||
cp ./system/arm/dt/*.dtb "${system_dir}/arm/dt" || true
|
||||
# TODO use the buildroot cross compiler here, and remove the dependencies from configure.
|
||||
make -C ./system/arm/simple_bootloader/ $cross_compile
|
||||
cp ./system/arm/simple_bootloader/boot_emm.arm "$binaries_dir"
|
||||
# TODO cross_compile is ignored because the make does not use CC...
|
||||
make -C ./system/arm/aarch64_bootloader/ $cross_compile
|
||||
cp ./system/arm/aarch64_bootloader/boot_emm.arm64 "$binaries_dir"
|
||||
fi
|
||||
make -C util/term
|
||||
cp util/term/m5term "${outdir}"
|
||||
37
getvar
37
getvar
@ -1,16 +1,21 @@
|
||||
#!/usr/bin/env bash
|
||||
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common"
|
||||
while getopts "h${common_getopts_flags}" OPT; do
|
||||
case "$OPT" in
|
||||
h)
|
||||
echo "https://github.com/cirosantilli/linux-kernel-module-cheat#getvar" 2>&1
|
||||
exit
|
||||
;;
|
||||
?)
|
||||
common_getopts_case "$OPT"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift "$(($OPTIND - 1))"
|
||||
common_setup
|
||||
eval "echo \$common_${1}"
|
||||
#!/usr/bin/env python3
|
||||
import common
|
||||
parser = common.get_argparse(argparse_args={
|
||||
'description': '''Print the value of a common.py variable.
|
||||
|
||||
This is useful to:
|
||||
|
||||
* give dry commands on the README that don't change when we refactor directory structure
|
||||
* create simple bash scripts that call use common.py variables
|
||||
|
||||
For example, to get the Buildroot output directory for an ARM build, use:
|
||||
|
||||
....
|
||||
./%(prog)s -a arm buildroot_build_dir
|
||||
....
|
||||
|
||||
'''
|
||||
})
|
||||
parser.add_argument('variable')
|
||||
args = common.setup(parser)
|
||||
print(getattr(common, args.variable))
|
||||
|
||||
@ -1,28 +1,16 @@
|
||||
# Misc.
|
||||
CONFIG_BLK_DEV_INITRD=y
|
||||
CONFIG_STRICT_DEVMEM=n
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_DYNAMIC_DEBUG=y
|
||||
CONFIG_MODULE_SRCVERSION_ALL=y
|
||||
CONFIG_OVERLAY_FS=y
|
||||
CONFIG_STRICT_DEVMEM=n
|
||||
|
||||
# GDB debugging.
|
||||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_KERNEL=y
|
||||
CONFIG_GDB_SCRIPTS=y
|
||||
|
||||
# Non-static variables show up on /proc/kallsyms
|
||||
# https://stackoverflow.com/questions/20196636/does-kallsyms-have-all-the-symbol-of-kernel-functions/44614878#44614878
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
|
||||
# /proc/config.gz
|
||||
CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
|
||||
# TODO make example.
|
||||
# This seems to allow userspace to create arbitrary configuration trees,
|
||||
# which kernel modules can then read and interpret.
|
||||
CONFIG_CONFIGFS_FS=y
|
||||
|
||||
# KGDB
|
||||
CONFIG_CONSOLE_POLL=y
|
||||
CONFIG_KDB_CONTINUE_CATASTROPHIC=0
|
||||
@ -38,6 +26,19 @@ CONFIG_MAGIC_SYSRQ=y
|
||||
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
|
||||
CONFIG_SERIAL_KGDB_NMI=n
|
||||
|
||||
# Non-static variables show up on /proc/kallsyms
|
||||
# https://stackoverflow.com/questions/20196636/does-kallsyms-have-all-the-symbol-of-kernel-functions/44614878#44614878
|
||||
CONFIG_KALLSYMS_ALL=y
|
||||
|
||||
# /proc/config.gz
|
||||
CONFIG_IKCONFIG=y
|
||||
CONFIG_IKCONFIG_PROC=y
|
||||
|
||||
# TODO make example.
|
||||
# This seems to allow userspace to create arbitrary configuration trees,
|
||||
# which kernel modules can then read and interpret.
|
||||
CONFIG_CONFIGFS_FS=y
|
||||
|
||||
# Module.symvers in kernel tree and modules tree contains CRC of signatures.
|
||||
# TODO: I think the CRC are stored in the built kernel and module, and checked
|
||||
# at insmod, but bgrep did not find it in kernel image.
|
||||
@ -1,4 +1,4 @@
|
||||
# This file contains only configs which are required to boot all configurations.
|
||||
# This file contains only configs which are required to boot all configurations and get a shell.
|
||||
|
||||
## gem5 x86
|
||||
|
||||
@ -1 +0,0 @@
|
||||
name: KERNEL_MODULE
|
||||
@ -1,28 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
. "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common"
|
||||
while getopts "h${common_getopts_flags}" OPT; do
|
||||
case "$OPT" in
|
||||
h)
|
||||
echo "https://github.com/cirosantilli/linux-kernel-module-cheat#getvar" 2>&1
|
||||
exit
|
||||
;;
|
||||
?)
|
||||
common_getopts_case "$OPT"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
shift "$(($OPTIND - 1))"
|
||||
common_linux_variant=bisect
|
||||
common_setup
|
||||
cd "$common_root_dir"
|
||||
# We need a clean rebuild becuase rebuilds at different revisions:
|
||||
# - may fail
|
||||
# - may not actually rebuild all files, e.g. on header changes
|
||||
rm -rf "$(./getvar -a "$common_arch" -L "$common_linux_variant" linux_variant_dir)"
|
||||
./build -a "$common_arch" -L "$common_linux_variant"
|
||||
status=0
|
||||
./run -a "$common_arch" -E 'm5 exit' -L "$common_linux_variant" -g || status=$?
|
||||
if [ "$status" -eq 125 ] || [ "$status" -gt 127 ]; then
|
||||
status=1
|
||||
fi
|
||||
exit "$status"
|
||||
7
packages/gem5/Config.in
Normal file
7
packages/gem5/Config.in
Normal file
@ -0,0 +1,7 @@
|
||||
config BR2_PACKAGE_GEM5
|
||||
bool "gem5"
|
||||
help
|
||||
Only for the m5 guest instrumentation tool of the gem5 system simulator,
|
||||
does not build the simulator itself.
|
||||
|
||||
http://gem5.org
|
||||
@ -5,7 +5,7 @@
|
||||
################################################################################
|
||||
|
||||
GEM5_VERSION = 1.0
|
||||
GEM5_SITE = $(BR2_EXTERNAL_GEM5_PATH)
|
||||
GEM5_SITE = $(LKMC_GEM5_SRCDIR)
|
||||
GEM5_SITE_METHOD = local
|
||||
|
||||
ifeq ($(ARCH),x86_64)
|
||||
@ -15,16 +15,13 @@ ARCH_MAKE = $(ARCH)
|
||||
endif
|
||||
|
||||
define GEM5_BUILD_CMDS
|
||||
# TODO cannot pass "-c '$(TARGET_CROSS)'" here because the ARM build uses aarch64 for the bootloader...
|
||||
cd '$(GEM5_LKMC_SRCDIR)' && '$(GEM5_SITE)/build' -a '$(ARCH)' -j '$(BR2_JLEVEL)' -o '$(GEM5_LKMC_OUTDIR)' -t '$(GEM5_LKMC_GEM5_BUILD_TYPE)'
|
||||
|
||||
# TODO cannot use TARGET_CONFIGURE_OPTS here because it overrides the CFLAGS on m5,
|
||||
# which have an include. We should patch gem5 to add a += instead of = there.
|
||||
cd '$(@D)/gem5/util/m5' && $(MAKE) -f 'Makefile.$(ARCH_MAKE)' CC='$(TARGET_CC)' LD='$(TARGET_LD)'
|
||||
cd '$(@D)/util/m5' && $(MAKE) -f 'Makefile.$(ARCH_MAKE)' CC='$(TARGET_CC)' LD='$(TARGET_LD)'
|
||||
endef
|
||||
|
||||
define GEM5_INSTALL_TARGET_CMDS
|
||||
$(INSTALL) -D -m 0755 '$(@D)/gem5/util/m5/m5' '$(TARGET_DIR)/usr/bin'
|
||||
$(INSTALL) -D -m 0755 '$(@D)/util/m5/m5' '$(TARGET_DIR)/usr/bin'
|
||||
endef
|
||||
|
||||
$(eval $(generic-package))
|
||||
@ -1,5 +1,5 @@
|
||||
config BR2_PACKAGE_KERNEL_MODULE
|
||||
bool "kernel_module"
|
||||
config BR2_PACKAGE_KERNEL_MODULES
|
||||
bool "kernel_modules"
|
||||
depends on BR2_LINUX_KERNEL
|
||||
help
|
||||
Linux Kernel Module Cheat.
|
||||
@ -1,4 +1,4 @@
|
||||
obj-m += $(addsuffix .o, $(notdir $(basename $(filter-out %.mod.c, $(wildcard $(BR2_EXTERNAL_KERNEL_MODULE_PATH)/*.c)))))
|
||||
obj-m += $(addsuffix .o, $(notdir $(basename $(filter-out %.mod.c, $(wildcard $(BR2_EXTERNAL_KERNEL_MODULES_PATH)/*.c)))))
|
||||
ccflags-y := -DDEBUG -g -std=gnu99 -Werror -Wno-declaration-after-statement -Wframe-larger-than=1000000000
|
||||
|
||||
.PHONY: all clean
|
||||
1
packages/kernel_modules/external.desc
Normal file
1
packages/kernel_modules/external.desc
Normal file
@ -0,0 +1 @@
|
||||
name: KERNEL_MODULES
|
||||
@ -1,24 +1,24 @@
|
||||
################################################################################
|
||||
#
|
||||
# kernel_module
|
||||
# kernel_modules
|
||||
#
|
||||
################################################################################
|
||||
|
||||
KERNEL_MODULE_VERSION = 1.0
|
||||
KERNEL_MODULE_SITE = $(BR2_EXTERNAL_KERNEL_MODULE_PATH)
|
||||
KERNEL_MODULE_SITE_METHOD = local
|
||||
KERNEL_MODULES_VERSION = 1.0
|
||||
KERNEL_MODULES_SITE = $(BR2_EXTERNAL_KERNEL_MODULES_PATH)
|
||||
KERNEL_MODULES_SITE_METHOD = local
|
||||
|
||||
ifeq ($(BR2_PACKAGE_EIGEN),y)
|
||||
KERNEL_MODULE_DEPENDENCIES += eigen
|
||||
KERNEL_MODULES_DEPENDENCIES += eigen
|
||||
endif
|
||||
ifeq ($(BR2_PACKAGE_LIBDRM),y)
|
||||
KERNEL_MODULE_DEPENDENCIES += libdrm
|
||||
KERNEL_MODULES_DEPENDENCIES += libdrm
|
||||
endif
|
||||
ifeq ($(BR2_PACKAGE_OPENBLAS),y)
|
||||
KERNEL_MODULE_DEPENDENCIES += openblas
|
||||
KERNEL_MODULES_DEPENDENCIES += openblas
|
||||
endif
|
||||
|
||||
define KERNEL_MODULE_BUILD_CMDS
|
||||
define KERNEL_MODULES_BUILD_CMDS
|
||||
$(MAKE) -C '$(@D)/user' $(TARGET_CONFIGURE_OPTS) \
|
||||
BR2_PACKAGE_EIGEN="$(BR2_PACKAGE_EIGEN)" \
|
||||
BR2_PACKAGE_LIBDRM="$(BR2_PACKAGE_LIBDRM)" \
|
||||
@ -26,7 +26,7 @@ define KERNEL_MODULE_BUILD_CMDS
|
||||
;
|
||||
endef
|
||||
|
||||
define KERNEL_MODULE_INSTALL_TARGET_CMDS
|
||||
define KERNEL_MODULES_INSTALL_TARGET_CMDS
|
||||
# The modules are already installed by the kernel-module package type
|
||||
# under /lib/modules/**, but let's also copy the modules to the root
|
||||
# for insmod convenience.
|
||||
@ -3,7 +3,7 @@
|
||||
# We can almost do everything from the Makefile itself by using default values for
|
||||
#
|
||||
# LINUX_DIR ?= "/lib/modules/$(uname -r)/build"
|
||||
# BR2_EXTERNAL_KERNEL_MODULE_PATH="$(pwd)"
|
||||
# BR2_EXTERNAL_KERNEL_MODULES_PATH="$(pwd)"
|
||||
#
|
||||
# The problem with that is that if you define those variables in your environment,
|
||||
# the build breaks, so this is more portable.
|
||||
@ -20,5 +20,5 @@ while getopts j: OPT; do
|
||||
esac
|
||||
done
|
||||
shift $(($OPTIND - 1))
|
||||
make -j "$j" KERNEL_MODULE_PATH="$(pwd)" LINUX_DIR="/lib/modules/$(uname -r)/build" "$@"
|
||||
make -j "$j" KERNEL_MODULES_PATH="$(pwd)" LINUX_DIR="/lib/modules/$(uname -r)/build" "$@"
|
||||
make -C user/ -j "$j" "$@"
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user