11.7.5. gem5 syscall emulation multiple executables

gem5 syscall emulation has the nice feature of allowing you to run multiple executables "at once".

Each executable starts running on the next free core much as if it had been forked right at the start of simulation: gem5 syscall emulation multithreading.

This can be useful to quickly create deterministic multi-CPU workload.

se.py --cmd takes a semicolon separated list, so we could do which LKMC exposes this by taking --userland multiple times as in:

./run \
  --arch aarch64 \
  --cpus 2 \
  --emulator gem5 \
  --userland userland/posix/getpid.c \
  --userland userland/posix/getpid.c \
;

We need at least one CPU per executable, just like when forking new processes.

The outcome of this is that we see two different pid messages printed to stdout:

pid=101
pid=100

since from gem5 Process we can see that se.py sets up one different PID per executable starting at 100:

    workloads = options.cmd.split(';')
    idx = 0
    for wrkld in workloads:
        process = Process(pid = 100 + idx)

We can also see that these processes are running concurrently with gem5 tracing by hacking:

  --debug-flags ExecAll \
  --debug-file cout \

which starts with:

      0: system.cpu1: A0 T0 : @__end__+274873647040    :   add   x0, sp, #0         : IntAlu :  D=0x0000007ffffefde0  flags=(IsInteger)
      0: system.cpu0: A0 T0 : @__end__+274873647040    :   add   x0, sp, #0         : IntAlu :  D=0x0000007ffffefde0  flags=(IsInteger)
    500: system.cpu0: A0 T0 : @__end__+274873647044    :   bl   <__end__+274873649648> : IntAlu :  D=0x0000004000001008  flags=(IsInteger|IsControl|IsDirectControl|IsUncondControl|IsCall)
    500: system.cpu1: A0 T0 : @__end__+274873647044    :   bl   <__end__+274873649648> : IntAlu :  D=0x0000004000001008  flags=(IsInteger|IsControl|IsDirectControl|IsUncondControl|IsCall)

and therefore shows one instruction running on each CPU for each process at the same time.