מעבר מ-ION ל-DMA-BUF Heaps

באנדרואיד 12, GKI 2.0 מחליף את מקצה ה-ION בערימות DMA-BUF מהסיבות הבאות:

  • אבטחה: מכיוון שכל ערימת DMA-BUF היא התקן אופי נפרד, ניתן לשלוט בגישה לכל ערימה בנפרד באמצעות sepolicy. זה לא היה אפשרי עם ION מכיוון שהקצאה מכל ערמה דרשה רק גישה למכשיר /dev/ion .
  • יציבות ABI: בניגוד ל-ION, ממשק IOCTL של מסגרת DMA-BUF heaps מובטחת להיות ABI יציב מכיוון שהוא נשמר בליבת לינוקס במעלה הזרם.
  • סטנדרטיזציה: מסגרת ה-DMA-BUF heaps מציעה UAPI מוגדר היטב. ION אפשרה דגלים מותאמים אישית ומזהי ערימה שמנעו פיתוח מסגרת בדיקה משותפת מכיוון שהטמעת ION של כל מכשיר יכולה להתנהג בצורה שונה.

סניף android12-5.10 של Android Common Kernel השבית את CONFIG_ION ב -1 במרץ 2021 .

רקע כללי

להלן השוואה קצרה בין ערימות ION ו-DMA-BUF.

קווי דמיון בין ה-ION ו-DMA-BUF heaps framework

  • מסגרות הערמות ION ו-DMA-BUF הן שתיהן יצואניות DMA-BUF מבוססות ערימות.
  • שניהם נותנים לכל ערימה להגדיר את המקצה שלה ואת פעולות ה-DMA-BUF שלה.
  • ביצועי ההקצאה דומים מכיוון ששתי הסכמות זקוקות ל-IOCTL יחיד להקצאה.

הבדלים בין ה-ION ו-DMA-BUF heaps framework

ערימות ION ערימות 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 heaps.

העברת מנהלי התקנים של ליבה מ-ION לערמות DMA-BUF

נהגי ליבה המטמיעים ערימות ION

גם ערימות ION וגם DMA-BUF מאפשרות לכל ערימה ליישם מקצים משלה ופעולות DMA-BUF. אז אתה יכול לעבור מיישום ערימת ION למימוש ערימת DMA-BUF על ידי שימוש בסט שונה של ממשקי API לרישום הערימה. טבלה זו מציגה את ממשקי ה-API לרישום ערימות של ION וממשקי ה-API של ערימת 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-BUF אינן תומכות בדגלים פרטיים. אז כל וריאנט של הערימה חייב להיות רשום בנפרד באמצעות ה-API dma_heap_add() . כדי להקל על שיתוף הקוד, מומלץ לרשום את כל הגרסאות של אותה ערימה בתוך אותו דרייבר. דוגמה זו של dma-buf: system_heap מציגה את ההטמעה של הווריאציות השמורות והלא מאוחסנות של ערימת המערכת.

השתמש בתבנית dma-buf: heaps: לדוגמה כדי ליצור ערימת DMA-BUF מאפס.

נהגי ליבה מקצים ישירות מערימות ION

המסגרת DMA-BUF heaps מציעה גם ממשק הקצאה עבור לקוחות בתוך הליבה. במקום לציין את מסכת הערימה והדגלים לבחירת סוג ההקצאה, הממשק המוצע על ידי ערימות DMA-BUF מקבל שם ערימה כקלט.

להלן מוצג ממשק API להקצאת ION בתוך הליבה וממשקי API להקצאת ערימות DMA-BUF המקבילים לו. מנהלי התקנים של ליבה יכולים להשתמש ב- dma_heap_find() API כדי לשאול את קיומו של ערימה. ה-API מחזיר מצביע למופע של struct dma_heap , שאותו ניתן להעביר כארגומנט ל- dma_heap_buffer_alloc() API.

ערימות ION ערימות 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)

מנהלי התקנים של ליבה המשתמשים ב-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 , שנה את התנהגות הלקוחות באופן הבא:

  • עקוב אחר שם הערימה לשימוש להקצאה, במקום מזהה ראש/מסכה ודגל הערימה.
  • החלף את ה-API ion_alloc_fd() , שלוקח ארגומנט ערימה ודגל, ב- 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 .

כדי לתמוך בשדרוג התקנים, ה-API של MapNameToIonHeap() מאפשר מיפוי של שם ערימה לפרמטרים של ערימה (שם ערימה/מסכה ודגלים) כדי לאפשר לממשקים אלה להשתמש גם בהקצאות מבוססות שמות. הנה דוגמה להקצאה מבוססת שם .

התיעוד לכל API שנחשף על ידי libdmabufheap זמין. הספרייה גם חושפת קובץ כותרת לשימוש על ידי לקוחות C.

התייחסות ליישום Gralloc

ההטמעה של Hikey960 gralloc משתמשת libdmabufheap , כך שתוכל להשתמש בו כיישום ייחוס .

תוספות חובות לאירועים

עבור כל ערימות DMA-BUF חדשות ספציפיות למכשיר שנוצרו, הוסף ערך חדש לקובץ ueventd.rc של המכשיר. דוגמה זו של התקנה תומכת בערימות DMA-BUF מדגימה כיצד זה נעשה עבור ערימת מערכת DMA-BUF.

תוספות נדרשות למדיניות ה-se

הוסף הרשאות sepolicy כדי לאפשר ללקוח מרחב משתמש לגשת לערמת DMA-BUF חדשה. דוגמה זו של הוספת הרשאות נדרשות מציגה את הרשאות sepolicy שנוצרו עבור לקוחות שונים כדי לגשת לערימת מערכת ה-DMA-BUF.

גישה לערמות ספקים מקוד המסגרת

כדי להבטיח תאימות ל-Treble, קוד המסגרת יכול להקצות רק מקטגוריות מאושרות מראש של ערימות ספקים.

בהתבסס על משוב שהתקבל משותפים, Google זיהתה שתי קטגוריות של ערימות ספקים שיש לגשת אליהם מקוד המסגרת:

  1. ערימות המבוססות על ערימת מערכת עם אופטימיזציית ביצועים ספציפית למכשיר או ל-SoC.
  2. ערימות להקצאה מזיכרון מוגן.

ערימות המבוססות על ערימת מערכת עם אופטימיזציית ביצועים ספציפית למכשיר או ל-SoC

כדי לתמוך במקרה שימוש זה, ניתן לעקוף את יישום הערימה של מערכת ברירת המחדל DMA-BUF heap.

  • CONFIG_DMABUF_HEAPS_SYSTEM כבוי ב- gki_defconfig כדי לאפשר לו להיות מודול ספק.
  • בדיקות תאימות VTS מבטיחות שהערימה קיימת ב- /dev/dma_heap/system . הבדיקות גם מאמתות שניתן להקצות את הערימה, ושניתן למפות את מתאר הקובץ המוחזר ( fd ) בזיכרון (ממפה) ממרחב המשתמש.

הנקודות הקודמות נכונות גם עבור הגרסה הלא מאוחסנת של ערימת המערכת, אם כי קיומה אינו חובה עבור התקנים קוהרנטיים לחלוטין של IO.

ערימות להקצאה מזיכרון מוגן

הטמעת ערימה מאובטחת חייבת להיות ספציפית לספק מכיוון שה-Android Common Kernel אינו תומך בהטמעת ערימה מאובטחת גנרית.

  • רשום את ההטמעות הספציפיות לספק שלך בתור /dev/dma_heap/system-secure<vendor-suffix> .
  • יישומי ערימה אלה הם אופציונליים.
  • אם הערימות קיימות, בדיקות VTS מבטיחות שניתן לבצע מהן הקצאות.
  • רכיבי מסגרת מסופקים עם גישה לערימות אלה כדי שיוכלו לאפשר שימוש בערימות באמצעות ה-HAL של Codec2/לא מקשר, באותו תהליך. עם זאת, תכונות מסגרת אנדרואיד כלליות אינן יכולות להיות תלויות בהן בשל השונות בפרטי היישום שלהן. אם בעתיד תתווסף יישום ערימה מאובטחת גנרית ל-Android Common Kernel, עליו להשתמש ב-ABI אחר כדי למנוע התנגשויות עם מכשירי שדרוג.

מקצה Codec 2 עבור ערימות DMA-BUF

מקצה codec2 עבור ממשק ה-DMA-BUF heaps זמין ב-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 כאשר הדגל ION_FLAG_MY_FLAG מופעל.

שלב 2: צור את השינויים ueventd עבור ערימות my_heap ו- my_heap_special DMA-BUF החדשות. בשלב זה, הערימות גלויות בתור /dev/dma_heap/my_heap ו- /dev/dma_heap/my_heap_special , עם ההרשאות המיועדות.

שלב 3: עבור לקוחות שמקצים מ- my_heap , שנה את הקבצים שלהם כדי לקשר ל- 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 */ )

במקום להשתמש ב-API של MapNameToIonHeap() עם הפרמטרים שם ודגל, אתה יכול ליצור את המיפוי מ- <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: צור את הרשאות ה-sepolicy הנדרשות ללקוח כדי לגשת לערימות ה-DMA-BUF החדשות. הלקוח מצויד כעת באופן מלא להקצאה מערימת ה-DMA-BUF החדשה.

שלב 6: ודא שההקצאות מתרחשות מערימת ה-DMA-BUF החדשה על ידי בדיקת logcat .

שלב 7: השבת את ערימת ה-ION my_heap בקרנל. אם קוד הלקוח אינו צריך לתמוך בהתקנים (שהגרעין שלהם עשוי לתמוך רק בערימות ION), תוכל גם להסיר את הפעלות MapNameToIonHeap() .