В настоящее время одной из задач микроэлектроники является создание систем на кристалле (СнК) с существенными ограничениями по тепловыделению и энергопотреблению [1]. Проектирование СнК включает в себя разработку ПО для решения задач взаимодействия оборудования и ОС [2]. Работа с трехмерной графикой в реальном масштабе времени, как правило, требует наличия графического ядра в СнК.
Архитектурой ОС предусмотрено создание компонента – драйвера, обеспечивающего прием и передачу данных устройства с использованием программного интерфейса [3]. При разработке драйверов для ОС с открытым исходным кодом, например, для ядра ОС Linux, возможно возникновение определенных трудностей из-за непрерывных изменений функций и структуры ядра [4]. Кроме того, количество источников информации по данному вопросу, находящихся в открытом доступе, невелико.
В настоящей статье приведены методы разработки драйверов графической подсистемы, обеспечивающих и установку графического режима отображения, рассмотрены проблемы, связанные с отладкой модулей ядра.
Графическая подсистема ОС Linux
Обработку 3D-графики обеспечивает графическая подсистема (или графический стек) ОС Li- nux [5]. Графический стек представляет собой набор компонентов, находящихся в разных адресных пространствах доступа виртуальной памяти ОС и взаимодействующих между собой посредством интерфейса системных вызовов [6] (рис. 1).
В пользовательском пространстве на верхнем уровне набор функций и их поведение описаны спецификацией OpenGL (Open Graphics Library). Свободную реализацию графического API (Application Programming Interface) OpenGL в ОС Linux представляет библиотека Mesa 3D, включающая в себя набор драйверов 3D-графики в пользовательском пространстве. Библиотека Mesa реализует независимый от поставщиков драйверов кроссплатформенный стандартный API-интерфейс для взаимодействия с графическими ускорителями различных производителей.
Библиотека libdrm реализует интерфейс DRM в пространстве пользователя, применяя системные вызовы ioctl [7]. Для обеспечения взаимодействия модуля высокого уровня OpenGL и библиотеки libdrm может быть использована библиотека создания драйверов Gallium3D.
Gallium3D является частью Mesa и направлен на упрощение разработки драйверов 3D-графики. Наличие Gallium3D API подразумевает использование TGSI (Tungsten Graphics Shader Infrastructure), являющегося промежуточным представлением описания шейдеров.
После предварительной обработки входящих данных в библиотеке OpenGL, включающих информацию об объектах прорисовки и шейдерных подпрограммах, производится преобразование данных в промежуточный байт-код. На этом этапе также осуществляется оптимизация операций, выполняемых в шейдерных программах, например, разворачивание циклов обработки. Далее сгенерированный байт-код передается в компилятор, преобразующий его в машинные инструкции, пред- назначенные для конкретного графического процессора, а также формирующий буфер команд. Программирование графического ядра выполняется при помощи заполнения буфера команд: для каждого приложения создается контекст графического ядра, содержащий свой командный буфер и все необходимые данные, используемые графическим ядром для отрисовки/расчетов, – координаты, векторы нормали, цвета, текстуры. Графическое ядро не располагает собственной памятью, поэтому буферы формируются в системной памяти.
Драйвер должен поддерживать многопоточное использование, где на каждый поток выделяются один буфер контекста и один буфер команд. За счет наличия только одного буфера команд синхронизация требуется лишь на момент передачи буфера в графическое ядро. На момент заполнения буфера она не требуется. Правильное выставление контекста в ядре для каждого потока должно гарантироваться драйвером графической подсистемы. Также определяются доступные операции для выполнения на конкретной модели графического процессора, ограничения для входящих данных, например, поддерживаемые форматы сжатия текстур.
В пространстве ядра модуль Direct Rendering Manager (DRM) предоставляет API, который используют программы пользовательского пространства для отправки команд и данных графическому ядру и настройки некоторых параметров режима отображения. DRM предоставляет только базовую функциональность, с которой могут работать различные драйверы, а также снабжает пользовательское пространство неким минимальным набором системных вызовов input output control (ioctl) с общей, независимой от оборудования функциональностью.
Существуют несколько подходов к установке графического режима. Установка графических режимов из пользовательского пространства (User Mode-Setting) имеет проблемы:
- неоднократная инициализация оборудования (BIOS, framebuffer и X-сервер);
- некорректное отображение при переключениях между виртуальными консолями и экземплярами X-сервера и в процессе загрузки;
- дублирование кода драйвера (fbdev и драйверов графики для X-сервера).
Решением данных проблем является исполь- зование модуля KMS (Kernel Mode Setting) [8]. Драйвер контроллера вывода на экран DC (Display Controller) находится в пространстве ядра Linux и также должен включать функционал KMS-модуля.
Kernel Mode Setting
Ioctl обычно используются для выполнения над устройством некоторых специфических (управляющих) действий, которые не обеспечиваются регулярными POSIX-вызовами (read(), write(), lseek() и др.) [9]. Часто это могут быть действия, зависящие от конкретных аппаратных особенностей реализации устройства. Для использования возможностей графического ядра в полном объеме необходимо обеспечить взаимодействие модулей ядра ОС и пространства пользователя посредством создания собственных системных вызовов, регламентирующих низкоуровневую работу с устройством (ioctl). На данный момент наиболее актуально применение KMS API для установки графического режима на контроллере вывода на экран. Данное API используется ключевыми производителями микропроцессоров и графических карт.
При построении KMS-модуля необходимы инициализация структур из KMS API, а также установление связей между блоками модуля. DRM-коннектор представляет собой совокупность структур и функций, которые необходимо реализовать в собственном драйвере. Коннектор обеспечивает получение данных от подключенного дисплея и проверку корректности задаваемых графических режимов.
Кадровый буфер (Frame buffer) служит источником данных для дисплей-контроллера. Он представляет собой объекты памяти (memory objects), которые передаются конвейеру отображения CRTC для вывода на экран (рис. 2).
Плоскость (plane) содержит информацию о параметрах изображения и ссылку на дополнительный кадровый буфер. Плоскость передается в CRTC для объединения изображения основного кадрового буфера с изображением дополнительного буфера. CRTC представляет собой общий конвейер отображения, принимая данные пикселей из плоскостей и смешивая их вместе, а также регла- ментируя временные интервалы отображения (display timing).
Графический контроллер не располагает соб- ственной памятью, поэтому буферы формируются в системной памяти. Менеджер графической памяти (GEM) управляет выделением памяти, чтением и записью в буферы. Системные вызовы, являющиеся частью драйвера, обеспечивают создание объектов памяти. Более того, фактически создание буфера для драйверов, использующих GEM, выполняется с помощью специфичного для драйвера ioctl – GEM имеет только общий интерфейс для совместного использования и уничто- жения объектов. Для задач, не требующих всей гибкости работы с памятью, например, выделение кадровых буферов для KMS, применяется API для работы с dumb-буферами. Буферы связываются в список, который автоматически опрашивается контроллером на наличие новых буферов.
Энкодер (encoder) является преобразователем изображения в требуемый выходной формат, например, цифровой или аналоговый. На сегодняшний день использование энкодеров считается устаревшим подходом, вместо них рекомендуется применять компоненты bridge. Основное отличие bridge от энкодера – недоступность из пространства пользователя.
В настоящее время рекомендуется применять атомарный подход к установке графического режима. В отличие от применяемого ранее транзакционного подхода атомарный подход обеспечивает возможность проверки корректности режимов работы без изменения состояния аппаратных средств. При атомарном подходе общее состояние драйве- ра определяется состоянием трех компонентов KMS-модуля с использованием структур состояний: drm_plane_state, drm_crtc_state и drm_connec- tor_state. Структура drm_atomic_state – глобальное состояние объекта для атомарных обновлений, включает в себя эти структуры состояний.
Файл описания аппаратной части
В ОС Linux предусмотрена возможность создания .dts-файла (Device Tree Source). Преимущество использования dts-файла в том, что разработчику модулей ядра не требуется перекомпилировать ядро для различных платформ, содержащих СнК. Файл описания используемой архитектуры и блоков СнК dtsi представлен в виде дерева узлов и служит в основном для предоставления информации ядру ОС. Разработчик, предоставляя дерево устройств, делает возможным более широкую поддержку различных конфигураций оборудования в рамках архитектурной линейки СнК.
Файлы дерева устройств могут быть разделены на несколько частей в нескольких файлах. Файлы уровня платы dts включают в себя dtsi-файлы, описывающие уровень СнК. При создании нового дерева устройств для аппаратной платформы необходимо полностью описывать свойства устройства. Файл дерева устройств хранит и данные о свойствах подключения коннектора видеоинтерфейса.
Отладка модулей ядра
В настоящее время разработка и отладка драйверов зачастую происходят параллельно с разработкой СнК. Как правило, в этих целях используют платформы прототипирования на основе FPGA-матриц. Платформы прототипирования позволяют проверить работоспособность ПО, получить некоторые характеристики производительности и выявить ошибки в СнК на ранних стадиях производства [10].
Однако даже при использовании современных программных и аппаратных средств отладка модулей ядра занимает значительное время из-за ограничений, накладываемых и платформой для прототипирования (тактовая частота, длительное время сборки проекта прошивки), и модулями ядра (многие ядерные механизмы принципиально существуют только во временных зависимостях и не могут быть приостановлены). Кроме того, ошибки, возникающие в коде ядра, трудновоспроизводимы, что также затрудняет отладку модулей ядра.
Запуск тестовых приложений с трехмерной графикой происходит с использованием моделирующего комплекса, зачастую не имеющего модуля вывода на экран. В таком случае для проверки корректности визуализации используется сохранение содержимого кадрового буфера в файлы. Для этого на этапе инициализации тестовой программы ис- пользуется флаг EGL_PBUFFER_BIT – он дает возможность установить конфигурацию системы, не требующей использования физического дисплея для вывода изображения и позволяющей прорисовывать изображения в системную память.
Заключение
При проектировании СнК необходим комплексный подход, учитывающий особенности платформ прототипирования и архитектуру графической подсистемы ОС. Поддержка разрабатываемого ПО в течение всего жизненного цикла СнК является необходимым процессом в условиях изменения архитектуры ядра ОС с открытым исходным кодом. Поддержка трехмерной графики требует от разработчика ПО построения согласованной графической подсистемы с набором компонентов, находящихся в различных адресных пространствах доступа виртуальной памяти ОС. Создание модулей графической подсистемы ОС Linux – актуальная и трудоемкая задача, которой в настоящее время посвящается все больше работ в открытой печати. Однако требуются новые инструменты разработки и отладки. В настоящее время отладка модулей ядра занимает значительное время из-за ограничений со стороны ОС и средств прототипирования.
Рассмотренные подходы к реализации KMS-модуля и компонентов графической подсистемы ОС Linux позволяют обеспечить корректное взаимодействие ОС и контроллера вывода на экран СнК. Планируются внедрение новой функциональности KMS-модуля, а также разработка драйверов пользовательского пространства.
Литература
1. Бобков С.Г. Высокопроизводительные вычислительные системы. М.: Изд-во НИИСИ РАН, 2014. 296 с.
2. Aryashev S.I., Rogatkin B.Y., Barskikh M.E. Modern methods of functional verification of rtl units of VLSI micropro- cessor // Проблемы разработки перспективных микро- и наноэлектронных систем МЭС. 2015. № 2. С. 119–122 (англ.).
3. Решетников В.Н. Космические телекоммуникации. Системы спутниковой связи и навигации. СПб: Ленинградское изд-во, 2010. 132 с.
4. Гиацинтов А.М., Баженов П.С. Визуализация виртуальных трехмерных сцен на однокристальных системах // Программные продукты, системы и алгоритмы. 2017. № 3. URL: http://swsys-web.ru/virtual-three-dimensional-scenes-on-single-chip-systems.html (дата обращения: 20.04.18).
5. Лав Р. Разработка ядра Linux. СПб: Вильямс, 2006. 448 с.
6. Venkateswaran S. Essential Linux Device Drivers. Prentice Hall, 2008, 714 с.
7. The Linux kernel documentation. URL: https://www.kernel.org/doc/html/v4.11/gpu/drm-kms.html (дата обращения: 20.04.2018).
8. Madieu J. Linux device drivers development. Packt Publishing Ltd, 2017, 586 с.
9. Bovet D.P., Cesati M. Understanding the Linux Kernel. USA, O’Reilly Media, 2005, 702 p.
10. Богданов А.Ю. Опыт применения платформы прототипирования на ПЛИС «Protium» для верификации микропроцессоров // Тр. НИИСИ РАН. 2017. Т. 7. № 2. С. 46–49.
References
- Bobkov S.G. High Performance Computing Systems. Moscow, 2014, SRISA RAS Publ., 296 p.
- Aryashev S.I., Rogatkin B.Y., Barskikh M.E. Modern methods of functional verification of rtl units of VLSI microprocessor. Development Problems of Advanced MES Micro- and Nanoelectronic Systems. 2015, no. 2, pp. 119–122
(in Russ.).
- Reshetnikov V.N. Space Telecommunications. Satellite Communication and Navigation Systems. St. Petersburg, Leningradskoe izdatelstvo Publ., 2010, 132 p.
- Giatsintov A.M., Bazhenov P.S. Visualization of virtual three-dimensional scenes on single-chip systems. Software, Systems and Algorithms. 2017, no. 3. Available at: http://swsys-web.ru/virtual-three-dimensional-scenes-on-single-chip-systems.html (accessed April 20, 2018).
- Love R. Linux Kernel Development. Sams Publ., 2003, 332 p.
- Venkateswaran S. Essential Linux Device Drivers. Prentice Hall Publ., 2008, 714 p.
- The Linux Kernel Documentation. Available at: https://www.kernel.org/doc/html/v4.11/gpu/drm-kms.html (accessed April 20, 2018).
- Madieu J. Linux Device Drivers Development. Packt Publ. Ltd, 2017, 586 p.
- Bovet D.P., Cesati M. Understanding the Linux Kernel. 3rd ed., O’Reilly Publ., 2005, 702 p.
- Bogdanov A.Yu. Using a prototype platform on the FPGA “Protium” for microprocessor verification. SRISA RAS Proc. 2017, vol. 7, no. 2, pp. 46–49 (in Russ.).