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

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

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

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

पृष्ठभूमि

निम्नलिखित ION और DMA-BUF हीप्स के बीच एक संक्षिप्त तुलना है।

ION और DMA-BUF हीप्स फ्रेमवर्क के बीच समानताएँ

  • 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 हीप्स में परिवर्तित करना

कर्नेल ड्राइवर ION हीप्स को कार्यान्वित कर रहे हैं

ION और DMA-BUF हीप्स दोनों प्रत्येक हीप को अपने स्वयं के आवंटनकर्ताओं और DMA-BUF ऑप्स को लागू करने की अनुमति देते हैं। तो आप हीप को पंजीकृत करने के लिए एपीआई के एक अलग सेट का उपयोग करके ION हीप कार्यान्वयन से DMA-BUF हीप कार्यान्वयन पर स्विच कर सकते हैं। यह तालिका ION हीप पंजीकरण API और उनके समकक्ष DMA-BUF हीप API दिखाती है।

आयन ढेर डीएमए-बीयूएफ ढेर
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 उदाहरण सिस्टम हीप के कैश्ड और अनकैश्ड वेरिएंट के कार्यान्वयन को दर्शाता है।

स्क्रैच से डीएमए -बीयूएफ हीप बनाने के लिए इस डीएमए-बीयूएफ: हीप्स: उदाहरण टेम्पलेट का उपयोग करें।

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

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

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

आयन ढेर डीएमए-बीयूएफ ढेर
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 DMA-BUF हीप्स और ION हीप्स में आवंटन का समर्थन करता है। यह पहले जाँचता है कि क्या निर्दिष्ट नाम का DMA-BUF हीप मौजूद है और यदि नहीं, तो यदि कोई मौजूद है, तो उसे समतुल्य ION हीप में वापस लाया जाता है।

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

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

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

यह तालिका इन परिवर्तनों को दर्शाती है कि कैसे libion ​​और libdmabufheap एक अनकैश्ड सिस्टम हीप आवंटन करते हैं।

आवंटन का प्रकार libion 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 द्वारा प्रदर्शित प्रत्येक एपीआई के लिए दस्तावेज़ उपलब्ध है। लाइब्रेरी C क्लाइंट द्वारा उपयोग के लिए एक हेडर फ़ाइल भी प्रदर्शित करती है।

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

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

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

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

आवश्यक सेपॉलिसी परिवर्धन

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

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

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

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

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

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

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

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

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

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

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

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

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

AOSP में DMA-BUF हीप्स इंटरफ़ेस के लिए एक कोडेक2 एलोकेटर उपलब्ध है।

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

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

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 हीप्स के लिए uventd परिवर्तन बनाएं। इस बिंदु पर, इच्छित अनुमतियों के साथ, ढेर /dev/dma_heap/my_heap और /dev/dma_heap/my_heap_special के रूप में दिखाई देते हैं।

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

उदाहरण के लिए:

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() से बदलें।

आवंटन प्रकार libion 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 हीप को खोलने के लिए आवश्यक सेपॉलिसी अनुमतियाँ नहीं हैं।

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

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

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