Работа с прерываниями

Тема в разделе "WASM.BEGINNERS", создана пользователем s3dworld, 27 дек 2010.

  1. s3dworld

    s3dworld Сергей

    Публикаций:
    0
    Регистрация:
    16 мар 2010
    Сообщения:
    387
    Адрес:
    Ртищево
    Всем доброго вечера!

    Ещё не работал с прерываниями, но уже пора бы. Прерывания нумеруются от 0 до 255 (всего 256 штук). Таблица векторов прерываний должна храниться в регистре IDR. Это всё понятно. Вот сами прерывания:

    [​IMG]

    Решил я сегодня почитать про клавиатуру. И оказалось что она может попросить процессор уделить ей немного времени (причём по приоритету не на последнем месте):

    [​IMG]

    И тут я не понял! Там прерывания, тут прерывания - объясните. Этот нижний список ничем не совпадает с верхним. Какое же тогда прерывание получает процессор от клавиатуры? Что за
     
  2. Pavia

    Pavia Well-Known Member

    Публикаций:
    0
    Регистрация:
    17 июн 2003
    Сообщения:
    2.409
    Адрес:
    Fryazino
    s3dworld
    Процессор может прерываться. Так вот различают программные и аппаратные прерывания.
    Аппаратные в свою очередь делятся на внешние и внутренние.

    Так вот для обработке прерываний в процессоре есть таблица прерываний на которую ссылается регистр IDR.

    Так вот первые 0-31 прерываний жестко соотнесены с внутренними аппаратными прерываниями процессора. Они у тебя записаны в 1 таблице.
    Они возникают в случае ошибок. Деления на ноль доступ за приделы лимита сегмента отсутствия страницы. Переполнения стека. и тд.

    А есть внешние прерывания которые поступают в процессор по линии #INTR. Поступают они от внешнего контроллера прерывания. Процессор по приходу сигнала делает запрос у контроллера прерываний чтобы получить номер прерывания.

    Так вот вторая таблица это номера ног в системе из двух внешних контролеров прерываний 8259А.
    Эти номера складываются с базой и получается номер вектора прерывания из таблицей IDT.
    Базу ты должен записать сам в 8259А.

    Система прерываний.
    Система прерываний стара и поэтому очень запутана.
    Источниками прерываний являются устройства эти устройства располагаются на шинах PCI и ISA.

    Во времена шины ISA каждое устройство цеплялось на свою линию IRQ( Interupt ReQuest) , а она в свою очередь шла на контроллер прерываний 8259А. Оттуда выходил сигнал по линии INTR на процессор или на другой контроллер прерываний.

    С выходом PCI все усложнилась. Шина PCI имела только 4 линии прерываний на все устройства.

    С вводам мультипроцессорных систем все еще больше усложнилось появилась системная меж процессорная шина. И появился еще один контролер APIC. Вернее два один внутри каждого процессора Local APIC, а второй I/O APIC на чипсете.


    PIC - PROGRAMMABLE INTERRUPT CONTROLLER
    Программируемый контроллер прерываний - ПКП
    Или также известный как 8259А
    Контроллер этот появился так давно, что совместим с процессорами 8080/8085 . Так как современные компьютеры их не используют. То нас больше интересует его работа в режиме совместимости с 8086/8088.
    Поэтому будет описана только часть относящаяся к нему.

    Контроллер имеет 8 линий IRQ. Этого мало, поэтому была разработана возможность каскадного подключения контроллеров. Когда к видящему Master контроллеру подключались, ведомые Slave контроллеры. Теоретически возможно, что мы имеем один ведущей и восемь подчиненных. Но в стандартном компьютере всего два - первый ведущий и второй ведомый.
    Первый контроллер прерываний 8259А использует порты 20h-21h, второй 8259А использует 0A0h-0A1h
    Второй контроллер сидит на IRQ2 первого контроллера.


    Стандартное назначение прерываний следующее. Согласно документации на Award BIOS и ряда других спецификаций.

    Код (Text):
    1. +-----+-------+----------------------------------------+
    2. | INT |  IRQ  | Назначение                             |
    3. +-----+-------+----------------------------------------+
    4. | 08h |  IRQ0 | Системный таймер (канал 0 8253/8254)   |
    5. +-----+-------+----------------------------------------+
    6. | 09h |  IRQ1 | Клавиатура                             |
    7. +-----+-------+----------------------------------------+
    8. | 0Ah |  IRQ2 | Каскадное подключение #2 8259A         |
    9. +-----+-------+----------------------------------------+
    10. | 0Bh |  IRQ3 | COM2                                   |
    11. +-----+-------+----------------------------------------+
    12. | 0Ch |  IRQ4 | COM1                                   |
    13. +-----+-------+----------------------------------------+
    14. | 0Dh |  IRQ5 | LPT2                                   |
    15. +-----+-------+----------------------------------------+
    16. | 0Eh |  IRQ6 | FDC(Floppy Disk Controller)            |
    17. +-----+-------+----------------------------------------+
    18. | 0Fh |  IRQ7 | LPT1                                   |
    19. +-----+-------+----------------------------------------+
    20. +-----+-------+----------------------------------------+
    21. | 70h |  IRQ8 | Real time clock                        |
    22. +-----+-------+----------------------------------------+
    23. | 71h |  IRQ9 | Резерв, используется PCI               |
    24. +-----+-------+----------------------------------------+
    25. | 72h |  IRQ10| Резерв, используется PCI               |
    26. +-----+-------+----------------------------------------+
    27. | 73h |  IRQ11| Резерв, используется PCI               |
    28. +-----+-------+----------------------------------------+
    29. | 74h |  IRQ12| Мышь PS/2, Резерв, используется PCI    |
    30. +-----+-------+----------------------------------------+
    31. | 75h |  IRQ13| 80387 математический сопроцессор       |
    32. +-----+-------+----------------------------------------+
    33. | 76h |  IRQ14| Первичный канал IDE HDD                |
    34. +-----+-------+----------------------------------------+
    35. | 77h |  IRQ15| Вторичный канал IDE HDD                |
    36. +-----+-------+----------------------------------------+
    Шина ISA рассчитано на активацию прерывание фронтом. Поэтому на одном прерывании может сидеть одно устройство. Для того чтобы не лазить по спецификациям была придумана технология PnP она позволяет определить на каком прерывании сидит устройство. И не просто определять, но и задавать его программно. Раньше для этого были перемычки. PnP так же позволяет получить информацию о ресурсах устройств.


    Контроллер PIC содержит следующие регистры.
    Регистр запроса на прерывание (Interrupt Request Register, IRR) доступ к которым осуществляется через входы IR0 - IR7 контроллера. Бит этого регистра устанавливается в 1 если был выбран режим запуска фронтом и происходит перепад напряжения от низкого к высокому. Или если был выбран режим запуска уровнем то устанавливается в 1 при высоком уровне. Этот бит устанавливается в 1 или сбрасывается в 0, даже если соответствующее прерывание было замаскировано.
    Он будет сброшен, как только поступит цикл запроса прерывания INTERRUPT ACKNOWLEDGE.

    Регистр обрабатываемых запросов, (In-Service Register, ISR) описывает в битах 0 - 7 номер прерывания которое (0 - 7) в данный момент обрабатывается. Эти биты устанавливаются и соответствующие ему IRR очищаются когда поступит цикл запроса прерывания INTERRUPT ACKNOWLEDGE. Этот бит будет сброшен как только будет получена команда подтверждение конца прерывания(End of Interrupt Command - EOI)

    Регистр маскирования запроса на прерывания (Interrupt Mask Register, IMR) описывает,какие номера прерывания в настоящий момент замаскированы. Единичное значение бита в IMR указывает на то, какое прерывание при появлении запроса в IRR будет заблокировано. При этом INTR не генерируется.

    Программирование контроллера осуществляется с помощью команд.

    Initialization Command Words (ICW1- ICW4)
    Командные слова для инициализации.

    Operation Command Words (OCW1- OCW3)
    Командные слова для действий.

    Перед началом работы процессор должен инициировать контроллер. Последовательностью из 2-4 команд ICW. После инициализации можно отправлять OCW.

    Команды инициализации подаются одна за другой. Сначала ICW1 затем ICW2 если был выбран каскадный режим, то подается ICW3 и если был запрошен то ICW4.

    Формат команд 9битный. 8 бит сама команда, а 9 бит это бит с шины адреса, он задается номером порта. Четный порт соответствует 0, а нечетный 1.

    Формат ICW1 следующий:
    Бит 0 говорит о том, будет ли послан ICW 4 или нет
    БИТ 1=0 говорит о каскадном подключение контроллеров именно такой способ используется в современной архитектуре. Если он установлен в 0 то нужно будет посылать ICW3 иначе нет.
    БИТ 2 используется в режиме 80/85
    Бит 3 определяет по какому состоянию линий будет срабатывать триггер
    Бит 4 =1 означает началу инициализации, посылку ICW1
    БИТ 5-7 используются в режиме 80/85
    Код (Text):
    1.    A0   7    6    5    4    3    2    1    0
    2.  +----+----+----+----+----+----+----+----+----+
    3.  |  0 | -- | -- | -- |  1 |LTIM| ADI|SNGL| IC4|
    4.  +----+----+----+----+----+-+--+-+--+-+--+-+--+
    5.                             |    |    |    |
    6.                             |    |    |    +-> 1=будет вывод ICW4
    7.                             |    |    |        0=не будет
    8.                             |    |    +------> 1=один контроллер
    9.                             |    |             0=каскад
    10.                             |    +-----------> игнорируются в режиме 86/88
    11.                             +----------------> 0=запуск запросов
    12.                                                  фронтом
    13.                                                1=запуск запросов
    14.                                                  уровнем
    Формат ICW2 следующий, это номер начального вектора прерывания. Биты 0-2 должны быть 0. При приходе прерывания. Номер линии, на которую пришло прерывание, складывается с этим числом. И выставляется на шину адреса.

    Код (Text):
    1.    A0   7    6    5    4    3    2    1    0
    2.  +----+----+----+----+----+----+----+----+----+
    3.  |  1 | T7 | T6 | T5 | T4 | T3 |  0 |  0 |  0 |
    4.  +----+----+----+----+----+----+----+----+----+
    Формат ICW3 различаются для ведущего и ведомого.

    У ведущего каждый бит говорит к какой линии подключен ведомы контроллер.
    Если у нас 2 ведущих контроллера и они подключены к с 7 и 6 контроллеру то будет равно 11000000b = 0E0h. В настоящей системе только один ведомый контроллер, подключенный ко второй линии
    00000100b = 04h

    Код (Text):
    1.    A0   7    6    5    4    3    2    1    0
    2.  +----+----+----+----+----+----+----+----+----+
    3.  |  1 | S7 | S6 | S5 | S4 | S3 | S2 | S1 | S0 |
    4.  +----+----+----+----+----+----+----+----+----+
    5. Ведущий.
    У ведомого это просто номер, линии по который он подключен к ведущему контроллеру. Т.е для реальной системы это вторая линия 2

    Код (Text):
    1.    A0   7    6    5    4    3    2    1    0
    2.  +----+----+----+----+----+----+----+----+----+
    3.  |  1 |  0 |  0 |  0 |  0 |  0 |ID2 |ID1 |ID0 |
    4.  +----+----+----+----+----+----+----+----+----+
    5. Ведомый.
    Последнее слово инициализации (ICW4) имеет следующий
    формат:

    Код (Text):
    1.    A0   7    6    5    4    3    2    1    0
    2.  +----+----+----+----+----+----+----+----+----+
    3.  |  1 |  0 |  0 |  0 |SFNM| BUF| M/S|AEOI| mPM|
    4.  +----+----+----+----+-+--+-+--+-+--+-+--+-+--+
    5.                        |    |    |    |    |
    6.                        |    |    |    |    +---> 1=8086/8088
    7.                        |    |    |    |          0=8080/8085
    8.                        |    |    |    +--------> 1=AEOI
    9.                        |    |    |               0=EOI
    10.                        |    |    +-------------> 1=ведущий
    11.                        |    |                    0=ведомый
    12.                        |    |                  (только при BUF=1)
    13.                        |    +------------------> 1= режим буферизации
    14.                        |                         0= режим без буферизации
    15.                        +-----------------------> 1=специальный
    16.                                                  вложенный режим
    БИТ 0 (mPM) определяет режим совместимости с 86/88 или 80/85 в нашем случи он равен 1

    БИТ 1 (AEOI) если равен 1, то контроллер будет автоматически сбрасывать ISR бит.
    А если равен 0, то обработчик прерывания сам должен его сбрасывать при помощи OCW.

    Бит 2 (M/S) игнорируется, если бит 3 (BUF) = 0. При наличии
    одного контроллера и BUF = 1 устанавливается в 1. При наличии
    каскада должен быть равен 1 только для ведущего контроллера.

    Бит 4 (SFNM) устанавливает специальный вложенный режим,
    применяемый при каскадировании для определения приоритетов
    запросов от разных контроллеров (Special Fully Nested Mode)

    Значение по умолчанию для ICW4. Intel выпускает чипсеты, где значение по умолчанию 01. Хотя когда-то раньше, когда контроллер не входил в чипсет и был предназначен для 80/85, значение по умолчанию было 00. Если не было запроса на ввод ICW4, то используется значение по умолчание.



    Управляющее слово OCW1
    Код (Text):
    1.    A0   7    6    5    4    3    2    1    0
    2.  +----+----+----+----+----+----+----+----+----+
    3.  |  1 | M7 | M6 | M5 | M4 | M3 | M2 | M1 | M0 |
    4.  +----+----+----+----+----+----+----+----+----+
    Установленный в 1 бит маскирует соответствующее прерывание. Это значит, что пришедшее прерывание не будет обрабатываться.

    Управляющее слово OCW2
    Код (Text):
    1.    A0   7    6    5    4    3    2    1    0
    2.  +----+----+----+----+----+----+----+----+----+
    3.  |  0 |  R | SL | EOI|  0 |  0 | L2 | L1 | L0 |
    4.  +----+----+----+----+----+----+----+----+----+
    Бит 4-3 позволяет отличить OCW2 от OCW3
    R,SL,EOI задают один из режимов

    000 = Rotate in Auto EOI Mode (Clear)
    001 = Non-specific EOI command
    010 = No Operation
    011 =* Specific EOI Command
    100 = Rotate in Auto EOI Mode (Set)
    101 = Rotate on Non-Specific EOI Command
    110 = * Set Priority Command
    111 = * Rotate on Specific EOI Command
    * Используются L0 – L2

    По завершению прерывания нужно вызвать EOI.


    PIC работает следующем образом. Когда выставляется сигнал на линию, контроллер получив сигнал вырабатывает запрос на прерывание по линии INTR- interrupt request сигнал. Процессор отвечает по линии INTA - INTERRUPT ACKNOWLEDGE . Контроллер замораживает состояние прерываний при помощи ISR. Процессор подает второй INTA и теперь уже контроллер отправляет данные на шину данных. Это номер прерывания. Начальный адрес записанный в контроллер плюс номер линии на которую поступило прерывание.
    Если имеется каскадное подключение. А такое подключение, как мы знаем, имеется. То ведущий контроллер выставляет ID на линии CAS0-2. Ведомый сравнивает его со своим ID ,который он получил по ICW3. И при втором запросе INTA ведомый выставляет номер прерывания на шину адреса.

    Пример программирования PIC.
    В защищенном режиме процессора прерывания от процессора занимают вектора с 0 по 13h и c 14h по 1Fh зарезервированы. Так что аппаратные прерывания надо подвинуть.
    Код (Text):
    1.         MOV    DX, 20h     // Ведущий
    2.         MOV    AH, 20h    //Номер начального прерывания для ведущего контроллера 08 стандартное для реального режима
    3.  
    4.         MOV     AL,11h     //ICW1 бит 0=1 сигнализирует, что будет послан ICW4
    5.         OUT     DX,AL
    6.         MOV     AL,AH      //ICW2  - начальный номера прерываний биты 2-0=0.
    7.         INC      DX
    8.         OUT     DX,AL
    9.         MOV     AL,4       //ICW3 ведущий 00000100 -  ведомый подключен ко второй линии
    10.         OUT     DX,AL
    11.         MOV     AL,1       //ICW4 режим 86/88  
    12.         OUT     DX,AL
    13.  
    14.         MOV    DX, 0A0h     // Ведомый
    15.         MOV    AH, 28h    //Номер начального прерывания для ведомого контроллера 70h стандартное для реального режима
    16.  
    17.         MOV     AL,11h     //ICW1 бит 0=1 сигнализирует, что будет послан ICW4
    18.         OUT     DX,AL
    19.         MOV     AL,AH      //ICW2  - начальный номера прерываний биты 2-0=0.
    20.         INC     DX
    21.         OUT     DX,AL
    22.         MOV     AL,2       //ICW3 ведомый, ведомый подключен ко второй линии ведущего
    23.         OUT     DX,AL
    24.         MOV     AL,1       //ICW4 режим 86/88  
    25.         OUT     DX,AL
    Шина PCI

    При появлении прерывании на шине PCI, сигнал преобразовывается c линий PIRQ в линию IRQ на контроллер прерываний. Тот выставляет INTR. Процессор, получив сигнал, генерирует ответ. Для этого на шине PCI выставляется специальный запрос - interrupt acknowledge cycle. Этот запрос распространяется по всей шине PCI в результате чего он доходит до контроллера прерываний. Контроллер прерываний находится на ISA(LPC) шине. Поэтому мост между PCI и ISA генерирует два сигнала INTA и получает ответ от контроллера прерываний, шина PCI передает ответ процессору, номер прерывания. Прекращается acknowledge cycle.

    Но такой подход не порадовал разработчиков. И был придуман второй способ посылки прерываний.
    Message Signaled Interrupt (MSI) сообщение сигнализирующее прерывание. Устройство пишет сообщение по определенном адресу, определенного формата. Это сообщение сигнализирует о прерывании. Это позволяет избежать задержек связанных с interrupt acknowledge cycle.

    Шина PCI устроена следующем образом. У нее 4 провода для прерываний И каждая карта имеет 4 вывода PIRQA# PIRQB# PIRQC# PIRQD#. Линии эти устроены, так что они циклически сдвигаются, при переходи от 1 устройства ко второму. Тем самым первое устройство подсоединю к линии A второе к B третье к С и четверное к D пятое к A и т.д. Устройств больше чем линий, тем самым на одной линии сидит несколько устройств. Когда устройству нужно прерывание оно выставляет логическую 1. Шина PCI позволяет совместно использовать прерывания.
    Вопрос как тогда отелить чье именно прерывание пришло? Ответ прост каждое устройство должно быть снабжено дополнительным битом. Обработчики прерываний сидящие на одном прерывании по очереди проверяют, а их ли это устройство вызвало прерывания. До появления спецификации PCI 2.3 это дело было железо зависимым. С появлением же добавили бит в PCI CFG регистр Device Status бит 3 interrupt status
    Только чтение. Выставление бита Interrupt Disable не приводит к сбросу interrupt status

    Так как провода просто соединены. То они тем самым выполняют роль логического И. Контроллер прерываний срабатывает в отличии от шины ISA не по перепаду из 0 в 1 (фронту). А по уровню – выставленному значению 1 . Если он видит 1 то срабатывает и будет срабатывать пока устройство не снимет прерывание. Поэтому ISA прерывания не должны пересекаться с прерываниями PCI. Для этого в PCI BIOS и в $PIR предусмотрено поле которое показывает доступные IRQ для PCI.
    Простая посылка EOI сбрасывает только триггер в контроллере и не меняет состояние линии поэтому контроллер должен тут же сработать еще раз. Поэтому чтобы такого не было нужно запретить прерывания. Это можно сделать одним из способов. Замаскировать прерывания на контроллере прерывания, но это приведет также к маскированию и других устройств висящих на этом же прерывании. Второй способ запретить прерывания на самом устройстве . В PCI 2.3 добавили в регистр Command бит 10 Interrupt Disable
    Этот бит запрещает прерывание по INTx#. Значение 0 разрешает сигнал по INTx# . А значение 1 запрещает сигнал по линии INTx# . После перезагрузки бит равен 0.
    INTx# это тоже самое что PIRQx# где x – A-D

    На самом деле если включен режим PIC , то линя PIRQx# преобразуется в IRQ.
    Если включен, I/O APIC линии не переназначаются они напрямую идут к контактам 16-19(IRQ16-19) а он уже волн сменить номер вектора.
    Это преобразование называется IRQ Routing. Номера какой линии PIRQ преобразуется в какой номер IRQ задается. Запрограммировать его можно одним из 3 способов: ACPI, PCI BIOS, через порты ввода вывода.
    Последний способ это железо зависимый способ. В мосту PCI -to –ISA выставляются соответствующие биты.
    ACPI – это тема для отдельной статьи или даже книге.

    Майкрософт ввела спецификацию PCI IRQ Routing Table Specification. Согласно этой спецификации PCI BIOS должен быть снабжен таблицей, которая описывает маршрутизацию. Эта таблица аналогична данным получаемым через функцию PCI BIOS GetIRQRoutingTable. А для перепрограммирования в PCI BIOS есть функция SetPCIHardwareInterrupt.
     
  3. newbie

    newbie New Member

    Публикаций:
    0
    Регистрация:
    2 дек 2008
    Сообщения:
    1.246
    ответ года!
     
  4. CrawlUp

    CrawlUp Member

    Публикаций:
    0
    Регистрация:
    1 фев 2018
    Сообщения:
    90
    [​IMG]

    Вот рисунок к вышеприведённой статье. Увы прочитав её мне так и не стало ясно как из 512 линий IRQ мы выходим на 256 обработчиков прерываний, какая линия IRQ с каким дескриптором в IDT связана. Есть ли какие нибудь функции для просмотра этого или команды в WinDbg. Команда !PIC отображает 16 IRQ, а !ioapic вообще не понятно что, что только добавляет каши в голову.
     
  5. Коцит

    Коцит Active Member

    Публикаций:
    0
    Регистрация:
    31 янв 2017
    Сообщения:
    130
    От куда число 512, для выбора - байт-же? итого 256.
    А вообще, векторы обработчиков находятся не только в IDT, но и в MMIO apic.
    Сейчас платы строится уже на Serial PCE-Express, а пар-шина PCI (с линейными IRQ) уже уходит в прошлое. Устройства PCIe сигнализируют о прерываниях через MSI, хотя могут и стандартным способом, если чипсет не поддерживает. Режим задаётся в конфигурационном пространстве устройства (функции) PCI.

    Сейчас Local-APIC имеет свою область памяти в верхних адресах, с фиксированной базой 0xFEE00000. ЦП расценивает любое обращение в эту/18-метровую область как запрос на прерывание MSI, а ОС должна контролировать этот регион от случайных вторжений. (кстати, поэтому 32-битная винда не видит больше 3.5 гигов озу, ОС просто затеняет системные регионы от юзера):

    scope.png

    Для запроса прерывания, драйвер устройства PCI посылает процу сообщение MSI. Эта мессага представляет собой обычную запись д'ворда в определённую ячейку MMIO. Адрес ячейки и шаблон сообщения записываются в конфиг/регистры девайса на этапе его конфигурирования, PCI-регистры называются Message_Address/Data соответственно (см.описание в манах IA32/64 vol.3 - Programming Guide). Поддерживающее MSI устройство определяется в конфиг/пространстве полем MSI_CapID (должно быть =5), там-же задаются и ресурсы устройству:

    addr.png
    В модели MSI устройство отправляет сообщение своему драйверу, записывая конкретный адрес памяти. Это действие генерит прерывание в LocalAPIC, после чего Win вызывает ISR с тушкой сообщения и адресом, в который была отправлена мессага. Устройство MSI может отправлять до 32-х различных типов сообщений, определяя конкретное событие (в MSI-X их увеличили вообще до 2048). Этим MSI отличается от линейных прерываний, которые способны передавать только (!)одно событие, а какое именно - драйвер должен определять перебором.

    Поскольку MSI основана на прямом взаимодействии с памятью (и контент доставляется вместе с прерыванием), необходимость в линиях IRQ отпадает, а значит их потолок ограничивает только число векторов прерываний в системе, а не физических линий IRQ APIC. Из-за огромного кол-ва прерываний MSI, это фактически сводит на нет любое преимущество обмена по INT, т.к. данные прямиком доставляются в соответствующий ISR.
    --------------------------------

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

    Под номера линейных IRQ выделяется 1-байт, возможное кол-во 256. Физических линий гораздо меньше (24 у одного apic i82093, но могут соединяться каскадно), поэтому девайсам приходится делить линии по-братски - на некоторых висят по 5-6 устройств. Скачай программу PCIScope, она выводит исчерпывающую инфу о девайсах, в частности пространстве MMIO с полным описание регистров PCI всех устройств. Советую..

    IDT - это 1 сегмент с лимитом 7FFh (32-бит система).
    В ней всего 256 записей, для каждого прерывания свой дескриптор 8-байт.
    Вот как видит её отладчик Syser.. Он не разделяет шлюзы прерываний и ловушек, хотя шлюз-задачи удостоился от отладчика личной метки (Task).

    При генерации прерывания происходит следующее..
    Из регистра IDTR извлекается база IDT, в которой по номеру прерывания определяется его дескриптор. Если бит Present(Р) в найденном дескрипторе сброшен, значит данное прерывание не обрабатывается системой - в этом случае GP#.

    Если Р=1, то проверяется RPL запросившей прерывание задачи, он должен быть меньше\равно DPL дескриптора прерывания, иначе опять GP#. Для исключений и аппаратных прерываний этот пункт игнорируется. Если всё ОК, то стек переключается и в стеке-обработчика сохраняется указатель на стек прерванной задачи SS:ESP, ну и адрес возврата:

    Код (Text):
    1. >> cpu 0
    2. GDT                 Base=8003F000  Limit=03FF
    3. IDT                 Base=8003F400  Limit=07FF
    4. TSS  Selector=0028  Base=80042000  Limit=20AB
    5. LDT  Selector=0000  Base=00000000  Limit=FF394D44
    6. >> idt
    7. IDTBase = 8003F400   Limit = 7FF
    8. -----------------------------------------------------------------
    9. Int   Type      Sel : Offset                 Attributes    Module
    10. 0000  IntG32    0008:804DF360                DPL=0 P       ntoskrnl
    11. 000E  IntG32    0008:F200A5C0(0008:804E167E) DPL=0 P       Syser(ntoskrnl)
    12. 0013  IntG32    0008:804E1CAC(0008:804E18F3) DPL=0 P       ntoskrnl(ntoskrnl)
    13. 001F  IntG32    0008:80712FD0(0008:804E18F3) DPL=0 P       hal(ntoskrnl)
    14. 0020  Reserved  0008:00000000                DPL=0 NP  
    15. ......
    16. 0029  Reserved  0008:00000000                DPL=0 NP  
    17. 00FC  IntG32    0008:804DE4BB                DPL=0 P       ntoskrnl
    18. 00FD  IntG32    0008:80713464(0008:804DE4C2) DPL=0 P       hal(ntoskrnl)
    19. 00FE  IntG32    0008:80713604(0008:804DE4C9) DPL=0 P       hal(ntoskrnl)
    20. 00FF  IntG32    0008:804DE4D0                DPL=0 P       ntoskrnl
    21. 0002  TaskG     0058:0000113E(0008:804DF5C6) DPL=0 P       (ntoskrnl)
    22. 0008  TaskG     0050:00001198(0008:804E06AD) DPL=0 P       (ntoskrnl)
    23. 0012  TaskG     00A0:804E18F3                DPL=0 P       ntoskrnl
    24. ....User DPL=3..............
    25. 0001  IntG32    0008:804DF4DB                DPL=3 P       ntoskrnl
    26. 0003  IntG32    0008:804DF8AD                DPL=3 P       ntoskrnl
    27. 0004  IntG32    0008:804DFA30                DPL=3 P       ntoskrnl
    28. 002A  IntG32    0008:804DEBA2                DPL=3 P       ntoskrnl
    29. 002B  IntG32    0008:804DECA5                DPL=3 P       ntoskrnl
    30. 002C  IntG32    0008:804DEE44                DPL=3 P       ntoskrnl
    31. 002D  IntG32    0008:F7ABCF96(0008:804DF78C) DPL=3 P       SDbgMsg(ntoskrnl)
    32. 002E  IntG32    0008:804DE631                DPL=3 P       ntoskrnl
    33. 002C  IntG32    0008:804DEE44                DPL=3 P       ntoskrnl
    34. 002D  IntG32    0008:F7ABCF96(0008:804DF78C) DPL=3 P       SDbgMsg(ntoskrnl)
    Кроме того, в сегменте TSS имеется 32-байтная карта перенаправления 'INT redirection bit-map'. Она позволяет перенаправлять: 32*8(бит)=256 юзерских прерываний. Одно прерывание - 1 бит, который отображается на соответствующий дескриптор в таблице(IDT). Если бит в битмапе =1, то управление передаётся через дескриптор(IDT) обработчику Р-моды. Если бит нуль, запрос перенаправляется в таблицу векторов R-моды 0:0. Этот битмап ввели для режима V86:

    Код (Text):
    1. >> tss
    2. TR = 0028   BASE = 80042000   LIMIT = 20AB
    3. CR3 = 17CEF000
    4. SS:ESP(0)=0010:F5D58DE0  SS:ESP(1)=4338:D0685000  SS:ESP(2)=C483:FFFF33B5
    5.  
    6. I/O permission map.....:  BASE = 20AC,     SIZE = 0
    7. INT redirection bit-map:  BASE = 80042068, SIZE = 32
    8.                    0 1 2 3 4 5 6 7 - 8 9 A B C D E F
    9.                    ------------------------------------
    10. 0x80042068  0400   0 0 1 0 0 0 0 0 - 0 0 0 0 0 0 0 0  0
    11. 0x8004206A  0018   0 0 0 0 0 0 0 0 - 0 0 0 1 1 0 0 0  1
    12. 0x8004206C  1800   0 0 0 1 1 0 0 0 - 0 0 0 0 0 0 0 0  2
    13. 0x8004206E  0000   0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0  3
    14. ~ ~ ~ ~ ~ ~ ~ ~ ~
    15. 0x80042084  0000   0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0  E
    16. 0x80042086  0000   0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0  F
     
    Последнее редактирование: 28 апр 2018
    _edge и CrawlUp нравится это.
  6. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.788
    Железки слишком сложны что бы самому понять как они устроены и написать обслуживающий код. Сейчас так не делается, это чёрный ящик к которому предоставляется драйвер от производителя.
    По тому же апик - есть системные доки(IA), но думаю их смысла нет даже открывать, это предназначено для разрабов железа. Но не для прикладного прог-ния. Эти железки очень сложны и изменяются с каждой реализацией, описание лишь условно.
     
  7. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.788
    IDT/TSS etc это базовая архитектура, но в этой схеме нет IOAPIC и прочих железячных фич.
     
  8. Коцит

    Коцит Active Member

    Публикаций:
    0
    Регистрация:
    31 янв 2017
    Сообщения:
    130
    не согласен. они просты до неприличия