armkernelcpuarmv8fuchsia

What is the purpose of Thread ID registers like TPIDR_EL0/TPIDR_EL1 in ARM?


According to ARM documentation, the thread ID registers like TPIDR_EL0 or TPIDR_EL1,

Provide locations to store the IDs of software threads and processes for OS management purposes. These registers have no effect on processor behavior.

Why would someone want to store the thread ID in a special register? Do ARM processors require threads to have special structures in memory just like the MMU has? Is a Thread something special to ARM, something ARM expect to find somewhere? Or can I implement threads (efficiently) without using this register at all?

I'm asking because I found this code on the Zircon Kernel from Fuchsia OS:

static inline void arch_set_current_thread(Thread* t) {
  __arm_wsr64("tpidr_el1", (uint64_t)&t->arch_.thread_pointer_location);
  __isb(ARM_MB_SY);
}

Right at boot it creates a thread and stores its pointer in tpidr_el1


Solution

  • Everything related to thread-local storage in userspace needs to be kept in a per-thread structure. You need to keep the address of this structure somewhere. In armv8, TPIDR_EL0 can be used for this purpose. In x86_64, typically the fs segment register was repurposed for this usage.

    Fuchsia's ABI for Thread-Local Storage is documented in their website.

    In fuchsia, the TPIDR_EL0 will get you the pthread structure. See __allocate_thread for how some of this memory is allocated.

    One usage example (other than thread-local variables), is the SafeStack feature, which stores a second stack pointer in the pthread structure.

    For the kernel, in armv8, TPIDR_EL1 is used, for a similar purpose, to hold a pointer for the kernel Thread structure.

    Note that in armv8, there's a register for EL0 (userspace) and EL1 (kernelspace). In x86-64, there's no separation, and the handling is kind of awkward: the kernel has an internal place to store the "kernel version" of the gs register, and uses the swapgs instruction to change between the userspace and kernelspace gs registers.