Прерывания От Внешних Устройств В Системе X86. Часть 3. Настройка Маршрутизации Прерываний В Чипсете На Примере Coreboot

Продолжаем рассматривать настройку прерываний от внешних устройств в системе x86. В первой части ( «Эволюция контроллеров прерываний» ) теоретические основы контроллеров прерываний и общие термины мы рассмотрели во второй части ( Параметры загрузки ядра Linux ) мы рассмотрели, как ОС выбирает между контроллерами на практике.

В этой части мы рассмотрим, как BIOS настраивает маршрутизацию IRQ для контроллеров прерываний в чипсете.

Ни одна современная компания-разработчик BIOS (AwardBIOS/AMIBIOS/Insyde) не раскрывает исходный код своих программ.

Но, к счастью, есть Основная загрузка — проект по замене проприетарного BIOS свободным ПО.

В его коде мы увидим, как в чипсете настроена маршрутизация прерываний.



Прерывания от внешних устройств в системе x86. Часть 3. Настройка маршрутизации прерываний в чипсете на примере coreboot



Теория

Для начала давайте освежим и дополним наши теоретические знания.

В часть 1 мы обозначили общий путь прерывания для случая PIC и APIC. ПОС:

Прерывания от внешних устройств в системе x86. Часть 3. Настройка маршрутизации прерываний в чипсете на примере coreboot

АПИК:

Прерывания от внешних устройств в системе x86. Часть 3. Настройка маршрутизации прерываний в чипсете на примере coreboot

На этих рисунках отображение устройства PCI → PIR показано абстрактно; на самом деле все несколько сложнее.

На самом деле каждое PCI-устройство имеет 4 линии прерываний (INTA#, INTB#, INTC#, INTD#).

Каждое устройство PCI может иметь до 8 функций, и каждая функция соответствует одному прерыванию INTx#.

Какую линию INTx# будет использовать каждая функция устройства, либо фиксировано в аппаратном обеспечении, либо определяется конфигурацией устройства.



Прерывания от внешних устройств в системе x86. Часть 3. Настройка маршрутизации прерываний в чипсете на примере coreboot

По сути, функции представляют собой отдельные логические блоки.

Например, одно устройство PCI может иметь функцию контроллера Smbus, функцию контроллера SATA или функцию моста LPC. Со стороны ОС каждая функция представляет собой отдельное устройство со своим пространством конфигурации PCI Config. В простейшем (и наиболее распространенном) случае PCI-устройство имеет только одну функцию, прерывание от которой идет по линии INTA#.

Но вообще-то функций в устройстве может быть и больше 4 (как мы уже говорили, до 8), тогда часть из них придется разместить на одной линии INTx# (прерывания PCI могут разделить линию).

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

Систематизируя наши знания, обозначим путь (маршрутизацию) прерываний от любой функции PCI через INTx#→PIRQy→IRQz, где:

  • INTx# — строка INT# (INTA#, INTB#, INTC#, INTD#) PCI-устройство, которое будет использовать функция.

  • PIRQy — линия PIRQ (PIRQA, PIRQB, .

    ) от PIR, к которой подключена линия INTx#

  • IRQz — линия IRQ (0, 1, 2, .

    ) на контроллере прерываний (APIC/PIC), который подключен к линии PIRQy.



Почему нельзя просто подключить INTA#→PIRQA, INTB#→PIRQB,… везде?

Зачем вообще уделять внимание настройке маршрутизации? Допустим, мы решаем не заморачиваться и подключаем все линии прерываний от всех PCI-устройств к одним и тем же линиям PIRQ. Так сказать:
  • ИНТА#→ПИРКА
  • INTB#→PIRQB
  • INTC#→PIRQC
  • INTD#→PIRQD
Как мы уже говорили выше, наиболее распространенным случаем является случай, когда PCI-устройство имеет одну функцию, а его прерывание подключено к линии INTA# (ибо зачем разработчику устройства подключать его иначе?).

Так что если мы вдруг решим запускать все строки так, как мы написали, то почти все прерывания от устройств будут разбиты на строки PIRQA. Допустим, он установлен на IRQ16. Затем каждый раз, когда процессору сообщается, что по линии IRQ16 произошло прерывание, ему придется опрашивать драйверы всех устройств, подключенных к линии IRQ16 (PIRQA), чтобы узнать, есть ли у них прерывание по нему.

Если таких устройств много, это естественно не ускорит реакцию системы на прерывания.

И линии PIRQB-PIRQD в этом случае будут большей частью простаивать.

Для наглядности рисунок, иллюстрирующий проблему:

Прерывания от внешних устройств в системе x86. Часть 3. Настройка маршрутизации прерываний в чипсете на примере coreboot

А ведь все можно было сделать так:

Прерывания от внешних устройств в системе x86. Часть 3. Настройка маршрутизации прерываний в чипсете на примере coreboot

Картина получилась немного запутанной, но суть в том, что мы просто соединяем линии INTx# с PIRQy по циклическому алгоритму (PIRQA, PIRQB, PIRQC, PIRQD, PIRQA, PIRQB, PIRQC, PIRQD, PIRQA, PIRQB, ПИРКК, ПИРКД, .

) Следует отметить, что здесь необходимо учитывать не только то, что каждая линия PIRQ нагружена одинаковым количеством функций PCI. Ведь некоторые функции могут создавать сбои очень редко, а другие постоянно (контроллер Ethernet, например).

В этом случае даже выделение отдельной линии PIRQ для прерываний от такой функции может оказаться вполне оправданным.

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

Что на самом деле должен делать BIOS?

Систематизируем это на рисунке:

Прерывания от внешних устройств в системе x86. Часть 3. Настройка маршрутизации прерываний в чипсете на примере coreboot

  • 1) Укажите, какая линия INTx# используется каждой из функций устройства PCI. Этот пункт не предназначен для внешних PCI-устройств, но для функций PCI-устройств, входящих в состав чипсета, вполне может быть.

  • 2) Настройте сопоставление INTx#→PIRQy для каждого устройства PCI. Стоит отметить, что сигналов PIRQy может быть больше четырех стандартных (PIRQA, PIRQB, PIRQC, PIRQD).

    Например 8: ПИРКА-ПИРКХ.

Сигналы PIRQy поступают на линию IRQz выбранного контроллера прерываний (APIC/PIC).

Поскольку мы хотим поддерживать все возможные способы загрузки (см.

часть 2 ) вам необходимо заполнить оба сопоставления:

  • 3a) Заполните сопоставление PIRQy→IRQz1 для соединения PIR→I/O APIC. Но обычно в этом нет необходимости, так как линии PIRQy привязаны к линии APIC. Общее решение PIRQA→IRQ16, PIRQB→IRQ17,.

    Самое простое решение, потому что.

    Размещая линии PIRQy на линии контроллера ≥16, вам не придется беспокоиться о конфликтах с неразделяемыми прерываниями от ISA-устройств.

  • 3b) Заполните сопоставление PIRQy→IRQz2 для соединения PIR→PIC. Это необходимо обеспечить в случае, если мы используем маршрутизацию через PIC-контроллер.

    Такого однозначного решения, как в случае с APIC, не существует, поскольку в случае с PIC следует помнить о возможности конфликтов с неразделяемыми прерываниями от ISA-устройств.

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

Эти регистры обычно не используются самим устройством.

  • 4) Заполните регистры линии прерывания/контакта прерывания для каждой функции PCI. Как правило, регистр вывода прерывания заполняется автоматически и обычно доступен только для чтения, поэтому, скорее всего, потребуется заполнить только регистр линии прерывания.

    Это необходимо обеспечить на случай, если мы будем использовать маршрутизацию через PIC-контроллер, не предоставляя ОС какой-либо таблицы маршрутизации прерываний (см.

    еще раз).

    часть 2 ).

    Если таблицы предоставлены и это сопоставление согласуется с таблицами маршрутизации ($PIR/ACPI), то ОС часто оставляет их.

Следует отметить, что мы пока не затрагиваем таблицы $PIR/MPtable/ACPI и рассматриваем, как нужно настроить регистры чипсета с точки зрения маршрутизации прерываний перед передачей управления системному загрузчику.

Таблицы прерываний — тема отдельной статьи (возможно, будущей).

Итак, теоретические основы изучены, приступим наконец к практике!

Упражняться

В качестве примера для статей этой серии я использую специальную плату с процессором Intel Haswell i7 и набором микросхем LynxPoint-LP. На этой плате я запускал coreboot совместно с SeaBIOS. Coreboot обеспечивает аппаратно-зависимую инициализацию, а полезная нагрузка SeaBIOS обеспечивает интерфейс BIOS для операционных систем.

В этой статье я не буду описывать процесс настройки coreboot, а лишь попытаюсь на примере показать, какие настройки BIOS следует сделать в чипсете для маршрутизации прерываний IRQ от внешних устройств.

Так как проект coreboot активно развивается, чтобы статья всегда была актуальной, мы будем рассматривать код на примере последней исправленной версии.

4.9 (выпуск от 20 декабря 2018 г.

).

Ближайшая к мне материнская плата — Google Beltino в варианте Panther. Основной папкой для этой материнской платы является папка "src\mainboard\google\beltino" .

Здесь сосредоточены все настройки и код, специфичные для этой платы.

Итак, приступим к рассмотрению того, где настраиваются вышеперечисленные пункты:

1) Укажите, какая линия INTx# используется каждой из функций устройства PCI.

Эта информация определена в файле "src/mainboard/google/beltino/romstage.c" в структуре rcba_config через регистры DxxIP (Device xx Interrupt Pin Register (IP)).

Этот регистр указывает, на какой вывод INTx# (A/B/C/D) каждая функция устройства выводит прерывание.

Возможные варианты (см.

файл "src/южный мост/intel/lynxpoint/pch.h" ):

  
   

0h = No interrupt 1h = INTA# 2h = INTB# 3h = INTC# 4h = INTD#

Один и тот же вывод может использоваться несколькими функциями.

Допускается, что функции не могут использовать вывод прерывания (без прерывания).

Все так, как мы видели на картинке в начале статьи.

Полный код, отвечающий за указанный нами элемент:

/* Device interrupt pin register (board specific) */ RCBA_SET_REG_32(D31IP, (INTC << D31IP_TTIP) | (NOINT << D31IP_SIP2) |

Теги: #открытый исходный код #C++ #Системное программирование #BIOS #PCI #apic #pic #coreboot #irq #interrupts

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.