Як процесор знаходить код ядра після перерви?


13

Коли відбувається переривання, процесор попереджує поточний процес і викликає код ядра для обробки переривання. Як процесор знає, куди ввести ядро?

Я розумію, що є обробники переривань, які можна встановити для кожної лінії переривання. Але оскільки процесор виконує лише "жорстку провідну логіку", має існувати якесь заздалегідь визначене місце, яке вказує або на сам обробник переривання, або на який-небудь код, який виконується перед обробником (оскільки для однієї лінії переривання може бути кілька обробників, я вважаю, що останні).

Відповіді:


13

При запуску ядро ​​ініціалізує таблицю векторів переривань (називається таблицею дескрипторів переривання або IDT на x86), яка вказує на обробник переривання для кожного рядка.

До 80286 IDT завжди зберігався за фіксованою адресою; починаючи з 80286, IDT завантажується за допомогою LIDTінструкції.

Векторні таблиці переривань вказують на одного обробника за лінію переривання; якщо говорити, ядро ​​може вибрати, наприклад, надати обробник переривання, який виконує кілька інших процедур переривання, або надати один обробник, який охоплює деякі або всі переривання. Linux робить це, надаючи загальний обробник переривання, який визначає, яка лінія переривання була викликана, і знаходить відповідний обробник вниз за течією.


1
тож процесор використовує рядок переривання в якості індексу для IDT, ставить запис у ПК і починає виконувати? але чи немає загальної функції, яка працює перед усіма обробниками переривань? для Linux це буде do_IRQ (). це функція, на яку вказує кожен запис IDT, незалежно від лінії переривання?
Філіп Меррі

@PhilippMurry так. Потім ядро ​​використовує власний набір обробників переривань (яких може бути більше одного на рядок), щоб реально обробити переривання, перш ніж повернутися до раніше виконуваного коду.
Адам Марас

Гаразд, тому насправді є два типи обробників переривань: ті, які викликає процесор (завжди do_IRQ ()), і ті, які викликає ядро ​​(те, що я зареєстрував через request_irq ()). ви можете, можливо, додати це до своєї відповіді? Я думаю, тоді я прийму це :) велике спасибі
Філіп Меррі

1
@PhilippMurry Я не знаю, як Linux обробляє переривання (і як розробники ядра включаються в цю систему), але я додав додаткову інформацію в більш широкому розумінні про те, як ядра можуть мати власне управління ISR.
Адам Марас

12

Так, є заздалегідь визначене місце, яке містить адресу коду для переходу: вектор переривання . Залежно від процесора, це може бути конкретне місце у фізичній пам'яті (8088), певне місце у віртуальній пам'яті, регістр процесора, місце в пам'яті, вказане регістром (ARM, 386),…

Деталі залежать від різних процесорів, але основними загальними елементами для обробки переривання в процесорі є:

  • Маска перебиває (так що будь-яке наступне переривання доведеться почекати).
  • Встановіть режим процесора на ядро ​​або режим переривання (якщо процесор має такі режими).
  • Збережіть значення лічильника програми у відомому місці (реєстрі чи пам'яті).
  • Можливо, збережіть значення інших реєстрів або переключиться між банками реєстрів).
  • Виконайте наступну інструкцію (за новим значенням ПК).

1

Інші два відповіді (на момент написання) говорять про перебої та ІДТ. Це правильно, однак у сучасному процесорі Intel-esque не менше трьох способів викликати ядро.

Метод №1: Переривання.

Це пояснено вище. Ви встановлюєте запис у таблиці дескрипторів переривання / вектор переривання, а потім виконуєте програмне переривання для введення в ядро.

Основна перевага цього методу полягає в тому, що типове ядро ​​потрібно мати можливість в будь-якому разі обробляти переривання, і воно працює на архаїчному обладнання.

Спосіб №2: Ворота викликів.

Ворота виклику - це особливий вид селекторного вибору. Ціль виклику потрібно завантажити в глобальну або локальну таблицю дескрипторів сегмента (GDT та LDT відповідно). Якщо потім виконувати вказівку віддаленого виклику, використовуючи ворота виклику як сегмент (зміщення дзвінка ігнорується), це дозволяє викликати більш привілейований код. Ворота викликів надзвичайно гнучкі; архітектура IA-32 має чотири рівні привілеїв, а ворота виклику дозволяють вам телефонувати на будь-якому рівні.

Я не вірю, що Linux ніколи не використовував ворота викликів, але Windows 95 зробив. Послуги ядра Win95 ( krnl386.exeі kernel.dll) фактично працювали в режимі користувача (кільце 3). Найвищий рівень привілеїв (дзвінок 0) використовувався лише для драйверів та мікроядер, які виконували лише комутацію процесу. Виклик драйверів здійснювався за допомогою воріт викликів. Це дозволило застарілому 16-бітовому коду (якого було багато!) Використовувати драйвери Win95 просто за допомогою стандартного дальнього виклику, як і завжди.

Недостатній захист таблиці глобальних дескрипторів став причиною декількох подвигів Windows 95, яким вдалося встановити власні ворота викликів, записавши на пам'ять.

Спосіб №3: SYSCALL / SYSRET та SYSENTER / SYSEXIT

Це два набори інструкцій, самостійно винайдені AMD та Intel, але вони по суті роблять те саме. SYSCALL / SYSRET вийшов першим і був лише AMD, SYSENTER / SYSEXIT був Intel, але AMD реалізує це зараз. Тому я опишу SYSENTER / SYSEXIT.

На відміну від воріт виклику, SYSENTER може використовуватися лише для передачі на дзвінок 0 і може передаватися лише в одне місце. Однак, вона має перевагу в надзвичайно низькій затримці, оскільки на відміну від дзвінка або переривання, він не торкається стека.

Місце передачі встановлюється за допомогою трьох конкретних моделей регістрів: один для інформації про сегмент і один для вказівника інструкції та вказівника стека коду ядра. Оскільки нічого не «штовхається» на стек, код режиму користувача відповідає за те, щоб сказати ядро, куди слід повернутися, передавши покажчик повернення інструкції та покажчик стека в регістри. Ядро відповідає за відновлення покажчика стека, а інструкція SYSEXIT відновлює покажчик інструкцій.

Детальна інформація про інструкції SYSENTER та SYSEXIT.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.