Використання плаваючої крапки в ядрі Linux


83

Я читаю "Розробку ядра Linux" Роберта Лава і натрапив на такий уривок:

Ні (просте) використання плаваючої крапки

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

На відміну від простору користувача, ядро ​​не має розкоші безперебійної підтримки плаваючої коми, оскільки воно не може легко захопити себе. Використання плаваючої крапки всередині ядра вимагає збереження та відновлення регістрів плаваючої крапки вручну, серед інших можливих справ. Коротка відповідь: не робіть цього! За винятком рідкісних випадків, в ядрі немає операцій з плаваючою комою.

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



2
Книга дещо заплутала проблему, говорячи про "режим". Цілочисельні інструкції завжди доступні, але FPU можна відключити повністю або частково. Жодна корисна функція ніколи не складалася повністю з FP-операцій, наприклад, усі інструкції управління вважаються "цілими числами". Докладніше див. Нижче.
DigitalRoss

@DigitalRoss: Я згоден з термінологією. Дякую за відповідь, до речі, це зробило речі кристально ясними.
NPE

Було б цікаво знати, з чого випливає бажання робити операції з плаваючою комою в ядрі. Спокусливо сказати "поганий дизайн" у сенсі спроби зробити щось у ядрі, що повинно бути зроблено поза ним, але, можливо, є те, що ядро ​​справді повинно робити, де використання FPU буде інноваційним рішенням?
Кріс Страттон,

2
Оскільки про це ніхто не згадував, якщо ви використовуєте FP (або SIMD) всередині ядра, вам потрібно зателефонувати kernel_fpu_begin()/ kernel_fpu_end()до / після вашого коду, щоб переконатися, що стан FPU простору користувача не пошкоджено. Це те, що mdробить код Linux для RAID5 / RAID6.
Пітер Кордес,

Відповіді:


86

Оскільки...

  • багато програм не використовують плаваючу крапку або не використовують її на певному часовому відрізку; і
  • збереження реєстрів FPU та інших станів FPU вимагає часу; отже

... ядро ​​ОС може просто вимкнути FPU. Presto, немає стану для збереження та відновлення, а отже, швидшого переключення контексту. (Це те, що означав режим , це просто означало, що FPU увімкнено.)

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

Під час перемикання контексту він знає, що насправді проходить логіку збереження стану. (І тоді це може знову вимкнути FPU.)

До речі, я вважаю, що пояснення книги, чому ядра (і не лише Linux) уникають операцій FPU, є ... не зовсім точним. 1

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

Цікаво відзначити, як часто потрібно було б зберігати стан FPU, якщо ядро ​​хотіло використовувати FP . . . кожен системний виклик, кожне переривання, кожен перехід між потоками ядра. Навіть якби була необхідність у випадкових FP ядра, 2 , швидше за все , це було б швидше зробити в програмному забезпеченні.


1. Тобто мертвий неправильно.
2. Є декілька відомих мені випадків, коли програмне забезпечення ядра містить арифметичну реалізацію з плаваючою комою . Деякі архітектури реалізують традиційні операційні процеси FPU в апаратному забезпеченні, але залишають деякі складні операції IEEE FP програмним забезпеченням. (Подумайте: денормальна арифметика.) Коли трапляється якийсь дивний випадок IEEE, вони потрапляють у програмне забезпечення, яке містить педантично правильну емуляцію операційних систем, які можуть захоплювати.


16

У деяких конструкціях ядра регістри з плаваючою точкою не зберігаються, коли завдання "ядра" або "системи" відключено. (Це тому, що регістри FP великі і займають як час, так і простір, щоб заощадити.) Отже, якщо ви спробуєте використовувати FP, значення будуть випадковим чином "пуф".

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

З цих причин (і ще декількох) деякі апаратні схеми FP захоплюються, коли ви використовуєте інструкцію FP вперше у завданні. Якщо вам дозволено використовувати FP, тоді у завданні ввімкнено прапор із плаваючою крапкою, якщо ні, то вас розстрілює стрілецький загін.


У Linux використовуйте kernel_fpu_begin()/ kernel_fpu_end()до / після коду, щоб ініціювати збереження / відновлення стану FPU в просторі користувача (і я думаю, що стан FPU вашого ядра проти попередження).
Пітер Кордес,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.