【问题标题】:Any CPUID like instruction in armv8?armv8中是否有类似CPUID的指令?
【发布时间】:2021-02-28 00:09:46
【问题描述】:

所以我在汇编 ARMv8 中编程,我想知道是否有任何指令,比如在 x86 中,来恢复有关 CPU 的信息。这是我需要的信息:

(CPUID)签名:660f01

(CPUID) 特性:MMX、AMD64、SSE、SSE2、SSE3、SSSE3、SSE4.1、SSE4.2、AES、AVX、CLMUL、FMA、FMA4、XOP、PSE、PSE-36、NX、SVM

(CPUID) 缓存 L1:4 x 32 KB 数据,4 x 96 KB 指令 (CPUID) 缓存 L2:4 x 1 MB 统一 (CPUID) 缓存 L3:无

或者类似的东西。例如,我知道 ARMS 不支持 MMX,但它支持 NEON。如何检查该处理器是否支持它?

【问题讨论】:

  • 有这样的事情。检查架构参考手册。不幸的是,我不知道细节。
  • 只需在架构参考手册中查找 CPUID。
  • @old_timer:我这样做了,但唯一的点击似乎是指 AArch32,如果没有更多背景,很难理解。
  • 好吧,它是一系列寄存器,可以为您提供大量 cpu 信息、什么样的指令或有时可用的特定指令等。
  • 是的,但是很难消化在哪里可以找到什么,而且我没有看到任何看起来直接等同于英特尔 CPUID 的东西。这似乎是一个问题,专家的总结可以为一个人节省大量的跑腿和死胡同

标签: assembly arm armv8


【解决方案1】:

(此答案适用于 AArch64。)

根据一些阅读和实验,您可以使用mrs 指令读取一些系统寄存器以获取有关 CPU 及其功能的信息。对此的参考是 Armv8 架构参考手册;在 K14.3.3 部分有一个 ID 寄存器列表(在我的修订版中,可能不是最新的)。

可能特别感兴趣的一对:

  • MIDR_EL1 包含有关 CPU 的一般信息:实施者(例如 Arm、Broadcom、NVidia)、变体、架构、部件号、修订版。

  • REVIDR_EL1 具有实现修订信息。 (在我的 Raspberry Pi 4 上为零。)

  • IID_AA64_ISAR{0,1}_EL1 有关于在设备上实现了哪些指令的信息:CRC。 SHA、Atomic、随机数等

似乎没有任何东西可以直接与 x86 的 CPUID 生成的人类可读的品牌字符串相媲美。

这是我在 Linux 下使用 gcc 进行测试的一些代码。某些寄存器在用户空间可能不可读并导致异常,因此程序会处理结果信号以便在这种情况下能够继续。

我还不太了解异常级别系统,无法确定它们是否真的直接读取硬件寄存器,或者它们是否会陷入陷阱,以便内核和/或管理程序可以模拟和/或审查结果。

#include <stdio.h>
#include <stdint.h>
#include <setjmp.h>
#include <signal.h>
#include <stdlib.h>

sigjmp_buf go_here;

void sigill_handler(int signum) {
    (void)signum;
    siglongjmp(go_here, 1);
}

#define PRINT_REG(s)                                            \
    do {                                                        \
        if (sigsetjmp(go_here, 1)) {                            \
            printf("%s:\tSIGILL\n", s);                         \
        } else {                                                \
            unsigned long ret;                                  \
            asm("mrs %0, " s : "=r" (ret));                     \
            printf("%s:\t%#lx\n", s, ret);                      \
        }                                                       \
    } while (0)

int main(void) {
    struct sigaction sa;
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = 0;
    sa.sa_handler = sigill_handler;
    if (sigaction(SIGILL, &sa, NULL) < 0) {
        perror("sigaction");
        exit(2);
    }
    
    PRINT_REG("MIDR_EL1");
    PRINT_REG("VPIDR_EL2");
    PRINT_REG("REVIDR_EL1");
    PRINT_REG("ID_AA64ISAR0_EL1");
    PRINT_REG("ID_AA64ISAR1_EL1");
    PRINT_REG("MVFR0_EL1");
    PRINT_REG("MVFR1_EL1");
    PRINT_REG("MVFR2_EL1");
    return 0;
}

【讨论】:

  • 有什么东西可以给我这样的东西吗? (CPUID) 签名:660f01 (CPUID) 特性:MMX、AMD64、SSE、SSE2、SSE3、SSSE3、SSE4.1、SSE4.2、AES、AVX、CLMUL、FMA、FMA4、XOP、PSE、PSE-36、NX , SVM (CPUID) 缓存 L1:4 x 32 KB 数据,4 x 96 KB 指令 (CPUID) 缓存 L2:4 x 1 MB 统一 (CPUID) 缓存 L3:无
  • mrs 是 arm64 状态寄存器,arm 是 vmrs。
  • @MarlonPedersoli Nate 的回答中给出的寄存器提供了这样的信息。您只需要检查各个功能位,例如在 x86 上。将其转换为文本表示是您必须自己编程的事情。
  • 但是mrs不是指令吗?我知道它只返回一些位,我必须自己把它变成文本
  • @MarlonPedersoli 没错,没错。 ARMv8 ARM 解释了哪些位有什么含义。请自己阅读。
【解决方案2】:

arm 中没有任何指令提供 CPU 实现的功能。但是有一些系统寄存器指示 CPU 支持哪些功能。这些通常以 ID_* 开头,例如,ID_AA64PFR0_EL1 是架构处理器功能寄存器。您可以参考 ARM 架构参考手册以获取系统寄存器列表和有关支持的功能的详细信息。这些不能从用户应用程序访问,只能使用 MRS 指令从更高的异常级别访问。另请注意,架构也提供了捕获访问的方法。

【讨论】:

  • 非常感谢。这就是我需要的
【解决方案3】:

您通常只需要检查 NEON 而不是所有个人功能。 aarch64 包括 NEON。 对于 linux 上的 arm32,您通常从 /proc/self/auxv 参见例如https://github.com/steinwurf/cpuid/blob/master/src/cpuid/detail/init_linux_gcc_arm.hpp

在 windows msvc 上,您通常只需要检查ifdef PLATFORM_WINDOWS_PHONE。这保证了NEON。类似于 clang 检查 __ARM_NEON__ 和通过静态定义的各种功能。

有一个状态寄存器,可以从中读取。 我也做了一些特定于手臂的 asm 内在函数,但它们太脆弱了。 https://github.com/simd-everywhere/simde 库可以提供更好的帮助。

【讨论】:

  • 在 ARMv8 上实际上有更多相关的指令集扩展,而不仅仅是 NEON。
  • Linux 如何判断 CPU 能做什么,从而填充/proc/self/auxv/proc/cpuinfo
  • @PeterCordes 在 ARMv7 和更早版本上,Linux 需要编译它,因为显然没有在运行时发现的机制(可能有一种机制仅适用于特权代码,但我不知道详情)
  • @fuz:也许会捕获无效指令异常,然后尝试执行?您可以使用 SIGILL 的信号处理程序在用户空间中执行此操作。但仅适用于您可以通过异常或缺少异常检测的功能,而不是原子性保证之类的东西。 (如果任何 CPU 上有 2 寄存器 ldm...)
  • @PeterCordes 许多未定义的指令在 ARMv7 上是“约束未定义的”,因此很难发现扩展是否存在。此外,处理器可能在指令集中的同一空间中存在多个不兼容的协处理器之一。
猜你喜欢
  • 2013-07-30
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多