Как правильно выйти из 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,

Другие вопросы по тегам