Расположение кода обработки прерывания в ядре Linux для архитектуры x86

Я занимаюсь этим исследованием, пытаясь найти в ядре Linux код, реализующий обработку прерываний; в частности, я пытаюсь найти код, отвечающий за обработку системного таймера.

Согласно http://www.linux-tutorial.info/modules.php?name=MContent&pageid=86

Ядро обрабатывает прерывания так же, как и исключения: все регистры общего назначения помещаются в системный стек и вызывается общий обработчик прерываний. > Текущий приоритет прерывания сохраняется, и загружается новый приоритет. Это предотвращает> прерывания с более низким уровнем приоритета от прерывания ядра, пока оно обрабатывает это прерывание. Затем вызывается реальный обработчик прерывания.

Я ищу код, который помещает в стек все регистры общего назначения, а также общий код обработки прерываний.

По крайней мере, размещение регистров общего назначения в стеке не зависит от архитектуры, поэтому я ищу код, связанный с архитектурой x86. На данный момент я смотрю исходники ядра версии 3.0.4, но любая версия, вероятно, подойдет. Я начал искать в kernel / irq / handle.c, но не вижу ничего похожего на сохранение регистров; похоже, что он вызывает зарегистрированный обработчик прерывания.


person ryanmcfall    schedule 24.01.2012    source источник
comment
Под независимой от архитектуры вы на самом деле имели в виду зависимый, верно?   -  person Ben Voigt    schedule 25.01.2012


Ответы (2)


Я ищу код, который помещает в стек все регистры общего назначения.

Аппаратное обеспечение сохраняет текущее состояние (включая регистры) перед выполнением обработчика прерывания. Код не задействован. И когда прерывание завершается, оборудование считывает состояние обратно из того места, где оно было сохранено.

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


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

См. Руководство разработчика программного обеспечения для архитектур Intel® 64 и IA-32, начало на стр. 6-15.

person Ben Voigt    schedule 25.01.2012
comment
Я думаю, что вы, скорее всего, правы, теперь, когда я вспомнил о существовании инструкции iret в архитектуре x86, это кажется возможным (без этой инструкции я не вижу возможности для оборудования узнать, когда завершится обработчик прерывания). Известно ли вам, где находится какая-либо документация по архитектуре x86, которая явно документирует действия, предпринимаемые ЦП при обнаружении сигнала прерывания? - person ryanmcfall; 25.01.2012
comment
@BenVoight: Спасибо за указатель; ваш комментарий в ответе Дэвида Шварца о необходимости аппаратного обеспечения для сохранения регистра eip перед передачей управления обработчику прерывания имеет смысл. Вы упомянули, что обработчик прерывания отвечает за сохранение и хранение любых регистров, которые он явно использует. Но что, если переключение процесса происходит в результате обработки прерывания? В этом случае кажется, что ВСЕ регистры нужно поместить в стек исходящего процесса; код, который фактически управляет блоками управления процессом, похоже, этого не делает. - person ryanmcfall; 25.01.2012
comment
@ryanmcfall: Я не думаю, что они хранятся в стеке потоков, если бы они были, у вас могло бы быть переполнение стека во время переключения контекста (фу!). Вместо этого в блоке управления потоком будет выделено место для этих регистров и, вероятно, MOV инструкции вместо _2 _ / _ 3_. - person Ben Voigt; 25.01.2012
comment
@BenVoight Я не вижу этих инструкций в функции context_switch (kernel / sched.c) или в коде манипуляции TCB (switch_to); единственная возможность, похоже, заключается в вызове arch_start_context_switch (prev); в context_switch; насколько я могу судить, похоже, что это работает: PVOP_VCALL1(pv_cpu_ops.start_context_switch, prev); что прямо сейчас я не копал достаточно глубоко, чтобы найти правильную реализацию start_context_switch. К сожалению, я, вероятно, не могу больше тратить время на то, чтобы понять это, поэтому пока я буду считать это ответом. - person ryanmcfall; 25.01.2012

32-битные версии находятся в arch/i386/kernel/entry_32.S, 64-битные версии в entry_64.S. Найдите различные ENTRY макросы, которые отмечают точки входа в ядро.

person David Schwartz    schedule 24.01.2012
comment
Спасибо, я нашел в этих файлах макрос SAVE_ALL; Однако я не уверен, действительно ли они вызываются кодом обработки прерывания. Ответ Бена Войта выше, похоже, указывает на то, что это не так. - person ryanmcfall; 25.01.2012
comment
@ryanmcfall: должно быть очевидно, что обработчик прерывания не может сохранить регистр EIP, поскольку он уже был изменен, чтобы указывать на инструкцию в обработчике прерывания. То же самое относится и к нескольким другим регистрам, которые изменяются при активации обработчика прерывания. Остальные регистры должны быть сохранены внутри обработчика, что является оптимизацией, поскольку необходимо сохранять и восстанавливать только регистры, измененные обработчиком. - person Ben Voigt; 25.01.2012