الانتقال من ION إلى DMA-BUF Heaps

في Android 12 ، يستبدل GKI 2.0 مخصص ION بأكوام DMA-BUF للأسباب التالية:

  • الأمان: نظرًا لأن كل كومة DMA-BUF عبارة عن جهاز أحرف منفصل ، يمكن التحكم في الوصول إلى كل كومة بشكل منفصل باستخدام نظام منفصل. لم يكن هذا ممكنًا مع ION لأن التخصيص من أي كومة يتطلب فقط الوصول إلى جهاز /dev/ion .
  • استقرار ABI: على عكس ION ، فإن واجهة IOCTL الخاصة بإطار عمل DMA-BUF مضمونة لتكون مستقرة ABI لأنه يتم الاحتفاظ بها في نواة Linux المنبع.
  • التوحيد القياسي: يوفر إطار عمل أكوام DMA-BUF واجهة مستخدم UAPI محددة جيدًا. سمحت ION بالعلامات المخصصة ومعرفات الكومة التي حالت دون تطوير إطار عمل اختبار مشترك لأن تطبيق ION لكل جهاز يمكن أن يتصرف بشكل مختلف.

قام فرع android12-5.10 من Android Common Kernel بتعطيل CONFIG_ION في 1 مارس 2021 .

خلفية

فيما يلي مقارنة موجزة بين أكوام ION و DMA-BUF.

أوجه التشابه بين إطار عمل أكوام ION و DMA-BUF

  • يعد كل من إطاري أكوام ION و DMA-BUF مصدرين يعتمدان على الكومة DMA-BUF.
  • كلاهما يسمح لكل كومة بتحديد المخصص الخاص به و DMA-BUF العمليات.
  • يتشابه أداء التخصيص لأن كلا النظامين يحتاجان إلى IOCTL واحد للتخصيص.

الاختلافات بين إطار عمل أكوام ION و DMA-BUF

أكوام أيون أكوام DMA-BUF
تتم جميع عمليات تخصيص ION باستخدام /dev/ion . كل كومة DMA-BUF عبارة عن جهاز أحرف موجود في /dev/dma_heap/<heap_name> .
يدعم ION الأعلام الخاصة الكومة. لا تدعم أكوام DMA-BUF إشارات الكومة الخاصة. يتم بدلاً من ذلك إجراء كل نوع مختلف من التخصيص من كومة مختلفة. على سبيل المثال ، متغيرات كومة النظام المخزنة مؤقتًا وغير المخزنة مؤقتًا هي أكوام منفصلة موجودة في /dev/dma_heap/system و /dev/dma_heap/system_uncached .
يجب تحديد معرف الكومة / القناع والعلامات للتخصيص. يُستخدم اسم الكومة للتخصيص.

تسرد الأقسام التالية المكونات التي تتعامل مع ION وتصف كيفية تحويلها إلى إطار عمل أكوام DMA-BUF.

نقل برامج تشغيل النواة من ION إلى أكوام DMA-BUF

تقوم برامج تشغيل Kernel بتنفيذ أكوام ION

تسمح كل من أكوام ION و DMA-BUF لكل كومة بتنفيذ المخصصات الخاصة بها وعمليات DMA-BUF. لذلك يمكنك التبديل من تطبيق كومة ION إلى تنفيذ كومة DMA-BUF باستخدام مجموعة مختلفة من واجهات برمجة التطبيقات لتسجيل الكومة. يوضح هذا الجدول واجهات برمجة تطبيقات تسجيل كومة ION وواجهات برمجة تطبيقات كومة DMA-BUF المكافئة.

أكوام أيون أكوام DMA-BUF
void ion_device_add_heap(struct ion_heap *heap) struct dma_heap *dma_heap_add(const struct dma_heap_export_info *exp_info);
void ion_device_remove_heap(struct ion_heap *heap) void dma_heap_put(struct dma_heap *heap);

لا تدعم أكوام DMA-BUF إشارات الكومة الخاصة. لذلك يجب تسجيل كل متغير من الكومة بشكل فردي باستخدام dma_heap_add() API. لتسهيل مشاركة الكود ، يوصى بتسجيل جميع المتغيرات من نفس الكومة داخل نفس برنامج التشغيل. يوضح مثال dma-buf: system_heap تنفيذ المتغيرات المخزنة مؤقتًا وغير المخزنة مؤقتًا في كومة النظام.

استخدم dma-buf: heaps: نموذج نموذج لإنشاء كومة DMA-BUF من البداية.

برامج تشغيل Kernel تخصص مباشرة من أكوام ION

يوفر إطار عمل أكوام DMA-BUF أيضًا واجهة تخصيص لعملاء داخل kernel. بدلاً من تحديد قناع الكومة والعلامات لتحديد نوع التخصيص ، تأخذ الواجهة التي توفرها أكوام DMA-BUF اسم كومة كمدخل.

يوضح ما يلي واجهة برمجة تطبيقات تخصيص ION في النواة وواجهات برمجة تطبيقات تخصيص كومة DMA-BUF المكافئة لها. يمكن لبرامج تشغيل Kernel استخدام dma_heap_find() API للاستعلام عن وجود كومة. تقوم واجهة برمجة التطبيقات بإرجاع مؤشر إلى مثيل هيكل dma_heap ، والذي يمكن بعد ذلك تمريره كوسيطة إلى dma_heap_buffer_alloc() API.

أكوام أيون أكوام DMA-BUF
struct dma_buf *ion_alloc(size_t len, unsigned int heap_id_mask, unsigned int flags)

struct dma_heap *dma_heap_find(const char *name)

struct dma_buf *struct dma_buf *dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, unsigned int fd_flags, unsigned int heap_flags)

برامج تشغيل Kernel التي تستخدم DMA-BUFs

لا توجد تغييرات مطلوبة لبرامج التشغيل التي تستورد DMA-BUFs فقط ، لأن المخزن المؤقت المخصص من كومة ION يتصرف تمامًا مثل المخزن المؤقت المخصص من كومة DMA-BUF مكافئة.

نقل عملاء مساحة المستخدم لـ ION إلى أكوام DMA-BUF

لتسهيل الانتقال لعملاء مساحة المستخدم لـ ION ، تتوفر مكتبة تجريد تسمى libdmabufheap . يدعم libdmabufheap التخصيص في أكوام DMA-BUF وأكوام ION. يتحقق أولاً من وجود كومة DMA-BUF بالاسم المحدد ، وإذا لم يكن الأمر كذلك ، فإنه يعود إلى كومة ION المكافئة ، إن وجدت.

يجب على العملاء تهيئة كائن BufferAllocator أثناء التهيئة بدلاً من الفتح /dev/ion using ion_open() . هذا لأن واصفات الملفات التي تم إنشاؤها عن طريق فتح /dev/ion و /dev/dma_heap/<heap_name> تتم إدارتها داخليًا بواسطة كائن BufferAllocator .

للتبديل من libion إلى libdmabufheap ، قم بتعديل سلوك العملاء كما يلي:

  • تتبع اسم الكومة المراد استخدامه للتخصيص ، بدلاً من معرّف / قناع الرأس وعلامة الكومة.
  • استبدل واجهة برمجة تطبيقات ion_alloc_fd() ، التي تأخذ قناع كومة وسيطة علامة ، بواجهة برمجة تطبيقات BufferAllocator::Alloc() ، والتي تأخذ اسم كومة بدلاً من ذلك.

يوضح هذا الجدول هذه التغييرات من خلال إظهار كيفية libion و libdmabufheap بتخصيص كومة النظام غير المخزن مؤقتًا.

نوع التخصيص ليبيون libdmabufheap
التخصيص المخزن مؤقتًا من كومة النظام ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, ION_FLAG_CACHED, &fd) allocator->Alloc("system", size)
تخصيص غير مخزن مؤقتًا من كومة النظام ion_alloc_fd(ionfd, size, 0, ION_HEAP_SYSTEM, 0, &fd) allocator->Alloc("system-uncached", size)

متغير كومة النظام غير المخزن في انتظار الموافقة الأولية ولكنه بالفعل جزء من فرع android12-5.10 .

لدعم ترقية الأجهزة ، تسمح API MapNameToIonHeap() اسم كومة لمعلمات كومة ION (اسم / قناع الكومة والعلامات) للسماح لتلك الواجهات باستخدام التخصيصات المستندة إلى الاسم. فيما يلي مثال على التخصيص المستند إلى الاسم .

الوثائق الخاصة بكل واجهة برمجة تطبيقات تم الكشف عنها بواسطة libdmabufheap متاحة. تعرض المكتبة أيضًا ملفًا رئيسيًا لاستخدامه بواسطة عملاء C.

مرجع تنفيذ Gralloc

يستخدم تطبيق Hikey960 libdmabufheap ، لذا يمكنك استخدامه كتطبيق مرجعي .

إضافات ueventd المطلوبة

لأي أكوام DMA-BUF جديدة خاصة بالجهاز تم إنشاؤها ، أضف إدخالاً جديدًا إلى ملف ueventd.rc الخاص بالجهاز. يوضح هذا المثال ueventd الإعداد لدعم DMA-BUF أكوام كيف يتم ذلك من أجل كومة نظام DMA-BUF.

إضافات الانقطاع المطلوبة

أضف أذونات منفصلة لتمكين عميل مساحة المستخدمين من الوصول إلى كومة DMA-BUF جديدة. يوضح مثال الأذونات المطلوبة الإضافة الأذونات المنفصلة التي تم إنشاؤها للعديد من العملاء للوصول إلى كومة نظام DMA-BUF.

الوصول إلى أكوام البائعين من كود الإطار

لضمان التوافق مع Treble ، يمكن تخصيص رمز إطار العمل فقط من الفئات المعتمدة مسبقًا لأكوام البائعين.

استنادًا إلى التعليقات الواردة من الشركاء ، حددت Google فئتين من أكوام البائعين التي يجب الوصول إليها من رمز إطار العمل:

  1. الأكوام التي تستند إلى كومة النظام مع تحسينات أداء الجهاز أو SoC الخاصة.
  2. أكوام للتخصيص من الذاكرة المحمية.

تعتمد الأكوام على كومة النظام مع تحسينات الأداء الخاصة بالجهاز أو SoC

لدعم حالة الاستخدام هذه ، يمكن تجاوز تنفيذ كومة الذاكرة المؤقتة لنظام DMA-BUF الافتراضي.

  • تم إيقاف تشغيل CONFIG_DMABUF_HEAPS_SYSTEM في gki_defconfig للسماح لها بأن تكون وحدة مورد.
  • تضمن اختبارات التوافق مع VTS وجود الكومة في /dev/dma_heap/system . تتحقق الاختبارات أيضًا من أنه يمكن تخصيص الكومة من ، وأن واصف الملف الذي تم إرجاعه ( fd ) يمكن تعيينه على الذاكرة (مميَّز) من مساحة المستخدم.

النقاط السابقة صحيحة أيضًا بالنسبة للمتغير غير المخزن من كومة النظام ، على الرغم من أن وجودها ليس إلزاميًا للأجهزة المترابطة بالكامل IO.

أكوام للتخصيص من الذاكرة المحمية

يجب أن تكون تطبيقات الكومة الآمنة خاصة بالمورد نظرًا لأن Android Common Kernel لا يدعم تنفيذ كومة آمنة عامة.

  • سجّل عمليات التنفيذ الخاصة بالمورد على أنه /dev/dma_heap/system-secure<vendor-suffix> .
  • تطبيقات الكومة اختيارية.
  • في حالة وجود أكوام ، تضمن اختبارات VTS إمكانية إجراء عمليات تخصيص منها.
  • يتم توفير مكونات إطار العمل مع إمكانية الوصول إلى هذه الأكوام بحيث يمكنها تمكين استخدام الأكوام من خلال HALs Codec2 / non-binderized ، نفس العملية. ومع ذلك ، لا يمكن أن تعتمد ميزات إطار عمل Android العام عليها نظرًا للتباين في تفاصيل تنفيذها. إذا تمت إضافة تطبيق كومة آمنة عامة إلى Android Common Kernel في المستقبل ، فيجب أن يستخدم ABI مختلفًا لتجنب التعارض مع ترقية الأجهزة.

مخصص الترميز 2 لأكوام DMA-BUF

يتوفر مخصص ترميز 2 لواجهة DMA-BUF أكوام في AOSP.

تتوفر واجهة مخزن المكونات التي تسمح بتحديد معلمات الكومة من C2 HAL مع مخصص الكومة C2 DMA-BUF.

عينة تدفق الانتقال لكومة ION

لتسهيل الانتقال من أكوام ION إلى DMA-BUF ، يسمح libdmabufheap بتبديل كومة واحدة في الوقت المناسب. توضح الخطوات التالية سير عمل مقترح لنقل كومة ION غير قديمة تسمى my_heap والتي تدعم علامة واحدة ، ION_FLAG_MY_FLAG .

الخطوة 1: إنشاء معادلات من كومة ION في إطار DMA-BUF. في هذا المثال ، نظرًا لأن كومة ION my_heap تدعم علامة ION_FLAG_MY_FLAG ، فإننا نسجل كومة DMA-BUF:

  • يتطابق سلوك my_heap تمامًا مع سلوك كومة ION مع تعطيل العلامة ION_FLAG_MY_FLAG .
  • يتطابق سلوك my_heap_special تمامًا مع سلوك ION heap مع تمكين العلامة ION_FLAG_MY_FLAG .

الخطوة 2: قم بإنشاء تغييرات my_heap و my_heap_special DMA-BUF. في هذه المرحلة ، تظهر أكوام الذاكرة المؤقتة كـ /dev/dma_heap/my_heap و /dev/dma_heap/my_heap_special ، مع الأذونات المقصودة.

الخطوة 3: بالنسبة للعملاء الذين يقومون بالتخصيص من my_heap ، قم بتعديل ملفات makefiles الخاصة بهم للارتباط بـ libdmabufheap . أثناء تهيئة العميل ، قم بإنشاء مثيل لكائن BufferAllocator واستخدم API MapNameToIonHeap() لتعيين تركيبة <ION heap name/mask, flag> إلى أسماء كومة DMA-BUF المكافئة.

فمثلا:

allocator->MapNameToIonHeap("my_heap_special" /* name of DMA-BUF heap */, "my_heap" /* name of the ION heap */, ION_FLAG_MY_FLAG /* ion flags */ )

بدلاً من استخدام MapNameToIonHeap() API مع معلمات الاسم والعلامة ، يمكنك إنشاء التعيين من <ION heap mask, flag> إلى أسماء كومة DMA-BUF المكافئة عن طريق تعيين معلمة اسم كومة ION على فارغة.

الخطوة 4: استبدل ion_alloc_fd() بـ BufferAllocator::Alloc() باستخدام اسم الكومة المناسب.

نوع التخصيص ليبيون libdmabufheap
التخصيص من my_heap مع عدم تعيين العلامة ION_FLAG_MY_FLAG ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, 0, &fd) allocator->Alloc("my_heap", size
التخصيص من my_heap مع مجموعة العلم ION_FLAG_MY_FLAG ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, ION_FLAG_MY_FLAG, &fd) allocator->Alloc("my_heap_special", size)

في هذه المرحلة ، يكون العميل وظيفيًا ولكنه لا يزال مخصصًا من كومة ION لأنه لا يمتلك أذونات منفصلة مطلوبة لفتح كومة DMA-BUF.

الخطوة 5: إنشاء الأذونات المنفصلة المطلوبة للعميل للوصول إلى أكوام DMA-BUF الجديدة. أصبح العميل الآن مجهزًا بالكامل للتخصيص من كومة DMA-BUF الجديدة.

الخطوة 6: تحقق من أن عمليات التخصيص تحدث من كومة DMA-BUF الجديدة بفحص logcat .

الخطوة 7: تعطيل ION heap my_heap في kernel. إذا لم يكن رمز العميل بحاجة إلى دعم ترقية الأجهزة (التي قد تدعم نواتها أكوام ION فقط) ، يمكنك أيضًا إزالة MapNameToIonHeap() .