В течение довольно долгого времени все еще существует проблема с QEMU / vExpress и U-boot, использующими более одного ядра ЦП (vExpress относится к ЦП ARM Cortex-A15). Прежде чем копаться в коде Qemu / U-boot, кто-нибудь исследовал это дальше? (Я готов углубиться в код начальной загрузки vExpress, пытаясь остановить другие процессоры, кроме первого). В настоящее время похоже, что Qemu запускает столько экземпляров U-boot, сколько заявленных процессоров (с использованием параметров -smp).
Проблема QEMU / vExpress относительно SMP и U-boot
Ответы (2)
Похоже, проблема в гостевом коде, который не ожидает запуска так же, как QEMU. Для vexpress QEMU имеет два способа загрузки:
- вы загружаете ядро Linux, которое мы загружаем по мере того, как vexpress bootrom загружает ядра Linux, то есть запускает основной ЦП и помещает вторичные ЦП в цикл WFI, ожидая, пока ядро дойдет до точки, в которой он хочет, чтобы они запустились
- вы загружаете что-то «голое железо», которое мы загружаем, запустив сразу все процессоры и ожидая, что образ «голого металла» их отсортирует (т.е. будет иметь небольшой код в его ранней загрузке, который смотрит на регистры идентификатора процессора и переключает вторичные ЦП в цикл удержания).
Если вы выполняете загрузку с нуля, но в вашем гостевом образе нет необходимого кода для обработки вторичных процессоров, эффект будет заключаться в том, что все они будут пытаться следовать кодовому пути основного процессора, который работает не очень хорошо ( несколько копий вывода консоли, странные сбои и прочая путаница).
Я не совсем уверен, как это работает на реальном оборудовании, но отчасти проблема здесь в том, что QEMU не эмулирует микроконтроллеры «конфигурационного контроллера» на реальном h / w, и мы не запускаем программное обеспечение «Boot Monitor». / firmware, которое обычно выполняет аппаратно-программное обеспечение, поэтому образ без покрытия для QEMU должен выполнять некоторую работу, которую на аппаратном обеспечении выполнял бы тот или иной из них.
Наконец-то мне удалось запустить U-boot на Qemu / vExpress с более чем одним процессором. Метод остановки вторичных процессоров аналогичен тому, как это делает Qemu при запуске образа ядра Linux.
Просто примените следующий патч в корневом каталоге U-boot (проверено на версиях> 2018)
From bf0fb125a3d85a5f0a6d7da744ebf110fc7e0f47 Mon Sep 17 00:00:00 2001
From: Daniel Rossier <[email protected]>
Date: Thu, 4 Jul 2019 13:06:39 +0200
Subject: [PATCH] ARM vExpress: stalling secondary CPUs when Qemu starts U-boot
Signed-off-by: Daniel Rossier <[email protected]>
---
board/armltd/vexpress/Makefile | 3 +-
board/armltd/vexpress/lowlevel_init.S | 91 +++++++++++++++++++++++++++
2 files changed, 93 insertions(+), 1 deletion(-)
create mode 100644 board/armltd/vexpress/lowlevel_init.S
diff --git a/board/armltd/vexpress/Makefile b/board/armltd/vexpress/Makefile
index 2a659de012..9048f9b39e 100644
--- a/board/armltd/vexpress/Makefile
+++ b/board/armltd/vexpress/Makefile
@@ -3,5 +3,6 @@
# (C) Copyright 2000-2004
# Wolfgang Denk, DENX Software Engineering, [email protected].
-obj-y := vexpress_common.o
+obj-y := vexpress_common.o
+obj-y += lowlevel_init.o
obj-$(CONFIG_TARGET_VEXPRESS_CA15_TC2) += vexpress_tc2.o
diff --git a/board/armltd/vexpress/lowlevel_init.S b/board/armltd/vexpress/lowlevel_init.S
new file mode 100644
index 0000000000..dca03d9606
--- /dev/null
+++ b/board/armltd/vexpress/lowlevel_init.S
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * (C) Copyright 2019 Daniel Rossier <[email protected]>
+ */
+
+#include <config.h>
+
+/*
+ * Routine: save_boot_params (called after reset from start.S)
+ * Description: check the running CPU and stall it if not running on
+ * the primary CPU.
+ * This allows U-boot to run on Qemu/vExpress with a number of CPU
+ * greater than 1 (-smp > 1)
+ */
+
+.global save_boot_params
+
+/*
+ * The stalling code is mainly based on the bootcode portion (smpboot)
+ * from Qemu.
+ */
+__start:
+stall_secondary_cpu:
+ ldr r2, GIC_CPU_IF
+ ldr r0, BOOT_REG
+ mov r1, #1
+ str r1, [r2]
+ mov r1, #0xff
+ str r1, [r2, #4]
+ dsb sy
+
+__wfi:
+ wfi
+ ldr r1, [r0]
+ tst r1, r1
+ beq __wfi
+ bx r1
+ @ Never reach this point
+
+ @ GIC CPI IF address
+GIC_CPU_IF:
+ .word 0x2c002000
+
+@ Store the entry point used at CPU wake-up
+BOOT_REG:
+ .word 0x1c010030
+
+@ vExpress SRAM
+DEST_ADDR:
+ .word 0x14000000
+
+__end:
+
+save_boot_params:
+
+ @ Check if we are on the primary (CPU #0)
+ @ Read Multiprocessor ID register
+ mrc p15, 0, r0, c0, c0, 5
+ ands r0, r0, #0x3
+ beq out_primary
+
+ @ Relocate the code handling the secondary CPUs to SRAM
+ @ thus allowing U-boot to be relocated itself in the DRAM
+ @ without interfering with this code.
+
+ ldr r0, =__start
+ ldr r1, DEST_ADDR
+
+ ldr r2, __code_size
+
+relocate:
+
+ ldr r3, [r0], #1
+ str r3, [r1], #1
+
+ subs r2, r2, #1
+ bne relocate
+
+ @ Now, jump to the stalling code
+ ldr pc, DEST_ADDR
+
+out_primary:
+
+ /* Returns */
+ b save_boot_params_ret
+
+__code_size:
+ .word __end - __start
+
+
+
--
2.17.1