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 exitcall
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.