Page 2 of 4

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Mon Jul 25, 2011 3:17 pm
by XVilka
По роду деятельности, я сталкивался часто с тем, что "железные баги" - на самом деле обычно баги либо в таблице ACPI, либо в самом коде BIOS. А ядро Linux содежит много обходных путей, для "исправления" этих ошибок.

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Mon Jul 25, 2011 3:47 pm
by Serge
XVilka

В любом случае этот баг не на нашей стороне.

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Mon Jul 25, 2011 3:58 pm
by Mario
Нам от этого не легче.

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Mon Jul 25, 2011 4:21 pm
by Serge
Мне легче. Не надо искать ошибку там, где её нет.

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Wed Jul 03, 2013 8:37 am
by Mario_r4
Чтобы не создавать отдельную тему спрошу здесь. Если админы/модераторы посчитают необходимым выделить в отдельную тему, то не возражаю.

Вопрос относительно обработчика прерывания. В свое время я написал код поддержки DMA. Добавлен в ядро он был программистом, гипотетически покинувшим проект, методом "реверс-инжиниринга" из выложенного мной бинарника ядра. Впрочем не суть есть важно, код был относительно рабочий и почти не менялся много лет. В коде я сделал переключение обработчика на нормальный:
Spoiler:

Code: Select all

        mov     [irq14_func], hdd_irq14
        mov     [irq15_func], hdd_irq15
и пустой обработчик:
Spoiler:

Code: Select all

        mov     [irq14_func], hdd_irq_null
        mov     [irq15_func], hdd_irq_null
В настоящее время, по сути, эти переменные используются как флаги. Однако одновременно с этим меняется и обработчик прерывания.
Так вот вопрос в том правильна ли такая логика. Может стоит сам обработчик оставлять с постоянным указателем? Теоретически пока код не подал команду на считывание или запись, то прерывание возникать не должно, но что происходит на практике я не знаю.
Код нормального обработчика прерывания и нулевого выглядит так:
Spoiler:

Code: Select all

align 4
hdd_irq14:
        pushfd
        cli
        pushad
        mov     [irq14_func], hdd_irq_null
        mov     dx, [IDEContrRegsBaseAddr]
        mov     al, 0
        out     dx, al
        popad
        popfd
align 4
hdd_irq_null:
        ret
Т.е. получается пустой обработчик не сбрасывает прерывание. Может ли это вызывать проблемы тоже вопрос.
Может имеет смысл сделать так:
Spoiler:

Code: Select all

align 4
hdd_irq14_null:
        pushfd
        cli
        pushad
        mov     dx, [IDEContrRegsBaseAddr]
        mov     al, 0
        out     dx, al
        popad
        popfd
        ret

align 4
hdd_irq15_null:
        pushfd
        cli
        pushad
        mov     dx, [IDEContrRegsBaseAddr]
        add     dx, 8
        mov     al, 0
        out     dx, al
        popad
        popfd
        ret
Также у меня есть подозрение, что это может быть причиной зависания в некоторых случаях для контроллеров работающих в PIO режиме.
З.Ы. На pushad и popad просьба внимание не обращать, я знаю что это "жирно", но это не вопрос данного обсуждения.

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Wed Jul 03, 2013 10:05 am
by Serge
Mario_r4
Лучше всего ставить обработчик через attach_int_handler
для примера клавиатура

Code: Select all

        stdcall attach_int_handler, 1, irq1, 0
и исправить

Code: Select all

align 16
irq_serv:

; .irq_1:
;      push 1
;      jmp .main
; etc...

irq_serv_h 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15
irq_serv_h 16, 17, 18, 19, 20, 21, 22, 23

purge irq_serv_h

align 16
.main:
        save_ring3_context

        mov     ebp, [esp + 32]
        mov     bx, app_data;os_data
        mov     ds, bx
        mov     es, bx

        cmp     [v86_irqhooks+ebp*8], 0
        jnz     v86_irq

        cmp     bp, 6
        jnz     @f
        push    ebp
        call    [fdc_irq_func]
        pop     ebp
@@:

;        cmp     bp, 14
;        jnz     @f
;        push    ebp
;        call    [irq14_func]
;        pop     ebp
;@@:
;        cmp     bp, 15
;        jnz     @f
;        push    ebp
;        call    [irq15_func]
;        pop     ebp
;@@:
        bts     [irq_active_set], ebp

        lea     esi, [irqh_tab+ebp*8]   ; esi= list head
        mov     ebx, esi
.next:
Для расшареных PCI IRQ обработчик должен возвращать ненулевое значение, если прерывание было обработано. Для линий ISA IRQ всегда ненулевое.

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Wed Jul 03, 2013 10:07 am
by Mario_r4
Serge
Это то и так понятно, ты по теме чего сказать можешь? Могут возникать прерывания без посыла команды?

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Wed Jul 03, 2013 10:13 am
by Serge
Какой команды ?

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Wed Jul 03, 2013 10:23 am
by Mario_r4
Mario_r4 wrote:В настоящее время, по сути, эти переменные используются как флаги. Однако одновременно с этим меняется и обработчик прерывания.
Так вот вопрос в том правильна ли такая логика. Может стоит сам обработчик оставлять с постоянным указателем? Теоретически пока код не подал команду на считывание или запись, то прерывание возникать не должно, но что происходит на практике я не знаю.

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Wed Jul 03, 2013 10:41 am
by Serge
Mario_r4
Не должно.
Spoiler:Как совет. Перепиши всю обработку прерываний на драйверную модель и всё сразу упростится. Тем более что для pci irq всё равно надо писать обработчик. Примеров уже много, а если что непонятно, я постараюсь помочь.

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Thu Jul 04, 2013 10:52 am
by Mario_r4
Меня смущает процедура irq_serv в файле core/irq.inc
Пришлось убрать:

Code: Select all

        cmp     ebp, 14
        jz      .fail
        cmp     ebp, 15
        jz      .fail
а также добавить:

Code: Select all

        cmp     ebp, 14
        jz      .try_next_irq
        cmp     ebp, 15
        jz      .try_next_irq
иначе не работало на некоторых машинах и выдавало на доску "K : warning: relinking handler from IRQ%d to IRQ%d\n".

Так вот это ненормально, если я буду назначать обработчик прерывания при загрузке по факту наличия контроллера. Код то динамически не поменяется ведь, а номер прерывания для SATA IDE меняется, в отличие от PATA IDE.

Также в коде целая портянка глубокомысленных размышлений, не знаю под чьим авторством:
Spoiler:

Code: Select all

; There is at least one configuration with one device which generates IRQ
; that is not the same as it should be according to PCI config space.
; For that device, the handler is registered at wrong IRQ.
; As a workaround, when nobody acknowledges the generated IRQ,
; try to ask all other registered handlers; if some handler acknowledges
; the IRQ this time, relink it to the current IRQ list.
; To make this more reliable, for every handler keep number of times
; that it has acknowledged an IRQ, and assume that handlers with at least one
; acknowledged IRQ are registered properly.
; Note: this still isn't 100% correct, because two IRQs can fire simultaneously,
; the better way would be to find the correct IRQ, but I don't know how to do
; this in that case.
; Also, [fdc_irq_func], [irq14_func], [irq15_func] could process interrupt
; but do not return whether they did it, so just ignore IRQs 6, 14, 15.
Так жить нельзя! Как быть?

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Thu Jul 04, 2013 11:05 am
by Serge
Mario
Хак писала Вероника. Имхо в этом случае лучше включить APIC, пусть это и требует некоторых телодвижений.
Ты ставишь обработчики irq 14 и 15 через attach_int_handler ? И возвращаешь ненулевое значение, если прерывание обработано ? А а legacy надо всегда ненулевое. Тебе наверное надо два типа обработчиков, для режима ISA и PCI.

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Thu Jul 04, 2013 11:33 am
by yogev_ezra
Mario_r4 wrote:Меня смущает процедура irq_serv в файле core/irq.inc
иначе не работало на некоторых машинах и выдавало на доску "K : warning: relinking handler from IRQ%d to IRQ%d\n".
Также в коде целая портянка глубокомысленных размышлений, не знаю под чьим авторством:

Code: Select all

; There is at least one configuration with one device which generates IRQ
; that is not the same as it should be according to PCI config space.
Этот код CleverMouse написала для одного из моих компьютеров (на работе), где без этого кода он зависал: viewtopic.php?f=30&t=2305 (пункт 8 в списке).

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Thu Jul 04, 2013 12:22 pm
by Mario_r4
Serge wrote:Имхо в этом случае лучше включить APIC, пусть это и требует некоторых телодвижений.
Зачем мне APIC для SATA в режиме эмуляции IDE? А если в компьютере тупо нету APIC?
Serge wrote:Ты ставишь обработчики irq 14 и 15 через attach_int_handler? И возвращаешь ненулевое значение, если прерывание обработано ? А а legacy надо всегда ненулевое.
Да, да, не уверен что всегда. К тому же в eBox весьма странный Native mode на PATA контроллере.
Serge wrote:Тебе наверное надо два типа обработчиков, для режима ISA и PCI.
Зачем мне ISA? Где ты видел в современных комперах IDE контроллер на ISA? Там только флопик на IRQ6 висит же.

Я еще не разобрался что передается третьим параметром при установке прерывания? Какие то дополнительные данные? Указатель на таблицу с данными? Даже краткого описания не нашел, а по логике USB кода не смог понять что передается.

Re: 2 акт. обработчика PCI IRQ на разных линиях вешают систе

Posted: Thu Jul 04, 2013 1:28 pm
by Serge
Имхо в этом случае лучше включить APIC, пусть это и требует некоторых телодвижений
Это относилось к хаку с поиском обработчика прерывания.
Где ты видел в современных комперах IDE контроллер на ISA?
В любом компьютере, в режиме совместимости.

ISA - это legacy mode с irq 14 и 15 (как и клавиатура на 1 и мышь 12). В этом режиме прерывания не расшарены и если ядро вызвало обработчик, значит прерывание действительно было. Для ISA irq обработчик всегда должен возвращать ненулевое значение, иначе ядро решит что это "левое" прерывание и замаскирует линию (сделаю это в будущем. Счётчик ложных прерываний уже есть). PCI - native mode с расшареным прерыванием.

Третий параметр может быть любым. Ядро передаёт его в установленный обработчик прерывания. Удобно передавать указатель на данные контроллера.
Spoiler:drm_device - монстроподобная структура в памяти со всей необходиморй информацией

Code: Select all

int drm_irq_install(struct drm_device *dev)
{
    AttachIntHandler(irq_line, intel_irq_handler, (u32)dev);
};
irqreturn_t intel_irq_handler(struct drm_device *dev)
{
//    printf("i915 irq\n");
    return dev->driver->irq_handler(0, dev);
}