3.10.1.1. CONFIG_PID_IN_CONTEXTIDR
https://stackoverflow.com/questions/54133479/accessing-logical-software-thread-id-in-gem5 on ARM the kernel can store an indication of PID in the CONTEXTIDR_EL1 register, making that much easier to observe from simulators.
In particular, gem5 prints that number out by default on ExecAll
messages!
Let’s test it out with Linux kernel build variants + gem5 checkpoint restore and run a different script:
./build-linux --arch aarch64 --linux-build-id CONFIG_PID_IN_CONTEXTIDR --config 'CONFIG_PID_IN_CONTEXTIDR=y' # Checkpoint run. ./run --arch aarch64 --emulator gem5 --linux-build-id CONFIG_PID_IN_CONTEXTIDR --eval './gem5.sh' # Trace run. ./run \ --arch aarch64 \ --emulator gem5 \ --gem5-readfile 'posix/getpid.out; posix/getpid.out' \ --gem5-restore 1 \ --linux-build-id CONFIG_PID_IN_CONTEXTIDR \ --trace FmtFlag,ExecAll,-ExecSymbol \ ;
The terminal runs both programs which output their PID to stdout:
pid=44 pid=45
By quickly inspecting the trace.txt
file, we immediately notice that the system.cpu: A<n>
part of the logs, which used to always be system.cpu: A0
, now has a few different values! Nice!
We can briefly summarize those values by removing repetitions:
cut -d' ' -f4 "$(./getvar --arch aarch64 --emulator gem5 trace_txt_file)" | uniq -c
gives:
97227 A39 147476 A38 222052 A40 1 terminal 1117724 A40 27529 A31 43868 A40 27487 A31 138349 A40 13781 A38 231246 A40 25536 A38 28337 A40 214799 A38 963561 A41 92603 A38 27511 A31 224384 A38 564949 A42 182360 A38 729009 A43 8398 A23 20200 A10 636848 A43 187995 A44 27529 A31 70071 A44 16981 A0 623806 A44 16981 A0 139319 A44 24487 A0 174986 A44 25420 A0 89611 A44 16981 A0 183184 A44 24728 A0 89608 A44 17226 A0 899075 A44 24974 A0 250608 A44 137700 A43 1497997 A45 227485 A43 138147 A38 482646 A46
I’m not smart enough to be able to deduce all of those IDs, but we can at least see that:
-
A44 and A45 are there as expected from stdout!
-
A39 must be the end of the execution of
m5 checkpoint
-
so we guess that A38 is the shell as it comes next
-
the weird "terminal" line is
336969745500: system.terminal: attach terminal 0
-
which is the shell PID? I should have printed that as well :-)
-
why are there so many other PIDs? This was supposed to be a silent system without daemons!
-
A0 is presumably the kernel. However we see process switches without going into A0, so I’m not sure how, it appears to count kernel instructions as part of processes
-
A46 has to be the
m5 exit
call
Or if you want to have some real fun, try: baremetal/arch/aarch64/contextidr_el1.c:
./run --arch aarch64 --emulator gem5 --baremetal baremetal/arch/aarch64/contextidr_el1.c --trace-insts-stdout
in which we directly set the register ourselves! Output excerpt:
31500: system.cpu: A0 T0 : @main+12 : ldr x0, [sp, #12] : MemRead : D=0x0000000000000001 A=0x82fffffc flags=(IsInteger|IsMemRef|IsLoad) 32000: system.cpu: A1 T0 : @main+16 : msr contextidr_el1, x0 : IntAlu : D=0x0000000000000001 flags=(IsInteger|IsSerializeAfter|IsNonSpeculative) 32500: system.cpu: A1 T0 : @main+20 : ldr x0, [sp, #12] : MemRead : D=0x0000000000000001 A=0x82fffffc flags=(IsInteger|IsMemRef|IsLoad) 33000: system.cpu: A1 T0 : @main+24 : add w0, w0, #1 : IntAlu : D=0x0000000000000002 flags=(IsInteger) 33500: system.cpu: A1 T0 : @main+28 : str x0, [sp, #12] : MemWrite : D=0x0000000000000002 A=0x82fffffc flags=(IsInteger|IsMemRef|IsStore) 34000: system.cpu: A1 T0 : @main+32 : ldr x0, [sp, #12] : MemRead : D=0x0000000000000002 A=0x82fffffc flags=(IsInteger|IsMemRef|IsLoad) 34500: system.cpu: A1 T0 : @main+36 : subs w0, #9 : IntAlu : D=0x0000000000000000 flags=(IsInteger) 35000: system.cpu: A1 T0 : @main+40 : b.le <main+12> : IntAlu : flags=(IsControl|IsDirectControl|IsCondControl) 35500: system.cpu: A1 T0 : @main+12 : ldr x0, [sp, #12] : MemRead : D=0x0000000000000002 A=0x82fffffc flags=(IsInteger|IsMemRef|IsLoad) 36000: system.cpu: A2 T0 : @main+16 : msr contextidr_el1, x0 : IntAlu : D=0x0000000000000002 flags=(IsInteger|IsSerializeAfter|IsNonSpeculative) 36500: system.cpu: A2 T0 : @main+20 : ldr x0, [sp, #12] : MemRead : D=0x0000000000000002 A=0x82fffffc flags=(IsInteger|IsMemRef|IsLoad) 37000: system.cpu: A2 T0 : @main+24 : add w0, w0, #1 : IntAlu : D=0x0000000000000003 flags=(IsInteger) 37500: system.cpu: A2 T0 : @main+28 : str x0, [sp, #12] : MemWrite : D=0x0000000000000003 A=0x82fffffc flags=(IsInteger|IsMemRef|IsStore) 38000: system.cpu: A2 T0 : @main+32 : ldr x0, [sp, #12] : MemRead : D=0x0000000000000003 A=0x82fffffc flags=(IsInteger|IsMemRef|IsLoad) 38500: system.cpu: A2 T0 : @main+36 : subs w0, #9 : IntAlu : D=0x0000000000000000 flags=(IsInteger) 39000: system.cpu: A2 T0 : @main+40 : b.le <main+12> : IntAlu : flags=(IsControl|IsDirectControl|IsCondControl) 39500: system.cpu: A2 T0 : @main+12 : ldr x0, [sp, #12] : MemRead : D=0x0000000000000003 A=0x82fffffc flags=(IsInteger|IsMemRef|IsLoad) 40000: system.cpu: A3 T0 : @main+16 : msr contextidr_el1, x0 : IntAlu : D=0x0000000000000003 flags=(IsInteger|IsSerializeAfter|IsNonSpeculative)
ARMv8 architecture reference manual db D13.2.27 "CONTEXTIDR_EL1, Context ID Register (EL1)" documents CONTEXTIDR_EL1
as:
Identifies the current Process Identifier.
The value of the whole of this register is called the Context ID and is used by:
The debug logic, for Linked and Unlinked Context ID matching.
The trace logic, to identify the current process.
The significance of this register is for debug and trace use only.
Tested on 145769fc387dc5ee63ec82e55e6b131d9c968538 + 1.