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

问题描述 投票:0回答:2

这是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

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

assembly arm inline-assembly arm64 msr
2个回答
2
投票

如果您的程序在

EL0
上运行,您应该使用 hwcaps 中提供的 HWCAP_CPUID API - 更多详细信息,请参阅本文 ARM64 CPU 功能寄存器。请参阅此处了解工作示例代码。


2
投票

mov
助记符仅用于在通用和/或 FP/SIMD 寄存器(x0-x30、xzr、sp、q0-q31)之间移动,以及将立即值移动到通用寄存器中。移入和移出系统寄存器分别使用
msr
mrs
。所以在这里你想要
mrs
而不是
mov

请注意,从您的标头来看,您似乎是在普通用户空间 C 程序中执行此操作。在典型的操作系统上,用户空间运行在异常级别 0 (EL0)。但

ID_AA64MMFR1_EL1
名称上的EL1标签表明它只能在EL1及更高版本(即内核模式)下读取。所以执行这条指令会陷入陷阱。

某些操作系统可能通过模拟指令来处理陷阱。我知道 Linux 对某些功能 ID 寄存器执行此操作,但不记得这是否是其中之一。但是,在这种情况下,返回到程序的值不一定等于硬件实际返回的值。例如,操作系统可以屏蔽它不想让您知道的功能位。

在其他操作系统上(例如 MacOS,如果我没记错的话),你的程序会因 SIGILL 而死掉。

通常,操作系统会提供其他类似这样的CPU特性查询机制。例如,Linux 有

/proc/cpuinfo
,MacOS 有
sysctl

© www.soinside.com 2019 - 2024. All rights reserved.