Переривання для самих маленьких

Сьогодні ми поговоримо про перериваннях процесорів сімейства x86 (-64). Детальніше під катом.
Переривання — це як би сигнал процесору, що треба перервати виконання (тому їх і назвали перериваннями) поточного коду і терміново зробити те, що зазначено в процесорі.

IDT
Усі адреси обробників переривань зберігаються у IDT. Це таблиця, в якій зберігаються 256 (можна більше або менше, але большие значення просто ігноруються) осередків (вектори переривань) з типом і атрибутами переривання, одним просто нульовим значенням, власне адресою обробника переривань і селектором коду в GDT чи LDT, який буде використовувати даний вектор переривань. Тепер трохи про тип і атрибутах.
Тип переривання та атрибути займають 8 біт. Перші 4 біти займають тип:
  • 0b0101: 32-бітний гейт завдання, при появі такого переривання відбувається хардверное перемикання завдання (так-так, є і таке, але його вже давно не використовують)
  • 0b0110: 16-бітний гейт переривання
  • 0b0111: 16-бітний гейт trap'a (я не знаю, як це перекласти на російську мову, вибачте)
  • 0b1110: 32-бітний гейт переривання
  • 0b1111: 32-бітний гейт trap'a
Далі йдуть атрибути. Першим атрибутом є 1 біт, який встановлений в 0 для гейтів переривання і в 1 для інших. Далі йде рівень привілей дескриптора — 2 біта, які визначають мінімальний рівень привілеїв для виклику переривань, і 1 біт, заданий 0 невикористовуваних переривань.
Тепер про те, як процесор викликає обробники.
Припустимо, що ви викликали інструкцію
int 0
в асемблері. Це дасть сигнал процесору, що треба викликати переривання 0, якщо це можливо. Ось послідовність дій, які відбуваються при цьому.
  1. Пошук вектора №0 в ІDT.
  2. Порівняння рівня привілей дескриптора та поточного рівня привілеїв процесора.
  3. Якщо поточний рівень привілеїв процесора менше рівня привілей дескриптора, то просто викликати генеральну помилку захисту і не викликати переривання.
  4. Відбувається збереження адреси повернення, регістрі (E)FLAGS та іншої інформації.
  5. Відбувається перехід на адресу, вказану у векторі №0 ІDT.
  6. Після виконання обробника інструкція
    iret
    повертає управління перерваного кодом.


Виключення
Ще є переривання, що генеруються самим процесором при певних обставинах — виключення. Ось їх список з короткими описами:
  • Ділення на нуль. Генерується при, власне, ділення на нуль.
  • Зневадження виняток. Генеруватися сама не може, використовується для, власне, налагодження.
  • Немаскируемое переривання. Генерується при помилках ОЗУ і невідновних помилки «заліза». Їх неможливо замаскувати за допомогою PIC (Programmable Interrupt Controller — програмований контролер переривань), так як воно йде відразу в процесор, минаючи PIC, але можна просто відключити.
  • Точка зупину. Теж використовується для налагодження, тому що його опкод займає 1 байт, на відміну від інших INT N. Переназначалось DOS-отладчиками для своїх цілей.
  • Переповнення. Генерується інструкцією
    INTO
    , якщо (E)FLAGS включений біт переповнення.
  • Вихід за межі. Генерується при помилці інструкції BOUND.
  • Неприпустимий опкод. Генерується при спробі виконання неприпустимого коду операції.
  • Пристрій недоступний. Зараз не використовується, генерувався при спробі використання операцій із плаваючою точкою на процесорах без FPU.
  • Double fault. Складно перекласти назву. Помилка невосстановима, відбувається при неможливості викликати обробник винятку.
  • Переповнення сегмента співпроцесора. Більше не використовується.
  • Неприпустимий TSS. Сегмент стану задачі поставлено неправильно.
  • Сегмент відсутній. Виникає при спробі завантаження сегмента з бітом Present == 0.
  • Помилка сегмента стека. Виникає при спробі завантаження сегмента з бітом Present == 0 або переповнення стека.
  • Генеральна помилка захисту. Генерується в дуже великому числі випадків, серед них є помилка сегмента, спроба виконання інструкції без необхідних прав, запис туди, куди не треба, спроба доступу до нульового дескриптору GDT і багато іншого.
  • Помилка сторінки. Відбувається при читанні або запису в неіснуючу сторінку пам'яті, спробі доступу до даних без необхідних прав або іншому.
  • Помилка з плаваючою точкою. Відбувається при виконанні інструкції FWAIT або WAIT з бітом №5 в CR0 == 0.
  • Помилка при перевірці на вирівнювання. Відбувається лише в третьому кільці привілеїв процесора, якщо ця помилка, звичайно, включена.
  • Помилка при перевірці машини. Генерується процесором при виявленні «залізних» помилок.
  • Виключення з плаваючою точкою SIMD. Генерується при помилках з 128-бітними числами з плаваючою точкою.
  • Помилка віртуалізації.
  • Помилка безпеки.
  • Потрійна помилка. По суті не є винятком, це навіть не переривання. Відбувається при неможливості викликати Double Fault. Викликає негайну перезавантаження комп'ютера.


IRQ
Існує особливий тип переривань — IRQ (Interrupt ReQuest), або ж апаратні переривання, але я буду їх для стислості називати просто IRQ. Технічно вони майже не відрізняються від будь-яких інших переривань, але генеруються не процесором або самим кодом, а пристроями, підключеними до комп'ютера. Приміром, IRQ №0 генерується PIT (таймер з програмованим інтервалом), IRQ 1 генерується при натисканні клавіші на клавіатурі, а IRQ 12 — при дії з PS/2-мишею.

Програмні переривання
Ще є так звані програмні переривання. Їх, як зрозуміло з назви, програма повинна викликати сама — ніхто за неї не викликає. Такими є, наприклад, системні виклики в деяких системах. В Linux, наприклад, вони висять на векторі 0x80. У багатьох хобі-ОС вони теж висять на векторі 0x80. Тепер трохи відсебеньок — я думаю, що сисвызовы зроблені у вигляді переривань з-за того, що 1) їх так дуже легко викликати, 2) їх можна викликати з будь-якого коду, що працює в ОС — ІDT одна на всю систему.
Інформація взята з OSDev Wiki.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.