summaryrefslogtreecommitdiff
path: root/sys/arch/loongson
diff options
context:
space:
mode:
authorVisa Hankala <visa@cvs.openbsd.org>2017-02-19 08:59:42 +0000
committerVisa Hankala <visa@cvs.openbsd.org>2017-02-19 08:59:42 +0000
commit2af95003a6848ab8b9c968daad70fd5580e8fb96 (patch)
treecdf05c776cbb6ed305b659c39c8187f5c02417f7 /sys/arch/loongson
parent18e943d3e510adc284583b9559af489301098bcd (diff)
Add SMP config and IPI control logic for Loongson 3A.
Diffstat (limited to 'sys/arch/loongson')
-rw-r--r--sys/arch/loongson/include/autoconf.h7
-rw-r--r--sys/arch/loongson/include/intr.h5
-rw-r--r--sys/arch/loongson/loongson/generic3a_machdep.c145
3 files changed, 149 insertions, 8 deletions
diff --git a/sys/arch/loongson/include/autoconf.h b/sys/arch/loongson/include/autoconf.h
index 3de86536b7b..48e651d1055 100644
--- a/sys/arch/loongson/include/autoconf.h
+++ b/sys/arch/loongson/include/autoconf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: autoconf.h,v 1.14 2017/01/19 15:09:04 visa Exp $ */
+/* $OpenBSD: autoconf.h,v 1.15 2017/02/19 08:59:41 visa Exp $ */
/*
* Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -94,6 +94,11 @@ extern uint loongson_cpumask;
extern uint loongson_ver;
extern int nnodes;
+#ifdef MULTIPROCESSOR
+extern uint64_t cpu_spinup_a0;
+extern uint64_t cpu_spinup_sp;
+#endif
+
struct mainbus_attach_args {
const char *maa_name;
};
diff --git a/sys/arch/loongson/include/intr.h b/sys/arch/loongson/include/intr.h
index f0aa4b8f9cd..cbd81ff538d 100644
--- a/sys/arch/loongson/include/intr.h
+++ b/sys/arch/loongson/include/intr.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: intr.h,v 1.11 2017/01/19 15:09:04 visa Exp $ */
+/* $OpenBSD: intr.h,v 1.12 2017/02/19 08:59:41 visa Exp $ */
/*
* Copyright (c) 2001-2004 Opsycon AB (www.opsycon.se / www.opsycon.com)
@@ -176,7 +176,8 @@ void intr_barrier(void *);
*/
/* Schedule priorities for base interrupts (CPU) */
-#define INTPRI_CLOCK 0
+#define INTPRI_IPI 0
+#define INTPRI_CLOCK 1
/* other values are system-specific */
#define NLOWINT 4 /* Number of low level registrations possible */
diff --git a/sys/arch/loongson/loongson/generic3a_machdep.c b/sys/arch/loongson/loongson/generic3a_machdep.c
index d6cb1b01afd..5bc6b9a6456 100644
--- a/sys/arch/loongson/loongson/generic3a_machdep.c
+++ b/sys/arch/loongson/loongson/generic3a_machdep.c
@@ -1,8 +1,8 @@
-/* $OpenBSD: generic3a_machdep.c,v 1.3 2016/12/11 07:57:14 visa Exp $ */
+/* $OpenBSD: generic3a_machdep.c,v 1.4 2017/02/19 08:59:41 visa Exp $ */
/*
* Copyright (c) 2009, 2010, 2012 Miodrag Vallat.
- * Copyright (c) 2016 Visa Hankala.
+ * Copyright (c) 2016, 2017 Visa Hankala.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -24,14 +24,16 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
+#include <sys/proc.h>
#include <mips64/archtype.h>
+#include <mips64/loongson3.h>
+#include <mips64/mips_cpu.h>
+
#include <machine/autoconf.h>
#include <machine/cpu.h>
#include <machine/pmon.h>
-#include <mips64/loongson3.h>
-
#include <dev/ic/i8259reg.h>
#include <dev/isa/isareg.h>
#include <dev/isa/isavar.h>
@@ -51,6 +53,18 @@ void generic3a_powerdown(void);
void generic3a_reset(void);
void generic3a_setup(void);
+#ifdef MULTIPROCESSOR
+void generic3a_config_secondary_cpus(struct device *, cfprint_t);
+void generic3a_boot_secondary_cpu(struct cpu_info *);
+int generic3a_ipi_establish(int (*)(void *), cpuid_t);
+void generic3a_ipi_set(cpuid_t);
+void generic3a_ipi_clear(cpuid_t);
+uint32_t generic3a_ipi_intr(uint32_t, struct trapframe *);
+
+paddr_t ls3_ipi_base[MAXCPUS];
+int (*ls3_ipi_handler)(void *);
+#endif /* MULTIPROCESSOR */
+
void rs780e_setup(void);
void rs780e_isa_attach_hook(struct device *, struct device *,
@@ -104,7 +118,15 @@ const struct platform rs780e_platform = {
.device_register = generic3a_device_register,
.powerdown = generic3a_powerdown,
- .reset = generic3a_reset
+ .reset = generic3a_reset,
+
+#ifdef MULTIPROCESSOR
+ .config_secondary_cpus = generic3a_config_secondary_cpus,
+ .boot_secondary_cpu = generic3a_boot_secondary_cpu,
+ .ipi_establish = generic3a_ipi_establish,
+ .ipi_set = generic3a_ipi_set,
+ .ipi_clear = generic3a_ipi_clear,
+#endif /* MULTIPROCESSOR */
};
const struct pic rs780e_pic = {
@@ -151,6 +173,11 @@ generic3a_setup(void)
}
loongson3_intr_init();
+
+#ifdef MULTIPROCESSOR
+ ipi_mask = CR_INT_4;
+ set_intr(INTPRI_IPI, CR_INT_4, generic3a_ipi_intr);
+#endif
}
void
@@ -195,6 +222,114 @@ generic3a_device_register(struct device *dev, void *aux)
#endif
}
+#ifdef MULTIPROCESSOR
+
+void
+generic3a_config_secondary_cpus(struct device *parent, cfprint_t print)
+{
+ struct cpu_attach_args caa;
+ struct cpu_hwinfo hw;
+ uint32_t boot_cpu = loongson3_get_cpuid();
+ uint32_t cpu, unit = 0;
+
+ ls3_ipi_base[unit++] = LS3_IPI_BASE(0, boot_cpu);
+
+ memset(&caa, 0, sizeof(caa));
+ hw = bootcpu_hwinfo;
+ for (cpu = 0; cpu < LOONGSON_MAXCPUS && ncpus < MAXCPUS; cpu++) {
+ if (!ISSET(loongson_cpumask, 1u << cpu))
+ continue;
+ if (cpu == boot_cpu)
+ continue;
+
+ ls3_ipi_base[unit++] = LS3_IPI_BASE(LS3_NODEID(cpu),
+ LS3_COREID(cpu));
+
+ caa.caa_maa.maa_name = "cpu";
+ caa.caa_hw = &hw;
+ config_found(parent, &caa, print);
+ }
+}
+
+void
+generic3a_boot_secondary_cpu(struct cpu_info *ci)
+{
+ vaddr_t kstack;
+
+ kstack = alloc_contiguous_pages(USPACE);
+ if (kstack == 0)
+ panic("unable to allocate idle stack");
+ ci->ci_curprocpaddr = (void *)kstack;
+
+ /*
+ * The firmware has put the secondary core into a wait loop which
+ * terminates when a non-zero value is written to mailbox0.
+ * After the core exits the loop, the firmware initializes the core's
+ * pc, sp, gp and a1 registers as follows:
+ *
+ * pc = mailbox0 | 0xffffffff00000000u;
+ * sp = mailbox1 | 0x9800000000000000u;
+ * gp = mailbox2 | 0x9800000000000000u;
+ * a1 = mailbox3;
+ */
+
+ cpu_spinup_a0 = (uint64_t)ci;
+ cpu_spinup_sp = kstack;
+ mips_sync();
+
+ REGVAL64(ls3_ipi_base[ci->ci_cpuid] + LS3_IPI_MBOX0) =
+ (uint64_t)hw_cpu_spinup_trampoline; /* pc */
+
+ while (!cpuset_isset(&cpus_running, ci))
+ continue;
+}
+
+int
+generic3a_ipi_establish(int (*func)(void *), cpuid_t cpuid)
+{
+ if (cpuid == 0)
+ ls3_ipi_handler = func;
+
+ /* Clear any pending IPIs. */
+ REGVAL32(ls3_ipi_base[cpuid] + LS3_IPI_CLEAR) = ~0u;
+
+ /* Enable the IPI. */
+ REGVAL32(ls3_ipi_base[cpuid] + LS3_IPI_IMR) = 1u;
+
+ return 0;
+}
+
+void
+generic3a_ipi_set(cpuid_t cpuid)
+{
+ REGVAL32(ls3_ipi_base[cpuid] + LS3_IPI_SET) = 1;
+}
+
+void
+generic3a_ipi_clear(cpuid_t cpuid)
+{
+ REGVAL32(ls3_ipi_base[cpuid] + LS3_IPI_CLEAR) = 1;
+}
+
+uint32_t
+generic3a_ipi_intr(uint32_t hwpend, struct trapframe *frame)
+{
+ cpuid_t cpuid = cpu_number();
+
+ /* Mask all IPIs. */
+ REGVAL32(ls3_ipi_base[cpuid] + LS3_IPI_IMR) = ~0u;
+
+ if (ls3_ipi_handler != NULL)
+ ls3_ipi_handler((void *)cpuid);
+
+ /* Enable the IPI. */
+ REGVAL32(ls3_ipi_base[cpuid] + LS3_IPI_IMR) = 1u;
+
+ return hwpend;
+}
+
+#endif /* MULTIPROCESSOR */
+
/*
* Routines for RS780E-based systems
*/