За окном уже наступило лето, ну а мы представляем вам продолжение цикла статей о практическом применении КолибриОС. В первой части мы провели теоретический обзор возможных сфер применения, а теперь, как и было обещано, переходим к более практической части: экзоверсии ядра для разработчиков железа.


Хочется сказать спасибо art_zh за потраченное время на подготовку материала для данной статьи.

Наверное, немногие наши читатели помнят те давние-давние времена, «когда компьютеры были большими» и практически не использовались для делопроизводства и развлечений. Основными сферами применения этих дорогущих монстров были зубодробительные вычисления, автоматизированные системы сбора данных, проектирования и управления сложными технологическими процессами.

Прошли десятилетия, компьютеры стали гораздо дешевле и быстрее, но старые задачи не стали проще. Постоянно возрастают требования к эффективности обработки широкополосных потоков данных, к быстроте и надежности схем управления, к простоте и наглядности пользовательского интерфейса.

Один из наших разработчиков — art_zh, инженер-электронщик из Англии, пришел в проект после долгих и безуспешных поисков оптимальной ОС для системы «быстрого» технического зрения на х86-платформе. Конкретная задача требовала обработки широкополосного видеопотока (500 SXGA-кадров, 660 миллионов пикселей в секунду), – из этой лавины данных нужно было выделить несколько характерных зон, найти среднюю яркость в каждой зоне и следить за изменением этой яркости в течение 10-12 часов. Периодически отображая полноформатную картинку на экране.



Задача осложнялась нестандартностью применяемого железа. Фреймграббер и DMA-контроллер были реализованы на экспериментальной PCI-express карте с мотором Virtex-5 от Xilinx. Суровый Verilog-код требовал тщательной отладки всех пакетных транзакций протоколу TLP-PCIe. Эту тему мы более подробно обсудим в одной из следующих публикаций этого цикла, здесь ограничимся констатацией того, что среда Windows для такой отладки представляется совершенно непригодной, а в Линуксе цикл модификация кода — компиляция драйвера – перезагрузка – анализ printk-сообщений занимал неприемлемо долгое время.

Итак, нужна была быстрая, графическая, 32-разрядная операционная система с экзоядром, прозрачным для доступа из приложения к аппаратным ресурсам самого низкого уровня – конфигурационному пространству PCI, регистрам PCIe Root Complex, адресам MMIO (отображаемого на память ввода вывода) и т.п.

КолибриОС привлекала своей быстротой и минимальной латентностью, простым и удобным графическим интерфейсом, очень компактным и открытым кодом ядра. Проблема была с ограниченным набором функций для работы с аппаратной частью ПК.

В стандартном ядре Колибри приложению был открыт доступ только к ограниченному диапазону портов ввода-вывода, системным сообщениям о некоторых аппаратных прерываниях и очень кривой PCI-сервис. Чтобы максимально ускорить работу программ с компьютерным железом, надо было прорубить экзодыру в монолитном ядре.

Так появилась Колибри-А, экзоверсия КолибриОС для платформ на базе AMD Fusion. Поскольку любое экзоядро несет в себе опасность фатального повреждения данных и оборудования ПК из-за некорректного доступа к критическим системным ресурсам, а также учитывая, что подавляющее большинство пользователей нашей системы – чайники малоопытные пользователи, пробующие новые ОС из чистого любопытства, Колибри-А изначально позиционировалась как совершенно обособленная ветка КолибриОС, предназначенная только для квалифицированных юзеров, имеющих представление как и с какими устройствами можно (и как нельзя) обращаться, и несущими полную ответственность за последствия своих действий.

Первым делом приложению напрямую был открыт доступ к
  1. Вводу/выводу во все порты (в основной ветке ядра приложение до сих пор должно «заказывать» нужный диапазон портов ввода/вывода через уродливое менуэтовское наследие – т.н. «сороковые функции»).
    Этого оказалось мало. Сейчас уже трудно найти устройство, общающееся с процессором исключительно через порты. Был добавлен удобный
  2. Доступ к MMIO (отображаемому на память пространству ввода/вывода) с помощью сисфункции 62:12. Сервис работает подобно линуксовской функции ioremap(), но реализован проще и гибче. Приложение указывает номер BAR-регистра в конфигурационном пространстве выбранного устройства и выбирает диапазон MMIO, к которому будет обращаться, а ядро отображает выбранный диапазон на линейное пространство приложения.
    Но и это еще не все. Приложение должно иметь полный доступ к конфигурационному пространству выбранного устройства. PCI-сервис ядра КолибриОС был реализован через медленные и неудобные порты CF8/CFC. В А-версию был добавлен быстрый доступ к
  3. Конфигурационному пространству PCI (включая расширенный конфигспейс PCI Express) с отображением на виртуальное адресное пространство приложения начиная с адреса 0xF0000000. Пример чтения заголовка PCI-устройства 1:18:2
    mov  eax, (1 shl 20) + (18 shl 15) + (2 shl 12)
    or   eax, 0xF0000000
    mov  [device_vendor], [eax]

    Нужно заметить, что отображение конфигспейса на память реализовано только для платформ на базе AMD-процессоров (кстати, именно это подчекивает название «Колибри-А»). Для интелов экзосервис пока не разработан: art_zh работает только с AMD-железом, а все остальные разработчики, к сожалению, особого интереса к экзоядру не проявляют.
    Ну хорошо, конфигспейс открыт. Теперь мы можем идентифицировать устройства, разрешать прерывания, следить за состоянием PCI-линии и обращаться к любым внутренним ресурсам, контролируя потоки данных и организуя прямой доступ в память… Хотя тут вот есть неувязочка: устройство ведь знает только физические адреса DMA-области, а приложение живет в своем линейном пространстве. Для этого
  4. Выделена статическая область DMA. Используя специальную сисфункцию 62:12-DA, приложение может запросить ее линейный адрес и работать с ней напрямую:
    mcall  62,11,0x0500                     ; init MMIO/DMA: bus=5, device=0, fn=0
    mov  [dma],eax                           ; store phys.addr of the DMA buffer: 
    mcall 62,0+12,4096,0                  ; map MMIO access to BAR0-space
    mov  [mio],eax                            ; store MMIO linear address
    mcall 62,0xDA0C,4096,0              ; 0x0da0c = create user DMA channel
    mov  [mem],eax                          ; store DMA buffer: linear @
    mov  eax, [dma]
    or   eax, DMA_FLAGS
    mov  dword[mio+4], eax              ; program device-specific DMA-register
    ;  ....
    mov  ecx, [mem]
    mov  eax, [index]
    mov  edx, dword[ecx+eax*4]       ; load the fresh data from DMA-buffer

    Вот теперь с устройством можно полноценно работать прямо из пользовательского приложения. Получился гибкий и универсальный инструмент, который art_zh уже 5 лет использует в повседневной работе для разработки нового железа и отладки низкоуровнего кода очень разных встраиваемых х86-устройств.
    К сожалению, разработав такой инструмент, автор переключился на другие задачи и нечасто публикует новые версии своего кода (оставаясь в проекте в роли «продвинутого юзера» и вечного брюзги на форуме). Но несмотря на длительные перерывы, работа потихоньку продолжается. Кроме вышеперечисленных, на сегодняшний день в Колибри-А имеются и другие экзофишки:
  5. Организация MSI-прерываний может быть организована через доступное юзеру адресное пространство LAPIC.
  6. Физическая память также может быть прочитана из приложения. Этот сервис очень полезен при отладке ядра.
  7. Бездисковая загрузка ОС опробована через CoreBoot (с помощью Xvilka) и через BIOS Extension ROM – из бортовой памяти PCIe-устройств.
  8. Открыто пространство GPU – пока только для установки аппаратных курсоров и реверс-инжиниринга ресурсов графического процессора AMD/ATI. Но кто знает, возможно когда-нибудь в Колибри будут программы и на GPU-ассемблере...


(продолжение следует)