assembly 如何使用内联汇编将ID_AA64MMFR1_EL1寄存器的内容读入64位变量?

vs91vp4v  于 2023-06-06  发布在  其他
关注(0)|答案(2)|浏览(196)

这是this回答的后续问题。
我尝试使用内联汇编将ID_AA64MMFR1_EL1寄存器的内容读入64位变量:

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main(void)
{
    uint64_t foo;
    __asm volatile("mov %0, ID_AA64MMFR1_EL1" : "=r"(foo) ::);
    printf("%"PRIx64"\n", foo);
}

注意:我需要读取ID_AA64MMFR1_EL1,以便知道AFP字段的值。
然而,汇编程序拒绝了这段代码:

$ gcc t1b.c
/tmp/ccTDGH7d.s: Assembler messages:
/tmp/ccTDGH7d.s:22: Error: undefined symbol ID_AA64MMFR1_EL1 used as an immediate value

一个简单的问题:如何正确地做?

q5lcpyga

q5lcpyga1#

如果您的程序运行在EL0上,您应该使用hwcaps中提供的HWCAP_CPUID API-本文ARM64 CPU Feature Registers中有更多详细信息。这里有一个工作示例代码。

9fkzdhlc

9fkzdhlc2#

mov助记符仅用于在通用和/或FP/SIMD寄存器(x 0-x30、xzr、sp、q 0-q31)之间移动,以及将立即值移动到通用寄存器中。分别使用msrmrs移入和移出系统寄存器。所以这里你需要mrs而不是mov
请注意,从标题中可以看出,您是在普通的用户空间C程序中执行此操作的。在典型的操作系统上,用户空间在异常级别0(EL 0)下运行。但是ID_AA64MMFR1_EL1名称上的EL 1标签表明它只能在EL 1和更高的级别上读取(即内核模式)。因此执行此指令将陷入陷阱。
一些操作系统可能通过模拟指令来处理陷阱。我知道Linux对一些特性ID寄存器这样做,但不记得这是不是其中之一。但是,在这种情况下,返回给程序的值不一定等于硬件实际返回的值。例如,操作系统可以屏蔽掉它不想让你知道的功能。
在其他操作系统上(例如MacOS,如果我没记错的话),你的程序将简单地死于SIGILL。
通常,操作系统会提供其他机制来查询CPU特性。例如,Linux有/proc/cpuinfo,MacOS有sysctl

相关问题