ترقية نظام التشغيل إلى Aarch64

Aarch64 عبارة عن بنية 64 بت من ARM (تسمى أحيانًا arm64). سأخبرك في هذه المقالة كيف يختلف عن ARM "العادي" (32 بت) ومدى صعوبة توصيل نظامك به.


هذه المقالة ليست دليلًا مفصلاً ، بل هي نظرة عامة على وحدات النظام التي يجب إعادة بنائها ، ومدى اختلاف الهندسة ككل عن ARMs العادية 32 بت ؛ كل هذا من تجربتي الشخصية نقل Embox إلى هذا الهيكل. من أجل النقل المباشر لنظام معين ، سيتعين عليك التعامل مع الوثائق بطريقة أو بأخرى ، وفي نهاية المقالة تركت روابط لبعض المستندات التي قد تكون مفيدة.


في الواقع ، هناك اختلافات أكثر من أوجه التشابه ، و Aarch64 هو بنية جديدة أكثر من امتداد 64 بت من ARM المألوف. سابق Aarch64 هو إلى حد كبير Aarch32 (هذا هو امتداد لل ARM 32 بت المعتادة) ، ولكن بما أنني لم يكن لدي خبرة في ذلك ، لن أكتب عن ذلك :)


كذلك في المقالة ، إذا كتبت عن ARM "القديم" أو "القديم" ، أقصد ARM 32 بت (مع مجموعة من أوامر ARM).


سوف أتطرق بإيجاز إلى قائمة التغييرات مقارنةً بـ ARM ذي 32 بت ، ثم سأقوم بتحليلها بمزيد من التفاصيل.


  • أصبحت سجلات الأغراض العامة أكبر بمرتين (الآن تبلغ 64 بت لكل منها) ، وقد تضاعف عددها (أي الآن لا يوجد 16 ، ولكن 32 منهم).
  • رفض مفهوم سجلات المعالج ، والآن يمكن الوصول إليها ببساطة بالاسم ، على سبيل المثال msr vbar_el1, x0 (مقابل mcr p15, 0, %0, c1, c1, 2 )
  • طراز MMU الجديد (غير متصل بالنموذج القديم بأي طريقة ، يجب عليك الكتابة مرة أخرى).
  • في السابق ، كان هناك مستويان للامتياز: المستخدم (المطابق لوضع المعالج USR) والنظام (المطابق لأنظمة SYS ، IRQ ، FIQ ، ABT ، ...) ، الآن أصبح كل شيء أسهل وأكثر تعقيدًا في الوقت نفسه - الآن هناك 4 أوضاع.
  • استبدال AdvSIMD NEON ، تتم عمليات الفاصلة العائمة من خلال ذلك.

الآن أكثر على النقاط.


السجلات ومجموعة التعليمات


سجلات الأغراض العامة هي r0-r30 ، في حين يمكنك الوصول إليها على هيئة 64 بت (x0-x30) أو 32 بت (w0-w30 ، الوصول إلى 32 بت أقل).


تسمى التعليمات المحددة لـ Aarch64 A64. اقرأ وصف التعليمات هنا . بقي الحساب الأساسي وبعض الأوامر الأخرى في لغة التجميع كما هي:


  mov w0, w1 /*    w1  w0 */ add x0, x1, 13 /*   x0  x1   13 */ b label /* ""   "label" bl label /* ""   "label",     x30 */ ldr x3, [x1, 0] /*   x3 ,    x1 */ str x3, [x0, 0] /*   x3  ,    x0 */ 

الآن قليلا عن الاختلافات:


  • ظهر " rzr/xzr/wzr " خاص "صفر" ، وهو صفر عند القراءة (يمكنك استخدام الكتابة إلى السجل ، ولكن لن تتم كتابة نتيجة الحساب في أي مكان).

 subs xzr, x1, x2 /*  x1  x2    NZCV,       */ 

  • لا يمكنك تكديس العديد من السجلات ( stmfd sp!, {r0-r3} ) في الحزمة في وقت واحد ، يجب عليك القيام بذلك في أزواج:

  stp x0, x1, [sp, 16]! stp x2, x3, [sp, 16]! 

  • سجل الكمبيوتر الشخصي (عداد البرنامج ، مؤشر إلى تعليمات التنفيذ الحالية) ليس الآن سجلًا عامًا (كان سابقًا R15) ، وبالتالي ، لا يمكن الوصول إليه باستخدام أوامر عادية ( mov ، ldr ) ، فقط من خلال ret ، bl وهكذا.


  • لا تعرض حالة البرنامج الآن CPSR (هذا السجل غير موجود ببساطة) ، ولكن سجلات DAIF (تحتوي على IRQ ، قناع FIQ ، وما إلى ذلك ، AIF - نفس البتات A ، I ، F من CPSR) ، NZCV (بت سالبة ، صفر ، تحمل ، oVerflow - فجأة ، نفس NZCV من CPSR) وسجل نظام التحكم (SCTLR ، لتمكين التخزين المؤقت ، MMU ، endianness وهلم جرا).



يبدو أن هذه الأوامر تكفي لكتابة أداة تحميل بسيطة يمكنها نقل التحكم إلى رمز مستقل عن النظام الأساسي :)


أوضاع الأداء والتبديل بينهما


مكتوبة بشكل جيد وسائط الأداء في أساسيات ARMv8-A ، وسأحدد باختصار جوهر هذه الوثيقة هنا.


يحتوي Aarch64 على 4 مستويات امتياز (مستوى التنفيذ ، المشار إليها فيما يلي باسم EL).


  • EL3 - Secure Monitor (من المفترض أن البرامج الثابتة تعمل على هذا المستوى)
  • EL2 - المشرف
  • EL1 - نظام التشغيل
  • EL0 - التطبيقات

على نظام تشغيل 64 بت ، يمكنك تشغيل كل من التطبيقات 32 بت و 64 بت. على نظام تشغيل 32 بت ، يمكن تشغيل تطبيقات 32 بت فقط.



تتم التحويلات بين ELs إما بمساعدة من الاستثناءات (مكالمات النظام ، الانقطاعات ، خطأ في الوصول إلى الذاكرة) ، أو بمساعدة أمر الإرجاع من الاستثناء ( eret ).


كل EL لها سجلاتها الخاصة SPSR ، ELR ، SP (أي أنها "سجلات مصرفية").


يتم تقسيم العديد من سجلات النظام أيضًا على EL - على سبيل المثال ، سجل سياق MMU ttbr0 - هناك ttbr0_el2 ، ttbr0_el1 ، وتحتاج إلى الوصول إلى السجل الخاص بك على EL المقابل. الأمر نفسه ينطبق على سجلات حالة البرنامج - DAIF ، NZCV ، SCTLR ، SPSR ، ELR ...


MMU


يدعم Armv8-A MMU ARMv8.2 LPA ، ويمكن الاطلاع على المزيد حول هذا الموضوع في الفصل D5 من دليل ARM Architecture المرجعي لـ Armv8 ، Armv8-A .


باختصار ، يدعم MMU صفحات 4 كيلوبايت (4 مستويات من جداول الذاكرة الظاهرية) و 16 كيلوبايت (4 مستويات) و 64 كيلوبايت (3 مستويات). في أي من المستويات المتوسطة ، يمكنك تحديد كتلة ذاكرة ، وبالتالي لا تشير إلى المستوى التالي من الجدول ، ولكن قطعة كاملة من الذاكرة بالحجم الذي يجب أن يغطيها جدول المستوى التالي. لدي مقال طويل العهد حول الذاكرة الافتراضية ، حيث يمكنك قراءة الجداول ومستويات الترجمة وكل ذلك.


من التغييرات الصغيرة ، رفضوا المجالات ، لكنهم أضافوا أعلامًا مثل الأوساخ القذرة.


بشكل عام ، باستثناء "الكتل" بدلاً من جداول الترجمة الوسيطة ، لم يلاحظ أي تغييرات مفاهيمية خاصة ، MMU كـ MMU.


simd المتقدمة


هناك اختلافات كبيرة في AdvSIMD في NEON القديم ، سواء عند العمل باستخدام الفاصلة العائمة أو مع العمليات المتجهة (SIMD). على سبيل المثال ، إذا كانت D0 السابقة تتألف من S0 و S1 ، و Q0 - من D0 و D1 ، فإن الأمر ليس كذلك الآن: Q0 تقابل D0 و S0 ، لل Q1 - D1 و S0 ، وهكذا. في الوقت نفسه ، يعد دعم VFP / SIMD إلزاميًا ، عن طريق الاتصال بالاتفاق لا يوجد الآن أي نقل معلمات برنامجي (ما كان يطلق عليه "soft float ABI" ، في دول مجلس التعاون الخليجي - flag -mfloat-abi=softfp ) ، لذلك يتعين عليك تنفيذ دعم الأجهزة للنقطة العائمة .


كان هناك 16 سجل من 128 بت:



هناك 32 سجل من 128 بت لكل:



يمكنك قراءة المزيد حول NEON في هذه المقالة ؛ يمكن العثور على قائمة بالأوامر المتوفرة لـ Aarch64 هنا .


العمليات الأساسية مع سجلات الفاصلة العائمة:


  fadd s0, s1, s2 /* s0 = s1 + s2 */ fmul d0, d1, d2 /* d0 = d1 * d2 */ 

عمليات SIMD الأساسية:


  /*  , : NEON,    */ /* q0 = q1 + q2,   --   4     */ vadd.s32 q0, q1, q2 /* : AdvSIMD,    */ /* v0 = v1 + v2,   --   4     */ add v0.4s, v1.4s, v2.4s /*   v1 (  2 64- )    d1 */ addv d1, v1.ds /*     4   0 */ movi v1.4s, 0x0 

منصة


كيمو


QEMU لديه دعم ل Aarch64. إحدى الأنظمة الأساسية موجودة ، بحيث يتم تشغيلها في وضع 64 بت ، يجب عليك بالإضافة إلى ذلك تمرير علامة -cpu cortex-a53 ، مثل هذا:


 qemu-system-aarch64 -M virt -cpu cortex-a53 -kernel ./embox -m 1024 -nographic # ./embox -- ELF-  

ما هو جميل ، يتم استخدام الكثير من الأجهزة الطرفية لهذا النظام الأساسي ، وكانت برامج التشغيل موجودة بالفعل في Embox - على سبيل المثال ، PL011 لوحدة التحكم ، ARM Generic Interrupt Controller ، إلخ. بالطبع ، هذه الأجهزة لها عناوين سجلات أساسية مختلفة وأرقام مقاطعة أخرى ، ولكن الشيء الرئيسي هو رمز السائق يعمل دون تغيير على الهيكل الجديد. عند بدء تشغيل النظام ، يكون عنصر التحكم في EL1.


i.MX8


بسبب هذه القطعة من الحديد ، بدأ النقل إلى Aarch64 - i.MX8MQ Nitrogen8M.



على عكس QEMU ، نقل u-boot التحكم إلى الصورة في EL2 ، علاوة على ذلك ، لسبب ما يتضمن MMU (يتم تعيين جميع الذاكرة من 1 إلى 1) ، مما يخلق بعض المشاكل الإضافية أثناء التهيئة.


لقد دعمت Embox بالفعل i.MX6 ، وكذلك ، في i.MX8 ، جزء من المحيط هو نفسه - على سبيل المثال ، UART و Ethernet ، التي عملت أيضًا (كان علي إصلاح بضعة أماكن حيث كان هناك رابط ضيق لعناوين 32 بت). من ناحية أخرى ، وحدة تحكم المقاطعة مختلفة هناك - ARM GICv3 ، والذي يختلف تمامًا عن الإصدار الأول.


استنتاج


في الوقت الحالي ، لم يكتمل دعم Aarch64 في Embox ، ولكن هناك بالفعل الحد الأدنى من الوظائف - المقاطعات ، MMU ، المدخلات والمخرجات عبر UART. لا يزال هناك الكثير مما يجب وضعه في صيغته النهائية ، ولكن الخطوات الأولى كانت أسهل من البداية مما كانت عليه. هناك وثائق ومقالات أقل بكثير من ARM ، ولكن هناك أكثر من معلومات كافية للتعامل مع كل شيء.


بشكل عام ، إذا كانت لديك خبرة في ARM ، فإن الانتقال إلى Aarch64 مهمة ممكنة. على الرغم من كالمعتاد ، يمكنك أن تتعثر في بعض الأشياء الصغيرة :)


يمكنك تنزيل المشروع لكزه في QEMU من مستودعنا ، إذا كان لديك أي أسئلة - الكتابة في التعليقات ، أو في النشرة الإخبارية ، أو في الدردشة في Telegram (هناك أيضًا قناة ).


روابط مفيدة



PS


من 24 إلى 25 أغسطس ، سنتحدث في TechTrain ، ونستمع إلى عروضنا حوالي مرتين أو ثلاث مرات ، تعال إلى المنصة - سنجيب عن أسئلتك :)

Source: https://habr.com/ru/post/ar463417/


All Articles