代码之家  ›  专栏  ›  技术社区  ›  Mark Adler

如何在AARCH64上检测CRC32

  •  4
  • Mark Adler  · 技术社区  · 6 年前

    有没有可能 用户 AARCH64上的程序检测CRC32指令是否可用?我找到了 references to kernel support 对于这种检测,意味着在用户模式下,具有哪些指令将在用户模式下工作的信息的寄存器在用户模式下不可用(!).

    是这样吗?或者是否有一种便携式方法来确定CRC32指令是否可用?

    注意:我所说的“用户程序”和“可移植”是一种不需要特权指令或操作系统特定调用或文件(例如/proc/cpuinfo)的方法。代码本身需要能够检测指令是否可用,如果可用,就使用它们;如果不可用,就返回到另一个选项。例如,Intel处理器具有 cpuid 用于此目的的说明。

    更新:

    在ARM架构描述中,我发现了一个用户级寄存器, PMCR_EL0 它为处理器提供8位实现者代码和8位ID代码。如果我能找到这些代码的列表,我可能会更接近我正在寻找的代码。

    更新2 :

    但是,当我尝试读取该寄存器时,会得到一个非法的指令异常。所以即使EL0寄存器也需要特权访问?

    3 回复  |  直到 6 年前
        1
  •  2
  •   Adenilson Cavalcanti    6 年前

    据我所知。

    我在Chromium的zlib中实现它的方法是使用可用的操作系统功能: https://cs.chromium.org/chromium/src/third_party/zlib/arm_features.c?l=29

    还需要指出的是,ARMV8上的CRC32指令是ARMV8上可选和ARMV8-1上必需的加密扩展的一部分。这也意味着运行时功能检测是必要的,有关详细信息,请检查: https://cs.chromium.org/chromium/src/third_party/zlib/BUILD.gn?l=64

    我将避免直接从/proc/cpuinfo读取,因为在某些上下文中可能不可用(也取决于Android风格,它可能是一个错误的否定)。

    在chromium中,zlib既可以在特权上下文(即主浏览器进程中的部分网络代码)中运行,也可以在沙盒上下文(即选项卡中的部分renderprocess)中运行。在renderprocess中,从/proc/cpuinfo读取应该失败。

    大锤方法是安装一个信号处理程序并使用内联asm执行该指令,如果该指令不可用(并且可能被处理程序捕获),则会导致故障。但不推荐。

    上述示例( https://github.com/torvalds/linux/blob/master/Documentation/arm64/cpu-feature-registers.txt )在我测试过的1个臂板上工作(Machiatobin),但在其他2个板上失败(Rock64和NanopiM4)。

    在Chromium中实现的方法适用于所有的板(以及我测试过的一些手机)。

    关于getauxval的另一个细节:如果在32位或64位上运行,则正确的标志将更改。所以在64位中它是hwcap_cc32,而在32位中它是hwcap2_cc32。

    关于 大锤 方法:信号容易出现竞争条件,而且您仍然依赖于使用操作系统特定的API(即安装信号处理程序)。

    最后,根据上下文的不同,如果给定的任务崩溃(即使按设计并与执行上下文隔离),它将触发红色标志。

    这是一个点(即功能检测),在这一点上,X86上的生活更加轻松。

    也就是说,依赖操作系统功能可能是一个可以接受的折衷方案。自从M66版本(目前稳定的版本是M72)发布以来,我们一直在用Chromium来运输链接代码,第一次登陆几乎是一年前,没有任何不良报告。

    安卓系统的一个考虑因素是,在内部,NDK可以使用dlopen()/dlsym()实现安卓的getcpuFeatures(),并且在第一次启动时可以将大约500us增加到1000us,这就是我们缓存CPU功能检测结果的原因。

    多线程应用程序(如chromium)的另一个考虑因素是,在执行CPU功能检测时,需要一个线程屏障(即pthread_once_t),以避免出现争用情况。

        2
  •  1
  •   Frant    6 年前

    更新:最初的答案没有回答这个问题,因为作者希望在EL0上运行一些通用部分的代码,能够确定CRC32功能是否存在,而不需要使用操作系统或裸机环境。

    我的理解是,这样的代码需要访问ID_aa64isar0_el1,并且因为在EL0上运行的代码无法访问它,所以无论如何都需要切换到更特权的异常级别。

    同样,使用“可移植”代码段捕获非法指令将需要访问vbar_elx寄存器,这无法通过运行在el0的程序实现,该程序不依赖任何底层操作系统/特权监视器。

    因此,我对问题“是这样吗?”可能是:是的,它是一个可移植/通用的代码段,在EL0上运行,无法确定CRC32功能是否可用。

    也就是说,文档中提供的示例代码 referenced 在这个问题中,运行aarch64 linux 4.14.80的expressobin运行得很好,应该优先使用getauxval(),这是内核文档中解释的原因。

        3
  •  0
  •   Martin Zeitler    6 年前

    这可能无法直接访问;但是 ARM 将提供 specifications 对于每个处理器-因此有机会创建一个图表,该图表可用于按型号名称查找CPU功能。 /proc/cpuinfo 是特定于Linux的;Windows相当于 WMI ;OSX不运行 手臂 (据我所知)。除非它是类型1的超级visor,完全绕过操作系统,否则必须有特定于操作系统的代码(用户还可以禁用 VT )