这是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
一个简单的问题:如何正确地做?
2条答案
按热度按时间q5lcpyga1#
如果您的程序运行在
EL0
上,您应该使用hwcaps中提供的HWCAP_CPUID API-本文ARM64 CPU Feature Registers中有更多详细信息。这里有一个工作示例代码。9fkzdhlc2#
mov
助记符仅用于在通用和/或FP/SIMD寄存器(x 0-x30、xzr、sp、q 0-q31)之间移动,以及将立即值移动到通用寄存器中。分别使用msr
和mrs
移入和移出系统寄存器。所以这里你需要mrs
而不是mov
。请注意,从标题中可以看出,您是在普通的用户空间C程序中执行此操作的。在典型的操作系统上,用户空间在异常级别0(EL 0)下运行。但是
ID_AA64MMFR1_EL1
名称上的EL 1标签表明它只能在EL 1和更高的级别上读取(即内核模式)。因此执行此指令将陷入陷阱。一些操作系统可能通过模拟指令来处理陷阱。我知道Linux对一些特性ID寄存器这样做,但不记得这是不是其中之一。但是,在这种情况下,返回给程序的值不一定等于硬件实际返回的值。例如,操作系统可以屏蔽掉它不想让你知道的功能。
在其他操作系统上(例如MacOS,如果我没记错的话),你的程序将简单地死于SIGILL。
通常,操作系统会提供其他机制来查询CPU特性。例如,Linux有
/proc/cpuinfo
,MacOS有sysctl
。