Jailhouse гипервизор часть 3

Пример bare metal inmate

Jailhouse поставлена с inmate демками, расположенными в каталоге inmates/demos. Текущая (v0.6) версия содержит два inmate: gic-demo и UART-demo. Те очень просто применяются для bare-metal которые демонстрирует прерывания uart и arm таймер прерываний. Эти демо являются общими для всех jailhouse платформ.

Более интересным может быть ti-app, демо, сделанное специально для AM572x SOC. Код находится в каталоге inmate/ti_app.

В основном это приложение является песочницей (версия для изучения), чтобы сделать некоторые эксперименты. Текущая версия демонстрирует использование UART, таймера и прерывания GIC SPI (таймер генерирует периодические прерывания). Приложение также имеет некоторый дополнительный код, который использовался для измерения задержки прерывания.

Как и любой inmate, inmate ti-app работает в cell. am57xx-evm-ti-app.c есть конфигурациия ячейки. Для этой ячейки будет использоваться только ядро ARM 1:

	.cpus = {
		0x2,
	},

Примечание: на самом деле на AM572 SOC, который имеет только 2 ARM core и Linux всегда использует ARM 0 core только ARM 1 может быть принято за inmate. Конфигурация cell имеет 5 областей памяти:

		/* UART... */ {
			.phys_start = 0x48020000,
			.virt_start = 0x48020000,
			.size = 0x1000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED,
		},
		/* UART... */ {
			.phys_start = 0x48424000,
			.virt_start = 0x48424000,
			.size = 0x1000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED,
		},
		/* TIMER... */ {
			.phys_start = 0x48826000,
			.virt_start = 0x48826000,
			.size = 0x1000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED,
		},
		/* L4_CFG */ {
			.phys_start = 0x4a000000,
			.virt_start = 0x4a000000,
			.size = 0xE00000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_IO | JAILHOUSE_MEM_ROOTSHARED,
		},
		/* RAM */ {
			.phys_start = 0xee000000,
			.virt_start = 0,
			.size = 0x800000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE,
		},

Два для UART-а. Первый для UART3, который является стандартным evm debug uart. Второй для UART 9, использование которого требует некоторых модификаций платы. Но UART9 не конфликтует с Linux или гипервизором и может быть более полезен, если inmate нужен определенный UART. Один регион для таймера 9 и для доступа к нескольким регистрам конфигурации. Последняя область предназначена для ОЗУ, выделяемого для inmate. Аналогично корневой cell памяти области конфигурации сопоставление памяти для всех регионов, за исключением оперативной памяти идентичны (VA = PA). Для области ОЗУ виртуальный адрес должен быть “0”. Физические адреса региона должны находиться в физической памяти, зарезервированной для inmate в файле DTS Linux. В .irqchip разделе файла конфигурации ячейки мы резервируем линию прерывания GIC

  
	/* GIC */ {
		.address = 0x48211000,
		.pin_base = 160,
		.pin_bitmap = {
			0x00000040,
		},
	},

Вот откуда пришел #134. 0x00000040 – это битовая маска шестого бита. Так .pin_base(160) + .pin_bitmap(6) – 32(номер SWI и PPI прерывания) = 134.

Как и другие jaihouse демо, ti-app использует код запуска jailhouse, которые устанавливают векторную таблицу inmate, нулевые BSS сегменты, устанавливает рост стека и вызов inamte_main(). Инициализация GIC контроллера делается с помощью гипервизора. Также гипервизор переназначает GICC интерфейс, чтобы GICV интерфейс перехватывал все inmate доступы к GICD. Это позволяет читать/писать только GICD регистры, связанные со строками, приведенными в .irq_chips section. В нашем случае только для линии #134.

В inmate_main() inmate инициализирует uart, устанавливает перекрестное переключение и вызывает quick_setup(), чтобы установить обработчик прерывания inmate. Jailhouse обеспечивает inmate прерывания контроллер API. Этим может пользоваться inmate.

Программа TI-app инициализирует таймер и входит в бесконечный цикл.

На самом деле код inmate содержит всего около 100 строк и не требует объяснений.

RTOS PDK Inmate

Jailhouse демо-приложение и “ti_app” создают inmate makefile внутри дерева исходников jailhouse. Более интересно построить inmate за пределами дерева исходного кода jailhouse, используя независимые makefile и сторонние библиотеки. Этот релиз предоставляет lib_test, простой пример приложения на bare metal, который использует готовые библиотеки RTOS PDK и который построен независимо от jailhouse. Он также имеет порты двух тестовых приложений TI RTOS SYS BIOS-pruss и icss_emac. Есть еще два примера: 1) bare-metal memcp_bm-простое приложение для измерения пропускной способности памяти 2) Ethercat_slave_demo-портирован в Jailhouse на примере “PRU-ICSS Industrial Software for Sitara Processors”. Этот пример требует внесения некоторых изменений в промышленное программное обеспечение PRU-ICSS, которое еще не опубликовано. Вот почему ethercat_slave_demo включен здесь только в качестве ссылки.

Код приложений расположен в  $(SDK_INSTALL_PATH)/processor_sdk_rtos_am57xx_4_01_00_04/demos/jailhouse-inmate директории, которая содержит:

├── baremetal
│   ├── led
│   │   ├── led_test.c
│   │   └── makefile
│   ├── memcp_bm
│   │   ├── makefile
│   │   └── memcp_bm.c
│   └── soc
│       └── am572x
│           ├── evmAM572x
│           │   ├── entry.S
│           │   ├── gic.c
│           │   ├── linker.cmd
│           │   └── make.inc
│           └── rules.mk
├── makefile
├── rtos
│   ├── ethercat_slave_demo
│   │   ├── bios
│   │   │   ├── am572x_app.cfg
│   │   │   └── makefile
│   │   ├── Makefile
│   │   └── src
│   │       └── board_jh.c
│   ├── icss_emac
│   │   ├── bios
│   │   │   ├── icss_emac_arm_wSoCLib.cfg
│   │   │   └── makefile
│   │   ├── lnk_pruss_fw.cmd
│   │   ├── Makefile
│   │   └── src
│   │       ├── idkAM572x_ethernet_config_jh.c
│   │       └── idkAM572x_jh.c
│   ├── pru-icss
│   │   ├── bios
│   │   │   ├── makefile
│   │   │   └── pruss_arm_wSoCLib.cfg
│   │   ├── Makefile
│   │   └── src
│   │       └── idkAM572x_jh.c
│   └── Rules.mk
└── setenv.sh

Bare-metal пример

Bare-metal директория содержит 3 под директории: soc – имеет общий для bare-metal приложений soc специфичный код; led – led_test код приложения; memcp_bm – memcp_bm код;

Поддиректория soc/am572x/evmAM572x содержит:

entry.S-стартовый файл для inmate;
gic.c – имеет фиктивный _weak_ INTCCommonIntrHandler(), который может быть переопределен фактическим обработчиком приложения.
linker.cmd – jailhouse требует, чтобы inmate начинал с адреса “0”. Он также требует, чтобы все сегменты inmate были расположены в непрерывной памяти. linker.cmd должен соответствовать этим требованиям.

Каталог led содержит:

Главный inmate код led_test.c. Этот файл лежит $(SDK_INSTALL_PATH)/pdk_am57xx_1_0_6/packages/ti/board/diag/led/src/led_test.c является диагностическим приложением. Поскольку inmate работает как виртуальная машина для того, чтобы использовать кэш, MMU должен быть включен. Таким образом, приложение создает таблицу перевода MMU с идентичным отображением и включает MMU. Он также имеет gic_init(), который теперь используется в этом выпуске. Makefile, чтобы построить inmate. Как вы можете видеть, он связывает количество перестроенных библиотек PDK.

Для построения led_test.bin (inmate jaihouse должен быть *.bin, но не *.out file):

cd to $(SDK_INSTALL_PATH)/processor_sdk_rtos_am57xx_4_01_00_04 drectory
source setupenv.sh
cd к $(SDK_INSTALL_PATH)/processor_sdk_rtos_am57xx_4_01_00_04/demos/jailhouse-inmates
source setenv.sh
run make led_test

Это должно собрать led_test.bin бинарь, который можно загрузить в jaihouse cell и его запустить. Как и любой другой inmate, он должен быть помещен в cell, созданную с соответствующей конфигурацией. В отличие от led_test.bin, который компилируется независимо от jailhouse, соответствующая конфигурация cell компилируется jailhouse makefile.

am57xx-pdk-leddiag.c конфигурационный файл cell находится в $TI_SDK_PATH/board-support/extra-drivers/jailhouse-0.7/configs каталоге. Используйте скомпилированный am57xx-pdk-leddiag.cell файл при создании cell для led_test.bin.

См. «Запуск демо» для запуска inmate.

Memcpy_bm очень похож на led_test. Он построен таким же образом, как led_test. Используйте am57xx-bm.cell файл от $TI_SDK_PATH/board-support/extra-drivers/jailhouse-0.7/configs для создания jailhouse cell для memcp_bm inmate.

RTOS BIOS примеры

Pruss и icss_emac примеры расположены в rtos/pruss и rtos/icss_emac директориях. Структуры обоих директорий одинаковые. Каждая директория содержит bios и src поддиректории. Bios содержит XDC тип файла конфигурации приложения and makefile. Конфигурационный файл переработанная копия оригинального конфигурационного файла RTOS приложения. Для примера конфигурационный файл для icss_emac inmate был портирован из $(SDK_INSTALL_PATH)/ti/pdk_am57xx_1_0_7/packages/ti/drv/icss_emac/test/am572x/armv7/bios/icss_emac_arm_wSoCLib.cfg файла. Поскольку jailhouse inmate не несет ответственности за конфигурацию, связанную с платой, из конфигурационного файла были удалены библиотеки платы, библиотека i2c, секции OCRAM MMU и некоторые другие ненужные для inmate компоненты.
Поскольку основная функция приложения вызывает функцию board_init(), эта функция, а также Board_moduleClockInit() (с необходимыми для icss_emac клоком приложения) реализованы в idkAM572x_jh.c файл.

Таким образом, портированный файл конфигурации idkAM572x_jh.c и makefile-это только новые файлы, необходимые для переноса существующего проекта

RTOS SDK в jailhouse inmate.
jailhouse-inmate/makefile и имеет “pruss_test” и “icss_emac_test” задачи для построения inmate в BIOS.

Структура примера ethercat_slave_demo очень похожа на примеры pruss и icss_emac. Поскольку это зависит от конкретной версии “PRU-ICSS Industrial Software”, которая должна быть установлена самостоятельно, сборка демо-версии не входит в makefile верхнего уровня.

RTOS BIOS примечание по портированию

Как вы можете видеть в предыдущем разделе, у inmate RTOS BIOS только несколько новых файлов. Почти все файлы были повторно использованы в примерах RTOS SDK. Но при записи приложения RTOS BIOS к inmate Jailhouse следует учитывать следующие примечания.

Jailhouse inmate работает в маленькой cell. Cell создается гипервизором, который был запущен из уже загруженного ОС Linux. Это говорит о том, что SOC плата и большинство клоков уже инициализированы, а inmate не нужен и обычно не может использовать каких-либо ресурсов, не указанных в файле конфигурации cell inmate.

Таким образом, использование библиотек платы и I2C был удален из конфигурационного файла. Также OCRAM был удален из конфигурации MMU.

Гипервизор Jailhouse позволяет inmate обращаться к некоторым GICD-регистрам, но только для тех строк прерываний, которые перечислены в файле конфигурации cell. Cell, создает связывающую реконфигурацию платформенных регистры GICD самостоятельно. Стандартный API-интерфейс gic_init() настраивает платформенные регистры для всех строк прерываний. Это не допускается для inmate. Чтобы избежать этого, последняя версия SYSBIOS имеет специальную функцию, которая позволяет отключить платформенную конфигурацию из функции инициализации GIC. См. следующий фрагмент в файле конфигурации:

var Hwi = xdc.useModule('ti.sysbios.family.arm.gic.Hwi');
Hwi.initGicd = false;

Приложения RTOS BIOS построены в формате *.out. Загрузчик RTOS может загрузить этот файл на плату, даже если образ имеет несколько разделов с адресами, распределенными по всему диапазону адресов SOC. Jailhouse поддерживает только формат *.bin, а inmate может использовать только выделенную для него память, вырезанную из Linux. Поэтому портированное приложение должно использовать только ограниченную память.

Jailhouse может запустить inmate, который начинается с виртуального адреса 0x0, но обычное приложение RTOS связано с адресом 0x80000000 и отличается от этой точки входа. Jailhouse позволяет запускать такие приложения (см. выше). Но при использовании linux-loader требуется дополнительный узел в конфигурации cell inmate.

		/* RAM loader */ {
			.phys_start = 0xed000000,
			.virt_start = 0x0,
			.size = 0x10000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE,
		},
		/* RAM RTOS 224MB*/ {
			.phys_start = 0xe0000000,
			.virt_start = 0x80000000,
			.size = 0xd000000,
			.flags = JAILHOUSE_MEM_READ | JAILHOUSE_MEM_WRITE |
				JAILHOUSE_MEM_EXECUTE | JAILHOUSE_MEM_LOADABLE,
		},

Вы можете видеть, что конфигурация ячейки для icss_emac inmate настраивает две области ОЗУ: маленькую с виртуальным адресом 0x0 для Linux-loader

Общие замечания по переносу

Когда вы начинаете портировать свой RTOS или bare metal приложение в jailhouse, вы должны рассмотреть несколько вещей. Они перечислены ниже. Этот список не является полным и содержит только рекомендации, основанные на здравом смысле и предыдущем опыте переноса.

Linux всегда запускается раньше гипервизора. Linux инициализирует все (или почти все) общие ресурсы SoC. Таким образом, он инициализирует контроллер памяти, таймеры, контроллера прерываний и т.д. Настраивает регистры PINMUX. В большинстве случаев он также заботится о конфигурации платы.

Конфигурация cell inmate определяет ресурсы, доступные inmate. Портированное приложение может использовать только эти ресурсы и отвечает только за их инициализацию. Портированное приложение будет работать не на плате, которую оно использовало для запуска, а на другой виртуальной плате, определенной конфигурацией cell. Вот почему приложение не может использовать какие-либо общие функции board_init или soc_init, которые могут касаться используемых ресурсов Linux. Inamte – только гость.

Как уже упоминалось выше, Linux инициализирует контроллер прерываний и динамически настраивает регистры раскладки. Это должно быть запланировано заранее, который может прервать  использование inmate. Эти прерывания должны быть зарезервированы в файле dts Linux. Также используемые inmate прерывания должны быть перечислены в конфигурации cell inmate. Гипервизор настраивает платформенные регистры GIC для этих прерываний. Inmate отвечает только за включение, отключение и подтверждение прерываний.

Linux владеет шинами I2C. Inmate не может иметь собственного драйвера для управления шиной I2C. Это практически невозможно, даже если и корневая cell, и конфигурация cell inmate имеют общий регион I2C, и Linux, и inmate имеют соглашение не использовать I2C одновременно. Проблема в том, что драйвер Linux I2C работает в режиме прерывания, и если inmate выдает I2C транзакцию, будет вызван обработчик прерываний Linux. Он тормозит Linux и I2C драйверы inmate машины состояния (или что у них есть).

Использование GPIO может иметь такие же проблемы, как I2C. Легко отключить весь банк GPIO от использования Linux и использовать его для inmate. Но непрактично делить один и тот же банк и Linux, и inmate.