【问题标题】:What is the purpose of Thread ID registers like TPIDR_EL0/TPIDR_EL1 in ARM?ARM 中 TPIDR_EL0/TPIDR_EL1 等线程 ID 寄存器的用途是什么?
【发布时间】:2021-02-27 13:34:54
【问题描述】:

根据ARM documentation,线程ID注册为TPIDR_EL0TPIDR_EL1

提供存储软件线程和进程 ID 的位置 用于操作系统管理目的。这些寄存器对 处理器行为。

为什么有人想将线程 ID 存储在一个特殊的寄存器中? ARM 处理器是否需要线程在内存中具有特殊的结构,就像 MMU 一样?线程对 ARM 来说是不是特别的东西,是 ARM 期望在某个地方找到的东西?或者我可以在不使用这个寄存器的情况下(有效地)实现线程吗?

我之所以问,是因为我在 Fuchsia OS 的 Zircon Kernel 上找到了这段代码:

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

在启动时它会创建一个线程并将其指针存储在tpidr_el1

【问题讨论】:

  • 操作系统需要记住当前在给定(逻辑)CPU 中运行的线程/进程。它需要一个 CPU 寄存器,该寄存器只能在管理员模式下更改,并且可以指定一个内存区域。在 x86 上是 fsgs 寄存器,ARM 有 TPIDR_ELx。每个 CPU 的内存区域是必要的,因为内核代码可以在任何 CPU 上同等运行(因此代码相同,但指针不同)。
  • @MargaretBloom 说得通,谢谢
  • 线程本地数据可以通过EL1进行索引。就像“PIC”一样,您可以拥有“静态基础”代码。所有全局变量都相对于固定寄存器进行引用。线程的实现类似于“静态基础”。但是,进程中的所有线程都可以对全局变量使用绝对寻址(在线程之间共享),但它们将 EL1 用于“线程局部”变量。切换线程只涉及更改此寄存器(可以在用户空间中完成),但操作系统需要在上下文切换时记录活动线程。当涉及到管理程序时,它必须被捕获。

标签: arm kernel cpu armv8 fuchsia


【解决方案1】:

与用户空间中的线程本地存储相关的所有内容都需要保存在每个线程的结构中。您需要将此结构的地址保存在某处。在 armv8 中,TPIDR_EL0 可用于此目的。在 x86_64 中,fs 段寄存器通常被重新用于此用途。

Fuchsia 的 ABI for Thread-Local Storage 记录在他们的网站上。

在紫红色中,TPIDR_EL0 将为您提供pthread structure。请参阅 __allocate_thread 了解如何分配部分内存。

一个用法示例(线程局部变量除外)是SafeStack feature,它将第二个堆栈指针存储在 pthread 结构中。

对于内核,在 armv8 中,TPIDR_EL1 用于类似目的,用于保存内核 Thread structure 的指针。

请注意,在 armv8 中,有一个用于 EL0(用户空间)和 EL1 (内核空间)的寄存器。在 x86-64 中,没有分离,处理起来有点尴尬:内核内部有一个地方来存储 gs 寄存器的“内核版本”,并使用swapgs 指令在用户空间和内核空间 gs 之间切换注册。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-15
    • 2013-07-20
    • 2012-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-11
    • 2021-10-01
    相关资源
    最近更新 更多