summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjmallett <jmallett@FreeBSD.org>2012-05-07 04:36:48 +0000
committerjmallett <jmallett@FreeBSD.org>2012-05-07 04:36:48 +0000
commite3d4e68217e11e23e42a56fe1cf45766bb3c5e13 (patch)
tree55869bcc6991ec3a1121e7bbb3580d2dd7e01810
parente79d08972f2bd9b33ceeb0ca93c41495ed2554ad (diff)
downloadFreeBSD-src-e3d4e68217e11e23e42a56fe1cf45766bb3c5e13.zip
FreeBSD-src-e3d4e68217e11e23e42a56fe1cf45766bb3c5e13.tar.gz
Add basic SMP support for GXemul. Ideally we would have some way to override
some of the IPI mechanisms used by the common MIPS SMP code so we could use the multicast IPI facilities, on GXemul as well as on several real hardware platforms, and the ability to have multiple hard IPI types.
-rw-r--r--sys/mips/conf/GXEMUL3
-rw-r--r--sys/mips/gxemul/gxemul_machdep.c69
-rw-r--r--sys/mips/gxemul/mpreg.h2
3 files changed, 74 insertions, 0 deletions
diff --git a/sys/mips/conf/GXEMUL b/sys/mips/conf/GXEMUL
index be6a9ae..ea58622 100644
--- a/sys/mips/conf/GXEMUL
+++ b/sys/mips/conf/GXEMUL
@@ -26,6 +26,9 @@ makeoptions MODULES_OVERRIDE=""
options DDB
options KDB
+# Make an SMP-capable kernel by default
+options SMP # Symmetric MultiProcessor Kernel
+
options SCHED_ULE
options INET # InterNETworking
options INET6 # IPv6 communications protocols
diff --git a/sys/mips/gxemul/gxemul_machdep.c b/sys/mips/gxemul/gxemul_machdep.c
index 41745b2..8996919 100644
--- a/sys/mips/gxemul/gxemul_machdep.c
+++ b/sys/mips/gxemul/gxemul_machdep.c
@@ -62,6 +62,11 @@ __FBSDID("$FreeBSD$");
#include <machine/pmap.h>
#include <machine/trap.h>
+#ifdef SMP
+#include <sys/smp.h>
+#include <machine/smp.h>
+#endif
+
#include <mips/gxemul/mpreg.h>
extern int *edata;
@@ -167,3 +172,67 @@ platform_start(__register_t a0, __register_t a1, __register_t a2,
mips_timer_init_params(platform_counter_freq, 0);
}
+
+#ifdef SMP
+void
+platform_ipi_send(int cpuid)
+{
+ GXEMUL_MP_DEV_WRITE(GXEMUL_MP_DEV_IPI_ONE, (1 << 16) | cpuid);
+}
+
+void
+platform_ipi_clear(void)
+{
+ GXEMUL_MP_DEV_WRITE(GXEMUL_MP_DEV_IPI_READ, 0);
+}
+
+int
+platform_ipi_intrnum(void)
+{
+ return (GXEMUL_MP_DEV_IPI_INTERRUPT - 2);
+}
+
+struct cpu_group *
+platform_smp_topo(void)
+{
+ return (smp_topo_none());
+}
+
+void
+platform_init_ap(int cpuid)
+{
+ int ipi_int_mask, clock_int_mask;
+
+ /*
+ * Unmask the clock and ipi interrupts.
+ */
+ clock_int_mask = hard_int_mask(5);
+ ipi_int_mask = hard_int_mask(platform_ipi_intrnum());
+ set_intr_mask(ipi_int_mask | clock_int_mask);
+}
+
+void
+platform_cpu_mask(cpuset_t *mask)
+{
+ unsigned i, n;
+
+ n = GXEMUL_MP_DEV_READ(GXEMUL_MP_DEV_NCPUS);
+ CPU_ZERO(mask);
+ for (i = 0; i < n; i++)
+ CPU_SET(i, mask);
+}
+
+int
+platform_processor_id(void)
+{
+ return (GXEMUL_MP_DEV_READ(GXEMUL_MP_DEV_WHOAMI));
+}
+
+int
+platform_start_ap(int cpuid)
+{
+ GXEMUL_MP_DEV_WRITE(GXEMUL_MP_DEV_STARTADDR, (intptr_t)mpentry);
+ GXEMUL_MP_DEV_WRITE(GXEMUL_MP_DEV_START, cpuid);
+ return (0);
+}
+#endif /* SMP */
diff --git a/sys/mips/gxemul/mpreg.h b/sys/mips/gxemul/mpreg.h
index 7e6780a..e09946d 100644
--- a/sys/mips/gxemul/mpreg.h
+++ b/sys/mips/gxemul/mpreg.h
@@ -36,10 +36,12 @@
#define GXEMUL_MP_DEV_START 0x0020
#define GXEMUL_MP_DEV_STARTADDR 0x0030
#define GXEMUL_MP_DEV_STACK 0x0070
+#define GXEMUL_MP_DEV_RANDOM 0x0080
#define GXEMUL_MP_DEV_MEMORY 0x0090
#define GXEMUL_MP_DEV_IPI_ONE 0x00a0
#define GXEMUL_MP_DEV_IPI_MANY 0x00b0
#define GXEMUL_MP_DEV_IPI_READ 0x00c0
+#define GXEMUL_MP_DEV_CYCLES 0x00d0
#define GXEMUL_MP_DEV_FUNCTION(f) \
(volatile uint64_t *)MIPS_PHYS_TO_DIRECT_UNCACHED(GXEMUL_MP_DEV_BASE + (f))
OpenPOWER on IntegriCloud