Фрагмент системной страницы, характеризующий сведения о векторах прерываний
#include <sys/syspage.h>
struct intrinfo_entry {
uint32_t vector_base;
uint32_t num_vectors;
uint32_t cascade_vector;
uint32_t cpu_intr_base;
uint16_t cpu_intr_stride;
uint16_t flags;
struct __intrgen_data id();
struct __intrgen_data eoi();
int (*mask)( struct syspage_entry *,
int );
int (*unmask)( struct syspage_entry *,
int );
unsigned (*config)( struct syspage_entry *,
struct intrinfo_entry *,
int );
uint32_t spare[4];
};
Структура содержит информацию системной страницы, характеризующую сведения о векторах прерываний и включает следующие поля:
- vector_base
- Базовый номер логического прерывания, который будет использоваться программами (т.е. вектор прерываний, передаваемый в функцию InterruptAttach()).
- num_vectors
- Количество векторов в записи, которая начинается с базового номера vector_base.
- cascade_vector
- Если запись описывает множество прерываний, которые каскадно подключены к другому контроллеру, эта переменная содержит номер логического прерывания, которое используется для каскадного подключения соответствующего контроллера.
- cpu_intr_base
- Связь между множеством прерываний и представлением источника прерываний на стороне ЦП (подробнее см. Информация о векторах прерываний).
- cpu_intr_stride
- Расстояние между записями векторов прерываний в системах с автоматическим назначением векторов. На платформе x86 со стандартным контроллером 8259 это значение равно
1
, т.е. вектор прерывания, который соответствует аппаратным источникам прерываний, смещается на 1
(например, вектор прерывания 0
соответствует прерыванию 0x30
, вектор прерывания 1
— прерыванию 0x31
и т.д.). В архитектурах, отличных от x86, автоматическое назначение векторов прерываний обычно не используется, и значение этого параметра равно 0
. - flags
- Этот параметр используется в модуле startup-* при генерации точек входа в функции обработки прерываний ядра. Первое множество относится к характеристикам прерываний:
- INTR_FLAG_NMI
- Указывает на немаскируемое прерывание, которое, в отличие от обычных прерываний, невозможно отключать сбросом флага включения прерывания ЦП. Немаскируемые прерывания обычно генерируются событиями, которые требуют немедленного реагирования (ошибка четности, аппаратный сбой или предстоящее отключение питания). Поскольку адрес обработчика немаскируемого прерывания хранится в таблице векторов прерываний BIOS в позиции 02H, немаскируемые прерывания часто обозначаются INT 02H.
Код ядра должен различать обычные и немаскируемые прерывания, поскольку немаскируемое прерывание нельзя игнорировать. Мы настоятельно рекомендуем не использовать вектор немаскируемых прерываний в системах с архитектурой x86 и не поддерживаем его на других платформах.
 | Обычные прерывания с номерами называются маскируемыми и могут игнорироваться, если процессору необходимо завершить текущую задачу. |
- INTR_FLAG_CASCADE_IMPLICIT_EOI
- Указывает на отсутствие необходимости передавать главному контроллеру сигнал окончания прерывания при обработке каскадного прерывания (например, если он передается автоматически). Этот флаг устанавливается только в записи, которая описывает каскадный контроллер.
- INTR_FLAG_CPU_FAULT
- Указывает, что один или несколько векторов, которые определяются в записи, не подключены к аппаратному источнику прерываний, а генерируются при сбое ЦП (например, сбое шины или ошибке четности). Мы настоятельно не рекомендуем применять этот подход к проектированию аппаратной платформы. Он подразумевает, что необходимо проверять исключение в генерируемом потоке кода и передавать контроллеру сигнал завершения прерывания после его идентификации. Фрагмент кода завершения прерывания (EIO) должен дополнительно определять адрес, по которому возник сбой, считывать его тип, а затем передавать сбой. Основной недостаток этого подхода заключается в необходимости вводить дополнительные команды в код.
- INTR_FLAG_SMP_BROADCAST_MASK
- INTR_FLAG_SMP_BROADCAST_UNMASK
- Включение / отключение широковещательных прерываний в SMP-системе.
- INTR_FLAG_MSI
- Отмечает диапазон векторов для использования в качестве векторов MSI.
- INTR_FLAG_IOAPIC
- Указывает, что идентификатор IOAPIC хранится в поле spare[1].
- PPC_INTR_FLAG_400ALT
- Этот флаг аналогичен флагу
INTR_FLAG_NMI
и указывает генератору кода, что необходимо использовать другую последовательность входа в ядро. Это связано с тем, что в процессорах серии PPC400 вместо немаскированных прерываний используется критически важное прерывание, которое можно маскировать. Поскольку критически важное прерывание отличается от «обычного» внешнего прерывания, данный флаг указывает ядру на это различие. - PPC_INTR_FLAG_CI
- Аналогичен флагу
PPC_INTR_FLAG_400ALT
; CI обозначает критически важное прерывание (critical interrupt). - PPC_INTR_FLAG_SHORTVEC
- Указывает, что размер текущего вектора в таблице исключений отличается от обычного (256 байт).
- PPC_INTR_FLAG_APU_MC
- Для внутреннего использования.
Второе множество флагов относится к генерации кода: - INTR_GENFLAG_LOAD_SYSPAGE
- Перед генерацией последовательности команд обнаружения или завершения прерывания необходимо вставлять код, который помещает указатель системной страницы в регистр, чтобы последовательность команд идентификации имела доступ к нему.
 | При использовании callout-ов interrupt_id_dec(), interrupt_id_dec_smp() и interrupt_eoi_dec() необходимо указывать флаг INTR_GENFLAG_LOAD_SYSPAGE в поле genflags структуры intrinfo_entry в коде для конкретной платы. |
- INTR_GENFLAG_LOAD_INTRINFO
- Аналогичен флагу
INTR_GENFLAG_LOAD_SYSPAGE
, но задает загрузку указателя на эту структуру. - INTR_GENFLAG_LOAD_INTRMASK
- Используется только процедурами завершения прерывания устройств, в которых маскирование не выполняется автоматически на уровне микросхемы. Процедура завершения прерывания должна включать только те прерывания, которые разрешены на пользовательском уровне (т.е. управляются с помощью функций InterruptMask() и InterruptUnmask()). Если этот флаг установлен, существующая маска прерываний помещается в регистр, где она доступна процедуре завершения прерывания. Нулевое значение в регистре указывает на то, что следует демаскировать прерывание, а ненулевое — на то, что следует оставить его в маскированном состоянии.
- INTR_GENFLAG_NOGLITCH
- Используется при обработке прерывания с конкретным кодом для проверки его генерации по ошибке или другим контроллером. Если этот флаг установлен, проверка не выполняется — считается, что вход в обработчика прерываний возможен только при фактической генерации прерывания устройством. Если флаг не установлен, выполняется проверка, что устройство действительно является источником прерывания.
- INTR_GENFLAG_LOAD_CPUNUM
- Аналогичен флагу
INTR_GENFLAG_LOAD_SYSPAGE
, но приводит к загрузке указателя на номер процессора, который используется этой структурой. - INTR_GENFLAG_ID_LOOP
- В некоторых контроллерах прерываний имеются регистры с очисткой после чтения. Первая операция чтения возвращает битовый набор ожидающих прерываний, а затем немедленно обнуляет регистр. Поскольку callout идентификатора прерывания возвращает только один номер прерывания, мы можем не обрабатывать некоторые прерывания, если в регистре состояния установлены несколько бит.
Если флаг INTR_GENFLAG_ID_LOOP
установлен, ядро генерирует код возврата в callout идентификатора после завершения обработки прерывания.
В callout-е идентификатора необходимо выделять область чтения/записи для выполнения обычных процедур. По умолчанию в эту область записывается начальное нулевое значение. После запуска callout немедленно проверяет это значение: - если оно не равно нулю, callout с его помощью идентифицирует следующее прерывание для обработки, сбрасывает этот бит, записывает новое значение в область памяти и возвращает идентифицированный номер прерывания.
- если область памяти содержит нулевое значение, callout считывает регистр состояния устройства (после чего он сбрасывается), определяет с его помощью номер прерывания, сбрасывает бит, записывает значение в область памяти и возвращает соответствующий номер прерывания.
- если область памяти и регистр устройства содержат нулевые значения, функция возвращает
-1
, тем самым указывая на отсутствие прерывания.
- id Фрагмент кода, который копируется в функцию обработки прерывания ядра, определяющую источник прерывания, если в результате нескольких аппаратных событий на процессор может поступать одно прерывание. Этот параметр дополнительно изменяется флагами
INTR_GENFLAG_*
. - eoi
- Фрагмент кода, который копируется в функцию обработки прерывания ядра и выполняет действия по завершению прерывания (End Of Interrupt, EOI). Он сообщает контроллеру, что обработка прерывания окончена, и демаскирует уровень прерывания. Код eoi идентифицирует причину сбоя, который обрабатывается как прерывание.
- mask
- Callout, который маскирует источник прерывания на уровне аппаратного контроллера. Этот вызов принимает номера векторов прерываний (от
0
до num_vectors - 1
). - unmask
- Callout, который демаскирует источник прерывания на уровне аппаратного контроллера. Он принимает те же номера векторов, что описанный выше вызов mask.
- config
- Предоставляет информацию о конфигурации уровней отдельных прерываний. Эта функция принимает указатель на системную страницу (1-й аргумент), указатель на запись с информацией о прерывании (2-й аргумент) и уровень прерывания, отсчитываемый от нуля; возвращает битовую маску (подробнее см. INTR_CONFIG_FLAG_* и Информация о векторах прерываний).
Callout может возвращать 0
или следующие флаги в любых сочетаниях: - INTR_CONFIG_FLAG_PREATTACH
- Обычно прерывание маскировано до тех пор, пока к нему не присоединяется процедура с помощью функции InterruptAttach() или InterruptAttachEvent(). Если сбои ЦП транслируются в аппаратное прерывание (не рекомендуется!), прерывание по умолчанию отключено. Установка этого флага приводит к созданию «пустого» соединения с этим источником и, как следствие, демаскированию уровня.
- INTR_CONFIG_FLAG_DISALLOWED
- Запрещает пользовательскому коду присоединяться к уровню прерывания. Обычно этот флаг используется совместно с флагом
INTR_CONFIG_FLAG_PREATTACH
, однако с его помощью можно запрещать пользовательскому коду присоединяться к любому прерыванию. - INTR_CONFIG_FLAG_IPI
- Определяет вектор, который используется в качестве цели межпроцессорного прерывания в SMP-системе.
ЗОСРВ «Нейтрино»
struct syspage_entry
Руководство по разработке модуля startup
Предыдущий раздел: Описание API системной библиотеки