Можете ли вы включить прерывания в обработчике ошибок страниц? Существует ли конфликт ядра ARM с упреждающим планированием?ARM Kernel Устранение прерываний в обработчике сбоев страницы или с упреждающим планированием
Я получил ядро ARM в UDP-приемнике с кодом CONFIG_PREEMPT или когда прерывание включено в обработчике ошибок.
Проблема аналогична what another user reported here. Но в моем случае, когда я отправляю 110% загружаемых UDP-пакетов в систему (система опускает около 10% пакетов), ядро упляет через несколько минут. Это происходит только при запуске сценариев оболочки busybox, а не только при запуске программы приема UDP. Я отслеживал адреса данных, которые всегда выглядят хорошо, буфер был выделен и использован до его освобождения.
Есть два способа избежать этого:
[1] При изменении расписания из PREEMPT (CONFIG_PREEMPT) к preempt_voluntary, эта проблема уходит. Это известная проблема с ARM на ядре 2.6.39? С предварительным планированием я также вижу проблему в jffs2 после долгого времени, но не с preempt_voluntary.
На мгновение я подозревал, что Ethernet DMA полностью использует шину, тем самым блокируя CPU от загрузки его записи TLB, что приводит к сбою страницы. Я выводю, потому что сценарии busybox должны быть на картинке, когда скрипт порожден, он создает адресное пространство и загружает многие записи TLB, тем самым перегружая шину. Если preempt_voluntary является решением, может ли быть исключена блокировка шины DMA?
Тестирование, которое я запускаю, представляет собой ядро LTIB 2.6.39.4 lpclinux для системы на основе phy3250.
[2] Еще несколько тестов показали, что обработчик ошибок страницы вложен в прерывания Ethernet. При отключении прерываний в обработчике ошибок страницы __dabt_svc, но сохраняйте его включенным в обработчике ошибок страницы пользователя __dabt_user, проблема исчезнет. Если нет, уровень гнезда поднимается до 4, и он утомляет. Поэтому возникает вопрос: правильно ли разрешены прерывания в обработчике ошибок страницы?
Код ошибки для [2] ниже. Строки с @@@@ добавляются или изменяются. Затем запишите уровень вложенности в do_DataAbort().
file arch/arm/kernel/entry-armv.S:
__dabt_svc:
svc_entry
... ...
@
@ set desired IRQ state, then call main handler
@
debug_entry r1
@@@@Not_Enable_Irq_In_Dabtsvc
ldr r2, =armv_dabtsvc_count @@@@
ldr r3, [r2] @@@@
add r3, r3, #1 @@@@
str r3, [r2] @@@@
msr cpsr_c, r9 @@@@disable thisk
mov r2, r2 @@@@add this extra inst
mov r2, sp
bl do_DataAbort
@
@ IRQs off again before pulling preserved data off the stack
@
disable_irq_notrace
ldr r2, =armv_dabtsvc_count @@@@
ldr r3, [r2] @@@@
sub r3, r3, #1 @@@@
str r3, [r2] @@@@
@
@ restore SPSR and restart the instruction
@
ldr r2, [sp, #S_PSR]
svc_exit r2 @ return from exception
UNWIND(.fnend )
ENDPROC(__dabt_svc)
И добавить переменную в файл тоже:
file arch/arm/kernel/entry-armv.S:
@@@@save nesting level:
.data @@@@
.align @@@@
armv_dabtsvc_count: @@@@
.long 0 @ count svc entry @@@@
Я пытаюсь связать все это вверх. Могут ли эксперты ядра понять, все ли тесты имеют смысл? Действительно ли отключить прерывания в обработчике ошибок страницы?
Редактировать: Упс в обработчике ошибок страницы не является первым сбоем. В обработчике выравнивания продолжается «do_bad_area». Впоследствии это неудачное исправление для нелицензионного доступа вызвало ошибку страницы. Да, как кто-то прокомментировал ниже, исправление несвязанного доступа очень хлопотно. Эти несвязанные обращения - это ip_input, ip_fragment и udp stack. Как только я исправил все те, что были в стеке, проблема исчезла.
Редактировать снова: проблема связана с двумя операциями в обработчике выравнивания: он извлекает команду и извлекает данные, на которые ссылается инструкция. Сообщения об ошибках сообщаются доступом к данным, но причина в том, что команда на выбор не выполнена с ошибкой сбоя первой страницы. Поскольку команда fetch находится в пространстве ядра, страница всегда действительна, что указывает на силовую ошибку. Если изменить код для извлечения снова, это будет успешным, что подтвердит, что это скорее силиконовая ошибка. Прерывание попадает в изображение из-за избыточного сброса TLB. Короче говоря, загрузка TLB автоматическая, поэтому извлечение инструкции в пространстве ядра не может потерпеть неудачу. Но все равно это провалилось.
Вы должны связаться с Linux Kernel список рассылки об этом. Если он падает, это ошибка. –
Два других соответствующих SO QAs: [Ошибка страницы в контексте прерывания] (http://stackoverflow.com/questions/4848457/page-fault-in-interrupt-context). [Что происходит, когда команда mov вызывает ошибку страницы с отключенными прерываниями на x86] (http://stackoverflow.com/questions/12607288/what-happens-when-a-mov-instruction-causes-a-page-fault- с-перебивает-инвалидов). – minghua
Нет, вы не должны отключать прерывания в обработчике ошибок страницы. Ошибка страницы может произойти в потоке ядра, который выполняет 'copy_from_user()'. В этом случае нет причин блокировать прерывания; вы увеличиваете задержку. Вероятно, вы скрываете проблему со всеми вашими предложениями; код ядра полон тонкостей. –