mirror of
https://github.com/cirosantilli/linux-kernel-module-cheat.git
synced 2026-01-23 02:05:57 +01:00
baremetal: only rebuild required files based on mtime
Move multcore test up with bootloader.
This commit is contained in:
10
README.adoc
10
README.adoc
@@ -1589,7 +1589,9 @@ See also: https://github.com/cirosantilli/linux-kernel-module-cheat/issues/19
|
||||
|
||||
The implementation is described at: https://stackoverflow.com/questions/46415059/how-to-observe-aarch64-system-registers-in-qemu/53043044#53043044
|
||||
|
||||
=== GDB step debug multicore
|
||||
=== GDB step debug multicore userland
|
||||
|
||||
For a more minimal baremetal multicore setup, see: <<arm-multicore>>.
|
||||
|
||||
We can set and get which cores the Linux kernel allows a program to run on with `sched_getaffinity` and `sched_setaffinity`:
|
||||
|
||||
@@ -10510,13 +10512,13 @@ output:
|
||||
|
||||
==== ARM multicore
|
||||
|
||||
TODO get working: CPU1 not waking up:
|
||||
TODO get working: CPU 1 not waking up:
|
||||
|
||||
....
|
||||
./run --arch aarch64 --baremetal arch/aarch64/no_bootloader/multicore
|
||||
./run --arch aarch64 --baremetal arch/aarch64/multicore --cpus 2
|
||||
....
|
||||
|
||||
Source: link:baremetal/arch/aarch64/no_bootloader/multicore.S[]
|
||||
Source: link:baremetal/arch/aarch64/multicore.S[]
|
||||
|
||||
CPU 0 of this program enters a spinlock loop: it repeatedly checks if a given memory address is `1`.
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-multicore */
|
||||
|
||||
.global mystart
|
||||
mystart:
|
||||
.global main
|
||||
main:
|
||||
/* Reset spinlock. */
|
||||
mov x0, #0
|
||||
ldr x1, =spinlock
|
||||
@@ -21,15 +21,7 @@ mystart:
|
||||
ldr x0, spinlock
|
||||
cbz x0, 1b
|
||||
|
||||
/* Semihost exit. */
|
||||
mov x1, #0x26
|
||||
movk x1, #2, lsl #16
|
||||
str x1, [sp,#0]
|
||||
mov x0, #0
|
||||
str x0, [sp,#8]
|
||||
mov x1, sp
|
||||
mov w0, #0x18
|
||||
hlt 0xf000
|
||||
ret
|
||||
|
||||
spinlock:
|
||||
.skip 8
|
||||
@@ -44,29 +44,32 @@ class BaremetalComponent(common.Component):
|
||||
uart_address = 0x09000000
|
||||
os.makedirs(build_dir, exist_ok=True)
|
||||
os.makedirs(common.baremetal_build_lib_dir, exist_ok=True)
|
||||
common.run_cmd(
|
||||
[gcc, common.Newline] +
|
||||
cflags +
|
||||
[
|
||||
'-c', common.Newline,
|
||||
'-o', bootloader_obj, common.Newline,
|
||||
os.path.join(common.baremetal_src_lib_dir, '{}{}'.format(args.arch, common.asm_ext)), common.Newline,
|
||||
]
|
||||
)
|
||||
for src, obj in [
|
||||
(common_src, common_obj),
|
||||
(syscalls_src, syscalls_obj),
|
||||
]:
|
||||
src = os.path.join(common.baremetal_src_lib_dir, '{}{}'.format(args.arch, common.asm_ext))
|
||||
if common.need_rebuild([src], bootloader_obj):
|
||||
common.run_cmd(
|
||||
[gcc, common.Newline] +
|
||||
cflags +
|
||||
[
|
||||
'-c', common.Newline,
|
||||
'-D', 'UART0_ADDR={:#x}'.format(uart_address), common.Newline,
|
||||
'-o', obj, common.Newline,
|
||||
'-o', bootloader_obj, common.Newline,
|
||||
src, common.Newline,
|
||||
]
|
||||
)
|
||||
for src, obj in [
|
||||
(common_src, common_obj),
|
||||
(syscalls_src, syscalls_obj),
|
||||
]:
|
||||
if common.need_rebuild([src], obj):
|
||||
common.run_cmd(
|
||||
[gcc, common.Newline] +
|
||||
cflags +
|
||||
[
|
||||
'-c', common.Newline,
|
||||
'-D', 'UART0_ADDR={:#x}'.format(uart_address), common.Newline,
|
||||
'-o', obj, common.Newline,
|
||||
src, common.Newline,
|
||||
]
|
||||
)
|
||||
self._build_dir(
|
||||
'',
|
||||
gcc=gcc,
|
||||
@@ -137,38 +140,39 @@ Build the baremetal examples with crosstool-NG.
|
||||
in_dir = os.path.join(common.baremetal_src_dir, subpath)
|
||||
out_dir = os.path.join(common.baremetal_build_dir, subpath)
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
common_objs = common_objs.copy()
|
||||
if bootloader:
|
||||
bootloader_cmd = [bootloader_obj, common.Newline]
|
||||
else:
|
||||
bootloader_cmd = []
|
||||
common_objs.append(bootloader_obj)
|
||||
for in_basename in os.listdir(in_dir):
|
||||
in_path = os.path.join(in_dir, in_basename)
|
||||
if os.path.isfile(in_path) and os.path.splitext(in_basename)[1] in (common.c_ext, common.asm_ext):
|
||||
in_name = os.path.splitext(in_basename)[0]
|
||||
main_obj = os.path.join(common.baremetal_build_dir, subpath, '{}{}'.format(in_name, common.obj_ext))
|
||||
common.run_cmd(
|
||||
[gcc, common.Newline] +
|
||||
cflags +
|
||||
[
|
||||
'-c', common.Newline,
|
||||
'-o', main_obj, common.Newline,
|
||||
os.path.join(common.baremetal_src_dir, in_path), common.Newline,
|
||||
]
|
||||
)
|
||||
common.run_cmd(
|
||||
[gcc, common.Newline] +
|
||||
cflags +
|
||||
[
|
||||
'-Wl,--section-start=.text={:#x}'.format(entry_address), common.Newline,
|
||||
'-o', os.path.join(common.baremetal_build_dir, subpath, in_name + common.baremetal_build_ext), common.Newline,
|
||||
'-T', os.path.join(common.baremetal_src_dir, 'link.ld'), common.Newline,
|
||||
] +
|
||||
bootloader_cmd +
|
||||
common.add_newlines(common_objs) +
|
||||
[
|
||||
main_obj, common.Newline,
|
||||
]
|
||||
)
|
||||
src = os.path.join(common.baremetal_src_dir, in_path)
|
||||
if common.need_rebuild([src], main_obj):
|
||||
common.run_cmd(
|
||||
[gcc, common.Newline] +
|
||||
cflags +
|
||||
[
|
||||
'-c', common.Newline,
|
||||
'-o', main_obj, common.Newline,
|
||||
src, common.Newline,
|
||||
]
|
||||
)
|
||||
objs = common_objs + [main_obj]
|
||||
out = os.path.join(common.baremetal_build_dir, subpath, in_name + common.baremetal_build_ext)
|
||||
link_script = os.path.join(common.baremetal_src_dir, 'link.ld')
|
||||
if common.need_rebuild(objs + [link_script], out):
|
||||
common.run_cmd(
|
||||
[gcc, common.Newline] +
|
||||
cflags +
|
||||
[
|
||||
'-Wl,--section-start=.text={:#x}'.format(entry_address), common.Newline,
|
||||
'-o', out, common.Newline,
|
||||
'-T', link_script, common.Newline,
|
||||
] +
|
||||
common.add_newlines(objs)
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
BaremetalComponent().build()
|
||||
|
||||
82
common.py
82
common.py
@@ -193,6 +193,39 @@ def write_string_to_file(path, string, mode='w'):
|
||||
with open(path, 'a') as f:
|
||||
f.write(string)
|
||||
|
||||
def cmd_to_string(cmd, cwd=None, extra_env=None, extra_paths=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.
|
||||
'''
|
||||
last_newline = ' \\\n'
|
||||
newline_separator = last_newline + ' '
|
||||
out = []
|
||||
if extra_env is None:
|
||||
extra_env = {}
|
||||
if cwd is not None:
|
||||
out.append('cd {} &&'.format(shlex.quote(cwd)))
|
||||
if extra_paths is not None:
|
||||
out.append('PATH="{}:${{PATH}}"'.format(':'.join(extra_paths)))
|
||||
for key in extra_env:
|
||||
out.append('{}={}'.format(shlex.quote(key), shlex.quote(extra_env[key])))
|
||||
cmd_quote = []
|
||||
newline_count = 0
|
||||
for arg in cmd:
|
||||
if arg == common.Newline:
|
||||
cmd_quote.append(arg)
|
||||
newline_count += 1
|
||||
else:
|
||||
cmd_quote.append(shlex.quote(arg))
|
||||
if newline_count > 0:
|
||||
cmd_quote = [' '.join(list(y)) for x, y in itertools.groupby(cmd_quote, lambda z: z == common.Newline) if not x]
|
||||
out.extend(cmd_quote)
|
||||
if newline_count == 1 and cmd[-1] == common.Newline:
|
||||
ending = ''
|
||||
else:
|
||||
ending = last_newline + ';'
|
||||
return newline_separator.join(out) + ending
|
||||
|
||||
def copy_dir_if_update_non_recursive(srcdir, destdir, filter_ext=None):
|
||||
# TODO print rsync equivalent.
|
||||
os.makedirs(destdir, exist_ok=True)
|
||||
@@ -207,6 +240,11 @@ def copy_dir_if_update_non_recursive(srcdir, destdir, filter_ext=None):
|
||||
update=1,
|
||||
)
|
||||
|
||||
def cp(src, dest):
|
||||
print_cmd(['cp', src, dest])
|
||||
if not common.dry_run:
|
||||
shutil.copy2(src, dest)
|
||||
|
||||
def gem_list_checkpoint_dirs():
|
||||
'''
|
||||
List checkpoint directory, oldest first.
|
||||
@@ -475,38 +513,13 @@ def make_run_dirs():
|
||||
os.makedirs(common.p9_dir, exist_ok=True)
|
||||
os.makedirs(common.qemu_run_dir, exist_ok=True)
|
||||
|
||||
def cmd_to_string(cmd, cwd=None, extra_env=None, extra_paths=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.
|
||||
'''
|
||||
last_newline = ' \\\n'
|
||||
newline_separator = last_newline + ' '
|
||||
out = []
|
||||
if extra_env is None:
|
||||
extra_env = {}
|
||||
if cwd is not None:
|
||||
out.append('cd {} &&'.format(shlex.quote(cwd)))
|
||||
if extra_paths is not None:
|
||||
out.append('PATH="{}:${{PATH}}"'.format(':'.join(extra_paths)))
|
||||
for key in extra_env:
|
||||
out.append('{}={}'.format(shlex.quote(key), shlex.quote(extra_env[key])))
|
||||
cmd_quote = []
|
||||
newline_count = 0
|
||||
for arg in cmd:
|
||||
if arg == common.Newline:
|
||||
cmd_quote.append(arg)
|
||||
newline_count += 1
|
||||
else:
|
||||
cmd_quote.append(shlex.quote(arg))
|
||||
if newline_count > 0:
|
||||
cmd_quote = [' '.join(list(y)) for x, y in itertools.groupby(cmd_quote, lambda z: z == common.Newline) if not x]
|
||||
out.extend(cmd_quote)
|
||||
if newline_count == 1 and cmd[-1] == common.Newline:
|
||||
ending = ''
|
||||
else:
|
||||
ending = last_newline + ';'
|
||||
return newline_separator.join(out) + ending
|
||||
def need_rebuild(srcs, dst):
|
||||
if not os.path.exists(dst):
|
||||
return True
|
||||
for src in srcs:
|
||||
if os.path.getmtime(src) > os.path.getmtime(dst):
|
||||
return True
|
||||
return False
|
||||
|
||||
def print_cmd(cmd, cwd=None, cmd_file=None, extra_env=None, extra_paths=None):
|
||||
'''
|
||||
@@ -576,11 +589,6 @@ def resolve_args(defaults, args, extra_args):
|
||||
argcopy.__dict__ = dict(list(defaults.items()) + list(argcopy.__dict__.items()) + list(extra_args.items()))
|
||||
return argcopy
|
||||
|
||||
def cp(src, dest):
|
||||
print_cmd(['cp', src, dest])
|
||||
if not common.dry_run:
|
||||
shutil.copy2(src, dest)
|
||||
|
||||
def rmrf(path):
|
||||
print_cmd(['rm', '-r', '-f', path])
|
||||
if not common.dry_run and os.path.exists(path):
|
||||
|
||||
Reference in New Issue
Block a user