aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClément Chigot <chigot@adacore.com>2024-01-31 09:50:46 +0100
committerPhilippe Mathieu-Daudé <philmd@linaro.org>2024-02-15 16:58:46 +0100
commit56bd9678ef553498274f1d29ebb2839f220bce6d (patch)
treeb1f37e949164d529abfa8b259894878fd6cbb97e
parentd65aba8286e40bc02f26f19e53fa20c9396d02e7 (diff)
downloadqemu-56bd9678ef553498274f1d29ebb2839f220bce6d.zip
qemu-56bd9678ef553498274f1d29ebb2839f220bce6d.tar.gz
qemu-56bd9678ef553498274f1d29ebb2839f220bce6d.tar.bz2
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>
-rw-r--r--hw/sparc/leon3.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c
index 1637900..bea84f3 100644
--- a/hw/sparc/leon3.c
+++ b/hw/sparc/leon3.c
@@ -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));