Проблема QEMU / vExpress относительно SMP и U-boot

В течение довольно долгого времени все еще существует проблема с QEMU / vExpress и U-boot, использующими более одного ядра ЦП (vExpress относится к ЦП ARM Cortex-A15). Прежде чем копаться в коде Qemu / U-boot, кто-нибудь исследовал это дальше? (Я готов углубиться в код начальной загрузки vExpress, пытаясь остановить другие процессоры, кроме первого). В настоящее время похоже, что Qemu запускает столько экземпляров U-boot, сколько заявленных процессоров (с использованием параметров -smp).


person Daniel Rossier    schedule 25.06.2019    source источник


Ответы (2)


Похоже, проблема в гостевом коде, который не ожидает запуска так же, как QEMU. Для vexpress QEMU имеет два способа загрузки:

  1. вы загружаете ядро ​​Linux, которое мы загружаем по мере того, как vexpress bootrom загружает ядра Linux, то есть запускает основной ЦП и помещает вторичные ЦП в цикл WFI, ожидая, пока ядро ​​дойдет до точки, в которой он хочет, чтобы они запустились
  2. вы загружаете что-то «голое железо», которое мы загружаем, запустив сразу все процессоры и ожидая, что образ «голого металла» их отсортирует (т.е. будет иметь небольшой код в его ранней загрузке, который смотрит на регистры идентификатора процессора и переключает вторичные ЦП в цикл удержания).

Если вы выполняете загрузку с нуля, но в вашем гостевом образе нет необходимого кода для обработки вторичных процессоров, эффект будет заключаться в том, что все они будут пытаться следовать кодовому пути основного процессора, который работает не очень хорошо ( несколько копий вывода консоли, странные сбои и прочая путаница).

Я не совсем уверен, как это работает на реальном оборудовании, но отчасти проблема здесь в том, что QEMU не эмулирует микроконтроллеры «конфигурационного контроллера» на реальном h / w, и мы не запускаем программное обеспечение «Boot Monitor». / firmware, которое обычно выполняет аппаратно-программное обеспечение, поэтому образ без покрытия для QEMU должен выполнять некоторую работу, которую на аппаратном обеспечении выполнял бы тот или иной из них.

person Peter Maydell    schedule 01.07.2019
comment
Спасибо, Питер, я попытаюсь пропатчить U-boot / vExpress, чтобы правильно управлять загрузкой процессора, и отправлю его как патч U-boot. - person Daniel Rossier; 03.07.2019

Наконец-то мне удалось запустить 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
person Daniel Rossier    schedule 04.07.2019