Включить исправления ARM во встроенной сборке

Я пытаюсь изучить asm, включив обходные пути для ошибок в драйвере. Это должно быть возможно, потому что код ядра выполняется в привилегированном мире. (Минималистичный) код выглядит следующим образом.

unsigned int cp15c15 = 0, result = 0;
__asm__ volatile("mrc p15, 0, %0, c15, c0, 1" : "=r" (cp15c15));
cp15c15 |= (1<<22); /* Errata 845369 */
__asm__ volatile("mcr p15, 0, %0, c15, c0, 1" : "+r" (cp15c15));

Кажется, это работает, но когда я читаю регистр несколько раз, я иногда получаю значение без включенного бита 22. (Например, 0x000001 вместо 0x400001).

char buf[10];
__asm__ volatile("mrc p15, 0, %0, c15, c0, 1" : "=r" (cp15c15));
sprintf(buf, "0x%.8x", cp15c15);
copy_to_user(buffer, buf, 10);

Я думаю, что делаю что-то не так в вызове asm. Если кто-то может дать мне понять, почему это работает только в 10% случаев, я был бы очень признателен. (Асм вроде круто).

РЕДАКТИРОВАТЬ:
Код сборки из оригинального описания ошибок NXP:

MRC p15,0,rt,c15,c0,1
ORR rt,rt,#0x00400000
MCR p15,0,rt,c15,c0,1

РЕДАКТИРОВАТЬ 2:
Если я включу это в ./linux/arch/arm/mm/proc-v7.S, бит останется установленным, когда я прочитаю его из своего драйвера. Однако, если я отключу его, кажется, что бит выключается и включается нерегулярно. Кажется, это подтверждает, когда бит установлен.


person Bayou    schedule 25.06.2020    source источник
comment
Вы не ссылаетесь на %1 во втором ассемблерном шаблоне. Вы предполагаете, что он выберет тот же регистр для "r" (cp15c15), что и для "=r"(result)? Потому что это не гарантировано. Используйте соответствующее ограничение, такое как "0"(cp15c15), или используйте один операнд чтения/записи "+r" (cp15c15).   -  person Peter Cordes    schedule 26.06.2020
comment
Кстати, я предполагаю, что это на самом деле позволяет обходной путь или устранение ошибки. Опечатка – это ошибка проектирования оборудования, и вы не хотите включать ошибки.   -  person Peter Cordes    schedule 26.06.2020
comment
Спасибо, что указали на это @PeterCordes. +r намного чище, чем у меня было, но это не решает проблему (думаю, я сделал эту ошибку из-за попытки заставить ее работать). Кроме того, я действительно не пытаюсь ввести больше ошибок :-)   -  person Bayou    schedule 26.06.2020
comment
Хорошо, теперь ваш asm в порядке и должен надежно делать то, что он пытается сделать. Возможно, сама ошибка объясняет, почему бит читается по-разному, если он не был установлен вручную, IDK. Вполне вероятно, что запись его как 1 имеет побочный эффект, который приводит к изменению поведения.   -  person Peter Cordes    schedule 26.06.2020
comment
Я думаю, что это как-то связано с записью в него после полного запуска ядра. Ассемблер в proc-v4.S — это код запуска, так что может случиться так, что чип уже что-то делает с этим регистром, и поэтому он переключается.   -  person Bayou    schedule 29.06.2020
comment
Вы запускаете это на всех процессорах?   -  person Timothy Baldwin    schedule 11.07.2020
comment
@ Тимоти Болдуин, что ты имеешь в виду?   -  person Bayou    schedule 12.07.2020


Ответы (1)


Если компьютер имеет несколько ядер процессора (например, некоторые чипы i.MX 6), то, если вы не примете меры для запуска всех ядер процессора, процессор, на котором он работает, будет зависеть от прихоти планировщика Linux.

Поэтому можно установить регистр на одном процессоре, тогда, если проверка выполняется на этом процессоре, модификация будет отображаться, но если проверка выполняется на другом процессоре, будет считано исходное значение.

person Timothy Baldwin    schedule 14.07.2020
comment
Процессор действительно многоядерный. Я хотел бы проверить, могу ли я запустить это на всех ядрах, прежде чем принять ваш ответ, но я думаю, что вы привели очень хороший аргумент. Спасибо. - person Bayou; 14.07.2020