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 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`: We can set and get which cores the Linux kernel allows a program to run on with `sched_getaffinity` and `sched_setaffinity`:
@@ -10513,10 +10515,10 @@ output:
TODO get working: CPU 1 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`. 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 */ /* https://github.com/cirosantilli/linux-kernel-module-cheat#arm-multicore */
.global mystart .global main
mystart: main:
/* Reset spinlock. */ /* Reset spinlock. */
mov x0, #0 mov x0, #0
ldr x1, =spinlock ldr x1, =spinlock
@@ -21,15 +21,7 @@ mystart:
ldr x0, spinlock ldr x0, spinlock
cbz x0, 1b cbz x0, 1b
/* Semihost exit. */ ret
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
spinlock: spinlock:
.skip 8 .skip 8

View File

@@ -44,19 +44,22 @@ class BaremetalComponent(common.Component):
uart_address = 0x09000000 uart_address = 0x09000000
os.makedirs(build_dir, exist_ok=True) os.makedirs(build_dir, exist_ok=True)
os.makedirs(common.baremetal_build_lib_dir, exist_ok=True) os.makedirs(common.baremetal_build_lib_dir, exist_ok=True)
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( common.run_cmd(
[gcc, common.Newline] + [gcc, common.Newline] +
cflags + cflags +
[ [
'-c', common.Newline, '-c', common.Newline,
'-o', bootloader_obj, common.Newline, '-o', bootloader_obj, common.Newline,
os.path.join(common.baremetal_src_lib_dir, '{}{}'.format(args.arch, common.asm_ext)), common.Newline, src, common.Newline,
] ]
) )
for src, obj in [ for src, obj in [
(common_src, common_obj), (common_src, common_obj),
(syscalls_src, syscalls_obj), (syscalls_src, syscalls_obj),
]: ]:
if common.need_rebuild([src], obj):
common.run_cmd( common.run_cmd(
[gcc, common.Newline] + [gcc, common.Newline] +
cflags + cflags +
@@ -137,37 +140,38 @@ Build the baremetal examples with crosstool-NG.
in_dir = os.path.join(common.baremetal_src_dir, subpath) in_dir = os.path.join(common.baremetal_src_dir, subpath)
out_dir = os.path.join(common.baremetal_build_dir, subpath) out_dir = os.path.join(common.baremetal_build_dir, subpath)
os.makedirs(out_dir, exist_ok=True) os.makedirs(out_dir, exist_ok=True)
common_objs = common_objs.copy()
if bootloader: if bootloader:
bootloader_cmd = [bootloader_obj, common.Newline] common_objs.append(bootloader_obj)
else:
bootloader_cmd = []
for in_basename in os.listdir(in_dir): for in_basename in os.listdir(in_dir):
in_path = os.path.join(in_dir, in_basename) 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): 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] in_name = os.path.splitext(in_basename)[0]
main_obj = os.path.join(common.baremetal_build_dir, subpath, '{}{}'.format(in_name, common.obj_ext)) main_obj = os.path.join(common.baremetal_build_dir, subpath, '{}{}'.format(in_name, common.obj_ext))
src = os.path.join(common.baremetal_src_dir, in_path)
if common.need_rebuild([src], main_obj):
common.run_cmd( common.run_cmd(
[gcc, common.Newline] + [gcc, common.Newline] +
cflags + cflags +
[ [
'-c', common.Newline, '-c', common.Newline,
'-o', main_obj, common.Newline, '-o', main_obj, common.Newline,
os.path.join(common.baremetal_src_dir, in_path), 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( common.run_cmd(
[gcc, common.Newline] + [gcc, common.Newline] +
cflags + cflags +
[ [
'-Wl,--section-start=.text={:#x}'.format(entry_address), common.Newline, '-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, '-o', out, common.Newline,
'-T', os.path.join(common.baremetal_src_dir, 'link.ld'), common.Newline, '-T', link_script, common.Newline,
] + ] +
bootloader_cmd + common.add_newlines(objs)
common.add_newlines(common_objs) +
[
main_obj, common.Newline,
]
) )
if __name__ == '__main__': if __name__ == '__main__':

View File

@@ -193,6 +193,39 @@ def write_string_to_file(path, string, mode='w'):
with open(path, 'a') as f: with open(path, 'a') as f:
f.write(string) 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): def copy_dir_if_update_non_recursive(srcdir, destdir, filter_ext=None):
# TODO print rsync equivalent. # TODO print rsync equivalent.
os.makedirs(destdir, exist_ok=True) os.makedirs(destdir, exist_ok=True)
@@ -207,6 +240,11 @@ def copy_dir_if_update_non_recursive(srcdir, destdir, filter_ext=None):
update=1, 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(): def gem_list_checkpoint_dirs():
''' '''
List checkpoint directory, oldest first. List checkpoint directory, oldest first.
@@ -475,38 +513,13 @@ def make_run_dirs():
os.makedirs(common.p9_dir, exist_ok=True) os.makedirs(common.p9_dir, exist_ok=True)
os.makedirs(common.qemu_run_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): def need_rebuild(srcs, dst):
''' if not os.path.exists(dst):
Format a command given as a list of strings so that it can return True
be viewed nicely and executed by bash directly and print it to stdout. for src in srcs:
''' if os.path.getmtime(src) > os.path.getmtime(dst):
last_newline = ' \\\n' return True
newline_separator = last_newline + ' ' return False
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 print_cmd(cmd, cwd=None, cmd_file=None, extra_env=None, extra_paths=None): 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())) argcopy.__dict__ = dict(list(defaults.items()) + list(argcopy.__dict__.items()) + list(extra_args.items()))
return argcopy return argcopy
def cp(src, dest):
print_cmd(['cp', src, dest])
if not common.dry_run:
shutil.copy2(src, dest)
def rmrf(path): def rmrf(path):
print_cmd(['rm', '-r', '-f', path]) print_cmd(['rm', '-r', '-f', path])
if not common.dry_run and os.path.exists(path): if not common.dry_run and os.path.exists(path):