ARM64 CPU 特性寄存器

作者:Suzuki K Poulose <suzuki.poulose@arm.com>

此文件描述了将 AArch64 CPU ID/特性寄存器导出到用户空间的 ABI。此 ABI 的可用性通过 HWCAP 中的 HWCAP_CPUID 进行通告。

1. 动机

ARM 架构定义了一组特性寄存器,这些寄存器描述了 CPU/系统的功能。对这些系统寄存器的访问受到 EL0 的限制,并且应用程序没有可靠的方法来提取此信息以在运行时做出更好的决策。通过 HWCAP,应用程序可以使用有限的信息,但是它们的使用存在一些问题。

  1. 对 HWCAP 的任何更改都需要更新用户空间(例如,libc)以检测新的更改,这可能需要很长时间才能在发行版中出现。公开寄存器允许应用程序获取信息,而无需更新工具链。

  2. 对 HWCAP 的访问有时受到限制(例如,在 libc 之前,或在启动时初始化 ld 时)。

  3. HWCAP 不能有效地表示非布尔信息。该架构为在 ID 寄存器中表示特性定义了规范格式;它是明确定义的,并且能够表示所有有效的架构变体。

2. 要求

  1. 安全性

    应用程序应该能够使用基础设施提供的信息在系统中安全运行。这对于具有异构 CPU 的系统具有更大的影响。该基础设施导出一个在系统上所有可用 CPU 中都安全的值。

    例如,如果至少一个 CPU 没有实现 CRC32 指令,而其他 CPU 实现了,我们应该报告未实现 CRC32。否则,当调度到不支持 CRC32 的 CPU 上时,应用程序可能会崩溃。

  2. 安全性

    应用程序应该只能接收与用户空间中正常操作相关的信息。因此,某些字段被屏蔽(即,变为不可见),并且它们的值被设置为指示该特性“不受支持”。有关可见特性的列表,请参阅第 4 节。此外,内核可能会根据它支持的内容来操作字段。例如,如果内核不支持 FP,则这些值可能表明 FP 不可用(即使 CPU 提供了它)。

  3. 实现定义的特性

    根据 ARMv8-A 架构,该基础设施不公开任何定义为“实现定义”的寄存器。

  4. CPU 标识

    公开 MIDR_EL1 以帮助识别处理器。在异构系统上,这可能是竞争的(就像 getcpu() 一样)。除非设置了 CPU 亲缘性,否则该进程可能会在它使用寄存器值时迁移到另一个 CPU。因此,不能保证该值反映它当前正在执行的处理器。由于此限制,REVIDR 不会公开,因为 REVIDR 仅在与 MIDR 结合使用时才有意义。或者,MIDR_EL1 和 REVIDR_EL1 通过 sysfs 在

    /sys/devices/system/cpu/cpu$ID/regs/identification/
                                                  \- midr
                                                  \- revidr
    

3. 实现

该基础设施基于对“MRS”指令的模拟。从应用程序访问受限的系统寄存器会生成一个异常,并最终将 SIGILL 传递给进程。如果源属于支持的系统寄存器空间,则该基础设施会挂钩到异常处理程序并模拟该操作。

该基础设施仅模拟以下系统寄存器空间

Op0=3, Op1=0, CRn=0, CRm=0,2,3,4,5,6,7

(有关寄存器列表,请参阅 ARMv8 ARM DDI 0487A.h 中的表 C5-6“非调试系统寄存器访问的系统指令编码”)。

以下规则适用于基础设施返回的值

  1. “实现定义”字段的值设置为 0。

  2. 保留字段的值将填充架构定义的保留值。

  3. “可见”字段的值保存特定特性的系统范围安全值(MIDR_EL1 除外,请参见第 4 节)。

  4. 所有其他字段(即,不可见字段)都设置为指示该特性缺失(由架构定义)。

4. 具有可见特性的寄存器列表

  1. ID_AA64ISAR0_EL1 - 指令集属性寄存器 0

    名称

    可见

    RNDR

    [63-60]

    TS

    [55-52]

    FHM

    [51-48]

    DP

    [47-44]

    SM4

    [43-40]

    SM3

    [39-36]

    SHA3

    [35-32]

    RDM

    [31-28]

    原子操作

    [23-20]

    CRC32

    [19-16]

    SHA2

    [15-12]

    SHA1

    [11-8]

    AES

    [7-4]

  2. ID_AA64PFR0_EL1 - 处理器特性寄存器 0

    名称

    可见

    DIT

    [51-48]

    MPAM

    [43-40]

    SVE

    [35-32]

    GIC

    [27-24]

    AdvSIMD

    [23-20]

    FP

    [19-16]

    EL3

    [15-12]

    EL2

    [11-8]

    EL1

    [7-4]

    EL0

    [3-0]

  3. ID_AA64PFR1_EL1 - 处理器特性寄存器 1

    名称

    可见

    SME

    [27-24]

    MTE

    [11-8]

    SSBS

    [7-4]

    BT

    [3-0]

  4. MIDR_EL1 - 主 ID 寄存器

    名称

    可见

    实现者

    [31-24]

    变体

    [23-20]

    架构

    [19-16]

    部件号

    [15-4]

    修订

    [3-0]

注意:MIDR_EL1 的“可见”字段将包含从其获取的 CPU 上可用的值,而不是系统范围的安全值。

  1. ID_AA64ISAR1_EL1 - 指令集属性寄存器 1

    名称

    可见

    I8MM

    [55-52]

    DGH

    [51-48]

    BF16

    [47-44]

    SB

    [39-36]

    FRINTTS

    [35-32]

    GPI

    [31-28]

    GPA

    [27-24]

    LRCPC

    [23-20]

    FCMA

    [19-16]

    JSCVT

    [15-12]

    API

    [11-8]

    APA

    [7-4]

    DPB

    [3-0]

  2. ID_AA64MMFR0_EL1 - 内存模型特性寄存器 0

    名称

    可见

    ECV

    [63-60]

  3. ID_AA64MMFR2_EL1 - 内存模型特性寄存器 2

    名称

    可见

    AT

    [35-32]

  4. ID_AA64ZFR0_EL1 - SVE 特性 ID 寄存器 0

    名称

    可见

    F64MM

    [59-56]

    F32MM

    [55-52]

    I8MM

    [47-44]

    SM4

    [43-40]

    SHA3

    [35-32]

    B16B16

    [27-24]

    BF16

    [23-20]

    BitPerm

    [19-16]

    AES

    [7-4]

    SVEVer

    [3-0]

  1. ID_AA64MMFR1_EL1 - 内存模型特性寄存器 1

    名称

    可见

    AFP

    [47-44]

  2. ID_AA64ISAR2_EL1 - 指令集属性寄存器 2

    名称

    可见

    CSSC

    [55-52]

    RPRFM

    [51-48]

    BC

    [23-20]

    MOPS

    [19-16]

    APA3

    [15-12]

    GPA3

    [11-8]

    RPRES

    [7-4]

    WFXT

    [3-0]

  3. MVFR0_EL1 - AArch32 媒体和 VFP 特性寄存器 0

名称

可见

FPDP

[11-8]

  1. MVFR1_EL1 - AArch32 媒体和 VFP 特性寄存器 1

名称

可见

SIMDFMAC

[31-28]

SIMDSP

[19-16]

SIMDInt

[15-12]

SIMDLS

[11-8]

  1. ID_ISAR5_EL1 - AArch32 指令集属性寄存器 5

名称

可见

CRC32

[19-16]

SHA2

[15-12]

SHA1

[11-8]

AES

[7-4]

附录 I:示例

/*
 * Sample program to demonstrate the MRS emulation ABI.
 *
 * Copyright (C) 2015-2016, ARM Ltd
 *
 * Author: Suzuki K Poulose <[email protected]>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#include <asm/hwcap.h>
#include <stdio.h>
#include <sys/auxv.h>

#define get_cpu_ftr(id) ({                                    \
              unsigned long __val;                            \
              asm("mrs %0, "#id : "=r" (__val));              \
              printf("%-20s: 0x%016lx\n", #id, __val);        \
      })

int main(void)
{

      if (!(getauxval(AT_HWCAP) & HWCAP_CPUID)) {
              fputs("CPUID registers unavailable\n", stderr);
              return 1;
      }

      get_cpu_ftr(ID_AA64ISAR0_EL1);
      get_cpu_ftr(ID_AA64ISAR1_EL1);
      get_cpu_ftr(ID_AA64MMFR0_EL1);
      get_cpu_ftr(ID_AA64MMFR1_EL1);
      get_cpu_ftr(ID_AA64PFR0_EL1);
      get_cpu_ftr(ID_AA64PFR1_EL1);
      get_cpu_ftr(ID_AA64DFR0_EL1);
      get_cpu_ftr(ID_AA64DFR1_EL1);

      get_cpu_ftr(MIDR_EL1);
      get_cpu_ftr(MPIDR_EL1);
      get_cpu_ftr(REVIDR_EL1);

#if 0
      /* Unexposed register access causes SIGILL */
      get_cpu_ftr(ID_MMFR0_EL1);
#endif

      return 0;
}