# Linux Kernel Module Cheat

##### 24.22.4.1. gem5 event queue AtomicSimpleCPU syscall emulation freestanding example analysis

Let’s now analyze every single event on a minimal gem5 syscall emulation mode in the simplest CPU that we have:

    ./run \
      --arch aarch64 \
      --emulator gem5 \
      --userland userland/arch/aarch64/freestanding/linux/hello.S \
      --trace Event,ExecAll,FmtFlag \
      --trace-stdout \
    ;

which gives:

          0: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 scheduled @ 0
    **** REAL SIMULATION ****
          0: Event: Event_70: generic 70 scheduled @ 0
    info: Entering event queue @ 0.  Starting simulation...
          0: Event: Event_70: generic 70 rescheduled @ 18446744073709551615
          0: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 executed @ 0
          0: ExecEnable: system.cpu: A0 T0 : @asm_main_after_prologue    :   movz   x0, #1, #0        : IntAlu :  D=0x0000000000000001  flags=(IsInteger)
          0: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 rescheduled @ 500
        500: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 executed @ 500
        500: ExecEnable: system.cpu: A0 T0 : @asm_main_after_prologue+4    :   adr   x1, #28            : IntAlu :  D=0x0000000000400098  flags=(IsInteger)
        500: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 rescheduled @ 1000
       1000: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 executed @ 1000
       1000: ExecEnable: system.cpu: A0 T0 : @asm_main_after_prologue+8    :   ldr   w2, #4194464       : MemRead :  D=0x0000000000000006 A=0x4000a0  flags=(IsInteger|IsMemRef|IsLoad)
       1000: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 rescheduled @ 1500
       1500: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 executed @ 1500
       1500: ExecEnable: system.cpu: A0 T0 : @asm_main_after_prologue+12    :   movz   x8, #64, #0       : IntAlu :  D=0x0000000000000040  flags=(IsInteger)
       1500: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 rescheduled @ 2000
       2000: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 executed @ 2000
       2000: ExecEnable: system.cpu: A0 T0 : @asm_main_after_prologue+16    :   svc   #0x0               : IntAlu :   flags=(IsSerializeAfter|IsNonSpeculative|IsSyscall)
    hello
       2000: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 rescheduled @ 2500
       2500: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 executed @ 2500
       2500: ExecEnable: system.cpu: A0 T0 : @asm_main_after_prologue+20    :   movz   x0, #0, #0        : IntAlu :  D=0x0000000000000000  flags=(IsInteger)
       2500: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 rescheduled @ 3000
       3000: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 executed @ 3000
       3000: ExecEnable: system.cpu: A0 T0 : @asm_main_after_prologue+24    :   movz   x8, #93, #0       : IntAlu :  D=0x000000000000005d  flags=(IsInteger)
       3000: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 rescheduled @ 3500
       3500: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 executed @ 3500
       3500: ExecEnable: system.cpu: A0 T0 : @asm_main_after_prologue+28    :   svc   #0x0               : IntAlu :   flags=(IsSerializeAfter|IsNonSpeculative|IsSyscall)
       3500: Event: Event_71: generic 71 scheduled @ 3500
       3500: Event: Event_71: generic 71 executed @ 3500

On the event trace, we can first see:

    0: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 scheduled @ 0

This schedules a tick event for time `0`, and leads to the first clock tick.

Then:

    0: Event: Event_70: generic 70 scheduled @ 0
    0: Event: Event_70: generic 70 rescheduled @ 18446744073709551615

schedules the end of time event for time `0`, which is later rescheduled to the actual end of time.

At:

    0: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 executed @ 0
    0: ExecEnable: system.cpu: A0 T0 : @asm_main_after_prologue    :   movz   x0, #1, #0        : IntAlu :  D=0x0000000000000001  flags=(IsInteger)
    0: Event: AtomicSimpleCPU tick.wrapped_function_event: EventFunctionWrapped 39 rescheduled @ 500

the tick event happens, the instruction runs, and then the instruction is rescheduled in `500` time units. This is done at the end of `AtomicSimpleCPU::tick()`:

    if (_status != Idle)
        reschedule(tickEvent, curTick() + latency, true);

At:

    3500: ExecEnable: system.cpu: A0 T0 : @asm_main_after_prologue+28    :   svc   #0x0               : IntAlu :   flags=(IsSerializeAfter|IsNonSpeculative|IsSyscall)
    3500: Event: Event_71: generic 71 scheduled @ 3500
    3500: Event: Event_71: generic 71 executed @ 3500

the exit system call is called, and then it schedules an exit evit, which gets executed and the simulation ends.

We guess then that `Event_71` comes from the SE implementation of the exit syscall, so let’s just confirm, the trace contains:

    exitSimLoop() at sim_events.cc:97 0x5555594746e0
    exitImpl() at syscall_emul.cc:215 0x55555948c046
    exitFunc() at syscall_emul.cc:225 0x55555948c147
    SyscallDesc::doSyscall() at syscall_desc.cc:72 0x5555594949b6
    Process::syscall() at process.cc:401 0x555559484717
    SimpleThread::syscall() at 0x555559558059
    ArmISA::SupervisorCall::invoke() at faults.cc:856 0x5555572950d7
    BaseSimpleCPU::advancePC() at base.cc:681 0x555559083133
    AtomicSimpleCPU::tick() at atomic.cc:757 0x55555907834c

and `exitSimLoop()` does:

    new GlobalSimLoopExitEvent(when + simQuantum, message, exit_code, repeat);

Tested in gem5 12c917de54145d2d50260035ba7fa614e25317a3.

- AtomicSimpleCPU initial events

- AtomicSimpleCPU tick reschedule timing

- AtomicSimpleCPU memory access

- gem5 se.py page translation