Чтение регистров Armv8-A с devmem из оболочки GNU / Linux - PullRequest
1 голос
/ 05 февраля 2020

Я хочу прочитать значения некоторых регистров Cortex-A53, таких как

  • D_AA64ISAR0_EL1 (AArch64)
  • ID_ISAR5 (Aarch32)
  • ID_ISAR5_EL1 (Aarch64 )

К сожалению, мне не хватает опыта встраивания / сборки. Документация раскрывает

Для доступа к ID_AA64ISAR0_EL1: MRS, ID_AA64ISAR0_EL1; Считать ID_AA64ISAR0_EL1 в Xt ID_AA64ISAR0_EL1 [31: 0] можно получить через внутренний отображенный в память интерфейс и внешний интерфейс отладки, смещение 0xD30.

Я решил использовать devmem2 в моей цели (так как busybox делает не включать апплет devmem). Является ли следующая процедура правильной для чтения регистра?

devmem2 0xD30

Часть, в которой я не уверен, использует «смещение» в качестве прямого физического адреса. Если это фактический адрес, зачем звонить, если «смещение», а не «адрес». Если это смещение, то каков базовый адрес? Я на 99% уверен, что это неправильная процедура, но как узнать базовый адрес, к которому нужно добавить смещение? Я искал техническое руководство Armv8 и документы A53 MPCore безрезультатно. Объясните содержимое регистра подробно, но, похоже, предполагается, что вы прочитали их из ASM, используя метку ID_AA64ISAR0_EL1.

Обновление:

Я нашел это:

Конфигурационный регистр базового адреса, EL1 Характеристики CBAR_EL1: Назначение Содержит физический базовый адрес отображаемых в памяти регистров интерфейса GI C.

Но это просто дублирует мою проблему, как читать этот другой регистр?

Обновление 2: Первое обновление представляется актуальным только для GI C, а не для регистров конфигурации, которые я пытаюсь прочитать (я неправильно понял информацию, которую я думаю ).

Для решения конкретной проблемы c (проверка доступности крипто-расширения) можно просто выполнить команду cat / proc / cpuinfo и найти aes / sha et c.

Обновление 3:

Сейчас я расследую http://infocenter.arm.com/help/index.jsp?topic= / com.arm.do c .dai0176c / ar01s04s01. html, а также базовый адрес Быть таким C конкретным c и, таким образом, может быть находится в справочном руководстве So C.

Обновление 4:

Благодаря отличному ответу я, кажется, могу читать данные через мой модуль ядра :

[ 4943.461948] ID_AA64ISA_EL1 : 0x11120
[ 4943.465775] ID_ISAR5_EL1     : 0x11121

PS: Это было очень проницательно, еще раз спасибо!

1 Ответ

1 голос
/ 05 февраля 2020

Отказ от ответственности: я не эксперт 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.

...