From bb6b27b143b1c5be8cba343c5af8456afc8aa296 Mon Sep 17 00:00:00 2001 From: bjh21 Date: Sat, 5 Oct 2002 23:30:03 +0000 Subject: [PATCH] Second phase of Hydra attachment: All CPUs are now set up sufficiently that they can call printf(), which they do before halting. --- sys/arch/acorn32/acorn32/genassym.cf | 8 +- sys/arch/acorn32/acorn32/hydra.c | 106 ++++++++++++++++++++++++-- sys/arch/acorn32/acorn32/hydra_boot.S | 86 ++++++++++++++++----- sys/arch/acorn32/acorn32/hydravar.h | 43 +++++++++++ sys/arch/acorn32/conf/files.acorn32 | 3 +- 5 files changed, 221 insertions(+), 25 deletions(-) create mode 100644 sys/arch/acorn32/acorn32/hydravar.h diff --git a/sys/arch/acorn32/acorn32/genassym.cf b/sys/arch/acorn32/acorn32/genassym.cf index a8304b22ffbe..673b6427460b 100644 --- a/sys/arch/acorn32/acorn32/genassym.cf +++ b/sys/arch/acorn32/acorn32/genassym.cf @@ -1,4 +1,4 @@ -# $NetBSD: genassym.cf,v 1.2 2001/12/20 01:20:21 thorpej Exp $ +# $NetBSD: genassym.cf,v 1.3 2002/10/05 23:30:03 bjh21 Exp $ # Copyright (c) 1982, 1990 The Regents of the University of California. # All rights reserved. @@ -35,6 +35,7 @@ # SUCH DAMAGE. include +include define IH_FUNC offsetof(struct irqhandler, ih_func) define IH_ARG offsetof(struct irqhandler, ih_arg) @@ -44,3 +45,8 @@ define IH_NUM offsetof(struct irqhandler, ih_num) define IH_MASKADDR offsetof(struct irqhandler, ih_maskaddr) define IH_MASKBITS offsetof(struct irqhandler, ih_maskbits) define IH_NEXT offsetof(struct irqhandler, ih_next) + +define HB_TTB offsetof(struct hydraboot_vars, hb_ttb) +define HB_BOOTPAGE_PA offsetof(struct hydraboot_vars, hb_bootpage_pa) +define HB_SP offsetof(struct hydraboot_vars, hb_sp) +define HB_ENTRY offsetof(struct hydraboot_vars, hb_entry) diff --git a/sys/arch/acorn32/acorn32/hydra.c b/sys/arch/acorn32/acorn32/hydra.c index f8b9f78bb04a..788e93bc2ac9 100644 --- a/sys/arch/acorn32/acorn32/hydra.c +++ b/sys/arch/acorn32/acorn32/hydra.c @@ -1,4 +1,4 @@ -/* $NetBSD: hydra.c,v 1.6 2002/10/05 13:46:57 bjh21 Exp $ */ +/* $NetBSD: hydra.c,v 1.7 2002/10/05 23:30:03 bjh21 Exp $ */ /*- * Copyright (c) 2002 Ben Harris @@ -29,7 +29,7 @@ #include -__KERNEL_RCSID(0, "$NetBSD: hydra.c,v 1.6 2002/10/05 13:46:57 bjh21 Exp $"); +__KERNEL_RCSID(0, "$NetBSD: hydra.c,v 1.7 2002/10/05 23:30:03 bjh21 Exp $"); #include #include @@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: hydra.c,v 1.6 2002/10/05 13:46:57 bjh21 Exp $"); #include #include +#include #include "locators.h" @@ -64,10 +65,19 @@ static void hydra_shutdown(void *); static void hydra_reset(struct hydra_softc *); +static int cpu_hydra_match(struct device *, struct cfdata *, void *); +static void cpu_hydra_attach(struct device *, struct device *, void *); +static void cpu_hydra_hatch(void); + CFATTACH_DECL(hydra, sizeof(struct hydra_softc), hydra_match, hydra_attach, NULL, NULL); +CFATTACH_DECL(cpu_hydra, sizeof(struct device), + cpu_hydra_match, cpu_hydra_attach, NULL, NULL); -extern char const hydra_bootcode[], hydra_ebootcode[]; +extern char const hydra_probecode[], hydra_eprobecode[]; +extern char const hydra_hatchcode[], hydra_ehatchcode[]; + +static struct hydra_softc *the_hydra; static int hydra_match(struct device *parent, struct cfdata *cf, void *aux) @@ -127,6 +137,9 @@ hydra_attach(struct device *parent, struct device *self, void *aux) bus_space_tag_t iot; bus_space_handle_t ioh; + if (the_hydra == NULL) + the_hydra = sc; + sc->sc_iot = mba->mb_iot; if (bus_space_map(sc->sc_iot, HYDRA_PHYS_BASE, HYDRA_PHYS_SIZE, 0, &sc->sc_ioh) != 0) { @@ -191,8 +204,8 @@ hydra_probe_slave(struct hydra_softc *sc, int slave) bus_space_handle_t ioh = sc->sc_ioh; int i, ret; - memcpy((caddr_t)sc->sc_bootpage_va, hydra_bootcode, - hydra_ebootcode - hydra_bootcode); + memcpy((caddr_t)sc->sc_bootpage_va, hydra_probecode, + hydra_eprobecode - hydra_probecode); bus_space_write_1(iot, ioh, HYDRA_MMU_SET, 1 << slave); bus_space_write_1(iot, ioh, HYDRA_HALT_SET, 1 << slave); bus_space_write_1(iot, ioh, HYDRA_RESET, 1 << slave); @@ -269,6 +282,89 @@ hydra_reset(struct hydra_softc *sc) bus_space_write_1(iot, ioh, HYDRA_MMU_CLR, 0xf); } +static int +cpu_hydra_match(struct device *parent, struct cfdata *cf, void *aux) +{ + + /* If there's anything there, it's a CPU. */ + return 1; +} + +static void +cpu_hydra_attach(struct device *parent, struct device *self, void *aux) +{ + struct hydra_softc *sc = (void *)parent; + struct hydra_attach_args *ha = aux; + int slave = ha->ha_slave; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + int i, ret, error; + vaddr_t uaddr; + struct hydraboot_vars *hb; + + /* + * Generate a kernel stack and PCB (in essence, a u-area) for the + * new CPU. + */ + uaddr = uvm_uarea_alloc(); + error = uvm_fault_wire(kernel_map, uaddr, uaddr + USPACE, + VM_FAULT_WIRE, VM_PROT_READ | VM_PROT_WRITE); + if (error) + panic("cpu_hydra_attach: uvm_fault_wire failed: %d", error); + + /* Copy hatch code to boot page, and set up arguments */ + memcpy((caddr_t)sc->sc_bootpage_va, hydra_hatchcode, + hydra_ehatchcode - hydra_hatchcode); + KASSERT(hydra_ehatchcode - hydra_hatchcode <= HYDRABOOT_VARS); + hb = (struct hydraboot_vars *)(sc->sc_bootpage_va + HYDRABOOT_VARS); + hb->hb_ttb = (paddr_t)curproc->p_addr->u_pcb.pcb_pagedir; + hb->hb_bootpage_pa = sc->sc_bootpage_pa; + hb->hb_sp = uaddr + USPACE; + hb->hb_entry = &cpu_hydra_hatch; + + cpu_drain_writebuf(); + + bus_space_write_1(iot, ioh, HYDRA_MMU_SET, 1 << slave); + bus_space_write_1(iot, ioh, HYDRA_HALT_SET, 1 << slave); + bus_space_write_1(iot, ioh, HYDRA_RESET, 1 << slave); + bus_space_write_1(iot, ioh, HYDRA_HALT_CLR, 1 << slave); + bus_space_write_1(iot, ioh, HYDRA_RESET, 0); + ret = 0; + for (i = 0; i < 100000; i++) { + if ((bus_space_read_1(iot, ioh, HYDRA_HALT_STATUS) & + (1 << slave)) != 0) { + ret = 1; + break; + } + } + bus_space_write_1(iot, ioh, HYDRA_HALT_SET, 1 << slave); + bus_space_write_1(iot, ioh, HYDRA_MMU_CLR, 1 << slave); + + cpu_dcache_inv_range((vaddr_t)hb, sizeof(*hb)); + + if (ret == 0) { + printf(": failed to spin up\n"); + return; + } + printf("\n"); +} + +static void +cpu_hydra_hatch(void) +{ + struct hydra_softc *sc = the_hydra; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + int slave; + + slave = bus_space_read_1(iot, ioh, HYDRA_ID_STATUS) & 0x3; + printf(": Number %d is alive!", slave); + bus_space_write_1(iot, ioh, HYDRA_HALT_SET, 1 << slave); + /* We only get here if someone resumes us. */ + for (;;) + continue; +} + #ifdef MULTIPROCESSOR void cpu_boot_secondary_processors(void) diff --git a/sys/arch/acorn32/acorn32/hydra_boot.S b/sys/arch/acorn32/acorn32/hydra_boot.S index 3571b4da12fd..aff12a3d2b66 100644 --- a/sys/arch/acorn32/acorn32/hydra_boot.S +++ b/sys/arch/acorn32/acorn32/hydra_boot.S @@ -1,4 +1,4 @@ -/* $NetBSD: hydra_boot.S,v 1.1 2002/09/30 23:22:05 bjh21 Exp $ */ +/* $NetBSD: hydra_boot.S,v 1.2 2002/10/05 23:30:03 bjh21 Exp $ */ /*- * Copyright (c) 2002 Ben Harris @@ -31,28 +31,20 @@ * hydra_boot.S - Code to run on a Hydra slave CPU when it comes out of reset. */ +#include "assym.h" + #include +#include #include +#include -RCSID("$NetBSD: hydra_boot.S,v 1.1 2002/09/30 23:22:05 bjh21 Exp $") +RCSID("$NetBSD: hydra_boot.S,v 1.2 2002/10/05 23:30:03 bjh21 Exp $") -ENTRY_NP(hydra_bootcode) +ENTRY_NP(hydra_probecode) /* * This code is mapped in at physical address zero when a CPU - * hatches, so it forms the vector table until the Hydra MMU - * is turned off and the CPU MMU is turned on. Any exception - * apart from a reset just puts us in a tight loop. + * is probed. It just halts the CPU as quickly as possible. */ - b Lhydra_reset /* Reset */ - b . /* Undefined instruction */ - b . /* SWI */ - b . /* Prefetch abort */ - b . /* Data abort */ - b . /* Address exception */ - b . /* IRQ */ - b . /* FIQ */ - -Lhydra_reset: mov r0, #HYDRA_PHYS_BASE ldr r1, [r0, #(HYDRA_ID_STATUS << 2)] and r1, r1, #3 /* Mask off slave ID */ @@ -62,5 +54,63 @@ Lhydra_reset: b . /* Get here if we're released */ .align 0 - .global _C_LABEL(hydra_ebootcode) -_C_LABEL(hydra_ebootcode): + .global _C_LABEL(hydra_eprobecode) +_C_LABEL(hydra_eprobecode): + + /* Code called when spinning up a slave CPU for real. */ +ENTRY_NP(hydra_hatchcode) + /* + * r0-r3: scratch + * r4: &hydraboot_vars + * r5: control reg + */ + + mov r4, #HYDRABOOT_VARS + + /* Enable 32-bit program and data space. */ + mov r5, #(CPU_CONTROL_32BP_ENABLE | CPU_CONTROL_32BD_ENABLE) + mcr p15, 0, r5, c1, c0, 0 + + /* Switch to SVC32 mode. */ + mrs r0, cpsr + bic r0, r0, #PSR_MODE + orr r0, r0, #PSR_SVC32_MODE + msr cpsr_c, r0 + + /* Switch to using the real physical address for this page. */ + ldr r0, [r4, #HB_BOOTPAGE_PA] + add r4, r4, r0 + add pc, pc, r0 + mov r0, r0 + mov r0, r0 + + /* Disable Hydra MMU for this processor. */ + mov r0, #HYDRA_PHYS_BASE + ldr r1, [r0, #(HYDRA_ID_STATUS << 2)] + and r1, r1, #3 /* Mask off slave ID */ + mov r2, #1 + mov r2, r2, lsl r1 /* Get the bit for this CPU */ + str r2, [r0, #(HYDRA_MMU_CLR << 2)] /* Disable MMU */ + + /* Set TTB */ + ldr r0, [r4, #HB_TTB] + mcr p15, 0, r0, c2, c0, 0 + /* Flush TLB */ + mov r0, #0 + mcr p15, 0, r0, c5, c0, 0 + /* Get start address */ + ldr r0, [r4, #HB_ENTRY] + /* Set up stack */ + ldr sp, [r4, #HB_SP] + mov fp, #0 + mov lr, #0 + /* Enable MMU */ + orr r5, r5, #CPU_CONTROL_MMU_ENABLE + orr r5, r5, #CPU_CONTROL_SYST_ENABLE + mcr p15, 0, r5, c1, c0, 0 + /* Run away before the pipeline runs out */ + mov pc, r0 + b . + .align 0 + .global _C_LABEL(hydra_ehatchcode) +_C_LABEL(hydra_ehatchcode): diff --git a/sys/arch/acorn32/acorn32/hydravar.h b/sys/arch/acorn32/acorn32/hydravar.h new file mode 100644 index 000000000000..ade1d26c000b --- /dev/null +++ b/sys/arch/acorn32/acorn32/hydravar.h @@ -0,0 +1,43 @@ +/* $NetBSD: hydravar.h,v 1.1 2002/10/05 23:30:03 bjh21 Exp $ */ + +/*- + * Copyright (c) 2002 Ben Harris + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Variables in the Hydra boot page used to pass critical data to a + * newly-hatched CPU. + */ +#define HYDRABOOT_VARS 0x0f00 + +#ifndef _LOCORE +struct hydraboot_vars { + paddr_t hb_ttb; + paddr_t hb_bootpage_pa; + register_t hb_sp; + void (*hb_entry)(void); +}; +#endif diff --git a/sys/arch/acorn32/conf/files.acorn32 b/sys/arch/acorn32/conf/files.acorn32 index 3e3558a0e3ce..b012644701ea 100644 --- a/sys/arch/acorn32/conf/files.acorn32 +++ b/sys/arch/acorn32/conf/files.acorn32 @@ -1,4 +1,4 @@ -# $NetBSD: files.acorn32,v 1.15 2002/09/30 23:22:06 bjh21 Exp $ +# $NetBSD: files.acorn32,v 1.16 2002/10/05 23:30:03 bjh21 Exp $ # # First try for arm-specific configuration info # @@ -21,6 +21,7 @@ file dev/isa/isadma.c isadma needs-flag # Simtec Hydra multiprocessor system device hydra { slave = -1 } attach hydra at mainbus +attach cpu at hydra with cpu_hydra file arch/acorn32/acorn32/hydra.c hydra needs-flag file arch/acorn32/acorn32/hydra_boot.S hydra needs-flag