24.15. gem5 simulate() limit reached

This error happens when the following instruction limits are reached:

system.cpu[0].max_insts_all_threads
system.cpu[0].max_insts_any_thread

If the parameter is not set, it defaults to 0, which is magic and means the huge maximum value of uint64_t: 0xFFFFFFFFFFFFFFFF, which in practice would require a very long simulation if at least one CPU were live.

So this usually means all CPUs are in a sleep state, and no events are scheduled in the future, which usually indicates a bug in either gem5 or guest code, leading gem5 to blow up.

Still, fs.py at gem5 08c79a194d1a3430801c04f37d13216cc9ec1da3 does not exit with non-zero status due to this…​ and so we just parse it out just as for m5 fail…​

A trivial and very direct way to see message would be:

./run \
  --emulator gem5 \
  --userland userland/arch/x86_64/freestanding/linux/hello.S \
  --trace-insts-stdout \
  -- \
  --param 'system.cpu[0].max_insts_all_threads = 3' \
;

which as of lkmc 402059ed22432bb351d42eb10900e5a8e06aa623 runs only the first three instructions and quits!

info: Entering event queue @ 0.  Starting simulation...
      0: system.cpu A0 T0 : @asm_main_after_prologue    : mov   rdi, 0x1
      0: system.cpu A0 T0 : @asm_main_after_prologue.0  :   MOV_R_I : limm   rax, 0x1 : IntAlu :  D=0x0000000000000001  flags=(IsInteger|IsMicroop|IsLastMicroop|IsFirstMicroop)
   1000: system.cpu A0 T0 : @asm_main_after_prologue+7    : mov rdi, 0x1
   1000: system.cpu A0 T0 : @asm_main_after_prologue+7.0  :   MOV_R_I : limm   rdi, 0x1 : IntAlu :  D=0x0000000000000001  flags=(IsInteger|IsMicroop|IsLastMicroop|IsFirstMicroop)
   2000: system.cpu A0 T0 : @asm_main_after_prologue+14    : lea        rsi, DS:[rip + 0x19]
   2000: system.cpu A0 T0 : @asm_main_after_prologue+14.0  :   LEA_R_P : rdip   t7, %ctrl153,  : IntAlu :  D=0x000000000040008d  flags=(IsInteger|IsMicroop|IsDelayedCommit|IsFirstMicroop)
   2500: system.cpu A0 T0 : @asm_main_after_prologue+14.1  :   LEA_R_P : lea   rsi, DS:[t7 + 0x19] : IntAlu :  D=0x00000000004000a6  flags=(IsInteger|IsMicroop|IsLastMicroop)
Exiting @ tick 3000 because all threads reached the max instruction count

The exact same can be achieved with the older hardcoded --maxinsts mechanism present in se.py and fs.py:

./run \
  --emulator gem5 \
  --userland \userland/arch/x86_64/freestanding/linux/hello.S \
  --trace-insts-stdout \
  -- \
  --maxinsts 3
;

Other related fs.py options are:

  • --abs-max-tick: set the maximum guest simulation time. The same scale as the ExecAll trace is used. E.g., for the above example with 3 instructions, the same trace would be achieved with a value of 3000.

The message also shows on User mode simulation deadlocks, for example in userland/posix/pthread_deadlock.c:

./run \
  --emulator gem5 \
  --userland userland/posix/pthread_deadlock.c \
  --cli-args 1 \
;

ends in:

Exiting @ tick 18446744073709551615 because simulate() limit reached

where 18446744073709551615 is 0xFFFFFFFFFFFFFFFF in decimal.

And there is a Baremetal example at baremetal/arch/aarch64/no_bootloader/wfe_loop.S that dies on WFE:

./run \
  --arch aarch64 \
  --baremetal baremetal/arch/aarch64/no_bootloader/wfe_loop.S \
  --emulator gem5 \
  --trace-insts-stdout \
;

which gives:

info: Entering event queue @ 0.  Starting simulation...
      0: system.cpu A0 T0 : @lkmc_start    :   wfe                      : IntAlu :  D=0x0000000000000000  flags=(IsSerializeAfter|IsNonSpeculative|IsQuiesce|IsUnverifiable)
   1000: system.cpu A0 T0 : @lkmc_start+4    :   b   <lkmc_start>         : IntAlu :   flags=(IsControl|IsDirectControl|IsUncondControl)
   1500: system.cpu A0 T0 : @lkmc_start    :   wfe                      : IntAlu :  D=0x0000000000000000  flags=(IsSerializeAfter|IsNonSpeculative|IsQuiesce|IsUnverifiable)
Exiting @ tick 18446744073709551615 because simulate() limit reached

Other examples of the message: