Как правильно выйти из QEMU после выполнения голой программы без вмешательства пользователя?
Я собираю испытательный стенд для кросс-компиляции для системы ARM и запускаю тесты на хост-компьютере с qemu-system-arm
, В частности, я использую qemu для эмуляции eval-платы Stellaris LM3S6965, так как она содержит процессор Cortex M3, как моя целевая среда. Бинарный прогон в qemu построен с помощью инструментов GNU для ARM.
ОС не задействована. Набор тестов запускается как "голое железо" с приложением qemu -nographic
Режим. Набор инструментов и сам испытательный стенд работают нормально. И тесты успешно выполняются до конца и дают хорошие результаты в QEMU.
Проблема заключается в том, что пакет qemu упакован в автоматизированный инструмент сборки (в данном случае Rake). Кроме клавиатурных команд, я еще не нашел хорошего способа заставить qemu завершать работу после запуска набора тестов и выкладывать его результаты. Это заставляет среду сборки зависать / полагаться на вмешательство пользователя.
Я посмотрел высоко и низко и не нашел хороших источников о том, как выполнить простой выход после завершения программы. Я нашел пару предложений по запуску QEMU с -no-reboot
вариант, а затем запуск сброса системы из программы, запущенной в эмуляторе. Я попробовал это. Это работает... вроде. Я записываю соответствующие значения в вектор сброса эмулируемого процессора после main()
выполняется, и это вызывает сброс. После запуска набора тестов qemu сообщает о перезапуске системы. Тем не менее, он сообщает об этом как об аппаратной ошибке, сбрасывает содержимое реестра, а затем завершает работу сердито (сообщение об ошибке ниже). Хотя это завершает выход после запуска набора тестов, он затем прерывает сценарий автоматической сборки из-за выхода qemu с ошибкой.
qemu: hardware error: System reset
Я хотел бы избежать взлома ввода клавиатурных команд в сборку, чтобы имитировать вмешательство пользователя. Я также хотел бы не полагаться на выход qemu в состоянии ошибки.
Кажется, я близко к чистому выходу, но не совсем там. Поиск сообщения об ошибке qemu (см. Выше) не дал соответствующей документации, кроме сообщений об ошибках, связанных с тангенциальной связью.
Есть ли механизм, чтобы заставить qemu выйти после main()
возвращается в голой металлической программе, которую мне не хватает? Будет ли это -no-reboot
+ стратегия сброса системы работает? Если это так, что еще необходимо, чтобы qemu корректно завершил работу?
5 ответов
Самым чистым вариантом для меня было найти исходный код стабильной версии Qemu, близкой к той, которую мы уже использовали. Следующее относится к версии 1.1.2 источника Qemu.
Я изменил эмуляцию обработки вектора сброса для Eval Board Cortex M3 + Stellaris LM3S6965 в armv7m_nvic.c
, Я заменил hw_error()
позвонить с призывом к qemu_system_reset_request()
, Этот внутренний системный вызов сбрасывает виртуальную машину, но также отвечает на -no-reboot
опция командной строки для чистого отключения, как обсуждалось в моем первоначальном вопросе.
Эти инструкции по сборке сработали для меня после получения снимка Qemu 1.1.2. Я столкнулся с несколькими ошибками сборки, но веб-поиск быстро решил каждую проблему.
Я рекомендую использовать интерфейс Angel для процессоров ARM. Это очень полезно для отладки. Вы можете прочитать об этом в Информационном центре ARM. Особенно посмотрите на операцию angel_SWIreason_ReportException (0x18) и параметр ADP_Stopped_ApplicationExit, к которому QEMU поймет, что ваше приложение завершилось.
Не забудьте запустить QEMU с аргументом -semihosting, например:
qemu-system-arm -nographic -semihosting -kernel your_binary
Вот код, который говорит QEMU остановиться (вам нужно использовать ассемблер):
register int reg0 asm("r0");
register int reg1 asm("r1");
reg0 = 0x18; // angel_SWIreason_ReportException
reg1 = 0x20026; // ADP_Stopped_ApplicationExit
asm("svc 0x00123456"); // make semihosting call
Вы также можете посмотреть мой проект на github, где я его использовал.
После ответа Дж. Хаврана он работал с использованием другой сборки, и я работал с zephyr qemu cortex m3:
static inline void _exit_qemu() {
register u32_t r0 __asm__("r0");
r0 = 0x18;
register u32_t r1 __asm__("r1");
r1 = 0x20026;
__asm__ volatile("bkpt #0xAB");
}
а также
qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -vga none -net none -pidfile qemu.pid -serial mon:stdio -semihosting -kernel build/zephyr/zephyr.elf
выход из полухостинга aarch64
/questions/39623933/kak-pravilno-vyijti-iz-qemu-posle-vyipolneniya-goloj-programmyi-bez-vmeshatelstva-polzovatelya/39623938#39623938 дал A32, вот A64:
.global main
main:
/* 0x20026 == ADP_Stopped_ApplicationExit */
mov x1, #0x26
movk x1, #2, lsl #16
str x1, [sp,#0]
/* Exit status code. Host QEMU process exits with that status. */
mov x0, #0
str x0, [sp,#8]
/* x1 contains the address of parameter block.
* Any memory address could be used. */
mov x1, sp
/* SYS_EXIT */
mov w0, #0x18
/* Do the semihosting call on A64. */
hlt 0xf000
Вот пример на GitHub:
Документация переместилась на: https://developer.arm.com/docs/100863/latest
Как правило, вам нужно сделать все, что на оборудовании, что приведет к отключению системы (отключение питания); QEMU заставит это сделать 'выход QEMU'. К сожалению, не все аппаратное обеспечение, которое мы эмулируем, реализует механизм отключения питания (и иногда он не подключен в модели QEMU, хотя это, как правило, легко исправить ошибку).
Текущая версия ARMv7M qEmu (на основе микроконтроллера TI Stellaris LM3S6965) поддерживает сброс из регистра AICRCR (регистра управления прерываниями и сбросом приложения). Запись в SYSRESETREQ
бит этого регистра выдает сигнал внешней системе, которая запрашивает сброс.
Запись в AICRCR
требует написать 0x5FA
к VECTKEY
поле, в противном случае процессор игнорирует запись.
Эта строка делает перезагрузку ARMv7M qEmu.
SCB->AIRCR = (0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk;
Чтобы предотвратить неограниченную перезагрузку qEmu, вы можете добавить аргумент qEmu -no-reboot
,