การเปลี่ยนแปลง ABI ของไอออน

อุปกรณ์ที่จัดส่งเคอร์เนล 4.14 และสูงกว่าได้รับผลกระทบจากการปรับโครงสร้างใหม่ที่สำคัญของ โมดูลเคอร์เนล Ion ซึ่งผู้จำหน่ายหลายรายใช้ตัวจัดสรรหน่วยความจำกราฟิก (gralloc) hardware abstraction layer (HAL) เพื่อจัดสรรบัฟเฟอร์หน่วยความจำที่ใช้ร่วมกัน บทความนี้ให้คำแนะนำเกี่ยวกับการโยกย้ายรหัสผู้จำหน่ายแบบเดิมไปยัง Ion เวอร์ชันใหม่ และกล่าวถึงการหยุดทำงานของ Application Binary Interface (ABI) ในอนาคตที่เป็นไปได้

เกี่ยวกับไอออน

ไอออนเป็นส่วนหนึ่งของ แผนผังการทำงานระหว่างดำเนินการของเคอร์เนล อัพสตรีม ในขณะที่อยู่ในการแสดงละคร ABI ของ userspace-to-kernel ของ Ion อาจแตกหักระหว่างเวอร์ชันเคอร์เนลหลัก แม้ว่า การหยุดทำงานของ Ion ABI จะไม่ส่งผลกระทบโดยตรงต่อแอปพลิเคชันทั่วไปหรืออุปกรณ์ที่เปิดตัวแล้ว ผู้จำหน่ายที่ย้ายไปยังเคอร์เนลเวอร์ชันหลักใหม่อาจพบการเปลี่ยนแปลงที่ส่งผลต่อการเรียกโค้ดของผู้จำหน่ายเข้าสู่ Ion นอกจากนี้ การหยุดทำงานของ ABI ในอนาคตอาจเกิดขึ้นเมื่อทีมระบบ Android ทำงานร่วมกับอัปสตรีมเพื่อย้าย Ion ออกจากแผนผังการแสดงละคร

การเปลี่ยนแปลงใน android-4.14

Kernel 4.12 ปรับโครงสร้างโค้ดเคอร์เนล Ion อย่างหนัก โดยทำความสะอาดและลบส่วนของ Ion ที่ทับซ้อนกับเฟรมเวิร์กเคอร์เนลอื่นๆ ด้วยเหตุนี้ ไอออน ioctls แบบเดิมจำนวนมากจึงไม่เกี่ยวข้องอีกต่อไปและถูกลบออกไปแล้ว

การถอดไคลเอนต์ไอออนและที่จับ

ก่อนเคอร์เนล 4.12 การเปิด /dev/ion จะจัดสรร ไคลเอนต์ Ion ION_IOC_ALLOC ioctl จัดสรรบัฟเฟอร์ใหม่และส่งคืนไปยังพื้นที่ผู้ใช้เป็น หมายเลขอ้างอิงไอออน (จำนวนเต็มทึบแสงมีความหมายเฉพาะกับไคลเอนต์ Ion ที่จัดสรรบัฟเฟอร์เท่านั้น) ในการแมปบัฟเฟอร์ในพื้นที่ผู้ใช้หรือแชร์กับกระบวนการอื่น Ion Handle จะถูกส่งออกอีกครั้งเป็น dma-buf fds โดยใช้ ION_IOC_SHARE ioctl

ในเคอร์เนล 4.12 นั้น ION_IOC_ALLOC ioctl จะส่งออก dma-buf fds โดยตรง สถานะด้ามจับไอออนระดับกลางถูกลบออก พร้อมด้วย ioctls ทั้งหมดที่ใช้หรือสร้างด้ามจับไอออน เนื่องจาก dma-buf fds ไม่ได้เชื่อมโยงกับไคลเอนต์ Ion เฉพาะ ION_IOC_SHARE ioctl จึงไม่จำเป็นอีกต่อไป และโครงสร้างพื้นฐานไคลเอนต์ Ion ทั้งหมดได้ถูกลบออกแล้ว

การเพิ่มเติม ioctls การเชื่อมโยงกันของแคช

ก่อนเคอร์เนล 4.12 Ion ได้จัดเตรียม ION_IOC_SYNC ioctl เพื่อซิงโครไนซ์ตัวอธิบายไฟล์กับหน่วยความจำ ioctl นี้ได้รับการบันทึกไว้ไม่ดีและไม่ยืดหยุ่น ด้วยเหตุนี้ ผู้จำหน่ายหลายรายจึงใช้ ioctls แบบกำหนดเองเพื่อดำเนินการบำรุงรักษาแคช

Kernel 4.12 แทนที่ ION_IOC_SYNC ด้วย DMA_BUF_IOCTL_SYNC ioctl ที่กำหนดไว้ใน linux/dma-buf.h เรียก DMA_BUF_IOCTL_SYNC ที่จุดเริ่มต้นและจุดสิ้นสุดของการเข้าถึง CPU ทุกรายการ โดยมีแฟล็กระบุว่าการเข้าถึงเหล่านี้เป็นการอ่านและ/หรือเขียนหรือไม่ แม้ว่า DMA_BUF_IOCTL_SYNC จะมีรายละเอียดมากกว่า ION_IOC_SYNC แต่ก็ทำให้พื้นที่ผู้ใช้สามารถควบคุมการดำเนินการบำรุงรักษาแคชพื้นฐานได้มากขึ้น

DMA_BUF_IOCTL_SYNC เป็นส่วนหนึ่งของ ABI ที่เสถียรของเคอร์เนล และสามารถใช้ได้กับ dma-buf fds ทั้งหมด ไม่ว่า Ion จะได้รับการจัดสรรหรือไม่ก็ตาม

การย้ายรหัสผู้ขายเป็น android-4.12+

สำหรับไคลเอนต์ userspace ทีมงานระบบ Android สนับสนุนอย่างยิ่งให้ใช้ libion ​​แทนที่จะเรียก ioctl() แบบเข้ารหัสเปิด สำหรับ Android 9 นั้น libion ​​จะตรวจจับ Ion ABI โดยอัตโนมัติเมื่อรันไทม์และพยายามปกปิดความแตกต่างระหว่างเคอร์เนล อย่างไรก็ตาม ฟังก์ชัน libion ​​ใด ๆ ที่สร้างหรือใช้ตัวจัดการ ion_user_handle_t จะไม่ทำงานอีกต่อไปหลังจากเคอร์เนล 4.12 คุณสามารถแทนที่ฟังก์ชันเหล่านี้ด้วยการดำเนินการที่เทียบเท่าต่อไปนี้บน dma-buf fds ซึ่งใช้ได้กับเคอร์เนลทุกเวอร์ชันจนถึงปัจจุบัน

การเรียก ion_user_handle_t แบบเดิม การเรียก dma-buf fd ที่เทียบเท่ากัน
ion_alloc(ion_fd, …, &buf_handle) ion_alloc_fd(ion_fd, ..., &buf_fd)
ion_share(ion_fd, buf_handle, &buf_fd) ไม่มี (ไม่จำเป็นต้องใช้การโทรนี้กับ dma-buf fds)
ion_map(ion_fd, buf_handle, ...) mmap(buf_fd, ...)
ion_free(ion_fd, buf_handle) close(buf_fd)
ion_import(ion_fd, buf_fd, &buf_handle) ไม่มี (ไม่จำเป็นต้องใช้การโทรนี้กับ dma-buf fds)
ion_sync_fd(ion_fd, buf_fd) If (ion_is_legacy(ion_fd))

ion_sync_fd(ion_fd, buf_fd);

else

ioctl(buf_fd, DMA_BUF_IOCTL_SYNC, ...);

สำหรับไคลเอ็นต์ ในเคอร์เนล เนื่องจาก Ion ไม่ส่งออก API ที่เกี่ยวข้องกับเคอร์เนลอีกต่อไป ไดรเวอร์ที่เคยใช้ Ion kernel API ในเคอร์เนลด้วย ion_import_dma_buf_fd() จะต้องถูกแปลงเพื่อใช้ dma-buf API ในเคอร์เนล ด้วย dma_buf_get()

ไอออน ABI ในอนาคตจะแตกตัว

ก่อนที่ไอออนจะถูกย้ายออกจากแผนผังการจัดเตรียม การปล่อยเคอร์เนลในอนาคตอาจต้องทำลาย Ion ABI อีกครั้ง ทีมงานระบบ Android ไม่คาดหวังว่า การเปลี่ยนแปลงเหล่านี้จะส่งผลกระทบต่ออุปกรณ์ที่เปิดตัวด้วย Android เวอร์ชันถัดไป แต่การเปลี่ยนแปลงดังกล่าวอาจส่งผลกระทบต่ออุปกรณ์ที่เปิดตัวด้วย Android เวอร์ชันถัดไป

ตัวอย่างเช่น ชุมชนอัปสตรีมได้เสนอให้แยกโหนด /dev/ion เดียวออกเป็นหลายโหนดต่อฮีป (เช่น /dev/ion/heap0 ) เพื่อให้อุปกรณ์ใช้นโยบาย SELinux ที่แตกต่างกันกับแต่ละฮีป หากการเปลี่ยนแปลงนี้ถูกนำไปใช้ในเคอร์เนลในอนาคต จะทำให้ Ion ABI เสียหาย

,

อุปกรณ์ที่จัดส่งเคอร์เนล 4.14 และสูงกว่าได้รับผลกระทบจากการปรับโครงสร้างใหม่ที่สำคัญของ โมดูลเคอร์เนล Ion ซึ่งผู้จำหน่ายหลายรายใช้ตัวจัดสรรหน่วยความจำกราฟิก (gralloc) hardware abstraction layer (HAL) เพื่อจัดสรรบัฟเฟอร์หน่วยความจำที่ใช้ร่วมกัน บทความนี้ให้คำแนะนำเกี่ยวกับการโยกย้ายรหัสผู้จำหน่ายแบบเดิมไปยัง Ion เวอร์ชันใหม่ และกล่าวถึงการหยุดทำงานของ Application Binary Interface (ABI) ในอนาคตที่เป็นไปได้

เกี่ยวกับไอออน

ไอออนเป็นส่วนหนึ่งของ แผนผังการทำงานระหว่างดำเนินการของเคอร์เนล อัพสตรีม ในขณะที่อยู่ในการแสดงละคร ABI ของ userspace-to-kernel ของ Ion อาจแตกหักระหว่างเวอร์ชันเคอร์เนลหลัก แม้ว่า การหยุดทำงานของ Ion ABI จะไม่ส่งผลกระทบโดยตรงต่อแอปพลิเคชันทั่วไปหรืออุปกรณ์ที่เปิดตัวแล้ว ผู้จำหน่ายที่ย้ายไปยังเคอร์เนลเวอร์ชันหลักใหม่อาจพบการเปลี่ยนแปลงที่ส่งผลต่อการเรียกโค้ดของผู้จำหน่ายเข้าสู่ Ion นอกจากนี้ การหยุดทำงานของ ABI ในอนาคตอาจเกิดขึ้นเมื่อทีมระบบ Android ทำงานร่วมกับอัปสตรีมเพื่อย้าย Ion ออกจากแผนผังการแสดงละคร

การเปลี่ยนแปลงใน android-4.14

Kernel 4.12 ปรับโครงสร้างโค้ดเคอร์เนล Ion อย่างหนัก โดยทำความสะอาดและลบส่วนของ Ion ที่ทับซ้อนกับเฟรมเวิร์กเคอร์เนลอื่นๆ ด้วยเหตุนี้ ไอออน ioctls แบบเดิมจำนวนมากจึงไม่เกี่ยวข้องอีกต่อไปและถูกลบออกไปแล้ว

การถอดไคลเอนต์ไอออนและที่จับ

ก่อนเคอร์เนล 4.12 การเปิด /dev/ion จะจัดสรร ไคลเอนต์ Ion ION_IOC_ALLOC ioctl จัดสรรบัฟเฟอร์ใหม่และส่งคืนไปยังพื้นที่ผู้ใช้เป็น หมายเลขอ้างอิงไอออน (จำนวนเต็มทึบแสงมีความหมายเฉพาะกับไคลเอนต์ Ion ที่จัดสรรบัฟเฟอร์เท่านั้น) ในการแมปบัฟเฟอร์ในพื้นที่ผู้ใช้หรือแชร์กับกระบวนการอื่น Ion Handle จะถูกส่งออกอีกครั้งเป็น dma-buf fds โดยใช้ ION_IOC_SHARE ioctl

ในเคอร์เนล 4.12 นั้น ION_IOC_ALLOC ioctl จะส่งออก dma-buf fds โดยตรง สถานะด้ามจับไอออนระดับกลางถูกลบออก พร้อมด้วย ioctls ทั้งหมดที่ใช้หรือสร้างด้ามจับไอออน เนื่องจาก dma-buf fds ไม่ได้เชื่อมโยงกับไคลเอนต์ Ion เฉพาะ ION_IOC_SHARE ioctl จึงไม่จำเป็นอีกต่อไป และโครงสร้างพื้นฐานไคลเอนต์ Ion ทั้งหมดได้ถูกลบออกแล้ว

การเพิ่มเติม ioctls การเชื่อมโยงกันของแคช

ก่อนเคอร์เนล 4.12 Ion ได้จัดเตรียม ION_IOC_SYNC ioctl เพื่อซิงโครไนซ์ตัวอธิบายไฟล์กับหน่วยความจำ ioctl นี้ได้รับการบันทึกไว้ไม่ดีและไม่ยืดหยุ่น ด้วยเหตุนี้ ผู้จำหน่ายหลายรายจึงใช้ ioctls แบบกำหนดเองเพื่อดำเนินการบำรุงรักษาแคช

Kernel 4.12 แทนที่ ION_IOC_SYNC ด้วย DMA_BUF_IOCTL_SYNC ioctl ที่กำหนดไว้ใน linux/dma-buf.h เรียก DMA_BUF_IOCTL_SYNC ที่จุดเริ่มต้นและจุดสิ้นสุดของการเข้าถึง CPU ทุกรายการ โดยมีแฟล็กระบุว่าการเข้าถึงเหล่านี้เป็นการอ่านและ/หรือเขียนหรือไม่ แม้ว่า DMA_BUF_IOCTL_SYNC จะมีรายละเอียดมากกว่า ION_IOC_SYNC แต่ก็ทำให้พื้นที่ผู้ใช้สามารถควบคุมการดำเนินการบำรุงรักษาแคชพื้นฐานได้มากขึ้น

DMA_BUF_IOCTL_SYNC เป็นส่วนหนึ่งของ ABI ที่เสถียรของเคอร์เนล และสามารถใช้ได้กับ dma-buf fds ทั้งหมด ไม่ว่า Ion จะได้รับการจัดสรรหรือไม่ก็ตาม

การย้ายรหัสผู้ขายเป็น android-4.12+

สำหรับไคลเอนต์ userspace ทีมงานระบบ Android สนับสนุนอย่างยิ่งให้ใช้ libion ​​แทนที่จะเรียก ioctl() แบบเข้ารหัสเปิด สำหรับ Android 9 นั้น libion ​​จะตรวจจับ Ion ABI โดยอัตโนมัติเมื่อรันไทม์และพยายามปกปิดความแตกต่างระหว่างเคอร์เนล อย่างไรก็ตาม ฟังก์ชัน libion ​​ใด ๆ ที่สร้างหรือใช้ตัวจัดการ ion_user_handle_t จะไม่ทำงานอีกต่อไปหลังจากเคอร์เนล 4.12 คุณสามารถแทนที่ฟังก์ชันเหล่านี้ด้วยการดำเนินการที่เทียบเท่าต่อไปนี้บน dma-buf fds ซึ่งใช้ได้กับเคอร์เนลทุกเวอร์ชันจนถึงปัจจุบัน

การเรียก ion_user_handle_t แบบเดิม การเรียก dma-buf fd ที่เทียบเท่ากัน
ion_alloc(ion_fd, …, &buf_handle) ion_alloc_fd(ion_fd, ..., &buf_fd)
ion_share(ion_fd, buf_handle, &buf_fd) ไม่มี (ไม่จำเป็นต้องใช้การโทรนี้กับ dma-buf fds)
ion_map(ion_fd, buf_handle, ...) mmap(buf_fd, ...)
ion_free(ion_fd, buf_handle) close(buf_fd)
ion_import(ion_fd, buf_fd, &buf_handle) ไม่มี (ไม่จำเป็นต้องใช้การโทรนี้กับ dma-buf fds)
ion_sync_fd(ion_fd, buf_fd) If (ion_is_legacy(ion_fd))

ion_sync_fd(ion_fd, buf_fd);

else

ioctl(buf_fd, DMA_BUF_IOCTL_SYNC, ...);

สำหรับไคลเอ็นต์ ในเคอร์เนล เนื่องจาก Ion ไม่ส่งออก API ที่เกี่ยวข้องกับเคอร์เนลอีกต่อไป ไดรเวอร์ที่เคยใช้ Ion kernel API ในเคอร์เนลด้วย ion_import_dma_buf_fd() จะต้องถูกแปลงเพื่อใช้ dma-buf API ในเคอร์เนล ด้วย dma_buf_get()

ไอออน ABI ในอนาคตจะแตกตัว

ก่อนที่ไอออนจะถูกย้ายออกจากแผนผังการจัดเตรียม การปล่อยเคอร์เนลในอนาคตอาจต้องทำลาย Ion ABI อีกครั้ง ทีมงานระบบ Android ไม่คาดหวังว่า การเปลี่ยนแปลงเหล่านี้จะส่งผลกระทบต่ออุปกรณ์ที่เปิดตัวด้วย Android เวอร์ชันถัดไป แต่การเปลี่ยนแปลงดังกล่าวอาจส่งผลกระทบต่ออุปกรณ์ที่เปิดตัวด้วย Android เวอร์ชันถัดไป

ตัวอย่างเช่น ชุมชนอัปสตรีมได้เสนอให้แยกโหนด /dev/ion เดียวออกเป็นหลายโหนดต่อฮีป (เช่น /dev/ion/heap0 ) เพื่อให้อุปกรณ์ใช้นโยบาย SELinux ที่แตกต่างกันกับแต่ละฮีป หากการเปลี่ยนแปลงนี้ถูกนำไปใช้ในเคอร์เนลในอนาคต จะทำให้ Ion ABI เสียหาย