ION से DMA-BUF हीप्स में संक्रमण

Android 12 में, GKI 2.0 निम्नलिखित कारणों से ION आवंटक को DMA-BUF हीप से बदल देता है:

  • सुरक्षा: क्योंकि प्रत्येक डीएमए-बीयूएफ हीप एक अलग कैरेक्टर डिवाइस है, प्रत्येक हीप तक पहुंच को अलग से नियंत्रित किया जा सकता है। ION के साथ यह संभव नहीं था क्योंकि किसी भी ढेर से आवंटन के लिए केवल /dev/ion डिवाइस तक पहुंच की आवश्यकता होती है।
  • ABI स्थिरता: ION के विपरीत, DMA-BUF हीप फ्रेमवर्क का IOCTL इंटरफ़ेस ABI स्थिर होने की गारंटी है क्योंकि यह अपस्ट्रीम लिनक्स कर्नेल में बनाए रखा जाता है।
  • मानकीकरण: डीएमए-बीयूएफ ढेर ढांचा एक अच्छी तरह से परिभाषित यूएपीआई प्रदान करता है। ION ने कस्टम फ़्लैग और हीप आईडी की अनुमति दी जो एक सामान्य परीक्षण ढांचे को विकसित करने से रोकते थे क्योंकि प्रत्येक डिवाइस का ION कार्यान्वयन अलग तरह से व्यवहार कर सकता था।

Android कॉमन कर्नेल की android12-5.10 शाखा ने 1 मार्च, 2021 को CONFIG_ION को अक्षम कर दिया।

पृष्ठभूमि

निम्नलिखित आईओएन और डीएमए-बीयूएफ ढेर के बीच एक संक्षिप्त तुलना है।

आईओएन और डीएमए-बीयूएफ ढेर ढांचे के बीच समानताएं

  • ION और DMA-BUF हीप फ्रेमवर्क दोनों हीप-आधारित DMA-BUF निर्यातक हैं।
  • वे दोनों प्रत्येक ढेर को अपने स्वयं के आवंटनकर्ता और डीएमए-बीयूएफ ऑप्स को परिभाषित करने देते हैं।
  • आवंटन प्रदर्शन समान है क्योंकि दोनों योजनाओं को आवंटन के लिए एक ही IOCTL की आवश्यकता है।

ION और DMA-BUF हीप फ्रेमवर्क के बीच अंतर

आयन ढेर डीएमए-बीयूएफ ढेर
सभी ION आवंटन /dev/ion के साथ किए जाते हैं। प्रत्येक DMA-BUF हीप एक कैरेक्टर डिवाइस है जो /dev/dma_heap/<heap_name> पर मौजूद है।
ION निजी झंडों के ढेर का समर्थन करता है। डीएमए-बीयूएफ ढेर निजी झंडों के ढेर का समर्थन नहीं करते हैं। इसके बजाय प्रत्येक अलग प्रकार का आवंटन एक अलग ढेर से किया जाता है। उदाहरण के लिए, कैश्ड और अनकैश्ड सिस्टम हीप वेरिएंट /dev/dma_heap/system और /dev/dma_heap/system_uncached पर स्थित अलग-अलग हीप्स हैं।
आवंटन के लिए हीप आईडी/मास्क और झंडे को निर्दिष्ट करने की आवश्यकता है। ढेर नाम आवंटन के लिए प्रयोग किया जाता है।

निम्नलिखित खंड उन घटकों को सूचीबद्ध करते हैं जो आईओएन से निपटते हैं और वर्णन करते हैं कि उन्हें डीएमए-बीयूएफ ढेर ढांचे में कैसे स्विच किया जाए।

कर्नेल ड्राइवरों को ION से DMA-BUF हीप्स में स्थानांतरित करना

आईओएन ढेर को लागू करने वाले कर्नेल ड्राइवर

आईओएन और डीएमए-बीयूएफ ढेर दोनों ही प्रत्येक ढेर को अपने स्वयं के आवंटकों और डीएमए-बीयूएफ ऑप्स को लागू करने की अनुमति देते हैं। तो आप ढेर को पंजीकृत करने के लिए एपीआई के एक अलग सेट का उपयोग करके ION हीप कार्यान्वयन से 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_heap_add() API का उपयोग करके व्यक्तिगत रूप से पंजीकृत किया जाना चाहिए। कोड साझाकरण की सुविधा के लिए, एक ही ढेर के सभी प्रकारों को एक ही ड्राइवर के भीतर पंजीकृत करने की अनुशंसा की जाती है। यह dma-buf: system_heap उदाहरण सिस्टम हीप के कैश्ड और अनकैश्ड वेरिएंट के कार्यान्वयन को दर्शाता है।

इस dma -buf का उपयोग करें: हीप्स: स्क्रैच से DMA-BUF हीप बनाने के लिए उदाहरण टेम्पलेट

कर्नेल ड्राइवर सीधे ION हीप्स से आबंटित करते हैं

डीएमए-बीयूएफ हीप्स फ्रेमवर्क इन-कर्नेल क्लाइंट के लिए आवंटन इंटरफेस भी प्रदान करता है। आवंटन के प्रकार का चयन करने के लिए हीप मास्क और झंडे को निर्दिष्ट करने के बजाय, डीएमए-बीयूएफ ढेर द्वारा पेश किया गया इंटरफ़ेस इनपुट के रूप में एक हीप नाम लेता है।

निम्नलिखित इन-कर्नेल आईओएन आवंटन एपीआई और इसके समकक्ष डीएमए-बीयूएफ ढेर आवंटन एपीआई दिखाता है। कर्नेल ड्राइवर ढेर के अस्तित्व को क्वेरी करने के लिए dma_heap_find() API का उपयोग कर सकते हैं। एपीआई स्ट्रक्चर dma_heap के उदाहरण के लिए एक पॉइंटर लौटाता है, जिसे बाद में dma_heap_buffer_alloc() एपीआई के तर्क के रूप में पारित किया जा सकता है।

आयन ढेर डीएमए-बीयूएफ ढेर
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)

कर्नेल ड्राइवर जो DMA-BUFs का उपयोग करते हैं

केवल डीएमए-बीयूएफ आयात करने वाले ड्राइवरों के लिए किसी बदलाव की आवश्यकता नहीं है, क्योंकि आईओएन हीप से आवंटित बफर एक समान डीएमए-बीयूएफ हीप से आवंटित बफर के समान व्यवहार करता है।

ION के यूजर-स्पेस क्लाइंट को DMA-BUF हीप्स में बदलना

ION के यूजर-स्पेस क्लाइंट के लिए ट्रांजिशन को आसान बनाने के लिए, libdmabufheap नामक एक एब्स्ट्रैक्शन लाइब्रेरी उपलब्ध है। libdmabufheap डीएमए-बीयूएफ ढेर और आयन ढेर में आवंटन का समर्थन करता है। यह पहले जांचता है कि निर्दिष्ट नाम का डीएमए-बीयूएफ ढेर मौजूद है या नहीं, यदि कोई मौजूद है तो समकक्ष आईओएन ढेर पर वापस आ जाता है।

क्लाइंट को /dev/ion using ion_open() खोलने के बजाय अपने आरंभीकरण के दौरान एक BufferAllocator ऑब्जेक्ट को इनिशियलाइज़ करना चाहिए। ऐसा इसलिए है क्योंकि /dev/ion और /dev/dma_heap/<heap_name> खोलकर बनाए गए फ़ाइल डिस्क्रिप्टर आंतरिक रूप से BufferAllocator ऑब्जेक्ट द्वारा प्रबंधित किए जाते हैं।

libdmabufheap से libion पर स्विच करने के लिए, क्लाइंट के व्यवहार को निम्नानुसार संशोधित करें:

  • हेड आईडी/मास्क और हीप फ्लैग के बजाय आवंटन के लिए उपयोग किए जाने वाले हीप नाम का ध्यान रखें।
  • ion_alloc_fd() API को बदलें, जो एक हीप मास्क और फ्लैग तर्क लेता है, BufferAllocator::Alloc() API के साथ, जो इसके बजाय एक हीप नाम लेता है।

यह तालिका इन परिवर्तनों को दिखाती है कि कैसे 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 शाखा का हिस्सा है।

उपकरणों के उन्नयन का समर्थन करने के लिए, MapNameToIonHeap() एपीआई उन इंटरफेस को नाम-आधारित आवंटन का उपयोग करने की अनुमति देने के लिए ION हीप मापदंडों (हीप नाम/मास्क और झंडे) के लिए एक हीप नाम को मैप करने की अनुमति देता है। यहां एक नाम-आधारित आवंटन उदाहरण है।

libdmabufheap द्वारा उजागर प्रत्येक एपीआई के लिए प्रलेखन उपलब्ध है। पुस्तकालय सी क्लाइंट द्वारा उपयोग के लिए हेडर फ़ाइल को भी उजागर करता है।

संदर्भ ग्रेलोक कार्यान्वयन

Hikey960 ग्रालोक कार्यान्वयन libdmabufheap का उपयोग करता है, इसलिए आप इसे संदर्भ कार्यान्वयन के रूप में उपयोग कर सकते हैं।

आवश्यक ueventd परिवर्धन

बनाए गए किसी भी नए डिवाइस-विशिष्ट DMA-BUF हीप्स के लिए, डिवाइस की ueventd.rc फ़ाइल में एक नई प्रविष्टि जोड़ें। DMA-BUF हीप उदाहरण का समर्थन करने के लिए यह सेटअप ueventd दर्शाता है कि यह DMA-BUF सिस्टम हीप के लिए कैसे किया जाता है।

आवश्यक सेपॉलिसी जोड़

नए डीएमए-बीयूएफ हीप तक पहुंचने के लिए यूजरस्पेस क्लाइंट को सक्षम करने के लिए सेपॉलिसी अनुमतियां जोड़ें। यह आवश्यक अनुमतियाँ जोड़ें उदाहरण DMA-BUF सिस्टम हीप तक पहुँचने के लिए विभिन्न क्लाइंट्स के लिए बनाई गई sepolicy अनुमतियों को दिखाता है।

फ्रेमवर्क कोड से विक्रेता ढेर तक पहुंचना

ट्रेबल अनुपालन सुनिश्चित करने के लिए, फ्रेमवर्क कोड केवल पूर्व-अनुमोदित श्रेणियों के विक्रेता ढेर से आवंटित किया जा सकता है।

भागीदारों से प्राप्त फीडबैक के आधार पर, Google ने विक्रेता ढेर की दो श्रेणियों की पहचान की जिन्हें फ्रेमवर्क कोड से एक्सेस किया जाना चाहिए:

  1. हीप्स जो डिवाइस या एसओसी-विशिष्ट प्रदर्शन अनुकूलन के साथ सिस्टम हीप पर आधारित होते हैं।
  2. संरक्षित स्मृति से आवंटित करने के लिए ढेर।

डिवाइस या एसओसी-विशिष्ट प्रदर्शन अनुकूलन के साथ सिस्टम ढेर पर आधारित ढेर

इस उपयोग के मामले का समर्थन करने के लिए, डिफ़ॉल्ट डीएमए-बीयूएफ हीप सिस्टम के ढेर कार्यान्वयन को ओवरराइड किया जा सकता है।

  • CONFIG_DMABUF_HEAPS_SYSTEM को gki_defconfig में बंद कर दिया गया है ताकि इसे विक्रेता मॉड्यूल बनाया जा सके।
  • VTS अनुपालन परीक्षण सुनिश्चित करते हैं कि हीप /dev/dma_heap/system पर मौजूद है। परीक्षण यह भी सत्यापित करते हैं कि ढेर से आवंटित किया जा सकता है, और लौटाई गई फ़ाइल डिस्क्रिप्टर ( fd ) को उपयोगकर्ता स्थान से मेमोरी-मैप (mmapped) किया जा सकता है।

पूर्ववर्ती बिंदु सिस्टम हीप के कैश न किए गए संस्करण के लिए भी सही हैं, हालांकि इसका अस्तित्व पूरी तरह से IO-संगत उपकरणों के लिए अनिवार्य नहीं है।

संरक्षित स्मृति से आवंटित करने के लिए ढेर

सुरक्षित हीप कार्यान्वयन विक्रेता-विशिष्ट होना चाहिए क्योंकि Android सामान्य कर्नेल सामान्य सुरक्षित हीप कार्यान्वयन का समर्थन नहीं करता है।

  • अपने विक्रेता-विशिष्ट कार्यान्वयन को /dev/dma_heap/system-secure<vendor-suffix> के रूप में पंजीकृत करें।
  • ये ढेर कार्यान्वयन वैकल्पिक हैं।
  • यदि ढेर मौजूद हैं, तो वीटीएस परीक्षण सुनिश्चित करते हैं कि आवंटन उनसे किया जा सकता है।
  • फ्रेमवर्क घटकों को इन ढेरों तक पहुंच प्रदान की जाती है ताकि वे कोडेक2 एचएएल/गैर-बाइंडराइज्ड, समान-प्रक्रिया एचएएल के माध्यम से ढेर के उपयोग को सक्षम कर सकें। हालांकि, जेनेरिक एंड्रॉइड फ्रेमवर्क फीचर्स उनके कार्यान्वयन विवरण में परिवर्तनशीलता के कारण उन पर निर्भर नहीं हो सकते हैं। यदि भविष्य में एंड्रॉइड कॉमन कर्नेल में एक सामान्य सुरक्षित हीप कार्यान्वयन जोड़ा जाता है, तो इसे उपकरणों के उन्नयन के साथ टकराव से बचने के लिए एक अलग एबीआई का उपयोग करना चाहिए।

डीएमए-बीयूएफ ढेर के लिए कोडेक 2 आवंटक

एओएसपी में डीएमए-बीयूएफ हीप्स इंटरफेस के लिए एक कोडेक2 आवंटक उपलब्ध है।

घटक स्टोर इंटरफ़ेस जो C2 HAL से हीप मापदंडों को निर्दिष्ट करने की अनुमति देता है, C2 DMA-BUF हीप एलोकेटर के साथ उपलब्ध है।

एक आयन ढेर के लिए नमूना संक्रमण प्रवाह

ION से DMA-BUF हीप में संक्रमण को सुचारू करने के लिए, libdmabufheap एक समय में एक हीप को स्विच करने की अनुमति देता है। निम्न चरण my_heap नामक एक गैर-विरासत ION हीप को बदलने के लिए सुझाए गए वर्कफ़्लो को प्रदर्शित करते हैं जो एक ध्वज, ION_FLAG_MY_FLAG का समर्थन करता है।

चरण 1: डीएमए-बीयूएफ ढांचे में आईओएन ढेर के समकक्ष बनाएं। इस उदाहरण में, क्योंकि ION हीप my_heap एक ध्वज ION_FLAG_MY_FLAG का समर्थन करता है, हम दो DMA-BUF हीप पंजीकृत करते हैं:

  • my_heap व्यवहार ION_FLAG_MY_FLAG अक्षम ध्वज के साथ ION हीप के व्यवहार से बिल्कुल मेल खाता है।
  • my_heap_special व्यवहार ION_FLAG_MY_FLAG सक्षम ध्वज के साथ ION हीप के व्यवहार से बिल्कुल मेल खाता है।

चरण 2: नए my_heap और my_heap_special DMA-BUF हीप्स के लिए ueventd परिवर्तन बनाएं। इस बिंदु पर, ढेर /dev/dma_heap/my_heap और /dev/dma_heap/my_heap_special के रूप में इच्छित अनुमतियों के साथ दिखाई दे रहे हैं।

चरण 3: my_heap से आवंटित क्लाइंट के लिए, उनके मेकफ़ाइल को libdmabufheap से लिंक करने के लिए संशोधित करें। क्लाइंट इनिशियलाइज़ेशन के दौरान, BufferAllocator ऑब्जेक्ट को इंस्टेंट करें और MapNameToIonHeap() API का उपयोग करके <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 हीप नाम पैरामीटर को खाली पर सेट करके <ION heap mask, flag> से समकक्ष DMA-BUF हीप नामों में मैपिंग बना सकते हैं।

चरण 4: उचित हीप नाम का उपयोग करके ion_alloc_fd() आह्वान को BufferAllocator::Alloc() से बदलें।

आवंटन प्रकार कामवासना libdmabufheap
ION_FLAG_MY_FLAG ध्वज के साथ my_heap से आवंटन अनसेट ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, 0, &fd) allocator->Alloc("my_heap", size
ध्वज ION_FLAG_MY_FLAG सेट के साथ my_heap से आवंटन ion_alloc_fd(ionfd, size, 0, ION_HEAP_MY_HEAP, ION_FLAG_MY_FLAG, &fd) allocator->Alloc("my_heap_special", size)

इस बिंदु पर, क्लाइंट क्रियाशील है, लेकिन फिर भी ION हीप से आवंटन कर रहा है क्योंकि उसके पास DMA-BUF हीप को खोलने के लिए आवश्यक sepolicy अनुमतियाँ नहीं हैं।

चरण 5: नए डीएमए-बीयूएफ ढेर तक पहुंचने के लिए क्लाइंट के लिए आवश्यक सेपॉलिसी अनुमतियां बनाएं। क्लाइंट अब नए DMA-BUF हीप से आवंटित करने के लिए पूरी तरह से सुसज्जित है।

चरण 6: सत्यापित करें कि आवंटन लॉगकैट की जांच करके नए डीएमए-बीयूएफ ढेर से हो रहा है।

चरण 7: कर्नेल में ION हीप my_heap को अक्षम करें। यदि क्लाइंट कोड को उपकरणों को अपग्रेड करने का समर्थन करने की आवश्यकता नहीं है (जिनके कर्नेल केवल ION हीप्स का समर्थन कर सकते हैं), तो आप MapNameToIonHeap() इनवोकेशन को भी हटा सकते हैं।