2013-05-21 5 views
1

Можете ли вы включить прерывания в обработчике ошибок страниц? Существует ли конфликт ядра 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 автоматическая, поэтому извлечение инструкции в пространстве ядра не может потерпеть неудачу. Но все равно это провалилось.

+1

Вы должны связаться с Linux Kernel список рассылки об этом. Если он падает, это ошибка. –

+0

Два других соответствующих 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

+1

Нет, вы не должны отключать прерывания в обработчике ошибок страницы. Ошибка страницы может произойти в потоке ядра, который выполняет 'copy_from_user()'. В этом случае нет причин блокировать прерывания; вы увеличиваете задержку. Вероятно, вы скрываете проблему со всеми вашими предложениями; код ядра полон тонкостей. –

ответ

1

Я думаю, что это ответ (неполный, апробировались):

Существует проблема при включении прерывания слишком рано. Предполагается, что __get_user() используется в атомном контексте, когда он используется с прерыванием, включенным в do_alignment(). Если включение прерывания отложено после этой точки, все должно быть в порядке.

Пожалуйста, изучите две передачи ядра. Первый - 25 июня 2011 года, который отключал прерывание. Второй - 25 февраля 2013 года, который меняет использование __get_user() на probling_kernel_address().

Первая фиксация:

3.x ядро ​​удалены прерывания позволяют в обработчиках низкоуровневых __dabt_svc и __dabt_user т.д. сообщение фиксации:

git diff 8b418616..02fe2845 entry-armv.S 
commit 02fe2845d6a837ab02f0738f6cf4591a02cc88d4 
Author: Russell King <[email protected]> 
Date: Sat Jun 25 11:44:06 2011 +0100 

    ARM: entry: avoid enabling interrupts in prefetch/data abort handlers 

    Avoid enabling interrupts if the parent context had interrupts enabled 
    in the abort handler assembly code, and move this into the breakpoint/ 
    page/alignment fault handlers instead. 

    This gets rid of some special-casing for the breakpoint fault handlers 
    from the low level abort handler path. 

    Acked-by: Will Deacon <[email protected]> 
    Signed-off-by: Russell King <[email protected]> 

commit 8b4186160b7894ca4583f702a562856d5d9e9118 
Author: Russell King <[email protected]> 
Date: Sat Jun 25 19:25:02 2011 +0100 

И дифф фрагмент кода:

diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S 
index d644d02..c46bafa 100644 
--- a/arch/arm/kernel/entry-armv.S 
+++ b/arch/arm/kernel/entry-armv.S 
@@ -185,20 +185,15 @@ ENDPROC(__und_invalid) 
__dabt_svc: 
     svc_entry 
... ... 
     dabt_helper 

     @ 
-  @ set desired IRQ state, then call main handler 
+  @ call main handler 
     @ 
-  debug_entry r1 
-  msr  cpsr_c, r9 
     mov  r2, sp 
     bl  do_DataAbort 
...... 

Это подтверждает, что прерываниям не нужно слишком рано включать обработчики ошибок.

Второй фиксации:

commit b255188f90e2bade1bd11a986dd1ca4861869f4d 
Author: Russell King <[email protected]> 
Date: Mon Feb 25 16:10:42 2013 +0000 

    ARM: fix scheduling while atomic warning in alignment handling code 

    Paolo Pisati reports that IPv6 triggers this warning: 

    BUG: scheduling while atomic: swapper/0/0/0x40000100 
    [<c001b1c4>] (unwind_backtrace+0x0/0xf0) from [<c0503c5c>] (__schedule_bug+0x48/0x5c) 
    [<c0503c5c>] (__schedule_bug+0x48/0x5c) from [<c0508608>] (__schedule+0x700/0x740) 
    [<c0508608>] (__schedule+0x700/0x740) from [<c007007c>] (__cond_resched+0x24/0x34) 
    [<c007007c>] (__cond_resched+0x24/0x34) from [<c05086dc>] (_cond_resched+0x3c/0x44) 
    [<c05086dc>] (_cond_resched+0x3c/0x44) from [<c0021f6c>] (do_alignment+0x178/0x78c) 
    [<c0021f6c>] (do_alignment+0x178/0x78c) from [<c00083e0>] (do_DataAbort+0x34/0x98) 
    [<c00083e0>] (do_DataAbort+0x34/0x98) from [<c0509a60>] (__dabt_svc+0x40/0x60) 
    Exception stack(0xc0763d70 to 0xc0763db8) 
    [<c0509a60>] (__dabt_svc+0x40/0x60) from [<c02a8490>] (__csum_ipv6_magic+0x8/0xc8) 

Fix this by using probe_kernel_address() stead of __get_user(). 
arch/arm/mm/alignment.c | 11 ++++------- 
+0

было ли это настоящим исправлением? – harmv

+0

см. Мое исследование как изменения в разделе вопросов. вот и все. поскольку проблема наблюдается только при интенсивном сетевом трафике, если на самом первом этапе приема пакетов дросселируется сетевая нагрузка, она не столкнется с проблемой. это до сих пор действительное обходное решение. что вы думаете? это может быть движок dma, поскольку поставщик выпустил патч, который позволяет избежать использования dma на nand. сеть использует dma. – minghua

 Смежные вопросы

  • Нет связанных вопросов^_^