Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/riscv risc-v: MULTIPROCESSOR support



details:   https://anonhg.NetBSD.org/src/rev/bfc499a2c3fc
branches:  trunk
changeset: 376349:bfc499a2c3fc
user:      skrll <skrll%NetBSD.org@localhost>
date:      Mon Jun 12 19:04:13 2023 +0000

description:
risc-v: MULTIPROCESSOR support

Add MULTIPROCESSOR support for RISC-V, but leave disabled for the moment
as it's not 100% stable.

Some other improvements to spl and cpu identification / reporting.

diffstat:

 sys/arch/riscv/conf/files.riscv      |    4 +-
 sys/arch/riscv/fdt/cpu_fdt.c         |  158 +++++++++++++-
 sys/arch/riscv/fdt/intc_fdt.c        |   69 +++--
 sys/arch/riscv/fdt/riscv_fdtvar.h    |   41 +++
 sys/arch/riscv/fdt/riscv_platform.c  |   14 +-
 sys/arch/riscv/include/cpu.h         |  100 ++++++++-
 sys/arch/riscv/include/db_machdep.h  |    7 +-
 sys/arch/riscv/include/intr.h        |    8 +-
 sys/arch/riscv/include/machdep.h     |    9 +-
 sys/arch/riscv/include/pmap.h        |   30 +-
 sys/arch/riscv/riscv/clock_machdep.c |   23 +-
 sys/arch/riscv/riscv/cpu.c           |  133 ++++++++++-
 sys/arch/riscv/riscv/cpu_subr.c      |  404 ++++++++++++++++++++++++++++++++++-
 sys/arch/riscv/riscv/db_interface.c  |   13 +-
 sys/arch/riscv/riscv/db_machdep.c    |    5 +-
 sys/arch/riscv/riscv/genassym.cf     |    8 +-
 sys/arch/riscv/riscv/interrupt.c     |   63 +++++-
 sys/arch/riscv/riscv/ipifuncs.c      |  168 ++++++++++++++
 sys/arch/riscv/riscv/locore.S        |  244 +++++++++++++++++---
 sys/arch/riscv/riscv/pmap_machdep.c  |  105 +-------
 sys/arch/riscv/riscv/riscv_machdep.c |   43 +++-
 sys/arch/riscv/riscv/riscv_tlb.c     |  127 +++++++++++
 sys/arch/riscv/riscv/spl.S           |   59 ++--
 23 files changed, 1574 insertions(+), 261 deletions(-)

diffs (truncated from 2656 to 300 lines):

diff -r 802297a920a1 -r bfc499a2c3fc sys/arch/riscv/conf/files.riscv
--- a/sys/arch/riscv/conf/files.riscv   Mon Jun 12 18:59:57 2023 +0000
+++ b/sys/arch/riscv/conf/files.riscv   Mon Jun 12 19:04:13 2023 +0000
@@ -1,4 +1,4 @@
-#      $NetBSD: files.riscv,v 1.12 2023/05/07 12:41:48 skrll Exp $
+#      $NetBSD: files.riscv,v 1.13 2023/06/12 19:04:13 skrll Exp $
 #
 
 maxpartitions  16
@@ -43,6 +43,7 @@ file  arch/riscv/riscv/kobj_machdep.c         mo
 file   arch/riscv/riscv/pmap_machdep.c
 file   arch/riscv/riscv/process_machdep.c
 file   arch/riscv/riscv/procfs_machdep.c       procfs
+file   arch/riscv/riscv/riscv_tlb.c
 file   arch/riscv/riscv/riscv_generic_dma.c
 file   arch/riscv/riscv/riscv_machdep.c
 file   arch/riscv/riscv/sbi.c                  # SBI
@@ -63,6 +64,7 @@ file  kern/subr_disk_mbr.c                    disk
 file   uvm/pmap/pmap.c
 file   uvm/pmap/pmap_devmap.c
 file   uvm/pmap/pmap_segtab.c
+file   uvm/pmap/pmap_synci.c
 file   uvm/pmap/pmap_tlb.c
 
 device  plic
diff -r 802297a920a1 -r bfc499a2c3fc sys/arch/riscv/fdt/cpu_fdt.c
--- a/sys/arch/riscv/fdt/cpu_fdt.c      Mon Jun 12 18:59:57 2023 +0000
+++ b/sys/arch/riscv/fdt/cpu_fdt.c      Mon Jun 12 19:04:13 2023 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu_fdt.c,v 1.1 2023/05/07 12:41:48 skrll Exp $ */
+/* $NetBSD: cpu_fdt.c,v 1.2 2023/06/12 19:04:13 skrll Exp $ */
 
 /*-
  * Copyright (c) 2017 Jared McNeill <jmcneill%invisible.ca@localhost>
@@ -29,13 +29,167 @@
 #include "opt_multiprocessor.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu_fdt.c,v 1.1 2023/05/07 12:41:48 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu_fdt.c,v 1.2 2023/06/12 19:04:13 skrll Exp $");
 
 #include <sys/param.h>
+#include <sys/cpu.h>
 
 #include <dev/fdt/fdtvar.h>
 
+#include <riscv/cpufunc.h>
 #include <riscv/cpuvar.h>
+#include <riscv/machdep.h>
+#include <riscv/sbi.h>
+
+#include <riscv/fdt/riscv_fdtvar.h>
+
+
+#ifdef MULTIPROCESSOR
+static bool
+riscv_fdt_cpu_okay(const int child)
+{
+       const char *s;
+
+       s = fdtbus_get_string(child, "device_type");
+       if (!s || strcmp(s, "cpu") != 0)
+               return false;
+
+       s = fdtbus_get_string(child, "status");
+       if (s) {
+               if (strcmp(s, "okay") == 0)
+                       return true;
+               if (strcmp(s, "disabled") == 0)
+                       return false;
+               return false;
+       } else {
+               return true;
+       }
+}
+#endif /* MULTIPROCESSOR */
+
+void
+riscv_fdt_cpu_bootstrap(void)
+{
+#ifdef MULTIPROCESSOR
+
+       const int cpus = OF_finddevice("/cpus");
+       if (cpus == -1) {
+               aprint_error("%s: no /cpus node found\n", __func__);
+               riscv_cpu_max = 1;
+               return;
+       }
+
+       /* Count harts and add hart IDs to to cpu_hartid array */
+       size_t cpuindex = 1;
+       for (int child = OF_child(cpus); child; child = OF_peer(child)) {
+               if (!riscv_fdt_cpu_okay(child))
+                       continue;
+
+               riscv_cpu_max++;
+
+               uint64_t reg;
+               if (fdtbus_get_reg64(child, 0, &reg, NULL) != 0)
+                       continue;
+
+               const cpuid_t hartid = reg;
+
+               struct sbiret sbiret = sbi_hart_get_status(hartid);
+               switch (sbiret.error) {
+               case SBI_ERR_INVALID_PARAM:
+                       aprint_error("Unknown hart id %lx", hartid);
+                       continue;
+               case SBI_SUCCESS:
+                       break;
+               default:
+                       aprint_error("Unexpected error (%ld) from get_status",
+                           sbiret.error);
+               }
+
+               /* Assume the BP is the only one started. */
+               if (sbiret.value == SBI_HART_STARTED) {
+                       if (cpu_hartid[0] != -1) {
+                               panic("more than 1 hart started");
+                       }
+                       cpu_hartid[0] = hartid;
+                       continue;
+               }
+
+               KASSERT(cpuindex < MAXCPUS);
+               cpu_hartid[cpuindex] = hartid;
+               cpu_dcache_wb_range((vaddr_t)&cpu_hartid[cpuindex],
+                   sizeof(cpu_hartid[cpuindex]));
+
+               cpuindex++;
+       }
+#endif
+}
+int
+riscv_fdt_cpu_mpstart(void)
+{
+       int ret = 0;
+#ifdef MULTIPROCESSOR
+       const int cpus = OF_finddevice("/cpus");
+       if (cpus == -1) {
+               aprint_error("%s: no /cpus node found\n", __func__);
+               return 0;
+       }
+
+       // riscv_fdt_cpu_bootstrap put the boot hart id in cpu_hartid[0]
+       const cpuid_t bp_hartid = cpu_hartid[0];
+
+       /* BootAPs */
+       size_t cpuindex = 1;
+       for (int child = OF_child(cpus); child; child = OF_peer(child)) {
+               if (!riscv_fdt_cpu_okay(child))
+                       continue;
+
+               uint64_t reg;
+               if (fdtbus_get_reg64(child, 0, &reg, NULL) != 0)
+                       continue;
+
+               cpuid_t hartid = reg;
+
+               if (hartid == bp_hartid)
+                       continue;               /* BP already started */
+
+               const paddr_t entry = KERN_VTOPHYS(cpu_mpstart);
+               struct sbiret sbiret = sbi_hart_start(hartid, entry, 0);
+               switch (sbiret.error) {
+               case SBI_SUCCESS:
+                       break;
+               case SBI_ERR_INVALID_ADDRESS:
+                       break;
+               case SBI_ERR_INVALID_PARAM:
+                       break;
+               case SBI_ERR_ALREADY_AVAILABLE:
+                       break;
+               case SBI_ERR_FAILED:
+                       break;
+               default:
+                       aprint_error("%s: failed to enable CPU %#lx\n",
+                           __func__, hartid);
+               }
+
+               size_t i;
+               /* Wait for AP to start */
+               for (i = 0x10000000; i > 0; i--) {
+                       if (cpu_hatched_p(cpuindex))
+                               break;
+               }
+
+               if (i == 0) {
+                       ret++;
+                       aprint_error("cpu%zu: WARNING: AP failed to start\n",
+                           cpuindex);
+               }
+
+               cpuindex++;
+       }
+#else
+       aprint_normal("%s: kernel compiled without MULTIPROCESSOR\n", __func__);
+#endif /* MULTIPROCESSOR */
+       return ret;
+}
 
 static int
 cpu_fdt_match(device_t parent, cfdata_t cf, void *aux)
diff -r 802297a920a1 -r bfc499a2c3fc sys/arch/riscv/fdt/intc_fdt.c
--- a/sys/arch/riscv/fdt/intc_fdt.c     Mon Jun 12 18:59:57 2023 +0000
+++ b/sys/arch/riscv/fdt/intc_fdt.c     Mon Jun 12 19:04:13 2023 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: intc_fdt.c,v 1.1 2023/05/07 12:41:48 skrll Exp $       */
+/*     $NetBSD: intc_fdt.c,v 1.2 2023/06/12 19:04:13 skrll Exp $       */
 
 /*-
  * Copyright (c) 2023 The NetBSD Foundation, Inc.
@@ -29,8 +29,10 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "opt_multiprocessor.h"
+
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intc_fdt.c,v 1.1 2023/05/07 12:41:48 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intc_fdt.c,v 1.2 2023/06/12 19:04:13 skrll Exp $");
 
 #include <sys/param.h>
 
@@ -237,42 +239,59 @@ static void
 intc_intr_handler(struct trapframe *tf, register_t epc, register_t status,
     register_t cause)
 {
+       const int ppl = splhigh();
        struct cpu_info * const ci = curcpu();
-       const int source = CAUSE_CODE(cause);
+       unsigned long pending;
+       int ipl;
 
        KASSERT(CAUSE_INTERRUPT_P(cause));
 
        struct intc_fdt_softc * const sc = intc_sc;
 
        ci->ci_intr_depth++;
-       struct intc_irq *irq = sc->sc_irq[source];
-       KASSERTMSG(irq != NULL, "source %d\n", source);
-       if (irq) {
-               struct intc_irqhandler *iih;
+       ci->ci_data.cpu_nintr++;
+
+       while (ppl < (ipl = splintr(&pending))) {
+               if (pending == 0)
+                       continue;
 
-               bool mpsafe = (irq->intr_istflags & IST_MPSAFE) != 0;
-               struct clockframe cf = {
-                       .cf_epc = epc,
-                       .cf_status = status,
-                       .cf_intr_depth = ci->ci_intr_depth
-               };
+               splx(ipl);
+
+               int source = ffs(pending) - 1;
+               struct intc_irq *irq = sc->sc_irq[source];
+               KASSERTMSG(irq != NULL, "source %d\n", source);
+
+               if (irq) {
+                       struct intc_irqhandler *iih;
 
-               if (!mpsafe) {
-                       KERNEL_LOCK(1, NULL);
-               }
+                       bool mpsafe =
+                           source != IRQ_SUPERVISOR_EXTERNAL ||
+                           (irq->intr_istflags & IST_MPSAFE) != 0;
+                       struct clockframe cf = {
+                               .cf_epc = epc,
+                               .cf_status = status,
+                               .cf_intr_depth = ci->ci_intr_depth
+                       };
+
+                       if (!mpsafe) {
+                               KERNEL_LOCK(1, NULL);
+                       }
 
-               TAILQ_FOREACH(iih, &irq->intr_handlers, ih_next) {
-                       int handled =
-                           iih->ih_fn(iih->ih_arg ? iih->ih_arg : &cf);
-                       if (handled)
-                               break;
+                       TAILQ_FOREACH(iih, &irq->intr_handlers, ih_next) {
+                               int handled =
+                                   iih->ih_fn(iih->ih_arg ? iih->ih_arg : &cf);
+                               if (handled)
+                                       break;
+                       }
+
+                       if (!mpsafe) {
+                               KERNEL_UNLOCK_ONE(NULL);
+                       }
                }
-
-               if (!mpsafe) {
-                       KERNEL_UNLOCK_ONE(NULL);
-               }



Home | Main Index | Thread Index | Old Index