hw/sparc/leon3: check cpu_id in the tiny bootloader

Now that SMP is possible, the asr17 must be checked in the little boot
code or the secondary CPU will reinitialize the Timer and the Uart.

Co-developed-by: Frederic Konrad <konrad.frederic@yahoo.fr>
Signed-off-by: Clément Chigot <chigot@adacore.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Message-ID: <20240131085047.18458-9-chigot@adacore.com>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
This commit is contained in:
Clément Chigot 2024-01-31 09:50:46 +01:00 committed by Philippe Mathieu-Daudé
parent d65aba8286
commit 56bd9678ef

View File

@ -99,12 +99,26 @@ static uint32_t *gen_store_u32(uint32_t *code, hwaddr addr, uint32_t val)
/*
* When loading a kernel in RAM the machine is expected to be in a different
* state (eg: initialized by the bootloader). This little code reproduces
* this behavior.
* state (eg: initialized by the bootloader). This little code reproduces
* this behavior. Also this code can be executed by the secondary cpus as
* well since it looks at the %asr17 register before doing any
* initialization, it allows to use the same reset address for all the
* cpus.
*/
static void write_bootloader(void *ptr, hwaddr kernel_addr)
{
uint32_t *p = ptr;
uint32_t *sec_cpu_branch_p = NULL;
/* If we are running on a secondary CPU, jump directly to the kernel. */
stl_p(p++, 0x85444000); /* rd %asr17, %g2 */
stl_p(p++, 0x8530a01c); /* srl %g2, 0x1c, %g2 */
stl_p(p++, 0x80908000); /* tst %g2 */
/* Filled below. */
sec_cpu_branch_p = p;
stl_p(p++, 0x0BADC0DE); /* bne xxx */
stl_p(p++, 0x01000000); /* nop */
/* Initialize the UARTs */
/* *UART_CONTROL = UART_RECEIVE_ENABLE | UART_TRANSMIT_ENABLE; */
@ -118,6 +132,10 @@ static void write_bootloader(void *ptr, hwaddr kernel_addr)
/* *GPTIMER0_CONFIG = GPTIMER_ENABLE | GPTIMER_RESTART; */
p = gen_store_u32(p, 0x80000318, 3);
/* Now, the relative branch above can be computed. */
stl_p(sec_cpu_branch_p, 0x12800000
+ (p - sec_cpu_branch_p));
/* JUMP to the entry point */
stl_p(p++, 0x82100000); /* mov %g0, %g1 */
stl_p(p++, 0x03000000 + extract32(kernel_addr, 10, 22));