3 điểm bởi GN⁺ 2025-08-08 | 1 bình luận | Chia sẻ qua WhatsApp
  • Bài viết này tập trung vào quá trình phát triển Tyr, trình điều khiển GPU Linux kernel hiện đại mới nhất được viết bằng Rust, và nguyên lý hoạt động của trình điều khiển GPU
  • Trong phát triển trình điều khiển GPU, UMD (User Mode Driver)KMD (Kernel Mode Driver) được giải thích vai trò phân tách và tương tác thông qua ví dụ VkCube
  • UMD chuyển đổi API cấp cao thành lệnh cấp thấp mà GPU có thể hiểu, còn KMD đảm nhiệm các vai trò cốt lõi như cấp phát bộ nhớ, lập lịch tác vụ, khởi tạo thiết bị
  • API mà trình điều khiển Tyr cung cấp giống với Panthor, gồm truy vấn thiết bị, quản lý bộ nhớ, quản lý nhóm, nộp tác vụ và quản lý heap Tiler
  • Bài tiếp theo sẽ đề cập đến kiến trúc phần cứng Arm CSF và các thành phần cốt lõi (ví dụ: MCU) cùng quy trình khởi động

Giới thiệu: Phát triển trình điều khiển kernel GPU hiện đại bằng Rust

  • Đây là bài thứ hai trong loạt bài về Tyr, trình điều khiển nhân GPU hiện đại cho GPU dựa trên Arm Mali CSF trên Linux kernel
  • Là ví dụ thực tế, tác giả chọn chương trình 3D đơn giản VkCube dùng Vulkan API để render một khối lập phương quay nhằm giải thích cách hoạt động bên trong của trình điều khiển GPU
  • Cấu trúc đơn giản của VkCube phù hợp làm ví dụ để học nguyên lý hoạt động của trình điều khiển GPU

Cơ bản về trình điều khiển GPU: Vai trò và kiến trúc của UMD và KMD

  • Gồm hai phần User Mode Driver (UMD)Kernel Mode Driver (KMD)
    • UMD: triển khai API của chương trình thông thường như panvk (driver Vulkan của Mesa, v.v.)
    • KMD: như Tyr, là trình điều khiển cấp kernel có đặc quyền truy cập phần cứng, hoạt động như một phần của Linux kernel
  • Trình điều khiển GPU chế độ kernel đóng vai trò cầu nối giữa UMD và GPU thực, còn UMD giải thích lệnh API thành tập lệnh mà GPU có thể hiểu được
  • UMD chuẩn bị dữ liệu cần thiết để dựng cảnh như hình học, texture, shader và trước khi thực thi, yêu cầu KMD cấp phát chúng vào bộ nhớ GPU
  • Shader là chương trình độc lập chạy trên GPU; trong VkCube, shader chịu trách nhiệm bố trí khối lập phương, tô màu và thực hiện quay. Việc chạy shader cần dữ liệu bên ngoài (geometry, color, ma trận quay, v.v.)
  • UMD truyền lệnh đã chuẩn bị (ví dụ: VkCommandBuffers) cho KMD để thực thi, và khi tác vụ hoàn tất sẽ nhận thông báo để lưu kết quả vào bộ nhớ

Trách nhiệm chính của KMD (kernel mode driver)

  • Cấp phát và ánh xạ bộ nhớ GPU (cung cấp cách ly theo từng ứng dụng)
  • Nộp tác vụ vào hàng đợi phần cứng và thông báo thời điểm hoàn tất cho người dùng
  • Trong môi trường phần cứng bất đồng bộ và song song, quản lý phụ thuộc giữa các tác vụ là bắt buộc; để đảm bảo kết quả đúng, KMD thực hiện vai trò lập lịch và kiểm chứng phụ thuộc
  • Bao gồm khởi tạo thiết bị, điều khiển regulator clock/điện áp, thực thi mã khởi động, và quản lý vòng xoay truy cập để nhiều client dùng chung phần cứng một cách công bằng

Nơi tập trung độ phức tạp: Phân công giữa UMD và KMD

  • Độ phức tạp của trình điều khiển GPU tập trung chủ yếu ở UMD
    • UMD: chuyển đổi lệnh API cấp cao thành lệnh phần cứng
    • KMD: cung cấp các chức năng cốt lõi như cách ly bộ nhớ, chia sẻ và truy cập công bằng để UMD hoạt động đúng

Cấu trúc giao diện trình điều khiển (API) mà Tyr cung cấp

  • API của trình điều khiển Tyr (= giống Panthor) có thể chia thành 5 nhóm lớn
    1. Truy vấn thông tin thiết bị: DEV_QUERY (kiểm tra thông tin phần cứng GPU bằng IOCTL, tận dụng vùng ROM)
    2. Phân bổ và cách ly bộ nhớ: VM_CREATE, VM_BIND, VM_DESTROY, VM_GET_STATE, BO_CREATE, BO_MMAP_OFFSET,...
    3. Quản lý nhóm lên lịch: GROUP_CREATE, GROUP_DESTROY, GROUP_GET_STATE (sẽ giải thích chi tiết trong bài sau)
    4. Nộp tác vụ: GROUP_SUBMIT (yêu cầu thực thi qua device command buffers trên GPU)
    5. Quản lý heap Tiler: TILER_HEAP_CREATE, TILER_HEAP_DESTROY (đáp ứng yêu cầu bộ nhớ của GPU render theo kiểu tiled)
  • Các API này về cơ bản không trực tiếp vẽ hình; UMD chịu trách nhiệm thực thi lệnh thực sự và KMD chỉ cung cấp các giao diện trên để truy cập phần cứng

Kết luận và kế hoạch tiếp theo

  • Trong bài này, chúng ta đã xem qua cấu trúc tổng thể và luồng hoạt động nội bộ của trình điều khiển GPU cùng các API cốt lõi mà Tyr cung cấp
  • Từ nội dung này, trong bài tiếp theo của loạt bài sẽ thảo luận về kiến trúc phần cứng Arm CSF, các thành phần cốt lõi như Microcontroller Unit (MCU) và quy trình khởi tạo trình điều khiển

1 bình luận

 
GN⁺ 2025-08-08
Bình luận Hacker News
  • Bài này rất hay, nhưng nội dung hơi ngắn; tôi vừa mới bắt đầu thấy thú vị hơn thì đã có cảm giác như kết thúc rồi, nên rất mong có phần tiếp theo.
    • Theo đó, tuần tới sẽ có thêm tập truyện nữa, nơi bạn sẽ nhìn thấy lệnh đang chờ trên GPU rời khỏi hàng đợi để thực thi. Mức trừu tượng mà bài này đề cập chỉ ở phần chuyển dữ liệu qua ranh giới user/kernel nên chủ yếu xoay quanh việc quản lý hàng đợi và buffer, không có nhiều xử lý tính toán. Điều quan trọng thực sự sẽ diễn ra khi các lệnh đã vào queue bắt đầu chạy; đồng thời có một tín hiệu hoàn thành lệnh khác gửi ngược lại từ GPU, chuyện đó cũng rất đáng tò mò. Phần lớn xử lý bất đồng bộ này diễn ra ở phía user code chứ không phải trong driver; driver chỉ chuyển tiếp tín hiệu hoàn thành.
  • Tôi đang dùng một thiết bị RK3588 như máy desktop với panfrost và thỉnh thoảng gặp lỗi ở Firefox là màn hình đen hoặc có vùng trong suốt, hiện tượng này thật kỳ quặc.
    • RK3588 thực ra không dùng panfrost; nó dùng driver panthor, đúng chủ đề của bài viết này.
  • Tôi tự hỏi có ai đã cân nhắc việc dùng uring_cmd thay cho ioctls không. Vì đây là dự án xây mới hoàn toàn nên nhìn có vẻ có khả năng áp dụng; tôi tò mò vì sao lại thấy lợi ích của nó gần như không đáng kể.
    • GPU đã có sẵn hàng đợi lệnh bất đồng bộ riêng nên IOCTL vốn dĩ chỉ đóng vai trò ghi vào hàng đợi đó với chi phí tương đối thấp, vì vậy tạo thêm một hàng đợi bất đồng bộ ở phía CPU để lên lịch ghi như vậy là một lựa chọn có ích hạn chế. Nếu là đề xuất biến luôn hàng đợi lệnh GPU thành uring để map sang userspace, thì để hỗ trợ đầy đủ chuẩn API io_uring thì phải sửa firmware khá nhiều; vì tính chất phần cứng, khả năng không thể thực hiện hoàn toàn.
    • Driver mà bài viết mô tả đang tuân theo đúng API mà userspace Mesa library yêu cầu.
  • Đọc rất thú vị, và tôi tò mò có phần nào sau đó hay phần nào có thể kết nối một cách logic không.
    • Đây là bài đầu tiên được công bố hôm nay, nên hy vọng sẽ có update tiếp theo.
  • Tôi hiểu rằng tiêu đề “Rust GPU driver” có thể thu hút nhấp chuột hơn, nhưng thực chất đây không phải driver GPU dựa trên Arm Mali CSF chứ? Cá nhân tôi không thích khi trọng tâm bị kéo sang công cụ meta cho phát triển; mục tiêu nghe như là làm cái gì đó bằng Rust. Bài báo đã chỉ rõ là “kernel driver gpu dựa trên arm mali” mà vẫn không gọi đó là driver arm mali, bởi vì theo tôi, viết driver chỉ là nối API hệ điều hành với API nhà sản xuất phần cứng; tôi không nghĩ đây là việc xây một framework tạo tầng trừu tượng thêm trên đó, và mong thông cảm vì cách diễn đạt khá trực tiếp.
    • Rust là từ khóa quan trọng ở đây vì đây là một trong những (hoặc trong số những) nỗ lực đầu tiên dùng hạ tầng Rust cho driver GPU trên Linux.
    • Đừng bận tâm nếu tôi nói hơi thô; chỉ qua cách nói của bạn tôi thấy bạn dường như chưa hề biết GPU driver hiện đại là gì. Tôi đã từng dùng chúng từ 15 năm trước, và cũng biết rằng từ đó đã phức tạp hơn nhiều. Chỉ cần nhìn vào source code của Linux kernel đã thấy GPU driver chiếm phần lớn nhất về số dòng code, và hầu hết các driver đều hỗ trợ nhiều card đồ họa. Tôi tự hỏi bạn có nhận ra việc mỗi lần lại viết một driver hoàn toàn độc lập cho từng card GPU là phi lý không. Làm GPU driver không phải chỉ là nối vài đường giữa hai API, mà thực sự khác xa như vậy; nếu bạn có thể phản biộc, hãy đưa driver GPU bạn viết cho tôi xem, để tôi xác nhận xem bạn chỉ cần nối vài đường rồi hết việc chưa.
    • Rust quan trọng vì đây là một trong những trường hợp đầu tiên (hoặc một trong những trường hợp đầu tiên) dùng Rust infra cho driver GPU.