⏳ متحف التاريخ: تشريح sched/user_init.rs
هذا الملف هو بمثابة قطعة أثرية من أيام "الإصدار الخامس" (Milestone 05). اليوم، نستخدم محمل الـ ELF المتطور. ولكن قديماً، كيف أثبتنا أن القفز من Ring 0 إلى Ring 3 يعمل؟
1. حقن الأسمبلي المباشر (Machine Code Injection)
بما أنه لم يكن لدينا قرص صلب لقراءة البرامج، قمنا بكتابة البرنامج الأول بالبايتات الخام (Hex):
rust
let code: &[u8] = &[
0x48, 0xC7, 0xC0, 0x01, 0x00, 0x00, 0x00, // mov rax, 1 (SYS_WRITE)
0x0F, 0x05, // syscall
// ...
];
core::ptr::copy_nonoverlapping(code.as_ptr(), base, code.len()); // لصقه في الذاكرة!2. خدعة العودة من المقاطعة (Iretq Jump)
الطريقة الوحيدة للانتقال للمستخدم היא إقناع المعالج أننا كنا أصلاً في وضع المستخدم وتم مقاطعتنا! نقوم بترتيب المكدس وتزوير مسجلات وضع المستخدم، ثم نطلق تعليمة iretq:
rust
unsafe fn jump_to_ring3(entry: u64, user_stack: u64) -> ! {
core::arch::asm!(
"push {ss}", // مقطع البيانات للمستخدم
"push {rsp_user}", // مكدس المستخدم
"push {rflags}", // أعلام المعالج
"push {cs}", // مقطع الكود للمستخدم
"push {rip_user}", // عنوان بداية برنامجنا بالـ Hex
"iretq", // انطلق!
// ...
);
}هذا الملف يوثق لحظة "الولادة" الحقيقية لفضاء المستخدم في QOS!