Хабрахабр

Embox начинает восхождение на Эльбрус

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

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

Приступим.

Объект исследований – макет встраиваемой системы на Эльбрус

Поскольку мы занимаемся Embox (а он, если кто не в курсе, ориентирован на встроенные системы), нас интересовал прежде всего вариант, который самим МЦСТ позиционируется в том числе для встраиваемых систем. Обратившись в МЦСТ мы выяснили, что в компании заинтересованы в применении своих процессоров для встраиваемых систем. Одним из последних решений для данного сегмента является плата E4C-COM . В процессе общения с МЦСТ стало понятно, что для портированая и освоения архитектуры, можно воспользоваться любой из имеющихся машин, и нам во временное пользование дали вычислитель под названием Монокуб. Вообще, монокуб не совсем то, к чему мы привыкли в embedded systems. Обычно во встраиваемых системах используют одноплатные компьютеры, чип — система на кристалле или вовсе микроконтроллер, монокуб же является полноценным компьютером, но поскольку он прошел испытания по “климатике и механике”, то его все-таки можно считать embedded system.

Компилятор, сборка, заливка образа

После получения системного блока, естественно, встал вопрос — как заливать образ. В МЦСТ используют свой BIOS (системный загрузчик первого уровня). По умолчанию устанавливается ОС Эльбрус (т.е. Debian с модификациями). Нам же интересно запускать собственный образ. На наше счастье загрузчик МЦСТ умеет запускать образы по сети. Для этого используется протокол ATA over Ethernet.

Для этого нам потребовался компилятор. После того, как нам помогли настроить стенд и запустить внешний образ по сети, мы приступили к разработке собственного образа. Компилятор оказался вполне себе gcc-совместимым, и нам ничего не пришлось менять, естественно за исключением флагов компиляции, которые у нас вынесены в отдельный конфигурационный файл. Компилятор в открытом доступе не нашли, но поскольку мы подписали NDA, нам выдали бинарники под Линукс. Что очень предсказуемо, ведь линукс, пусть и с модификациями, собирается этим компилятором.

Пара технических вопросов

Те, кто занимался такой специфичной деятельностью, как портирование ОС на какую-либо платформу, знают, что первое, что нужно сделать — это правильно разместить программный код в памяти. То есть написать линкер-скрипт (lds) и реализовать стартовый код. С линкер-скриптом довольно быстро разобрались, но вот при реализации стартового кода, мы столкнулись с первой магией, которую так до конца и не поняли. Дело в том, что у Эльбруса есть режим x86-совместимости и по адресу 0x00FF0000 лежит код, на который просто дам ссылку, поскольку мы его позаимствовали из примера МЦСТ. Линкер скрипт содержит

.bootinfo : SECTION_REGION(bootinfo)
.text : { _start = .; /* 0x01000000 */ *(.e2k_entry);

Сам же стартовый код написан даже не на ассемблере, а просто на Си. Он положен в секцию, размещенную по адресу 0x01000000, что кстати вполне соответствует стартовому адресу обычных x86-машин — там по этому адресу лежит заголовок multiboot либо другой заголовок.

Если получится вывести какой-нибудь символ, то, скорее всего, не возникнет проблем с выводом строк. Для того, чтобы удостовериться, что стартовый код и адреса верны, нужно добиться какого-нибудь вывода. К тому же, большинство платформ предоставляет возможность выводить символы, делая простую запись в определенный регистр (т.к. Используя этот вывод, уже можно будет использовать привычный printf() для отладки. загрузчик уже, скорее всего, настроил UART как надо).

Тут же столкнулись со странной проблемой — часть символов, выводимых printf, будто бы дублировалась, но при этом иногда перемешивалась. В нашем компьютере используется контроллер последовательного порта am85с30 (он же z85с30 мы достаточно быстро нашли, как вывести один символ, а этого достаточно для работы нашего printf-а. Получалось что-то вроде Hhelellloo,, woworrlldd. Например, при попытке вывести Hello, world! В нашем монокубе стоит двухъядерный Эльбрус-2С+ (1891ВМ7Я) (четыре DSP ядра не в счет) и загрузчик активизирует все процессорные ядра. Сейчас кажется очевидным, что дело в многоядерности, но сначала мы долго ковырялись в самом драйвере. Для этого мы ввели переменную для номера процессора и с помощью атомарного сложения инкрементируем ее. В итоге, чтобы не возиться с многоядерностью (SMP), все ядра кроме первого отправляем в бесконечный цикл. Нулевое ядро продолжает работать, а другие ядра зацикливаются.

cpuid = __e2k_atomic32_add(1, &last_cpuid); if (cpuid > 1) { /* XXX currently we support only single core */ while(1); } /* copy of trap table */ memcpy((void*)0, &_t_entry, 0x1800); kernel_start();

Вызов kernel_start() — это уже передача управления нашему коду.
Атомарное сложение мы тоже позаимствовали, для нас оно смахивает на магию. Но, как известно, работает — не трогай!

#define WMB_AFTER_ATOMIC ".word 0x00008001\n" \ ".word 0x30000084\n" #define __e2k_atomic32_add(__val, __addr) \
({ \ int __rval; \ asm volatile ("\n1:" \ "\n\tldw,0 %[addr], %[rval], mas=0x7" \ "\n\tadds %[rval], %[val], %[rval]" \ "\n\t{"\ "\n\tstw,2 %[addr], %[rval], mas=0x2" \ "\n\tibranch 1b ? %%MLOCK" \ "\n\t}" \ WMB_AFTER_ATOMIC \ : [rval] "=&r" (__rval), [addr] "+m" (*(__addr)) \ : [val] "ir" (__val) \ : "memory"); \ __rval; \
})

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

static inline void e2k_wait_all(void) { _Pragma ("no_asm_inline") asm volatile ("wait \ttrap = %0, ma_c = %1, fl_c = %2, ld_c = %3, " "st_c = %4, all_e = %5, all_c = %6" : : "i" (0), "i" (1), "i" (1), "i" (0), "i" (0), "i" (1), "i" (1) : "memory");
}

В итоге, после написания стартового кода у нас не только появились сообщения, выводимые с помощью printk, но и стали загружаться модули, что вообще то не очень тривиально для не совсем стандартных компиляторов. Так что еще раз отмечу, что на этот раз совместимость с gcc очень сильно порадовала.

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

Это графический контроллер для встроенных применений, имеет на борту поддержку 2d-графики. В монокубе используется графический контроллер из серии sm750. Исходники для драйвера под линукса можно найти тут. Микросхема напаяна прямо на материнскую плату, насколько я понял.

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

/* * Do load with specified MAS */
#define _E2K_READ_MAS(addr, mas, type, size_letter, chan_letter) \
({ \ register type res; \ asm volatile ("ld" #size_letter "," #chan_letter " \t0x0, [%1] %2, %0" \ : "=r" (res) \ : "r" ((__e2k_ptr_t) (addr)), \ "i" (mas)); \ res; \
}) #define _E2K_WRITE_MAS(addr, val, mas, type, size_letter, chan_letter) \
({ \ asm volatile ("st" #size_letter "," #chan_letter " \t0x0, [%0] %2, %1" \ : \ : "r" ((__e2k_ptr_t) (addr)), \ "r" ((type) (val)), \ "i" (mas) \ : "memory"); \
})

Тут есть некоторое понимание происходящего. У Эльбруса несколько альтернативных адресных пространств, как, например, в SPARC архитектуре. Идентификация идет с помощью идентификатора адресного пространства. То есть одна и та же команда ld попадает по разным внутренним адресам, еще и сгенерит операции чтения разной длины (8, 16, 32, 64 бита). Если в SPARC это отдельная команда lda/sta то в Эльбрусе за счет параметров, это команда ld. Из SPARC архитектуры позаимствовали регистровые окна. Более подробный рассказ я отложу для последующих статей.

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

В завершение данной статьи я просто приведу вывод в консоль (по последовательному порту). Мы продвинулись и в других направлениях: прерывания и системные вызовы, но об этом мы также расскажем в следующих статьях данной подсерии.

Выводы

Как я говорил в предисловии, я хочу сосредоточиться в первую очередь не на технических деталях, а на общих ощущениях. Так вот, ощущения противоречивые, хотя конечно больше положительные. С одной стороны, процессор существует и является очень интересным с точки зрения архитектурных особенностей. На основе этого процессора выпускаются вычислительные системы, есть ПО, достаточно высокого качества. Как я сказал, к компилятору не было претензий (до определенного момента, который опишу чуть позже), есть полноценный Линукс (ОС “Эльбрус”). Я лично видел, как в самом МЦСТ, разработчик творил прямо на десктопе с архитектурой Эльбрус.

Ведь нигде в мире не используют процессоры на основе VLIW архитектуры в качестве универсальных персональных компьютеров. Но с другой стороны, я не понимаю, почему с таким упорством пытаются сделать из данного процессора банальную замену интеловским x86. Нет экскаватором конечно можно вырыть ямку для посадки деревца, но стоит ли. VLIW в силу своих архитектурных особенностей является крутой “числодробилкой”, на ней делают DSP, делали сервера itanium, делали графические карты.

Да, для того чтобы получить описание системы команд, нужно просто подписать NDA, но ведь этого мало. Главной же проблемой препятствующей развитию архитектуры, на мой взгляд является закрытость всей экосистемы. Да, я всегда считал, что какое-то базовое ПО должно разрабатываться прямо у производителя процессоров, ну или в тесном сотрудничестве с ним. Архитектура незнакомая и очень сложная. Но все же слишком наивно считать, что одна компания, пусть даже крупная, может обеспечить качественную поддержку всем составляющим: процессор, компилятор, средства разработки и отладки, системное ПО (ОС различные), прикладное ПО, …. По этому принципу у ПК на Эльбрусах есть комплект ПО с ОС “Эльбрус”. Мир давно идет в сторону так называемой коллаборации или совместной разработки. такое не под силу даже Интелу.

Драйвер последовательного порта в какой то момент перестал выводить символы, причем, на первый взгляд, ничего не изменилось. Приведу пример проблемы с компилятором, на которую мы наткнулись. То есть, если функция присутствует, все нормально, если нет, то пропадает вывод. Оказалось, что мы убрали неиспользуемую отладочную функцию, которую вставили для того, чтобы через дизассемблер понять, как на ассемблере передать аргументы в функцию. Пока данную проблему не решили, продолжаем исследовать, чтобы показать разработчикам компилятора из МЦСТ или понять, где мы ошиблись. Сначала грешили на выравнивание, но оказалось, что функцию можно перенести и в конец Си-шника, поэтому все символы из драйвера оказывались на тех же местах, что и раньше, но проблема воспроизводилась.

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

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

Еще один важный момент, когда мы обсуждали проблему закрытости с разработчиками МЦСТ, они возразили, что, например, исходники ядра линукса открыты долгое время, однако только мы и разработчики компании Доломант задавали вопросы и как то их использовали.

На котором можно будет собрать и запустить ПО на ПК с архитектурой Эльбрус. Кроме того, по моей информации, в компании МЦСТ собираются организовать стенд
доступный удаленно. Данные я передам в МЦСТ или свяжу желающих с организаторами. Если есть подобный интерес и хочется использовать стенд, то следует обратиться, например, ко мне: описать, как планируется его использовать, сколько времени нужно и так далее, ведь для совместного доступа с изменением ПО, нужно организовать расписание.

Полезные ссылки:

Адрес рассылки для пользователей — user[at]mcst.ru
Краткое описание архитектуры Эльбрус
Исходники ядра Линукс
Исходники Embox

S. P. Всем желающим мы покажем, то что у нас получилось, на IT-фестивале TechTrain 1-2 сентября.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть