Сколько портов процессора необходимо выделить одному контроллеру прерываний i8259

Ввод-вывод

Программирование контроллера прерываний i8259А

Большая популярность применения этой микросхемы в качестве диспетчера аппаратных прерываний в компьютерах на базе микропроцессоров Intel объясняется наличием большого количества различных режимов ее работы, что позволяет сделать подсистему прерываний достаточно гибкой и эффективной. Действительно, если посмотреть на развитие аппаратной части компьютеров, начиная, например, с i8088/8086, то видно, что менялись самые разные компоненты, но подсистема прерываний, основанная на микросхеме i8259А, так и осталась неизменной.
В процессе загрузки компьютера и в дальнейшем во время работы контроллер прерываний настраивается на работу в одном из четырех режимов:

  1. FNM (Fully Nested Mode) — режим вложенных прерываний. В этом режиме каждому входу (уровню) irq0. irq7 присваивается фиксированное значение приоритета, причем уровень irq0 имеет наивысший приоритет, а irq7 — наименьший. Приоритетность прерываний определяет их право на прерывание обработки менее приоритетного прерывания более приоритетным (при условии, конечно, что IF = 1).
  2. ARM (Automatic Rotation Mode) — режим циклической обработки прерываний. В этом режиме значения приоритетов уровней прерываний также линейно упорядочены, но уже не фиксированным образом, а изменяются после обработки очередного прерывания по следующему принципу: значению приоритета последнего обслуженного прерывания присваивается наименьшее значение. Следующий по порядку уровень прерывания получает наивысшее значение, и поэтому при одновременном приходе запросов на прерывания от нескольких источников преимущество будет иметь этот уровень. Это дает возможность обеспечить «равноправие» при обработке прерываний.
  3. SRM (Specific Rotation Mode) — режим адресуемых приоритетов. Этот режим можно рассматривать как вариант режима ARM. В режиме SRM программист или система самостоятельно могут назначить уровень прерывания с наивысшим приоритетом.
  4. PM (Polling Mode) — режим опроса. Этот режим запрещает контроллеру автоматически прерывать работу микропроцессора при появлении прерывания от некоторого внешнего устройства. Для того чтобы микропроцессор смог узнать о наличии того или иного запроса на прерывание, он должен сам обратиться к i8259А для получения содержимого IRR, проанализировать его и далее действовать по своему алгоритму. Данный режим моделирует так называемую опросную дисциплину обработки прерываний. Мы упоминали о ней в начале урока. Согласно этому подходу, инициатором обработки прерывания становится не само прерывание, как при векторной дисциплине, а микропроцессор, причем в определяемые им (точнее, операционной системой, выполняемой на нем) моменты времени.

Программирование контроллера прерываний осуществляется через адресное пространство ввода-вывода посредством двух 8-битовых портов с адресами 20h и 21h. Управление контроллером осуществляется путем посылки в определенной последовательности в эти порты специальных приказов двух типов:

  • ICW (Initialization Control Word) — управляющее слово инициализации. Всего имеются четыре таких слова с жесткой внутренней структурой — ICW1. ICW4. Эти слова предназначены для задания режима работы контроллера. Количество этих слов (4) определено количеством режимов (см. выше).
  • OCW (Operation Control Word) — операционное управляющее слово. Таких слов всего три, и они несут информационную нагрузку для определенных выше режимов работы контроллера прерываний. Обычно их обозначают OCW1. OCW3.

Как вы уже, наверное, успели понять, процесс программирования контроллера жестко регламентирован. Поэтому рассмотрим вначале формат приказов управления, а затем их практическое применение.

Первое.ICW1 — определить особенности последовательности приказов

Состояние битов этого приказа (табл ниже) определяет особенности в последовательности приказов при инициализации контроллера. Данный приказ посылается в порт 20h.

Второе. ICW2 — определение базового адреса

Настало время прояснить еще один принципиальный момент, до этого времени сознательно замалчиваемый. Он связан с принципом определения числового диапазона адресов векторов прерываний для аппаратных прерываний, замкнутых на контроллер прерываний. В реальном режиме работы микропроцессора для хранения указателей (векторов) на процедуры-обработчики прерываний используется специальная область памяти — таблица векторов прерываний. Эта таблица начинается с нулевого адреса оперативной памяти и занимает 1 Кбайт. Среди векторов есть, конечно, и вектора, указывающие на процедуры-обработчики тех прерываний, которые замкнуты на контроллер. Эти вектора располагаются в таблице последовательно, одной группой, и их нумерация начинается с некоторого номера вектора, называемого базовым. Приказ ICW2 (табл. 15.2) позволяет задать номер этого базового вектора для контроллера прерываний в соответствии с тем номером, который назначен соответствующему вектору в таблице векторов прерываний. В реальном режиме работы микропроцессора BIOS в процессе начальной загрузки системы инициализируется ведущий контроллер значением 08h, а ведомый — значением 70h. Теперь понятно, почему обработчику прерываний от таймера соответствует номер вектора 08h в таблице векторов прерываний, хотя физически он замкнут на уровень 0 контроллера i8259A. При желании мы вполне можем изменить значение базового номера на любой не используемый в системе номер, к примеру — 90h. Также следует учитывать, что некорректная установка нового номера этим приказом может полностью нарушить работу всей системы.
Данный приказ посылается в порт 21h.

Как видно, для задания номера базового вектора используются биты с 3 по 7 приказа ICW2. Объяснить это можно тем, что на контроллер замыкаются 8 источников прерываний. Выше мы отметили, что номера векторов, соответствующих прерываниям, замкнутых на контроллер, имеют последовательные номера, начиная с базового. Так, для контроллера, инициализированного значением базового номера 08h, номера векторов в таблице векторов прерываний будут 08h, 09h, 0ah, 0bh и т. д. Отсюда и получается, что для задания базового номера биты 0. 2 использовать нельзя, так как они применяются для формирования адресов векторов прерываний следующих после базового уровней.

Третье. ICW3 — связь контроллеров

Этот приказ предназначен для связи контроллеров в системе с несколькими контроллерами прерываний.
Вариант работы с одной микросхемой i8259А, позволяющий обрабатывать запросы от 8 источников, использовался в ранних системах на базе микропроцессоров i8088/86 (в архитектуре XT). Но i8259А позволяет организовать так называемое каскадное соединение этих микросхем, при котором выход INT одной микросхемы подается на вход одного из уровней irq другой микросхемы (см. рис. 15.1). Это позволяет организовать обработку запросов от большего числа источников. При этом один контроллер является ведущим, а другой — ведомым (тот, который подключен ко входу irq ведущего). Ниже мы разберемся с каскадированием более подробно. Сейчас отметим, что формат приказа ICW3 зависит от того, какой контроллер инициализируется — ведущий (табл. 15.3) или ведомый (табл. 15.4). При инициализации ведущего контроллера ICW3M сообщает, к каким его входам irq подсоединены ведомые контроллеры. Соответственно, при инициализации ведомого контроллера нужна другая форма этого приказа, которая несет информацию о том, к какому входу ведущего подключен данный ведомый контроллер.
Приказ ICW3 посылается в порт 21h.

Четвёртое. ICW4 — дополнительные особенности обработки прерываний

Этот приказ (см. таблицу ниже) определяет дополнительные особенности обработки прерываний контроллером i8259А. Данный приказ посылается в порт 21h.

Таким образом, приказы инициализации задают контроллеру режимы работы в условиях вложенных прерываний. Если требуется конкретизировать порядок обработки для отдельных уровней прерываний, необходимо использовать специальные операционные управляющие слова — OCW, назначение и форматы которых мы рассмотрим ниже.

Сколько портов процессора необходимо выделить одному контроллеру прерываний i8259

Вы используете устаревший браузер. Этот и другие сайты могут отображаться в нём некорректно.
Необходимо обновить браузер или попробовать использовать другой.

Прерывания в защищенном режиме процессора IA-32

Прерывания в защищенном режиме процессора IA-32 — Архив WASM.RU

Вообщем-то на написание этой статьи меня толкнула незавершённость цикла статей http://www.wasm.ru/series.php?sid=20 «Процессор Intel в защищенном режиме». К сожалению, автор не успел рассмотреть детально сам процесс переключения режимов, смены адресации, а так же обработку прерываний, без которой невозможна полноценная работа программы в защищенном режиме. Писать мы будем код для транслятора FASM, сгенерируем чистый бинарный файл и используем его как образ загрузочной дискеты в эмуляторе Bochs или запишем на дискету и загрузим с нее реальный компьютер.

После Power-On-Self-Test процессор генерирует прерывание 19h, обработчик которого управляет дальнейшим ходом загрузки. Он находит первый (в порядке приоритетов, устанавливаемых в BIOS Setup) загрузочный диск, считывает его первый сектор по линейному адресу 07C00 и передает ему управление.

Поскольку процессор при загрузке работает в реальном режиме с 16битной адресацией, нашей задачей будет переключение процессора в защищенный режим с 32битной адресацией, установка обработчиков прерываний и считывание символов с клавиатуры. Так же мы рассмотрим процесс переключения из защищенного режима обратно в реальный.

Итак, сначала некоторые подготовительные действия. Поскольку наше тело загрузят по адресу 7C00 и мы вряд ли уместимся в пределы одного сектора (512 байт), надо обеспечить загрузку всего остального кода с диска. Этот код приведу без дополнительных пояснений, потому что он не совсем в тему нашей статьи:

Теперь в памяти аккуратно распологается весь наш код. Далее нам необходимо включить отключенные (опять же для совместимости) адресные линии, потому что после включения компьютера функционируют только адресные линии A0-A19. Для использования полноценной 32битной адресации нам нужно включить адресную линию A20, установкой бита 1 на порту ввода-вывода 92h:

На время переключения режимов обязательно надо отключить все прерывания, ибо первый же тик таймера свалит нашу систему. Мы отключим не только аппаратные прерывания, но и замаскируем NMI установкой 7-го бита (отсчет веду с нулевого, как всегда; по счету он, конечно, восьмой) в порту 70h:

Далее нам необходимо построить GDT и IDT. Если с GDT все понятно, то про IDT стоит рассказать подробнее. И в реальном и в защищенном режиме в регистре IDTR процессор хранит адрес и лимит таблицы прерываний.

В реальном режиме база IDTR = 00000h, а лимит — 3FFh (размер 400h байт минус еденица). По адресу 00000 находится так называемая таблица векторов прерываний (Interrupt Vector Table), состоящая из 256 векторов. Каждый вектор содержит смещение и сегмент своего обработчика. Обе компоненты занимают 2 байта, таким образом общий размер таблицы составляет 256*2*2 = 1024 = 400h байт.

В защищенном режиме дело обстоит совершенно по-другому. IDTR должен указывать на так называемую дескрипторную таблицу прерываний (Interrupt Descriptor Table, IDT), состоящую из 8байтных дескрипторов для каждого прерывания, которая может содержать шлюзы задачи, прерывания и ловушки. Мы рассмотрим только шлюз прерывания.

Шлюз прерывания описывается следующей структурой:

Как нетрудно заметить, его формат напоминает дескриптор из GDT/LDT, но есть некоторые изменения. Первое и последнее слова дескриптора шлюза прерывания содержат 32битный адрес обработчика прерывания (зеленое поле «смещение» на картинке). Второе слово содержит селектор сегмента кода, где находится код обработчика. Из дескрипторов сегмента унаследованы только следующие биты:

P (Present) — бит присутствия. Если =1, прерывание обрабатывается, если =0 генерируется исключение общей защиты. DPL (Descriptor Privilege Level) — уровень привилегий, о нем позже. D — разрядность.

При генерации прерывания происходит следующее. Из IDTR извлекается база таблицы дескрипторов прерываний. В этой таблице по номеру прерывания находится дескриптор шлюза прерывания. Если его бит Present сброшен, генерируется исключение общей защиты. Если текущий уровень привилегий отличается от уровня привилегий обработчика, происходит переключение стека и в стеке обработчика сохраняется указатель на стек прерванной задачи (SS и ESP). В стек помещаются регистры EFLAGS, CS, EIP. Для некоторых исключений последним в стек помещается еще и код ошибки, который, кстати, должен вытолкнуть обработчик исключения после обработки. Очищается бит TF, для программного прерывания или исключения сбрасываются биты VM, RF и NT. При вызове обработчика через шлюз прерывания очищается бит IF, блокируя дальнейшие маскируемые аппаратные прерывания.

После обработки прерывания обработчик должен вытолкнуть из стека код ошибки, если он там есть, и выполнить инструкцию IRETD, которая восстанавливает регистр флагов из стека (поле IOPL меняется, если CPL=0, IF меняется, если CPL to clear display» на экране:

Далее ставим положение последующего вывода строк на 160 (третья строчка экрана) и переходим в бесконечный цикл ожидания прерываний:

Теперь рассмотрим наши обработчики. Начнем с простого — системный сервис INT 1:

Я думаю, ничего пояснять не надо ) Кроме того, что селектор ES у нас по-прежнему должен указывать в сегмент видеобуфера.

Далее обработчик #GP — покажем злостные ругательства и возвратим управление. Стоит заметить, что управление возвращается на ту же инструкцию, которая и вызвала исключение. Не забываем так же вытолкнуть из стека 4х байтный код ошибки.

Далее мы напишем обработчик IRQ0 от системного таймера. Мы будем инкрементировать байт ES:[0], который является самым первым байтом видеобуфера и будет отображаться в левом верхнем углу экрана:

Где int_EOI — наш «ничегонеделающий» обработчик, который просто сбрасывает заявку в контроллере прерываний.

Рассмотрим подробнее аппаратные прерывания. В компьютере есть программируемый контроллер прерываний, котогрый тесно взаимосвязан с процессором:

При возникновении аппаратного прерывания инициируется выход #INT контроллера. Он напрямую соединен с входом #INTR процессора. Если флаг IF=0, прерывание отбрасыватеся. Процессор опрашивает вход #INTR после выполнения каждой инструкции. Как только обнаруживается сигнал, процессор сразу же подтверждает прерывание через выход #INTA. Контроллер прерываний принимает сигнал INTA и выставляет на шину данных значние номера прерывания. Процессор считывает номер прерывания и входит в прерывание по описанной выше схеме. Контроллер прерываний 8259A имеет восемь входов IRQ0-IRQ7, открытых для внешних источников, выход INT и вход INTA, соединенные с #INTR и #INTA входом и выходом процессора соответственно. При получении внешнего прерывания на шине данных формируется номер прерывания из суммы IRQ-номера входа и некоторого базового значения, которое обычно равно восьми, а в защищенном режиме придется базу сдвинуть до 20h, как именно — смотри ниже. Таким образом, при получении сигнала на входе IRQ0 генерируется прерывания 8 (у нас будет 32), IRQ1 — 9 (33) и так далее.

При поступлении нескольких заявок от разных источников они обрабатываются по порядку начиная с меньшего номера IRQ. Можно также выборочно заблокировать некоторые заявки от отдельных IRQ-входов. Блокировку, или маскирование заявок, а так же выбор заявки с наибольним приоритетом обеспечивают три байтовых регистра контроллера — interrupt Mask register (iMr), interrupt Request register (iRr), interrupt Service register (iSr) и арбитр приоритетов Page Resolver (PR).

Каждый вход IRQ блокируется отдельным битом регистра масок iMr. Если прерывания на входе IRQn разрешены, бит n регистра iMr сброшен. Регистр маски iMr подключен к порту 21h процессора.

Пусть поступление запросов на вход IRQn разрешено — бит n регистра iMr сброшен. Бит n регистра запросов на прерывание iRr установится, когда придет сигнал на вход IRQn. Арбитр приоритетов PR по значению регистра iSr принимает решение о возможности обслуживания запроса. Заявка может быть принята к обслуживанию, если в регистре iSr не зафиксировано заявок с равным или большим номером. Если все нормально, контроллер выставляет сигнал INT. Заявка принимается к обслуживанию при получении сигнала INTA от процессора, на шину данных выставляется номер прерывания, бит n регистра iRr сбрасывается, бит n регистра iSr устанавливается. Установленный бит n регистра iSr теперь блокирует прерывания от входов с номерами большими либо равными n. Блокировку необходимо снять вручную в процедуре обсдуживания прерывания сбросом бита x в регистре iSr, который подключен к порту 20h (нужно записать значение 3Nh, где N — номер входа). На практике обычно пользуются командой неопределенного сброса, реализуемой посылкой в порт 20h значения 20h. По этой команде в iSr сбрасывается заявка с наименьшим номером — которая обслуживается в данный момент как наиболее приоритетная.

8 входов слишком мало, поэтому чаще всего используются два контроллера прерываний 8259A — так называемые ведомый контроллер, выход INT которого подключен к входу IRQ2 ведущего контроллера, который уже в свою очередь общается с процессором. Это называется каскадным включением контроллеров прерываний. Регистр iMr ведомого контроллера доступен через порт 0a1h, а регистр iSr — через 0a0h.

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

Теперь рассмотрим обработчик прерывания IRQ1 от клавиатуры. Прерывание IRQ1 генерируется контроллером клавиатуры каждый раз при нажатии клавиши. Обработчику клавиатуры скан-код считанной клавиши доступен для чтения через порт 060h. Скан-код нужно преобразовать в соответствующий ему ASCII-код символа (если он печатаем) и отобразить на экране. Преобразование произведем по следующей таблице:

Эта таблица содержит символы, индексы которых в таблице соответствуют их сканкодам, либо нули, если символы непечатаемые. Поскольку нажатие клавиш Shift и Caps Lock мы не обрабатываем, поэтому регистр букв у нас различаться не будет. В нашем обработчике нам нужно проверить, нажата ли клавиша (Её скан-код равен еденице). Если это действительно так, то вызовем процедуру переключения в реальный режим и генерации там прерывания 10h для очистки экрана. Если это не так, отобразим символ на экране. В любом случае нужно перед сбросом заявки на прерывание в контроллере прерываний послать подтверздение обработки прерывания контроллеру клавиатуры в порт 061h — необходимо установить и сразу сбросить 7 бит этого порта. После чего необходимо сбросить заявку на прерывание и вернуть управление:

Аппаратные прерывания. Контроллер прерываний

Прерывание означает временное прекращение основного процесса вычислений для выполнения некоторых запланированных или незапланированных действий, вызываемых работой аппаратуры или программы. Механизм прерываний поддерживается на аппаратном уровне. Аппаратные прерывания возникают как реакция микропроцессора на физический сигнал от некоторого устройства (клавиатура, системные часы, клавиатура, жесткий диск и т.д.), по времени возникновения эти прерывания асинхронны, т.е. происходят в случайные моменты времени. Контроллер прерываний предназначен для обработки и арбитража поступающих запросов на обслуживание к центральному процессору от переферийных устройств. Прерывания имеют определённый приоритет, который позволяет контроллеру прерываний отдавать предпочтение в данный момент времени одному устройству, а не другому. В современном компьютере существует до 16 внешних и переферийных устройств, генерирующие прерывания.

Ключевые слова

Текст научной работы

Введение

Прерывание означает временное прекращение основного процесса вычислений для выполнения некоторых запланированных или незапланированных действий, вызываемых работой аппаратуры или программы. Т.е. это процесс, временно переключающий микропроцессор на выполнение другой программы с последующим возвратом к прерванной программе. Нажимая клавишу на клавиатуре, мы инициируем немедленный вызов программы, которая распознает клавишу, заносит ее код в буфер клавиатуры, из которого он считывается другой программой. Т.е. на некоторое время микропроцессор прерывает выполнение текущей программы и переключается на программу обработки прерывания, так называемый обработчик прерывания. После того, как обработчик прерывания завершит свою работу, прерванная программа продолжит выполнение с точки, где было приостановлено ее выполнение. Адрес программы-обработчика прерывания вычисляется по таблице векторов прерываний.

Механизм прерываний поддерживается на аппаратном уровне. В зависимости от источника, прерывания делятся на:

  • аппаратные — возникают как реакция микропроцессора на физический сигнал от некоторого устройства (клавиатура, системные часы, клавиатура, жесткий диск и т.д.), по времени возникновения эти прерывания асинхронны, т.е. происходят в случайные моменты времени;
  • программные — вызываются искусственно с помощью соответствующей команды из программы (int), предназначены для выполнения некоторых действий операционной системы, являются синхронными;
  • исключения — являются реакцией микропроцессора на нестандартную ситуацию, возникшую внутри микропроцессора во время выполнения некоторой команды программы (деление на ноль, прерывание по флагу TF (трассировка)) [1].

Аппаратные средства системы прерываний

Система прерываний — это совокупность программных и аппаратных средств, реализующих механизм прерываний.

К аппаратным средствам системы прерываний относятся:

  • выводы микропроцессора — на них формируются сигналы, извещающие микропроцессор либо о том, что некоторое внешнее устройство «просит уделить ему внимание» (INTR), либо о том, что требуется безотлагательная обработка некоторого события или катастрофическая ошибка (NMI);
  • INTR — вывод для входного сигнала запроса на прерывание;
  • NMI — вывод для входного сигнала немаскируемого прерывания;
  • INTA — вывод для выходного сигнала подтверждения получения сигнала прерывания микропроцессором (этот сигнал поступает на одноименный вход микросхемы контроллера 8259А;
  • программируемый контроллер прерываний 8259А (предназначен для фиксирования сигналов прерываний от восьми различных внешних устройств; он выполнен в виде микросхемы; обычно используют две последовательно соединенные микросхемы, поэтому кол-во возможных источников внешних прерываний до 15 плюс одно немаскируемое прерываний; именно он формирует номер вектора прерывания и выдает его шину данных);
  • внешние устройства (таймер, клавиатура, магнитные диски и т.п.).

Обработка прерываний

Прерывание вызывает ряд событий, которые происходят как в аппаратном, так и в программном обеспечении. На рис. 1 показана типичная последовательность этих событий.

После завершения работы устройства ввода-вывода происходит следующее:

  • Устройство посылает процессору сигнал прерывания;
  • Перед тем как ответить на прерывание, процессор должен завершить исполнение текущей команды (см. рис. 1);
  • Процессор производит проверку наличия прерывания, обнаруживает его и посылает устройству, приславшему это прерывание, уведомляющий сигнал об успешном приеме. Этот сигнал позволяет устройству снять свой сигнал прерывания.

Временная диаграмма программы: медленный ввод-вывод

Рисунок 1. Временная диаграмма программы: медленный ввод-вывод

Теперь процессору нужно подготовиться к передаче управления обработчику прерываний. Сначала необходимо сохранить всю важную информацию, чтобы в дальнейшем можно было вернуться к тому месту текущей программы, где она была приостановлена. Минимальная требуемая информация — это слово состояния программы и адрес очередной выполняемой команды, который находится в программном счетчике. Эти данные заносятся в системный управляющий стек.

Обработка простого прерывания

Рисунок 2. Обработка простого прерывания

Далее в программный счетчик процессора загружается адрес входа программы обработки прерываний, которая отвечает за обработку данного прерывания. В зависимости от архитектуры компьютера и устройства операционной системы может существовать как одна программа для обработки всех прерываний, так может быть и своя программа обработки для каждого устройства и каждого типа прерываний. Если для обработки прерываний имеется несколько программ, то процессор должен определить, к какой из них следует обратиться. Эта информация может содержаться в первоначальном сигнале прерывания; в противном случае для получения необходимой информации процессор должен по очереди опросить все устройства, чтобы определить, какое из них отправило прерывание.

Как только в программный счетчик загружается новое значение, процессор переходит к следующему циклу команды, приступая к ее извлечению из памяти. Так как команда извлекается из ячейки, номер которой задается содержимым программного счетчика, управление переходит к программе обработки прерываний. Исполнение этой программы влечет за собой следующие операции.

Содержимое программного счетчика и слово состояния прерываемой программы уже хранятся в системном стеке. Однако это еще не вся информация, имеющая отношение к состоянию исполняемой программы. Например, нужно сохранить содержимое регистров процессора, так как эти регистры могут понадобиться обработчику прерываний. Поэтому необходимо сохранить всю информацию о состоянии программы. Обычно обработчик прерываний начинает свою работу с записи в стек содержимого всех регистров. Другая информация, которая должна быть сохранена, обсуждается в главе 3, «Описание процессов и управление ими». На рис. показан простой пример, в котором программа пользователя прерывается после выполнения команды из ячейки N. Содержимое всех регистров, а также адрес следующей команды (N+1), в сумме составляющие М слов, заносятся в стек. Указатель стека при этом обновляется, указывая на новую вершину стека. Обновляется и программный счетчик, указывая на начало программы обработки прерывания.

Теперь обработчик прерываний может начать свою работу. В процесс обработки прерывания входит проверка информации состояния, имеющая отношение к операциям ввода-вывода или другим событиям, вызвавшим прерывание. Сюда может также входить пересылка устройствам ввода-вывода дополнительных инструкций или уведомляющих сообщений.

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

Последний этап — восстановление из стека слова состояния программы и содержимого программного счетчика. В результате следующей будет выполняться команда прерванной программы.

Из-за того, что прерывание не является подпрограммой, вызываемой из программы, для полного восстановления важно сохранить всю информацию состояния прерываемой программы. Однако прерывание может произойти в любой момент и в любом месте программы пользователя. Это событие непредсказуемо [2].

Контроллер прерываний

Контроллер прерываний предназначен для обработки и арбитража поступающих запросов на обслуживание к центральному процессору от периферийных устройств. По аналогии функции контроллера прерываний можно сравнить с секретарём какого–нибудь начальника. Секретарь должен решить, кого из посетителей допустить к боссу в первую очередь, а кого и потом, исходя из приоритетов, отдаваемых боссом и статуса самого посетителя. Так и в компьютерной системе, возможна такая ситуация, когда несколько периферийных устройств послали сигнал прерывания или запрос на прерывание. В компьютерной литературе этот сигнал обозначается IRQ (Interrupt Request).

Как уже выше говорилось, прерывания имеют определённый приоритет, который позволяет контроллеры прерываний отдавать предпочтение в данный момент времени одному устройству, а не другому. В современном компьютере существует до 16 внешних и периферийных устройств, генерирующие прерывания. Вот эти устройства:

  • IRQ 0, системный таймер;
  • IRQ 1, клавиатура;
  • IRQ 2, используется для запросов устройств, подключенных каскадом;
  • IRQ 8, часы реального времени;
  • IRQ 9, зарезервировано;
  • IRQ 10, зарезервировано;
  • IRQ 11, зарезервировано;
  • IRQ 12, ps/2–мышь;
  • IRQ 13, сопроцессор;
  • IRQ 14, контроллер «жёсткого» диска;
  • IRQ 15, зарезервировано;
  • IRQ 3, порты COM2,COM4;
  • IRQ 4, порты COM1,COM3;
  • IRQ 5, порт LPT2;
  • IRQ 6, контроллер дисковода;
  • IRQ 7, порт LPT1,принтер.

Здесь сигналы приведены в порядке убывания приоритетов. Можно заметить, что после IRQ 2, следует IRQ 8. Дело в том, что в своё время контроллер прерываний состоял из двух микросхем, одна была подключена к другой. Вот эта вторая микросхема и подключается к линии IRQ 2, образуя каскад. Она обслуживает линии IRQ8–IRQ 15. А затем следуют линии первой микросхемы [3].

Работа контроллера прерывания

Работа контроллеров прерываний рассматривается на основе микросхем фирмы Intel 8259A, которые применялись в теперь уже очень старых компьютерах с процессорами до 386 серии. В этих компьютерах обычно было 2 микросхемы 8259A, подключенных каскадно, то есть одна к другой. Одна из микросхем, подключенная по линии запроса на прерывание непосредственно к процессору является ведущей или мастером. Остальные, подключаются к ведущей через аналогичные выводы, называются ведомыми.

Схема подключения контроллеров прерываний и их взаимодействие с центральным процессором

Рисунок 3. Схема подключения контроллеров прерываний и их взаимодействие с центральным процессором

На рисунке 3 изображена схема подключения контроллеров прерываний и их взаимодействие с центральным процессором. Сигналы на прерывание от периферийных устройств или ведомых контроллеров поступают на входы IR0–IR7 ведущего контроллера. Внутренняя логика ведущего контроллера обрабатывает поступившие запросы с точки зрения приоритета. Если приоритет запроса устройства достаточен, то на выходе INT контроллера вырабатывается сигнал, поступающий на вход INTR процессора. В противном случае, запрос блокируется.

Если процессор разрешает прерывания, то после завершения выполнения текущей команды, он вырабатывает по линии INTA последовательность сигналов, которая переводит ведомый контроллер в состояние невосприимчивости к поступающим новым запросам на прерывание, а кроме того, на линию данных выводится информация из внутренних регистров контроллера по которой процессор распознаёт тип прерывания.

Разрешение на прерывание процессор передаёт контроллеру прерываний через контроллер шины. Сигнал RD предназначен для того, чтобы контроллер прерываний поместил на шину данных содержимое внутренних регистров. По сигналу WR контроллер прерываний, наоборот, принимает данные с одноимённой шины и записывает их во внутренние регистры. Соответственно, это влияет на режим работы контроллера прерываний.

Вход CS подключается к шине адреса и по этому сигналу происходит идентификация конкретного контроллера прерываний. Вход A0 указывает на порт контроллера прерываний в пространстве ввода–вывода.

Входы IR0–IR7 предназначены для приёма запросов на прерывание от периферийных устройств и ведомых контроллеров.

Выходы CAS0–CAS2 предназначены для идентификации конкретного ведомого контроллера [4].

В статье рассмотрены аппаратные прерывания и устройство, функции, работу контроллера прерываний. Данный контроллер прерываний появился ещё в первых PC–совместимых компьютерах. С тех пор, и процессоры, и сам компьютер во многом изменились, хотя некоторые моменты остались. Поэтому, для того, чтобы было понятней и была рассмотрена организация контроллера прерываний 8295A.

На приведенной выше схеме показаны сигналов приходящие не только на ведомый и ведущий контроллеры прерываний, но и на остальные ведомые. Однако на вашем компьютере или ноутбуке на самом деле 2 контроллера прерываний, как выше указывалось: ведущий и ведомый. Но можно создавать свои компьютерные системы, используя таким образом до 64 ведомых контроллеров прерываний.

В современных компьютерах уже давно функции контроллера прерываний выполняют не микросхемы 8259A, а южный мост. Однако, для всех программ и устройств всё остаётся по–прежнему. Более того, контроллер прерываний можно программировать, и обращаться к внутренним регистрам и портам необходимо точно также, как и к контроллеру 8259A [5].

Заключение

В данной работе были рассмотрены прерывания, а именно аппаратные средства обработки прерываний и принцип обработки прерываний. Также рассмотрены контроллеры прерываний и принцип их работы.

Прерывание означает временное прекращение основного процесса вычислений для выполнения некоторых запланированных или незапланированных действий, вызываемых работой аппаратуры или программы. Механизм прерываний поддерживается на аппаратном уровне. Аппаратные прерывания возникают как реакция микропроцессора на физический сигнал от некоторого устройства (клавиатура, системные часы, клавиатура, жесткий диск и т.д.), по времени возникновения эти прерывания асинхронны, т.е. происходят в случайные моменты времени.

Контроллер прерываний предназначен для обработки и арбитража поступающих запросов на обслуживание к центральному процессору от периферийных устройств. Прерывания имеют определённый приоритет, который позволяет контроллеру прерываний отдавать предпочтение в данный момент времени одному устройству, а не другому. В современном компьютере существует до 16 внешних и периферийных устройств, генерирующие прерывания.

Прерывания от внешних устройств в системе x86. Часть 1. Эволюция контроллеров прерываний

В данной статье хотелось бы рассмотреть механизмы доставки прерываний от внешних устройств в системе x86 и попытаться ответить на вопросы:

  • что такое PIC и для чего он нужен?
  • что такое APIC и для чего он нужен? Для чего нужны LAPIC и I/O APIC?
  • в чём отличия APIC, xAPIC и x2APIC?
  • что такое MSI? В чём отличия MSI и MSI-X?
  • как с этим связаны таблицы $PIR, MPtable, ACPI?

Введение

Все мы знаем, что такое прерывание. Для тех, кто нет, цитата из википедии:

Прерывание (англ. interrupt) — сигнал от программного или аппаратного обеспечения, сообщающий процессору о наступлении какого-либо события, требующего немедленного внимания. Прерывание извещает процессор о наступлении высокоприоритетного события, требующего прерывания текущего кода, выполняемого процессором. Процессор отвечает приостановкой своей текущей активности, сохраняя свое состояние и выполняя функцию, называемую обработчиком прерывания (или программой обработки прерывания), которая реагирует на событие и обслуживает его, после чего возвращает управление в прерванный код.

В зависимости от источника возникновения сигнала прерывания делятся на:

  • асинхронные, или внешние (аппаратные) — события, которые исходят от внешних аппаратных устройств (например, периферийных устройств) и могут произойти в любой произвольный момент: сигнал от таймера, сетевой карты или дискового накопителя, нажатие клавиш клавиатуры, движение мыши. Факт возникновения в системе такого прерывания трактуется как запрос на прерывание (англ. Interrupt request, IRQ) — устройства сообщают, что они требуют внимания со стороны ОС;
  • синхронные, или внутренние — события в самом процессоре как результат нарушения каких-то условий при исполнении машинного кода: деление на ноль или переполнение стека, обращение к недопустимым адресам памяти или недопустимый код операции;

В данной статье хотелось бы обсудить внешние прерывания IRQ.

Зачем они нужны? Допустим мы хотим выполнить какое-либо действие со входным пакетом для сетевой карты, когда он придёт. Чтобы не спрашивать сетевую карту постоянно «есть ли у тебя новый пакет?» и не тратить на это ресурсы процессора, можно использовать прерывание IRQ. Линия прерываний устройства соединяется с линией INTR процессора, и при получении пакета сетевая карта «дергает» эту линию. Процессор понимает, что для него есть информация и читает пакет.

Но что делать если устройств много? На все внешние устройства ножек процессора не напасёшься.

Чтобы решить эту проблему, придумали микросхему — контроллер прерываний.

Первой была микросхема Intel 8259 PIC. 8 входных линий (IRQ0-7), и одна выходная, соединяющая контроллер с линией INTR процессора. Когда возникает прерывание от какого-либо устройства, 8259 дёргает линию INTR, процессор понимает, что какое-то устройство сигнализирует о прерывании и опрашивает PIC, чтобы понять по какой именно ножке IRQx возникло прерывание. Появляется дополнительная задержка на данный опрос, но зато количество линий прерываний увеличивается до 8.

Однако 8 линий быстро оказалось мало, и чтобы увеличить их количество стали использовать 2 контроллера 8259 (master и slave) соединённых каскадно (Dual PIC).

IRQ с 0 по 7 обрабатываются первым Intel 8259 PIC (master), а IRQ с 8 по 15 вторым 8259 PIC (slave). О возникновении прерывания CPU сигнализирует только master. Если возникло прерывание на линиях 8-15, второй PIC (slave) сигнализирует о прерывании мастеру по линии IRQ 2, и тот уже в свою очередь сигнализирует CPU. Это каскадное прерывание отнимает одну из 16 линий, но в итоге даёт 15 доступных прерываний для устройств.

Схема утвердилась, и именно её имеют ввиду, когда говорят сейчас о PIC (Programm Interrupt Controller). Впоследствии контроллеры 8259 получили некоторые улучшения, и стали называться 8259A, а эта схема вошла в состав чипсета. Во времена когда основной шиной для подключения внешних устройств была шина ISA, такой системы в целом хватало. Надо было лишь следить, чтобы разные устройства не подключались на одну линию IRQ для избежания конфликтов, так как прерывания ISA не разделяемые.

Обычно раскладка прерываний под устройства была более менее стандартная

Пример (взят отсюда):
IRQ 0 — system timer
IRQ 1 — keyboard controller
IRQ 2 — cascade (прерывание от slave контроллера)
IRQ 3 — serial port COM2
IRQ 4 — serial port COM1
IRQ 5 — parallel port 2 and 3 or sound card
IRQ 6 — floppy controller
IRQ 7 — parallel port 1
IRQ 8 — RTC timer
IRQ 9 — ACPI
IRQ 10 — open/SCSI/NIC
IRQ 11 — open/SCSI/NIC
IRQ 12 — mouse controller
IRQ 13 — math co-processor
IRQ 14 — ATA channel 1
IRQ 15 — ATA channel 2

Конфигурация и работа с микросхемами 8259 осуществляется через I/O порты:

Чип Регистр I/O port
Master PIC Command 0x0020
Master PIC Data 0x0021
Slave PIC Command 0x00A0
Slave PIC Data 0x00A1

→Документацию на 8259A можно найти тут

На смену шине ISA пришла шина PCI. И количество устройств явно стало превосходить число 15, плюс в отличие от статической шины ISA в данном случае случае устройства могут добавляться в систему динамически. Но к счастью в данной шине прерывания могут быть разделяемыми (то есть к одной линии IRQ можно подсоединить несколько устройств). В итоге чтобы решить проблему нехватки линий IRQ, прерывания ото всех PCI устройств решили группировать в линии PIRQ (Programmable Interrupt Request).

Допустим у нас 4 линии прерываний свободно на PIC контроллере, а PCI устройств 20 штук. Мы объединяем прерывания по 5 устройств на линию PIRQx и подключаем линии PIRQx к контроллеру. При возникновении прерывания на линии PIRQx процессору придётся опросить все устройства подключённые к данной линии, чтобы понять от кого именно пришло прерывание, но в целом это решает задачу. Устройство осуществляющее связывание линий прерываний PCI в линии PIRQ часто называют PIR router.

В данном методе надо следить, чтобы линии PIRQx не подсоединялись к линиям IRQx на которых уже заведены прерывания ISA (так как это вызовет конфликты), и чтобы линии PIRQx были сбалансированы (ведь чем больше устройств мы подключили к одной линии PIRQ, тем больше устройств надо будет опрашивать процессору, чтобы понять, какое именно из этих устройств вызвало прерывание).

Замечание: на рисунке маппинг PCI device -> PIR изображён абстрактно, потому что на самом деле он несколько сложнее. В реальности каждый PCI device имеет 4 линии прерываний (INTA, INTB, INTC, INTD). У каждого PCI устройства (device) может быть до 8 функций (functions) и вот каждой функции соответствует уже одно прерывание INTx. Какую именно INTx будет дёргать каждая функция устройства определяется конфигурацией чипсета.

По сути функции это отдельные логические блоки. Например в одном PCI устройстве может быть функция Smbus controller, функция SATA controller, функция LPC bridge. Со стороны ОС каждая функция — это как отдельное устройство со своим конфигурационным пространством PCI Config.

Информацию о роутинге прерываний на PIC контроллере BIOS передавал ОС с помощью таблицы $PIR и с помощью заполнения регистров 3Ch (INT_LN Interrupt Line (R/W)) и 3Dh (INT_PN Interrupt Pin (RO)) конфигурационного пространства PCI для каждой функции. Спецификация о таблице $PIR раньше была на сайте Microsoft, но сейчас её там уже нет. Содержимое строк таблицы $PIR можно понять из PCI BIOS Specification [4.2.2. Get PCI Interrupt Routing Options] или почитать вот тут

Предыдущий метод работал пока не появились многопроцессорные системы. Дело в том, что по своему устройству PIC может передавать прерывания только на один главный процессор. А хотелось бы, чтобы нагрузка на процессоры от обработки прерываний была сбалансированной. Решением данной задачи стал новый интерфейс APIC (Advanced PIC).

Для каждого процессора добавляется специальный контроллер LAPIC (Local APIC) и для маршрутизации прерываний от устройств добавляется контроллер I/O APIC. Все эти контроллеры объединяются в общую шину с названием APIC (новые системы сейчас уже соединяются по стандартной системной шине).

Когда прерывание от устройства приходит на вывод I/O APIC, контроллер направляет прерывание в LAPIC одного из процессоров. Наличие I/O APIC позволяет сбалансировано распределять прерывания от внешних устройств между процессорами.

Первой микросхемой APIC был 82489DX, это был отдельный чип, соединяющий в себе LAPIC и I/O APIC. Для создания системы из 2 процессоров нужно было 3 таких микросхемы. 2 функционировали бы как LAPIC и одна как I/O APIC. Позднее функциональность LAPIC была напрямую включена в процессоры, а функциональность I/O APIC была оформлена в чип 82093AA.

I/O APIC 82093AA содержала 24 входных вывода, а архитектура APIC могла поддерживать до 16 CPU. Для поддержки совместимости со старыми системами, прерывания 0

15 отвели под старые прерывания ISA. А прерывания от PCI устройств стали выводить на линии IRQ 16-23. Теперь можно было не задумываться о конфликтах прерываний от ISA и PCI устройств. Также благодаря увеличенному количеству свободных линий прерываний возможно стало также увеличить количество линий PIRQx.

Программирование I/O APIC и LAPIC осуществляется через MMIO. Регистры LAPIC расположены обычно по адресу 0xFEE00000, регистры I/O APIC по адресу 0xFEС00000. Хотя в принципе все эти адреса возможно переконфигурировать.

Как и в случае с PIC первоначально отдельные микросхемы позже вошли в состав чипсета.

В дальнейшем архитектура APIC получила модернизацию и новый вариант получил название xAPIC (x — extended). Сохранена обратная совместимость с предыдущим вариантом. Количество возможных CPU в системе увеличилось до 256.

Следующий виток развития архитектуры получил название x2APIC. Количество возможных CPU в системе увеличилось до 2^32. Контроллеры могут работать в режиме совместимости с xAPIC, а могут в новом режиме x2APIC, где программирование LAPIC осуществляется не через MMIO, а через MSR регистры (что гораздо быстрее). Cудя по этой ссылке для работы этого режима необходима поддержка IOMMU.

Следует заметить, что в системе может быть несколько контроллеров I/O APIC. Например один на 24 прерывания в южном мосту, другой на 32 в северном. В контексте I/O APIC прерывания часто обозначаются GSI (Global System Interrupt). Так вот в такой системе будут GSI 0-55.

Есть ли в CPU встроенный LAPIC и какой именно архитектуры можно понять по бит-флагам в CPUID.
Чтобы система могла обнаружить LAPIC и I/O APIC, BIOS должен представить информацию о них системе либо через таблицу MPtable (старый метод), либо через таблицу ACPI (таблицу MADT в данном случае). Помимо общей информации, и в MPtable и в ACPI (на этот раз в таблице DSDT) должна содержаться информация о роутинге прерываний, то есть информация о том, какое устройство сидит на какой линии прерываний (аналог таблицы $PIR).

О таблице MPTable можно почитать в официальной спецификации. Раньше спецификация была на сайте Intel, а сейчас её можно найти только в архиве. Спецификация ACPI сейчас расположена на сайте UEFI (текущая версия 6.2). Следует отметить, что с помощью ACPI можно указать роутинг прерываний и для систем без APIC (вместо использования таблицы $PIR).

Предыдущий вариант с APIC хорош, но не лишён недостатков. Все эти линии прерываний от устройств усложняют схему, и увеличивают вероятности ошибок. На смену шины PCI пришёл PCI express, в котором линии прерываний решили просто-напросто убрать. Чтобы сохранить совместимость, сигналы о возникновении прерываний (INTx#) эмулируются отдельными видами сообщений. В этой схеме логическое сложение линий прерываний, которое раньше производилось физическим соединением проводов, легло на плечи PCI мостов. Однако поддержка legacy INTx прерываний — это лишь поддержка обратной совместимости с шиной PCI. На деле PCI express предложил новый метод доставки сообщений о прерываниях — MSI (Message Signaled Interrupts). В этом методе для сигнализации о прерывании устройство просто производит запись в MMIO область отведённую под LAPIC процессора.

Если раньше на одно PCI устройство (то есть на все его функции) выделялось всего 4 прерывания, то сейчас сейчас стало возможным адресовать до 32 прерываний.

В случае с MSI нет никакого sharing для линий, каждое прерывание соответствует своему устройству.

Прерывания MSI решают также ещё одну проблему. Допустим устройство проводит memory-write транзакцию, и хочет сообщить о её завершении через прерывание. Но write транзакция может быть задержана на шине в процессе передачи (о чём устройство никак не знает), и сигнал о прерывании придёт до процессора раньше. Таким образом CPU будет читать ещё невалидные данные. В случае если используется MSI, информация об MSI передаётся также как и данные, и раньше прийти просто не сможет.

Следует заметить, что прерывания MSI не могут работать без LAPIC, но использование MSI может заменить нам I/O APIC (упрощение дизайна).

В последствии данный метод получил расширение MSI-X. Теперь каждое устройство может иметь до 2048 прерываний. И стало возможным указывать индивидуально каждому прерыванию на каком процессоре оно должно выполняться. Это может быть очень полезно для высоконагруженных устройств, например сетевых карт.

Для поддержки MSI не требуется никаких дополнительных таблиц BIOS. Но устройство должно сообщить о поддержке MSI в одной из Capability в своём PCI Config, а драйвер устройства должен поддерживать работу с MSI.

Заключение

В данной статье мы рассмотрели эволюцию контроллеров прерываний, и получили общую теоретическую информацию о доставке прерываний от внешних устройств в x86 системе.

В следующей части мы посмотрим как на практике задействовать в Linux каждый из описанных контроллеров.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *