Отказ от ответственности: я не эксперт Aarch64, но в настоящее время я изучаю архитектуру и немного прочитал.
Вы не можете прочитать ID_AA64ISAR0_EL1
, ID_ISAR5_EL1
или ID_ISAR5
от пользователя- приложение режима работает на EL0
: суффикс _EL1
означает, что для выполнения этих двух регистров требуется суффикс * хотя бы на EL1
.
Может оказаться полезным прочитать псевдо- код в документации по вооружению здесь и здесь . Например, в случае ID_ISAR5 псевдокод является очень явным:
if PSTATE.EL == EL0 then
UNDEFINED;
elsif PSTATE.EL == EL1 then
if EL2Enabled() && !ELUsingAArch32(EL2) && HSTR_EL2.T0 == '1' then
AArch64.AArch32SystemAccessTrap(EL2, 0x03);
elsif EL2Enabled() && ELUsingAArch32(EL2) && HSTR.T0 == '1' then
AArch32.TakeHypTrapException(0x03);
elsif EL2Enabled() && !ELUsingAArch32(EL2) && HCR_EL2.TID3 == '1' then
AArch64.AArch32SystemAccessTrap(EL2, 0x03);
elsif EL2Enabled() && ELUsingAArch32(EL2) && HCR.TID3 == '1' then
AArch32.TakeHypTrapException(0x03);
else
return ID_ISAR5;
elsif PSTATE.EL == EL2 then
return ID_ISAR5;
elsif PSTATE.EL == EL3 then
return ID_ISAR5;
Один простой способ прочитать эти регистры - написать крошечный загружаемый модуль ядра, который вы можете вызвать из приложения в пользовательском режиме: поскольку ядро Linux работает на EL1
, оно прекрасно умеет читать эти три регистра.
См., например, эту статью для получения отличной информации. введение в Linux загружаемые модули ядра.
И вполне вероятно, что приложение, работающее с EL0
, не может получить доступ к отображенным в памяти регистрам, доступным только с EL1
, поскольку это, очевидно, нарушит схему защиты.
Фрагменты кода C, необходимые для чтения этих регистров в состоянии Aarch64, будут (проверены с g cc -arm-9.2-2019.12-x86_64-aarch64-none- linux -gnu ):
#include <stdint.h>
// read system register value ID_AA64ISAR0_EL1 (s3_0_c0_c6_0).
static inline uint64_t system_read_ID_AA64ISAR0_EL1(void)
{
uint64_t val;
asm volatile("mrs %0, s3_0_c0_c6_0" : "=r" (val));
return val;
}
// read system register value ID_ISAR5_EL1 (s3_0_c0_c2_5).
static inline uint64_t system_read_ID_ISAR5_EL1(void)
{
uint64_t val;
asm volatile("mrs %0, s3_0_c0_c2_5" : "=r" (val));
return val;
}
Обновление # 1 : набор инструментов G CC не понимает всех имен регистров системы охраны, но, тем не менее, может правильно кодировать инструкции доступа к системным регистрам, если указано какие точные значения полей copro c, opc1, CRn, CRm и opc2 связаны с этим регистром.
В случае ID_AA64ISAR0_EL1
значения указаны в Arm® Architecture Регистры Armv8, для профиля архитектуры Armv8-A Документ :
coproc=0b11
, opc1=0b000
, CRn=0b0000
, CRm=0b0110
, opc2=0b000
Тогда псевдоним системного регистра будет s[coproc]_[opc1]_c[CRn]_c[CRm]_[opc2]
, то есть s3_0_c0_c6_0
в случае ID_AA64ISAR0_EL1
.