QEMU / vExpress проблема, касающаяся SMP и U-boot - PullRequest
0 голосов
/ 25 июня 2019

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

Ответы [ 2 ]

0 голосов
/ 04 июля 2019

Мне наконец-то удалось запустить U-boot на Qemu / vExpress с более чем одним процессором. Метод остановки вторичных процессоров аналогичен тому, что делает Qemu при запуске образа ядра Linux.

Просто примените следующий патч в корневом каталоге U-boot (протестировано на версиях> 2018)

From bf0fb125a3d85a5f0a6d7da744ebf110fc7e0f47 Mon Sep 17 00:00:00 2001
From: Daniel Rossier <daniel.rossier@heig-vd.ch>
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 <daniel.rossier@heig-vd.ch>
---

 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, wd@denx.de.

-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 <daniel.rossier@heig-vd.ch>
+ */
+
+#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
0 голосов
/ 01 июля 2019

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

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

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

Я не совсем уверен, как реальное оборудование делает это, но отчасти проблема заключается в том, что QEMU не эмулирует микроконтроллеры "контроллера конфигурации" в реальном времени, и мы не запускаем "Boot" Мониторинг "программного / микропрограммного обеспечения, обычно выполняемого ч / б, поэтому образ QEMU с" голым металлом "должен выполнять некоторую работу, которая была бы выполнена одним или другим из этих ч / б.

...