Вбудований асемблер
Іноді нам потрібно використовувати асемблер для того, щоб робити речі, які неможливо зробити за допомогою коду на Rust. Наприклад, зробити HVC (виклик гіпервізора), щоб сказати прошивці вимкнути систему:
#![no_main] #![no_std] use core::arch::asm; use core::panic::PanicInfo; mod exceptions; const PSCI_SYSTEM_OFF: u32 = 0x84000008; // БЕЗПЕКА: Не існує іншої глобальної функції з таким іменем. #[unsafe(no_mangle)] extern "C" fn main(_x0: u64, _x1: u64, _x2: u64, _x3: u64) { // БЕЗПЕКА: тут використовуються тільки оголошені регістри // і нічого не робиться з пам'яттю. unsafe { asm!("hvc #0", inout("w0") PSCI_SYSTEM_OFF => _, inout("w1") 0 => _, inout("w2") 0 => _, inout("w3") 0 => _, inout("w4") 0 => _, inout("w5") 0 => _, inout("w6") 0 => _, inout("w7") 0 => _, options(nomem, nostack) ); } loop {} }
(Якщо ви справді хочете це зробити, скористайтеся крейтом smccc, у якому є оболонки для всіх цих функцій.)
- PSCI — це Arm Power State Coordination Interface, стандартний набір функцій для керування станами живлення системи та CPU, серед іншого. Він реалізований прошивкою EL3 і гіпервізорами на багатьох системах.
 - Синтаксис 
0 => _означає ініціалізацію реєстру до 0 перед виконанням вбудованого асемблеру та ігнорування його вмісту після цього. Нам потрібно використовуватиinout, а неin, оскільки виклик потенційно може знищити вміст реєстрів. - Ця 
mainфункція має бути#[unsafe(no_mangle)]іextern "C", оскільки вона викликається з нашої точки входу вentry.S. _x0–_x3– це значення регістрівx0–x3, які традиційно використовуються завантажувачем для передачі таких речей, як покажчик на дерево пристроїв. Відповідно до стандартної угоди про виклики aarch64 (це те, що вказуєextern "C"), регістриx0–x7використовуються для перших 8 аргументів, що передаються до функції, томуentry.Sне потрібно робити нічого особливого, окрім як переконатися, що він не змінює ці регістри.- Запустіть приклад у QEMU за допомогою 
make qemu_psciвsrc/bare-metal/aps/examples.