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

Internal structure and you change requests/suggestions
  • XVilka

    В любом случае этот баг не на нашей стороне.
  • Нам от этого не легче.
  • Мне легче. Не надо искать ошибку там, где её нет.
  • Чтобы не создавать отдельную тему спрошу здесь. Если админы/модераторы посчитают необходимым выделить в отдельную тему, то не возражаю.

    Вопрос относительно обработчика прерывания. В свое время я написал код поддержки 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 просьба внимание не обращать, я знаю что это "жирно", но это не вопрос данного обсуждения.
    Всем чмоки в этом проекте! Засуньте эти 11 лет себе в жопу!
  • 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 всегда ненулевое.
    Last edited by Serge on Wed Jul 03, 2013 10:13 am, edited 1 time in total.
  • Serge
    Это то и так понятно, ты по теме чего сказать можешь? Могут возникать прерывания без посыла команды?
    Всем чмоки в этом проекте! Засуньте эти 11 лет себе в жопу!
  • Какой команды ?
  • Mario_r4 wrote:В настоящее время, по сути, эти переменные используются как флаги. Однако одновременно с этим меняется и обработчик прерывания.
    Так вот вопрос в том правильна ли такая логика. Может стоит сам обработчик оставлять с постоянным указателем? Теоретически пока код не подал команду на считывание или запись, то прерывание возникать не должно, но что происходит на практике я не знаю.
    Всем чмоки в этом проекте! Засуньте эти 11 лет себе в жопу!
  • Mario_r4
    Не должно.
    Spoiler:Как совет. Перепиши всю обработку прерываний на драйверную модель и всё сразу упростится. Тем более что для pci irq всё равно надо писать обработчик. Примеров уже много, а если что непонятно, я постараюсь помочь.
  • Меня смущает процедура 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.
    Так жить нельзя! Как быть?
    Всем чмоки в этом проекте! Засуньте эти 11 лет себе в жопу!
  • Mario
    Хак писала Вероника. Имхо в этом случае лучше включить APIC, пусть это и требует некоторых телодвижений.
    Ты ставишь обработчики irq 14 и 15 через attach_int_handler ? И возвращаешь ненулевое значение, если прерывание обработано ? А а legacy надо всегда ненулевое. Тебе наверное надо два типа обработчиков, для режима ISA и PCI.
  • 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 в списке).
  • 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 кода не смог понять что передается.
    Всем чмоки в этом проекте! Засуньте эти 11 лет себе в жопу!
  • Имхо в этом случае лучше включить 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);
    }
    
  • Who is online

    Users browsing this forum: No registered users and 5 guests