Как приручить ядро процессора*

Как приручить ядро процессора*

В данной статье рассказывается о этапах загрузки ядер процессоров серии QoriQ и участии в этом загрузчика u-boot, и о исполнении раздельно забранной программы на отдельном процессорном ядре без участия ОС. Статья может заинтересовать системных программистов, стремящихся постичь все разнообразие процессорных архитектур. Кроме этого направляться осознавать, что кое-какие определения и приемы актуальны и для других процессоров и систем.
Смотрите кроме этого: Qualcomm может создать обновлённую версию Snapdragon 810 специально для Samsung

Бессчётные сообщения о проблемах с перегревом процессора Snapdragon 810 не останавливают производителей оснащать данным чипсетом собственные мобильные устройства. К примеру, LG дала предпочтение восьмиядерному Snapdragon 810, в то время, когда разрабатывала смартфон G Flex 2. Со своей стороны, Qualcomm объявила, что уровень нагревания того же G Flex 2 со Snapdragon 810 на борту есть оптимальным. После этого последовала информация о том, что компания Samsung однако решила отказаться от проблемной комплектующей в пользу собственного процессора Exynos.

* на примере процессоров freescale qoriq c ядрами e500mc и ppc booke isa.К делу !Жизнь начинается со старта ядра* номер 0, которое делает с фиксированного адреса код загрузчика. В нашем случае загрузчиком есть u-boot, расположенный в flash памяти и дешёвый по физическим адресам 0x3ffff000. Сразу после старта данный адрес отображается на виртуальный 0xfffff000, о чем имеется запись в таблице отображения (см. документацию на e500). * тут и потом под ядром понимается ядро процессора (core), если не указано иного.

Первой командой, исполняемой процессором есть команда, расположенная по адресу 0xfffffffc. Как вы, предположительно, уже додумались данной командой в обязательном порядке должна быть команда перехода в точку старта u-boot на данной странице.

Как-то так:/* */ .section .resetvec,ax b _start_e500для тех, кто в Интлеb ? jmpдля тех, кто в Javaэто команда абсолютного перехода на метку _start_e500Потом в задачи u-boot входит настройка и включение кэшей, механизмов разграничения доступа, таблицы отображения адресов и, само собой разумеется, нужно отобразить другую часть себя в адресное пространство ядра процессора. По большому счету u-boot — молодец: берет на себя всю грязную работу, в отличие от некоторых (не будем тыкать пальцем, это не его вина).А как же остальные ядра?

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

Для предотвращения этого uboot поменяют адрес трансляции загрузочной области на место размещения дополнительного загрузчика остальных ядер(см. ccsr boot space translation registerы).Кстати, в настройках u-boot существуют возможность не инициализировать работу остальных ядер процессора, но в этом случае исполнение грязной работы по их инициализации делается отечественной предстоящей заботой. Которую, но, возможно решить копированием кода из u-boot, а сам запуск ядра осуществляется записью соответствующего бита в регистр ccsr.В задачи дополнительного загрузчика кроме этого входит настройка добавление и кэш записи в таблицу отображения адресов, по окончании чего ядра крутятся в таковой радостной карусельки:/* spin waiting for addr */ 2: lwz r4,ENTRY_ADDR_LOWER(r10)/* загрузить эти по адресу*/ andi. r11,r4,1 /* еслимладший бит = 1, то…*/ bne 2b /* …переход выше, к метке 2*/ Крутятся они , пока в определенный u-boot адрес не запишут адрес точки старта с 0 младшим битом.

Место, куда нужно записать эту команду в u-boot именуется spin-таблица и расположена она по фиксированному адресу (0xfffff000 + ENTRY_ADDR_LOWER). Не считая адреса старта, в эту таблицу возможно записать значения регистров r6 и r3, каковые будут загружены перед исполнением команды перехода в точку старта.

На точку старта накладывается ограничение в размер уже отображенной u-boot 64Мб страницы, это связано с внутренними тараканами uboot.Для тех, кто обучался на современных книжках информатикиВ PowerPC и некоторых вторых архитектурах страница есть растяжимым понятием. В частности, на процессорах e500* она может растянуться в диапазоне от 4К до 4Гб (ограничения и подробности см. в документации).Создание приложений для ядра.

Давайте создадим программу для отечественного ядра, которая традиционно будет печатать «hello world». Будем вычислять, что кросс компилятор и легковесную библиотеку libc мы уже собрали, и мы можем загружать ОС без помощи многоядерности на одном из ядер (в качестве ОС возможно, к примеру, применять скомпилированный соответствующим образом linux либо lynxos-178). Исходя из этого приступим к самому тяжелому — программированию:#includeint main (int argc, char *argv[]) { printf («hello world\n»); return 0; } Готово.

А куда и как будет выводить printf ?! Для этого нужно написать кое-какие заглушки для libc, каковые возможно подсмотреть в исходниках u-boot. Я использую упрощенный вариант:int write (int fildes, char *buf, int nbyte){ int wbyte = 0; while (nbyte 0) { __putc(*buf); buf++; nbyte—; wbyte++; } return wbyte; }int fstat(int fildes, struct stat *buf); { buf-st_mode = S_IFCHR; return 0; } И функция __putc обязана обеспечить вывод одного знака в последовательный порт. extern volatile unsigned char *uart_data; extern volatile unsigned char *uart_status;static void __putc(unsigned char c) { unsigned char v;do { v = *uart_status; } while (!(v (1 Полноценный драйвер для этого писать необязательно, достаточно воспользоваться настройками по умолчанию и записывать знак по обрисованному в документации адресу.

Физическому адресу. Что необходимо еще отобразить. Функцию отображения я приводить не буду в силу ее специфичности, но готов поделиться ей по запросу.И обрезаем настоящую точку старта исполняемого файла— функцию _start. Для инициализации возможно покинуть лишь обнуление bss сегмента:int _start(int argv, char **argc) { unsigned char * cp = (unsigned char *) &__sbss; while (cp (unsigned char *)&направляться;__ebss) { *cp++ = 0; } return main(argv, argc); } Итак, сейчас мы можем обходиться без ОС и функция printf знает куда ей выводить данные.

Компилируем:$ powerpc-eabi-gcc -o hello hello.c start.cБудет трудиться? Нет! Процессор не осознаёт формат исполняемого файла elf. Нужно отрезать прочие атрибуты и лишний заголовок исполняемого файла. Обрезаем:$ powerpc-eabi-objcopy -O binaryhello hello.binБудет трудиться? Нет!

Раньше точка старта задавалась в elf, а сейчас она далеко. Более подробное расположение возможно взглянуть утилиткой powerpc-eabi-objdump.

Само собой разумеется, возможно в качестве точки старта указать u-boot и на это место, но лучше написать указания линковщику о размещении точки старта в начале файла: OUTPUT_ARCH(powerpc:common) ENTRY(_start) STARTUP(start.o) …Предстоящее содержание файла будет зависеть от версии средств сборки и вы это имеете возможность подсмотреть в сценариях прилагаемых к компилятору.Сейчас, в соответствии с сценарию, линковщик полностью добавит файл start.o в начало исполняемого файла. Порядок следования функций наряду с этим обязан соответствовать исходному тексту, но будет спокойнее покинуть в этом файле лишь одну функцию — _start.

По большому счету вариант с добавлением STARTUP есть стремительным и узким ответом. В случае если в будущем мы захотим большего, то нужно будет копаться с привязкой функций к сегментам и размещением их в сценария.Собираем еще раз и думаем как комфортно это делать с makefile:$ powerpc-eabi-gcc -T hello.ld -o hello hello.c start.c Сейчас, в случае если мы все собрали верно, у нас имеется готовая для запуска на отдельном ядре, без ОС программа. Но лучше дополнительно все проверить посредством objdump.

Должно окажется как-то так:Disassembly of section .text: 00004000 : 4000: 3d 00 00 01 lis r8,1 4004: 3c e0 00 32 lis r7,50 4008: 39 08 70 00 addir8,r8,28672 400c: 38 e7 80 78 addir7,r7,-32648 4010: 39 48 ff ff addir10,r8,-1 4014: 39 27 ff ff addir9,r7,-1 … Кстати, вы увидели адреса сегментов сбоку? Если не указано иного, то отечественная программа имеет позиционно зависимый код и запускать ее откуда попало запрещено.

Но на данный момент это нас не должно тревожить, а исправить смещение возможно посредством сценария линковщика. Верно собранная программа обязана запускаться кроме того через u-boot. Запуск ядра С позиций ОС, дополнительное ядро ничем не будет различаться от остальных периферийных устройств применяющих DMA и для его работы нам потребуется выделить память.

Память будет употребляться для размещения отечественной программы, а в будущем для обмена результатами ее работы, размещения обработчиков исключений и пр. Выделяется память простыми средствами ОС: kmalloc для linux, alloc_cmem для lynxos и т.д., но физический адрес начала данной памяти должен быть выравнен по размеру страницы.

Неспециализированная схема отображения памяти будет смотреться примерно так:В случае если мы не желаем отстрелить ОС ногу, то будет разумно, в случае если размер выделенной ОС памяти будет соответствовать размеру отображаемой памяти для другого ядра. В другом случае отечественное ядро может записать в область памяти, которая употребляется ОС для внутренних целей. Тут вам не гипервизор.

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

А про ограничение в размер точки старта забыли?Запрещено верить в каком диапазоне адресов у совокупности останется свободная память и может так произойдёт, что выделенная память придется на неотображаемый u-boot диапазон адресов. Это приведет к исполнению исключения неточности страницы, которое у нас не настроено, что в конечном итоге приведет к останову ядра процессора.Ответов этого возможно пара и мне больше всего понравилось сделать в ОС собственный инициализатор ядра, расположенный в начальных адресах, что:

  • преодолеет ограничение точки старта;
  • ограничит отечественное приложение в применяемой памяти так, дабы был виден лишь участок памяти выделенный ОС;
  • настроит доступные для ядра устройства;
  • совершит прыжок в начало отечественной программы;

По окончании передачи управления программе в консоль должно вывестись «hello world» В будущем, применяя регистры управления, ядра процессора возможно останавливать, перезапускать, поменять частоту, выдавать им прерывания (это занимательная, но весьма специфичная тема) и другое. Заключение Само собой разумеется, многие современные ОС предоставляют возможность изолировать ядра процессора для отдельных приложений и необходимость писать собственный код для помощи многоядерности вызывающа большие сомнения.

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

Случайная статья:

Повышение фпс в играх — Скрытые ядра процессора


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

Комментирование и размещение ссылок запрещено.

Обсуждение закрыто.