بنية AVF

يوفر Android تطبيقًا مرجعيًا لجميع المكونات اللازمة لتنفيذ Android Virtualization Framework. يقتصر هذا التنفيذ حاليًا على ARM64. تشرح هذه الصفحة بنية الإطار.

خلفية

تسمح بنية Arm بما يصل إلى أربعة مستويات استثناء، مع كون مستوى الاستثناء 0 (EL0) هو الأقل امتيازًا، ومستوى الاستثناء 3 (EL3) هو الأكثر. يعمل الجزء الأكبر من قاعدة بيانات Android (جميع مكونات مساحة المستخدم) عند EL0. أما باقي ما يسمى عادة "Android" فهو نواة Linux، والتي تعمل على EL1.

تسمح طبقة EL2 بإدخال برنامج Hypervisor الذي يتيح عزل الذاكرة والأجهزة إلى وحدات pVM فردية عند EL1/EL0، مع ضمانات قوية للسرية والنزاهة.

مراقب الأجهزة الافتراضية

تم بناء الجهاز الظاهري المحمي القائم على kernel (pKVM) على برنامج Hypervisor Linux KVM ، والذي تم توسيعه مع القدرة على تقييد الوصول إلى الحمولات النافعة التي تعمل في الأجهزة الافتراضية الضيف التي تحمل علامة "محمية" في وقت الإنشاء.

يدعم KVM/arm64 أوضاع تنفيذ مختلفة اعتمادًا على توفر ميزات معينة لوحدة المعالجة المركزية (CPU)، وهي ملحقات مضيف المحاكاة الافتراضية (VHE) (ARMv8.1 والإصدارات الأحدث). في أحد هذه الأوضاع، والمعروف باسم الوضع غير VHE، يتم فصل كود برنامج Hypervisor من صورة kernel أثناء التمهيد وتثبيته في EL2، بينما يعمل kernel نفسه عند EL1. على الرغم من أنه جزء من قاعدة بيانات Linux، إلا أن مكون EL2 لـ KVM هو مكون صغير مسؤول عن التبديل بين عدة EL1s، ويتم التحكم فيه بالكامل بواسطة نواة المضيف. يتم تجميع مكون برنامج Hypervisor مع Linux، ولكنه موجود في قسم ذاكرة منفصل ومخصص لصورة vmlinux . تستفيد pKVM من هذا التصميم من خلال توسيع كود برنامج Hypervisor بميزات جديدة تسمح له بوضع قيود على نواة مضيف Android ومساحة المستخدم، وتقييد وصول المضيف إلى ذاكرة الضيف وبرنامج Hypervisor.

وحدات بائع pKVM

وحدة بائع pKVM هي وحدة نمطية خاصة بالأجهزة تحتوي على وظائف خاصة بالجهاز، مثل برامج تشغيل وحدة إدارة ذاكرة الإدخال والإخراج (IOMMU). تتيح لك هذه الوحدات ميزات أمان المنفذ التي تتطلب الوصول إلى مستوى الاستثناء 2 (EL2) إلى pKVM.

لمعرفة كيفية تنفيذ وتحميل وحدة بائع pKVM، راجع تنفيذ وحدة بائع pKVM .

إجراء التمهيد

يوضح الشكل التالي إجراء تمهيد pKVM:

إجراء التمهيد pKVM

الشكل 1. إجراء التمهيد pKVM

  1. يدخل محمل الإقلاع إلى النواة العامة عند EL2.
  2. تكتشف النواة العامة أنها تعمل عند EL2 وتحرم نفسها من EL1 بينما تستمر pKVM ووحداتها في العمل عند EL2. بالإضافة إلى ذلك، يتم تحميل وحدات بائع pKVM في هذا الوقت.
  3. تستمر النواة العامة في التشغيل بشكل طبيعي، وتحميل جميع برامج تشغيل الأجهزة الضرورية حتى تصل إلى مساحة المستخدم. عند هذه النقطة، يكون pKVM في مكانه ويتعامل مع جداول صفحات المرحلة الثانية.

يثق إجراء التمهيد في أداة تحميل التشغيل للحفاظ على سلامة صورة kernel فقط أثناء التمهيد المبكر. عندما يتم حرمان النواة من الامتيازات، فإنها لم تعد تعتبر موثوقة من قبل برنامج Hypervisor، الذي يكون بعد ذلك مسؤولاً عن حماية نفسه حتى لو تم اختراق النواة.

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

علاوة على ذلك، فإن اعتماد GKI في نظام Android البيئي يسمح تلقائيًا بنشر برنامج Hypervisor pKVM على أجهزة Android في نفس الملف الثنائي للنواة.

حماية الوصول إلى ذاكرة وحدة المعالجة المركزية

تحدد بنية Arm وحدة إدارة الذاكرة (MMU) مقسمة إلى مرحلتين مستقلتين، ويمكن استخدام كل منهما لتنفيذ ترجمة العناوين والتحكم في الوصول إلى أجزاء مختلفة من الذاكرة. يتم التحكم في المرحلة 1 MMU بواسطة EL1 وتسمح بالمستوى الأول من ترجمة العناوين. يتم استخدام المرحلة الأولى من MMU بواسطة Linux لإدارة مساحة العنوان الافتراضية المتوفرة لكل عملية مساحة مستخدم ومساحة العنوان الافتراضية الخاصة بها.

يتم التحكم في المرحلة 2 MMU بواسطة EL2 ويتيح تطبيق ترجمة العنوان الثاني على عنوان الإخراج للمرحلة 1 MMU، مما يؤدي إلى عنوان فعلي (PA). يمكن لمشرفي الأجهزة الافتراضية استخدام ترجمة المرحلة الثانية للتحكم في عمليات الوصول إلى الذاكرة وترجمتها من جميع الأجهزة الافتراضية الضيف. كما هو موضح في الشكل 2، عندما يتم تمكين مرحلتي الترجمة، يسمى عنوان الإخراج للمرحلة 1 بالعنوان الفعلي المتوسط ​​(IPA) ملاحظة: تتم ترجمة العنوان الظاهري (VA) إلى IPA ثم إلى PA.

حماية الوصول إلى ذاكرة وحدة المعالجة المركزية

الشكل 2. حماية الوصول إلى ذاكرة وحدة المعالجة المركزية

تاريخيًا، يتم تشغيل KVM مع تمكين ترجمة المرحلة الثانية أثناء تشغيل الضيوف ومع تعطيل المرحلة الثانية أثناء تشغيل Linux kernel المضيف. تسمح هذه البنية بالوصول إلى الذاكرة من المرحلة المضيفة 1 MMU بالمرور عبر المرحلة 2 MMU، وبالتالي السماح بالوصول غير المقيد من المضيف إلى صفحات ذاكرة الضيف. من ناحية أخرى، يتيح pKVM حماية المرحلة الثانية حتى في سياق المضيف، ويضع برنامج Hypervisor مسؤولاً عن حماية صفحات ذاكرة الضيف بدلاً من المضيف.

تستفيد KVM بشكل كامل من ترجمة العناوين في المرحلة الثانية لتنفيذ تعيينات IPA/PA المعقدة للضيوف، مما يخلق وهم الذاكرة المتجاورة للضيوف على الرغم من التجزئة المادية. ومع ذلك، يقتصر استخدام المرحلة 2 MMU للمضيف على التحكم في الوصول فقط. تم تعيين هوية المرحلة المضيفة 2، مما يضمن أن الذاكرة المتجاورة في مساحة IPA المضيفة متجاورة في مساحة PA. تسمح هذه البنية باستخدام تعيينات كبيرة في جدول الصفحات وبالتالي تقلل الضغط على المخزن المؤقت للترجمة (TLB). نظرًا لأنه يمكن فهرسة تعيين الهوية بواسطة PA، يتم استخدام المرحلة المضيفة 2 أيضًا لتتبع ملكية الصفحة مباشرةً في جدول الصفحات.

حماية الوصول المباشر للذاكرة (DMA).

كما هو موضح سابقًا، يعد إلغاء تعيين صفحات الضيف من مضيف Linux في جداول صفحات وحدة المعالجة المركزية خطوة ضرورية ولكنها غير كافية لحماية ذاكرة الضيف. يحتاج pKVM أيضًا إلى الحماية من عمليات الوصول إلى الذاكرة التي تتم بواسطة الأجهزة التي تدعم DMA تحت سيطرة kernel المضيف، وإمكانية حدوث هجوم DMA بواسطة مضيف ضار. لمنع مثل هذا الجهاز من الوصول إلى ذاكرة الضيف، يتطلب pKVM جهاز وحدة إدارة ذاكرة الإدخال والإخراج (IOMMU) لكل جهاز قادر على DMA في النظام، كما هو موضح في الشكل 3.

حماية الوصول إلى الذاكرة Dma

الشكل 3. حماية الوصول إلى ذاكرة DMA

كحد أدنى، توفر أجهزة IOMMU وسائل منح وإلغاء حق الوصول للقراءة/الكتابة لجهاز ما إلى الذاكرة الفعلية عند دقة الصفحة. ومع ذلك، فإن أجهزة IOMMU هذه تحد من استخدام الأجهزة في pVMs لأنها تفترض مرحلة محددة للهوية 2.

لضمان العزل بين الأجهزة الافتراضية، يجب أن تكون معاملات الذاكرة التي يتم إنشاؤها نيابة عن كيانات مختلفة قابلة للتمييز بواسطة IOMMU بحيث يمكن استخدام المجموعة المناسبة من جداول الصفحات للترجمة.

بالإضافة إلى ذلك، يعد تقليل كمية التعليمات البرمجية الخاصة بـ SoC في EL2 استراتيجية رئيسية لتقليل قاعدة الحوسبة الموثوقة الشاملة (TCB) لـ pKVM ويتعارض مع تضمين برامج تشغيل IOMMU في برنامج Hypervisor. للتخفيف من هذه المشكلة، يكون المضيف في EL1 مسؤولاً عن مهام إدارة IOMMU المساعدة، مثل إدارة الطاقة والتهيئة ومعالجة المقاطعة حيثما كان ذلك مناسبًا.

ومع ذلك، فإن جعل المضيف يتحكم في حالة الجهاز يضع متطلبات إضافية على واجهة البرمجة الخاصة بأجهزة IOMMU لضمان عدم إمكانية تجاوز عمليات التحقق من الأذونات بوسائل أخرى، على سبيل المثال، بعد إعادة ضبط الجهاز.

إن IOMMU القياسي والمدعوم جيدًا لأجهزة Arm والذي يجعل العزل والتخصيص المباشر ممكنًا هو بنية وحدة إدارة ذاكرة نظام الذراع (SMMU). هذه البنية هي الحل المرجعي الموصى به.

ملكية الذاكرة

في وقت التمهيد، يُفترض أن جميع الذاكرة غير الخاصة ببرنامج Hypervisor مملوكة للمضيف، ويتم تعقبها على هذا النحو بواسطة برنامج Hypervisor. عندما يتم إنشاء pVM، يتبرع المضيف بصفحات الذاكرة للسماح له بالتشغيل ويقوم برنامج Hypervisor بنقل ملكية تلك الصفحات من المضيف إلى pVM. وبالتالي، يضع برنامج Hypervisor قيودًا على التحكم في الوصول في جدول صفحات المرحلة الثانية للمضيف لمنعه من الوصول إلى الصفحات مرة أخرى، مما يوفر السرية للضيف.

أصبح التواصل بين المضيف والضيوف ممكنًا من خلال مشاركة الذاكرة التي يتم التحكم فيها بينهم. يُسمح للضيوف بمشاركة بعض صفحاتهم مرة أخرى مع المضيف باستخدام اتصال فائق، والذي يوجه برنامج Hypervisor لإعادة تعيين تلك الصفحات في جدول صفحات المرحلة 2 للمضيف. وبالمثل، أصبح اتصال المضيف بـ TrustZone ممكنًا من خلال مشاركة الذاكرة و/أو عمليات الإقراض، والتي تتم مراقبتها والتحكم فيها عن كثب بواسطة pKVM باستخدام مواصفات Firmware Framework for Arm (FF-A) .

نظرًا لأن متطلبات ذاكرة pVM يمكن أن تتغير بمرور الوقت، يتم توفير اتصال فائق يسمح بالتخلي عن ملكية الصفحات المحددة التي تخص المتصل مرة أخرى إلى المضيف. عمليًا، يتم استخدام هذا الاتصال الفائق مع بروتوكول Virtio Balloon للسماح لـ VMM بطلب استعادة الذاكرة من pVM، ولكي يقوم pVM بإخطار VMM بالصفحات التي تم التخلي عنها، بطريقة يمكن التحكم فيها.

يكون برنامج Hypervisor مسؤولاً عن تتبع ملكية جميع صفحات الذاكرة في النظام وما إذا كان يتم مشاركتها أو إقراضها لكيانات أخرى. يتم إجراء معظم تتبع الحالة باستخدام بيانات التعريف المرفقة بجداول صفحات المرحلة الثانية للمضيف والضيوف، باستخدام البتات المحجوزة في إدخالات جدول الصفحات (PTEs) والتي، كما يوحي اسمها، محجوزة لاستخدام البرنامج.

يجب أن يتأكد المضيف من أنه لا يحاول الوصول إلى الصفحات التي تعذر الوصول إليها بواسطة برنامج Hypervisor. يؤدي الوصول غير القانوني للمضيف إلى إدخال استثناء متزامن في المضيف بواسطة برنامج Hypervisor، مما قد يؤدي إما إلى تلقي مهمة مساحة المستخدم المسؤولة لإشارة SEGV، أو تعطل نواة المضيف. لمنع الوصول غير المقصود، تصبح الصفحات التي تم التبرع بها للضيوف غير مؤهلة للتبديل أو الدمج بواسطة النواة المضيفة.

مقاطعة التعامل والموقتات

تعد المقاطعات جزءًا أساسيًا من الطريقة التي يتفاعل بها الضيف مع الأجهزة وللاتصال بين وحدات المعالجة المركزية (CPUs)، حيث تكون المقاطعات بين المعالجات (IPIs) هي آلية الاتصال الرئيسية. يهدف نموذج KVM إلى تفويض كل إدارة المقاطعة الافتراضية إلى المضيف في EL1، والذي يتصرف لهذا الغرض كجزء غير موثوق به من برنامج Hypervisor.

تقدم pKVM محاكاة كاملة لوحدة تحكم المقاطعة العامة الإصدار 3 (GICv3) استنادًا إلى كود KVM الموجود. يتم التعامل مع المؤقت وIPIs كجزء من رمز المحاكاة غير الموثوق به.

دعم GICv3

يجب أن تضمن الواجهة بين EL1 وEL2 أن حالة المقاطعة الكاملة مرئية لمضيف EL1، بما في ذلك نسخ سجلات برنامج Hypervisor المتعلقة بالمقاطعات. يتم تحقيق هذه الرؤية عادةً باستخدام مناطق الذاكرة المشتركة، واحدة لكل وحدة المعالجة المركزية الافتراضية (vCPU).

يمكن تبسيط رمز دعم وقت تشغيل سجل النظام لدعم تعويض تسجيل تسجيل المقاطعة المُنشأ بواسطة البرامج (SGIR) وإلغاء تنشيط تسجيل المقاطعة (DIR) فقط. تنص البنية على أن هذه السجلات تصطاد دائمًا EL2، في حين أن المصائد الأخرى حتى الآن كانت مفيدة فقط لتخفيف الأخطاء. يتم التعامل مع كل شيء آخر في الأجهزة.

على جانب MMIO، تتم محاكاة كل شيء في EL1، مع إعادة استخدام كل البنية التحتية الحالية في KVM. أخيرًا، يتم دائمًا ترحيل انتظار المقاطعة (WFI) إلى EL1، لأن هذا أحد أساسيات الجدولة الأساسية التي تستخدمها KVM.

دعم الموقت

يجب أن يتم تعريض قيمة المقارنة للمؤقت الافتراضي إلى EL1 في كل محاصرة WFI حتى يتمكن EL1 من إدخال مقاطعات المؤقت أثناء حظر وحدة المعالجة المركزية الافتراضية (vCPU). تتم محاكاة المؤقت الفعلي بالكامل، ويتم ترحيل كافة المصائد إلى EL1.

التعامل مع MMIO

للتواصل مع شاشة الجهاز الظاهري (VMM) وإجراء محاكاة GIC، يجب إعادة ترحيل اعتراضات MMIO مرة أخرى إلى المضيف في EL1 لمزيد من الفرز. يتطلب pKVM ما يلي:

  • IPA وحجم الوصول
  • البيانات في حالة الكتابة
  • Endianness وحدة المعالجة المركزية عند نقطة الملاءمة

بالإضافة إلى ذلك، يتم ترحيل المصائد ذات سجل الأغراض العامة (GPR) كمصدر/وجهة باستخدام سجل زائف للنقل المجرد.

واجهات الضيف

يمكن للضيف التواصل مع ضيف محمي باستخدام مجموعة من المكالمات الفائقة والوصول إلى الذاكرة إلى المناطق المحاصرة. يتم عرض المكالمات الفائقة وفقًا لمعيار SMCCC ، مع نطاق محجوز لتخصيص البائع بواسطة KVM. تعتبر المكالمات الفائقة التالية ذات أهمية خاصة لضيوف pKVM.

مكالمات مفرطة عامة

  • توفر PSCI آلية قياسية للضيف للتحكم في دورة حياة وحدات المعالجة المركزية الافتراضية الخاصة به بما في ذلك الاتصال بالإنترنت وعدم الاتصال بالإنترنت وإيقاف تشغيل النظام.
  • يوفر TRNG آلية قياسية للضيف لطلب الإنتروبيا من pKVM الذي ينقل المكالمة إلى EL3. تعد هذه الآلية مفيدة بشكل خاص عندما لا يمكن الوثوق بالمضيف في محاكاة مولد الأرقام العشوائية للأجهزة (RNG).

مكالمات pKVM المفرطة

  • مشاركة الذاكرة مع المضيف. لا يمكن للمضيف الوصول إلى كل ذاكرة الضيف في البداية، ولكن الوصول إلى المضيف ضروري للاتصال بالذاكرة المشتركة وللأجهزة شبه الافتراضية التي تعتمد على المخازن المؤقتة المشتركة. تسمح عمليات Hypercalls لمشاركة الصفحات وإلغاء مشاركتها مع المضيف للضيف بتحديد أجزاء الذاكرة التي يمكن لبقية أجهزة Android الوصول إليها دون الحاجة إلى المصافحة.
  • التنازل عن الذاكرة للمضيف. عادةً ما تكون كل ذاكرة الضيف ملكًا للضيف حتى يتم تدميرها. يمكن أن تكون هذه الحالة غير مناسبة للأجهزة الافتراضية طويلة العمر ذات متطلبات الذاكرة التي تختلف بمرور الوقت. يتيح التنازل عن المكالمة relinquish للضيف نقل ملكية الصفحات بشكل صريح مرة أخرى إلى المضيف دون الحاجة إلى إنهاء خدمة الضيف.
  • محاصرة الوصول إلى الذاكرة إلى المضيف. تقليديًا، إذا وصل ضيف KVM إلى عنوان لا يتوافق مع منطقة ذاكرة صالحة، فإن مؤشر ترابط vCPU يخرج إلى المضيف ويتم استخدام الوصول عادةً لـ MMIO ويتم محاكاته بواسطة VMM في مساحة المستخدم. لتسهيل هذه المعالجة، يُطلب من pKVM الإعلان عن تفاصيل حول التعليمات الخاطئة مثل عنوانها، وتسجيل المعلمات وربما محتوياتها مرة أخرى إلى المضيف، مما قد يؤدي عن غير قصد إلى كشف بيانات حساسة من ضيف محمي إذا لم تكن المصيدة متوقعة. تحل pKVM هذه المشكلة عن طريق التعامل مع هذه الأخطاء على أنها قاتلة ما لم يكن الضيف قد أصدر مسبقًا اتصالاً فائقًا لتحديد نطاق IPA المسبب للخطأ باعتباره النطاق الذي يُسمح بالوصول إليه بالرجوع إلى المضيف. يُشار إلى هذا الحل باسم حارس MMIO .

جهاز الإدخال/الإخراج الظاهري (virtio)

يعد Virtio معيارًا شائعًا ومحمولًا وناضجًا لتنفيذ الأجهزة شبه الافتراضية والتفاعل معها. يتم تنفيذ غالبية الأجهزة المعرضة للضيوف المحميين باستخدام Virtio. يدعم Virtio أيضًا تطبيق vsock المستخدم للاتصال بين الضيف المحمي وبقية أجهزة Android.

عادةً ما يتم تنفيذ أجهزة Virtio في مساحة المستخدم الخاصة بالمضيف بواسطة VMM، الذي يعترض عمليات الوصول إلى الذاكرة المحاصرة من الضيف إلى واجهة MMIO لجهاز Virtio ويحاكي السلوك المتوقع. يعد الوصول إلى MMIO مكلفًا نسبيًا لأن كل وصول إلى الجهاز يتطلب رحلة ذهابًا وإيابًا إلى VMM والعودة، لذلك تتم معظم عمليات نقل البيانات الفعلية بين الجهاز والضيف باستخدام مجموعة من قوائم الانتظار الفاضلة في الذاكرة. الافتراض الرئيسي للفضيلة هو أن المضيف يمكنه الوصول إلى ذاكرة الضيف بشكل تعسفي. يتضح هذا الافتراض في تصميم قائمة الانتظار الافتراضية، والتي قد تحتوي على مؤشرات إلى المخازن المؤقتة الموجودة في الضيف والتي تهدف محاكاة الجهاز إلى الوصول إليها مباشرة.

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

جهاز افتراضي

الشكل 4. جهاز فيرتيو

التفاعل مع TrustZone

على الرغم من أن الضيوف غير قادرين على التفاعل مباشرة مع TrustZone، إلا أنه يجب أن يظل المضيف قادرًا على إصدار مكالمات SMC في العالم الآمن. يمكن لهذه الاستدعاءات تحديد مخازن الذاكرة المؤقتة الموجهة فعليًا والتي لا يمكن للمضيف الوصول إليها. ونظرًا لأن البرنامج الآمن بشكل عام لا يكون على علم بإمكانية الوصول إلى المخزن المؤقت، فقد يستخدم مضيف ضار هذا المخزن المؤقت لتنفيذ هجوم نائب مشوش (مشابه لهجوم DMA). لمنع مثل هذه الهجمات، يقوم pKVM باحتجاز جميع مكالمات SMC المضيفة إلى EL2 ويعمل كوكيل بين المضيف والشاشة الآمنة في EL3.

تتم إعادة توجيه مكالمات PSCI من المضيف إلى البرنامج الثابت EL3 مع الحد الأدنى من التعديلات. على وجه التحديد، تتم إعادة كتابة نقطة الإدخال الخاصة بوحدة المعالجة المركزية المتصلة بالإنترنت أو الاستئناف من التوقف المرحلي بحيث يتم تثبيت جدول صفحات المرحلة 2 عند EL2 قبل العودة إلى المضيف عند EL1. أثناء التمهيد، يتم فرض هذه الحماية بواسطة pKVM.

تعتمد هذه البنية على SoC التي تدعم PSCI، ويفضل أن يكون ذلك من خلال استخدام إصدار محدث من TF-A كبرنامج ثابت EL3.

يعمل إطار عمل البرنامج الثابت للذراع (FF-A) على توحيد التفاعلات بين العالمين العادي والآمن، لا سيما في ظل وجود برنامج Hypervisor آمن. يحدد جزء كبير من المواصفات آلية مشاركة الذاكرة مع العالم الآمن، باستخدام تنسيق رسالة مشترك ونموذج أذونات محدد جيدًا للصفحات الأساسية. يقوم وكلاء pKVM بإرسال رسائل FF-A للتأكد من أن المضيف لا يحاول مشاركة الذاكرة مع الجانب الآمن الذي ليس لديه أذونات كافية له.

تعتمد هذه البنية على برنامج العالم الآمن الذي يفرض نموذج الوصول إلى الذاكرة، للتأكد من أن التطبيقات الموثوقة وأي برامج أخرى تعمل في العالم الآمن يمكنها الوصول إلى الذاكرة فقط إذا كانت مملوكة حصريًا للعالم الآمن أو تمت مشاركتها بشكل صريح معه باستخدام FF -أ. في نظام مزود بـ S-EL2، يجب أن يتم تنفيذ نموذج الوصول إلى الذاكرة بواسطة وحدة إدارة التقسيم الآمنة (SPMC)، مثل Hafnium ، التي تحافظ على جداول صفحات المرحلة الثانية للعالم الآمن. في نظام لا يحتوي على S-EL2، يمكن لـ TEE بدلاً من ذلك فرض نموذج الوصول إلى الذاكرة من خلال جداول صفحات المرحلة 1 الخاصة به.

إذا لم يكن استدعاء SMC إلى EL2 عبارة عن مكالمة PSCI أو رسالة محددة FF-A، فسيتم إعادة توجيه رسائل SMC غير المعالجة إلى EL3. الافتراض هو أن البرامج الثابتة الآمنة (الموثوقة بالضرورة) يمكنها التعامل مع SMCs غير المعالجة بأمان لأن البرامج الثابتة تتفهم الاحتياطات اللازمة للحفاظ على عزل pVM.

مراقبة الآلة الافتراضية

crosvm عبارة عن شاشة جهاز ظاهري (VMM) تقوم بتشغيل الأجهزة الافتراضية من خلال واجهة KVM الخاصة بـ Linux. ما يجعل crosvm فريدًا هو تركيزه على السلامة من خلال استخدام لغة برمجة Rust ووضع الحماية حول الأجهزة الافتراضية لحماية النواة المضيفة. لمزيد من المعلومات حول crosvm، راجع الوثائق الرسمية الخاصة به هنا .

واصفات الملفات وioctls

يعرض KVM جهاز الأحرف /dev/kvm لمساحة المستخدمين باستخدام ioctls التي تشكل واجهة برمجة تطبيقات KVM. تنتمي ioctls إلى الفئات التالية:

  • يقوم نظام ioctls بالاستعلام وتعيين السمات العامة التي تؤثر على نظام KVM الفرعي بأكمله، وإنشاء pVMs.
  • يقوم VM ioctls بالاستعلام وتعيين السمات التي تنشئ وحدات المعالجة المركزية (CPUs) والأجهزة الافتراضية، وتؤثر على pVM بالكامل، مثل تضمين تخطيط الذاكرة وعدد وحدات المعالجة المركزية (CPUs) والأجهزة الافتراضية.
  • استعلام vCPU ioctls وتعيين السمات التي تتحكم في تشغيل وحدة المعالجة المركزية الافتراضية الواحدة.
  • يقوم ioctls الخاص بالجهاز بالاستعلام عن السمات التي تتحكم في تشغيل جهاز ظاهري واحد وتعيينها.

تقوم كل عملية crosvm بتشغيل مثيل واحد فقط من الجهاز الظاهري. تستخدم هذه العملية نظام ioctl KVM_CREATE_VM لإنشاء واصف ملف VM يمكن استخدامه لإصدار ioctls pVM. يقوم KVM_CREATE_VCPU أو KVM_CREATE_DEVICE ioctl على VM FD بإنشاء vCPU/جهاز وإرجاع واصف ملف يشير إلى المورد الجديد. يمكن استخدام ioctls على vCPU أو جهاز FD للتحكم في الجهاز الذي تم إنشاؤه باستخدام ioctl على VM FD. بالنسبة لوحدات المعالجة المركزية الافتراضية، يتضمن ذلك المهمة المهمة المتمثلة في تشغيل كود الضيف.

داخليًا، يقوم crosvm بتسجيل واصفات ملفات VM مع النواة باستخدام واجهة epoll التي يتم تشغيلها بواسطة الحافة. تقوم النواة بعد ذلك بإعلام crosvm عندما يكون هناك حدث جديد معلق في أي من واصفات الملف.

تضيف pKVM إمكانية جديدة، KVM_CAP_ARM_PROTECTED_VM ، والتي يمكن استخدامها للحصول على معلومات حول بيئة pVM وإعداد الوضع المحمي لجهاز VM. يستخدم crosvm هذا أثناء إنشاء pVM إذا تم تمرير علامة --protected-vm ، للاستعلام عن مقدار الذاكرة المناسب وحجزه لبرنامج pVM الثابت، ثم لتمكين الوضع المحمي.

تخصيص الذاكرة

إحدى المسؤوليات الرئيسية لجهاز VMM هي تخصيص ذاكرة الجهاز الظاهري وإدارة تخطيط الذاكرة الخاص به. يقوم crosvm بإنشاء تخطيط ذاكرة ثابت موصوف بشكل فضفاض في الجدول أدناه.

FDT في الوضع العادي PHYS_MEMORY_END - 0x200000
مساحة فارغة ...
رامديسك ALIGN_UP(KERNEL_END, 0x1000000)
نواة 0x80080000
محمل الإقلاع 0x80200000
FDT في وضع BIOS 0x80000000
قاعدة الذاكرة المادية 0x80000000
البرامج الثابتة PVM 0x7FE00000
ذاكرة الجهاز 0x10000 - 0x40000000

يتم تخصيص الذاكرة الفعلية باستخدام mmap ويتم التبرع بالذاكرة إلى VM لملء مناطق الذاكرة الخاصة به، والتي تسمى memslots ، باستخدام KVM_SET_USER_MEMORY_REGION ioctl. لذلك تُنسب كل ذاكرة pVM الضيف إلى مثيل crosvm الذي يديرها ويمكن أن يؤدي إلى إنهاء العملية (إنهاء VM) إذا بدأ المضيف في نفاد الذاكرة الحرة. عند إيقاف جهاز افتراضي، يتم مسح الذاكرة تلقائيًا بواسطة برنامج Hypervisor وإعادتها إلى kernel المضيف.

في ظل نظام KVM العادي، يحتفظ VMM بإمكانية الوصول إلى كافة ذاكرة الضيف. باستخدام pKVM، يتم إلغاء تعيين ذاكرة الضيف من مساحة العنوان الفعلي للمضيف عند التبرع بها للضيف. الاستثناء الوحيد هو الذاكرة التي تمت مشاركتها بشكل صريح من قبل الضيف، مثل الأجهزة الفاضلة.

يتم ترك مناطق MMIO في مساحة عنوان الضيف بدون تعيين. يتم حظر وصول الضيف إلى هذه المناطق ويؤدي إلى حدوث حدث إدخال/إخراج على VM FD. تُستخدم هذه الآلية لتنفيذ الأجهزة الافتراضية. في الوضع المحمي، يجب أن يقر الضيف بأنه يتم استخدام منطقة من مساحة العنوان الخاصة به لـ MMIO باستخدام اتصال فائق، لتقليل مخاطر تسرب المعلومات غير المقصود.

الجدولة

يتم تمثيل كل وحدة معالجة مركزية افتراضية بواسطة سلسلة POSIX ويتم جدولتها بواسطة برنامج جدولة Linux المضيف. يستدعي مؤشر الترابط KVM_RUN ioctl على vCPU FD، مما يؤدي إلى تحويل برنامج Hypervisor إلى سياق vCPU الضيف. يقوم برنامج جدولة المضيف بحساب الوقت الذي يقضيه في سياق الضيف باعتباره الوقت المستخدم بواسطة مؤشر ترابط vCPU المقابل. يُرجع KVM_RUN عندما يكون هناك حدث يجب معالجته بواسطة VMM، مثل الإدخال/الإخراج، أو نهاية المقاطعة، أو توقف وحدة المعالجة المركزية الافتراضية. يعالج VMM الحدث ويستدعي KVM_RUN مرة أخرى.

أثناء KVM_RUN ، يظل مؤشر الترابط قابلاً للاستباقية بواسطة برنامج جدولة المضيف، باستثناء تنفيذ رمز برنامج Hypervisor EL2، وهو أمر غير قابل للاستباقية. ليس لدى pVM الضيف نفسه آلية للتحكم في هذا السلوك.

نظرًا لأنه تمت جدولة جميع سلاسل عمليات وحدة المعالجة المركزية الافتراضية (vCPU) مثل أي مهام أخرى في مساحة المستخدم، فإنها تخضع لجميع آليات جودة الخدمة القياسية. على وجه التحديد، يمكن ربط كل سلسلة عمليات لوحدة المعالجة المركزية الافتراضية (vCPU) بوحدات المعالجة المركزية (CPU) الفعلية، أو وضعها في مجموعات وحدات المعالجة المركزية (CPUsets)، أو تعزيزها أو تقييدها باستخدام تثبيت الاستخدام، وتغيير سياسة الأولوية/الجدولة الخاصة بها، والمزيد.

الأجهزة الافتراضية

يدعم crosvm عددًا من الأجهزة، منها ما يلي:

  • Virtio-blk لصور القرص المركبة، للقراءة فقط أو للقراءة والكتابة
  • vhost-vsock للتواصل مع المضيف
  • virtio-pci كوسيلة نقل virtio
  • pl030 ساعة الوقت الحقيقي (RTC)
  • 16550a UART للاتصال التسلسلي

البرامج الثابتة PVM

البرنامج الثابت لـ pVM (pvmfw) هو أول رمز يتم تنفيذه بواسطة pVM، على غرار ذاكرة القراءة فقط (ROM) الخاصة بالتمهيد لجهاز فعلي. الهدف الأساسي لـ pvmfw هو تمهيد التمهيد الآمن واستخلاص سر pVM الفريد. لا يقتصر استخدام pvmfw مع أي نظام تشغيل محدد، مثل Microdroid ، طالما أن نظام التشغيل مدعوم بواسطة crosvm وتم توقيعه بشكل صحيح.

يتم تخزين الملف الثنائي pvmfw في قسم فلاش يحمل نفس الاسم ويتم تحديثه باستخدام OTA .

تمهيد الجهاز

تتم إضافة التسلسل التالي من الخطوات إلى إجراء التمهيد لجهاز يدعم pKVM:

  1. يقوم Android Bootloader (ABL) بتحميل pvmfw من القسم الخاص به إلى الذاكرة والتحقق من الصورة.
  2. تحصل ABL على أسرار محرك تكوين معرف الجهاز (DICE) (معرفات الأجهزة المركبة (CDIs) وسلسلة شهادات التمهيد (BCC)) من جذر الثقة.
  3. يقوم ABL بإجراء قياس واشتقاق DICE لأسرار pvmfw (CDIs)، وإلحاقها بثنائي pvmfw.
  4. تضيف ABL عقدة منطقة الذاكرة المحجوزة linux,pkvm-guest-firmware-memory إلى DT، مع وصف موقع وحجم الملف الثنائي pvmfw والأسرار التي اشتقها في الخطوة السابقة.
  5. يقوم ABL بتسليم التحكم إلى Linux ويقوم Linux بتهيئة pKVM.
  6. يقوم pKVM بإلغاء تحديد منطقة ذاكرة pvmfw من جداول صفحات المرحلة الثانية للمضيف وحمايتها من المضيف (والضيوف) طوال وقت تشغيل الجهاز.

بعد تشغيل الجهاز، يتم تشغيل Microdroid وفقًا للخطوات الواردة في قسم تسلسل التمهيد في مستند Microdroid .

التمهيد pVM

عند إنشاء pVM، يجب أن يقوم crosvm (أو VMM آخر) بإنشاء فتحة memslot كبيرة بما يكفي ليتم ملؤها بصورة pvmfw بواسطة برنامج Hypervisor. يتم أيضًا تقييد VMM في قائمة السجلات التي يمكن تعيين قيمتها الأولية (x0-x14 لوحدة المعالجة المركزية الافتراضية الأساسية، ولا شيء لوحدات المعالجة المركزية الافتراضية الثانوية). السجلات المتبقية محجوزة وهي جزء من Hypervisor-pvmfw ABI.

عند تشغيل pVM، يقوم برنامج Hypervisor أولاً بتسليم التحكم في وحدة المعالجة المركزية الافتراضية (vCPU) الأساسية إلى pvmfw. تتوقع البرامج الثابتة أن يكون crosvm قد قام بتحميل نواة موقعة بـ AVB، والتي يمكن أن تكون أداة تحميل تشغيل أو أي صورة أخرى، وFDT غير موقعة إلى الذاكرة بإزاحات معروفة. يتحقق pvmfw من صحة توقيع AVB، وإذا نجح، فإنه ينشئ شجرة أجهزة موثوقة من FDT المستلم، ويمسح أسرارها من الذاكرة، ويفرعها إلى نقطة دخول الحمولة. إذا فشلت إحدى خطوات التحقق، فسيصدر البرنامج الثابت اتصالاً فائقًا بـ PSCI SYSTEM_RESET .

بين عمليات التمهيد، يتم تخزين المعلومات حول مثيل pVM في قسم (جهاز Virtio-blk) ويتم تشفيرها بسر pvmfw لضمان توفير السر للمثيل الصحيح، بعد إعادة التشغيل.