baremetal: only rebuild required files based on mtime

Move multcore test up with bootloader.
This commit is contained in:
Ciro Santilli 六四事件 法轮功
2018-11-22 00:00:03 +00:00
parent f73eaaffd2
commit 8dd01415f5
4 changed files with 99 additions and 93 deletions

View File

@@ -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`.

View File

@@ -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

View File

@@ -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()

View File

@@ -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):