Module Name:    src
Committed By:   matt
Date:           Mon Jun  1 22:55:13 UTC 2015

Modified Files:
        src/sys/arch/evbmips/cavium: mach_intr.c machdep.c
        src/sys/arch/evbmips/conf: ERLITE files.octeon
        src/sys/arch/evbmips/malta: machdep.c
        src/sys/arch/evbmips/rmixl: machdep.c
        src/sys/arch/mips/cavium: mainbus_octeon1p.c octeon_intr.c
            octeon_iobus.c octeonvar.h
        src/sys/arch/mips/cavium/dev: octeon_ciureg.h octeon_corereg.h
            octeon_dwctwo.c octeon_gmx.c octeon_ipd.c octeon_mpi.c octeon_pci.c
            octeon_pow.c octeon_uart.c
        src/sys/arch/mips/conf: files.octeon std.octeon
        src/sys/arch/mips/include: cpu.h cpuregs.h intr.h lock.h locore.h
            mips_opcode.h
        src/sys/arch/mips/mips: cpu_subr.c locore.S locore_mips3.S
            locore_octeon.S mips_fixup.c mips_machdep.c
        src/sys/arch/mips/rmi: rmixl_cpu.c
Added Files:
        src/sys/arch/mips/cavium: octeon_cpunode.c

Log Message:
Rework cavium support in preparation for MULTIPROCESSOR support


To generate a diff of this commit:
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/evbmips/cavium/mach_intr.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/evbmips/cavium/machdep.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/evbmips/conf/ERLITE
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/evbmips/conf/files.octeon
cvs rdiff -u -r1.43 -r1.44 src/sys/arch/evbmips/malta/machdep.c
cvs rdiff -u -r1.14 -r1.15 src/sys/arch/evbmips/rmixl/machdep.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/mips/cavium/mainbus_octeon1p.c \
    src/sys/arch/mips/cavium/octeon_iobus.c \
    src/sys/arch/mips/cavium/octeonvar.h
cvs rdiff -u -r0 -r1.1 src/sys/arch/mips/cavium/octeon_cpunode.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/mips/cavium/octeon_intr.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/mips/cavium/dev/octeon_ciureg.h \
    src/sys/arch/mips/cavium/dev/octeon_corereg.h \
    src/sys/arch/mips/cavium/dev/octeon_dwctwo.c \
    src/sys/arch/mips/cavium/dev/octeon_gmx.c \
    src/sys/arch/mips/cavium/dev/octeon_ipd.c \
    src/sys/arch/mips/cavium/dev/octeon_mpi.c \
    src/sys/arch/mips/cavium/dev/octeon_pci.c \
    src/sys/arch/mips/cavium/dev/octeon_pow.c \
    src/sys/arch/mips/cavium/dev/octeon_uart.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/mips/conf/files.octeon
cvs rdiff -u -r1.3 -r1.4 src/sys/arch/mips/conf/std.octeon
cvs rdiff -u -r1.111 -r1.112 src/sys/arch/mips/include/cpu.h
cvs rdiff -u -r1.90 -r1.91 src/sys/arch/mips/include/cpuregs.h
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/mips/include/intr.h
cvs rdiff -u -r1.18 -r1.19 src/sys/arch/mips/include/lock.h \
    src/sys/arch/mips/include/mips_opcode.h
cvs rdiff -u -r1.97 -r1.98 src/sys/arch/mips/include/locore.h
cvs rdiff -u -r1.19 -r1.20 src/sys/arch/mips/mips/cpu_subr.c
cvs rdiff -u -r1.191 -r1.192 src/sys/arch/mips/mips/locore.S
cvs rdiff -u -r1.102 -r1.103 src/sys/arch/mips/mips/locore_mips3.S
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/mips/mips/locore_octeon.S
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/mips/mips/mips_fixup.c
cvs rdiff -u -r1.264 -r1.265 src/sys/arch/mips/mips/mips_machdep.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/mips/rmi/rmixl_cpu.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/evbmips/cavium/mach_intr.c
diff -u src/sys/arch/evbmips/cavium/mach_intr.c:1.1 src/sys/arch/evbmips/cavium/mach_intr.c:1.2
--- src/sys/arch/evbmips/cavium/mach_intr.c:1.1	Wed Apr 29 08:32:01 2015
+++ src/sys/arch/evbmips/cavium/mach_intr.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: mach_intr.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $	*/
+/*	$NetBSD: mach_intr.c,v 1.2 2015/06/01 22:55:12 matt Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -38,12 +38,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mach_intr.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mach_intr.c,v 1.2 2015/06/01 22:55:12 matt Exp $");
 
 #include "opt_ddb.h"
 
 #include <sys/param.h>
 #include <sys/bus.h>
+#include <sys/lwp.h>
 #include <sys/device.h>
 #include <sys/intr.h>
 #include <sys/kernel.h>
@@ -56,7 +57,7 @@ __KERNEL_RCSID(0, "$NetBSD: mach_intr.c,
 void
 evbmips_intr_init(void)
 {
-	octeon_intr_init();
+	octeon_intr_init(curcpu());
 }
 
 void

Index: src/sys/arch/evbmips/cavium/machdep.c
diff -u src/sys/arch/evbmips/cavium/machdep.c:1.2 src/sys/arch/evbmips/cavium/machdep.c:1.3
--- src/sys/arch/evbmips/cavium/machdep.c:1.2	Mon May 18 01:32:18 2015
+++ src/sys/arch/evbmips/cavium/machdep.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.2 2015/05/18 01:32:18 matt Exp $	*/
+/*	$NetBSD: machdep.c,v 1.3 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright 2001, 2002 Wasabi Systems, Inc.
@@ -112,7 +112,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.2 2015/05/18 01:32:18 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.3 2015/06/01 22:55:12 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -318,6 +318,7 @@ mach_init_console(void)
 void
 mach_init_memory(u_quad_t memsize)
 {
+	extern char kernel_text[];
 	extern char end[];
 
 	physmem = btoc(memsize);
@@ -342,10 +343,16 @@ mach_init_memory(u_quad_t memsize)
 		mem_cluster_cnt = 3;
 	}
 
+	
+#ifdef MULTIPROCESSOR
+	const u_int cores = mipsNN_cp0_ebase_read() & MIPS_EBASE_CPUNUM;
+	mem_clusters[0].start = cores * 4096;
+#endif
+
 	/*
 	 * Load the rest of the available pages into the VM system.
 	 */
-	mips_page_physload(MIPS_KSEG0_START, mips_round_page(end),
+	mips_page_physload(mips_trunc_page(kernel_text), mips_round_page(end),
 	    mem_clusters, mem_cluster_cnt, NULL, 0);
 
 	/*

Index: src/sys/arch/evbmips/conf/ERLITE
diff -u src/sys/arch/evbmips/conf/ERLITE:1.8 src/sys/arch/evbmips/conf/ERLITE:1.9
--- src/sys/arch/evbmips/conf/ERLITE:1.8	Thu May 21 09:53:05 2015
+++ src/sys/arch/evbmips/conf/ERLITE	Mon Jun  1 22:55:12 2015
@@ -1,11 +1,11 @@
-#	$NetBSD: ERLITE,v 1.8 2015/05/21 09:53:05 jmcneill Exp $
+#	$NetBSD: ERLITE,v 1.9 2015/06/01 22:55:12 matt Exp $
 
 include 	"arch/mips/conf/std.octeon"
 include 	"arch/evbmips/conf/files.octeon"
 
 #options 	INCLUDE_CONFIG_FILE	# embed config file in kernel binary
 
-#ident 		"ERLITE-$Revision: 1.8 $"
+#ident 		"ERLITE-$Revision: 1.9 $"
 
 maxusers	32
 
@@ -24,9 +24,9 @@ maxusers	32
 
 # Standard system options
 options 	KTRACE		# system call tracing support
-#options 	SYSVMSG		# System V message queues
-#options 	SYSVSEM		# System V semaphores
-#options 	SYSVSHM		# System V shared memory
+options 	SYSVMSG		# System V message queues
+options 	SYSVSEM		# System V semaphores
+options 	SYSVSHM		# System V shared memory
 options 	NTP		# network time protocol
 
 # Debugging options
@@ -119,7 +119,8 @@ config		netbsd	root on ? type ?
 #config		netbsd	root on cnmac0 type nfs
 
 mainbus0	at root
-cpu0		at mainbus?
+cpunode0	at mainbus?
+cpu*		at cpunode? core ?
 
 iobus0		at mainbus?
 bootbus0	at mainbus?

Index: src/sys/arch/evbmips/conf/files.octeon
diff -u src/sys/arch/evbmips/conf/files.octeon:1.3 src/sys/arch/evbmips/conf/files.octeon:1.4
--- src/sys/arch/evbmips/conf/files.octeon:1.3	Mon May 18 01:53:50 2015
+++ src/sys/arch/evbmips/conf/files.octeon	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-#	$NetBSD: files.octeon,v 1.3 2015/05/18 01:53:50 matt Exp $
+#	$NetBSD: files.octeon,v 1.4 2015/06/01 22:55:12 matt Exp $
 
 file	arch/evbmips/cavium/autoconf.c
 file	arch/evbmips/cavium/machdep.c
@@ -9,9 +9,9 @@ file	arch/evbmips/evbmips/interrupt.c
 
 file	kern/subr_disk_mbr.c
 
-device	cpu
-attach	cpu at mainbus
-file	arch/evbmips/evbmips/cpu.c		cpu
+#device	cpu
+#attach	cpu at mainbus
+#file	arch/evbmips/evbmips/cpu.c		cpu
 
 # Memory Disk
 file	dev/md_root.c				memory_disk_hooks

Index: src/sys/arch/evbmips/malta/machdep.c
diff -u src/sys/arch/evbmips/malta/machdep.c:1.43 src/sys/arch/evbmips/malta/machdep.c:1.44
--- src/sys/arch/evbmips/malta/machdep.c:1.43	Mon Mar 24 20:06:31 2014
+++ src/sys/arch/evbmips/malta/machdep.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.43 2014/03/24 20:06:31 christos Exp $	*/
+/*	$NetBSD: machdep.c,v 1.44 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright 2001, 2002 Wasabi Systems, Inc.
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.43 2014/03/24 20:06:31 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.44 2015/06/01 22:55:12 matt Exp $");
 
 #include "opt_ddb.h"
 #include "opt_execfmt.h"
@@ -282,7 +282,7 @@ mach_init(int argc, char **argv, yamon_e
 	/*
 	 * We can never be running on more than one processor but we can dream.
 	 */
-	mips_fixup_exceptions(mips_fixup_zero_relative);
+	mips_fixup_exceptions(mips_fixup_zero_relative, NULL);
 #endif
 }
 

Index: src/sys/arch/evbmips/rmixl/machdep.c
diff -u src/sys/arch/evbmips/rmixl/machdep.c:1.14 src/sys/arch/evbmips/rmixl/machdep.c:1.15
--- src/sys/arch/evbmips/rmixl/machdep.c:1.14	Mon Mar 24 20:06:32 2014
+++ src/sys/arch/evbmips/rmixl/machdep.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: machdep.c,v 1.14 2014/03/24 20:06:32 christos Exp $	*/
+/*	$NetBSD: machdep.c,v 1.15 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright 2001, 2002 Wasabi Systems, Inc.
@@ -74,7 +74,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.14 2014/03/24 20:06:32 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.15 2015/06/01 22:55:12 matt Exp $");
 
 #define __INTR_PRIVATE
 
@@ -217,7 +217,7 @@ void rmixlfw_mmap_print(rmixlfw_mmap_t *
 
 
 #ifdef MULTIPROCESSOR
-static bool rmixl_fixup_cop0_oscratch(int32_t, uint32_t [2]);
+static bool rmixl_fixup_cop0_oscratch(int32_t, uint32_t [2], void *);
 void rmixl_get_wakeup_info(struct rmixl_config *);
 #ifdef MACHDEP_DEBUG
 static void rmixl_wakeup_info_print(volatile rmixlfw_cpu_wakeup_info_t *);
@@ -408,7 +408,7 @@ mach_init(int argc, int32_t *argv, void 
 	__asm __volatile("dmtc0 %0,$%1"
 		:: "r"(&cpu_info_store), "n"(MIPS_COP_0_OSSCRATCH));
 #ifdef MULTIPROCESSOR
-	mips_fixup_exceptions(rmixl_fixup_cop0_oscratch);
+	mips_fixup_exceptions(rmixl_fixup_cop0_oscratch, NULL);
 #endif
 	rmixl_fixup_curcpu();
 }
@@ -451,7 +451,7 @@ rmixl_pcr_init_core(void)
 
 #ifdef MULTIPROCESSOR
 static bool
-rmixl_fixup_cop0_oscratch(int32_t load_addr, uint32_t new_insns[2])
+rmixl_fixup_cop0_oscratch(int32_t load_addr, uint32_t new_insns[2], void *arg)
 {
 	size_t offset = load_addr - (intptr_t)&cpu_info_store;
 

Index: src/sys/arch/mips/cavium/mainbus_octeon1p.c
diff -u src/sys/arch/mips/cavium/mainbus_octeon1p.c:1.1 src/sys/arch/mips/cavium/mainbus_octeon1p.c:1.2
--- src/sys/arch/mips/cavium/mainbus_octeon1p.c:1.1	Wed Apr 29 08:32:00 2015
+++ src/sys/arch/mips/cavium/mainbus_octeon1p.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: mainbus_octeon1p.c,v 1.1 2015/04/29 08:32:00 hikaru Exp $	*/
+/*	$NetBSD: mainbus_octeon1p.c,v 1.2 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright (c) 2007
@@ -31,14 +31,14 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mainbus_octeon1p.c,v 1.1 2015/04/29 08:32:00 hikaru Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mainbus_octeon1p.c,v 1.2 2015/06/01 22:55:12 matt Exp $");
 
 #include <sys/param.h>
 
 #include <mips/cavium/include/mainbusvar.h>
 
 const char * const mainbus_devs[] = {
-	"cpu",
+	"cpunode",
 #if 1
 /* XXX board-specific, not cpu-specific... */
 	"flash",
@@ -48,4 +48,4 @@ const char * const mainbus_devs[] = {
 	"iobus",
 	"bootbus"
 };
-const size_t mainbus_ndevs = sizeof(mainbus_devs) / sizeof(mainbus_devs[0]);
+const size_t mainbus_ndevs = __arraycount(mainbus_devs);
Index: src/sys/arch/mips/cavium/octeon_iobus.c
diff -u src/sys/arch/mips/cavium/octeon_iobus.c:1.1 src/sys/arch/mips/cavium/octeon_iobus.c:1.2
--- src/sys/arch/mips/cavium/octeon_iobus.c:1.1	Wed Apr 29 08:32:00 2015
+++ src/sys/arch/mips/cavium/octeon_iobus.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: octeon_iobus.c,v 1.1 2015/04/29 08:32:00 hikaru Exp $	*/
+/*	$NetBSD: octeon_iobus.c,v 1.2 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright (c) 2007
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: octeon_iobus.c,v 1.1 2015/04/29 08:32:00 hikaru Exp $");
+__KERNEL_RCSID(0, "$NetBSD: octeon_iobus.c,v 1.2 2015/06/01 22:55:12 matt Exp $");
 
 #include "locators.h"
 
@@ -132,7 +132,7 @@ iobus_print(void *aux, const char *pnp)
 	if (pnp)
 		aprint_normal("%s at %s", aa->aa_name, pnp);
 
-	aprint_normal(": address=0x%016" PRIx64, aa->aa_unit->addr);
+	aprint_normal(" address 0x%016" PRIx64, aa->aa_unit->addr);
 
 	return UNCONF;
 }
Index: src/sys/arch/mips/cavium/octeonvar.h
diff -u src/sys/arch/mips/cavium/octeonvar.h:1.1 src/sys/arch/mips/cavium/octeonvar.h:1.2
--- src/sys/arch/mips/cavium/octeonvar.h:1.1	Wed Apr 29 08:32:00 2015
+++ src/sys/arch/mips/cavium/octeonvar.h	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: octeonvar.h,v 1.1 2015/04/29 08:32:00 hikaru Exp $	*/
+/*	$NetBSD: octeonvar.h,v 1.2 2015/06/01 22:55:12 matt Exp $	*/
 
 /*-
  * Copyright (c) 2001 The NetBSD Foundation, Inc.
@@ -33,6 +33,7 @@
 #define _MIPS_OCTEON_OCTEONVAR_H_
 
 #include <sys/bus.h>
+#include <sys/evcnt.h>
 #include <mips/locore.h>
 #include <dev/pci/pcivar.h>
 
@@ -76,6 +77,36 @@ struct octeon_config {
 	int	mc_mallocsafe;
 };
 
+#define NIRQS	64
+
+struct cpu_softc {
+	struct cpu_info *cpu_ci;
+	uint64_t cpu_int0_sum0;
+	uint64_t cpu_int1_sum0;
+	uint64_t cpu_int2_sum0;
+
+	uint64_t cpu_int0_en0;
+	uint64_t cpu_int1_en0;
+	uint64_t cpu_int2_en0;
+
+	uint64_t cpu_int0_en1;
+	uint64_t cpu_int1_en1;
+	uint64_t cpu_int2_en1;
+
+	uint64_t cpu_int32_en;
+
+	struct evcnt cpu_intr_evs[NIRQS];
+
+	uint64_t cpu_int0_enable0;
+	uint64_t cpu_int1_enable0;
+	uint64_t cpu_int2_enable0;
+
+#ifdef MULTIPROCESSOR
+	uint64_t cpu_mbox_set;
+	uint64_t cpu_mbox_clr;
+#endif
+};
+
 /*
  * FPA map
  */
@@ -187,17 +218,23 @@ struct octeon_fau_map {
 
 #ifdef _KERNEL
 extern struct octeon_config	octeon_configuration;
+#ifdef MULTIPROCESSOR
+extern struct cpu_softc		octeon_cpu1_softc;
+#endif
 
 void	octeon_bus_io_init(bus_space_tag_t, void *);
 void	octeon_bus_mem_init(bus_space_tag_t, void *);
 void	octeon_cal_timer(int);
 void	octeon_dma_init(struct octeon_config *);
-void	octeon_intr_init(void);
-int	octeon_intr_check_masks(void);
+void	octeon_intr_init(struct cpu_info *);
 void	octeon_iointr(int, vaddr_t, uint32_t);
 void	octeon_pci_init(pci_chipset_tag_t, struct octeon_config *);
-void	*octeon_intr_establish(int, int, int, int (*)(void *), void *);
+void	*octeon_intr_establish(int, int, int (*)(void *), void *);
 void	octeon_intr_disestablish(void *cookie);
+
+uint64_t mips_cp0_cvmctl_read(void);
+void	 mips_cp0_cvmctl_write(uint64_t);
+
 #endif /* _KERNEL */
 
 #if defined(__mips_n32)

Index: src/sys/arch/mips/cavium/octeon_intr.c
diff -u src/sys/arch/mips/cavium/octeon_intr.c:1.2 src/sys/arch/mips/cavium/octeon_intr.c:1.3
--- src/sys/arch/mips/cavium/octeon_intr.c:1.2	Tue May 19 05:51:16 2015
+++ src/sys/arch/mips/cavium/octeon_intr.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: octeon_intr.c,v 1.2 2015/05/19 05:51:16 matt Exp $	*/
+/*	$NetBSD: octeon_intr.c,v 1.3 2015/06/01 22:55:12 matt Exp $	*/
 /*
  * Copyright 2001, 2002 Wasabi Systems, Inc.
  * All rights reserved.
@@ -42,7 +42,7 @@
 #define __INTR_PRIVATE
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: octeon_intr.c,v 1.2 2015/05/19 05:51:16 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: octeon_intr.c,v 1.3 2015/06/01 22:55:12 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/cpu.h>
@@ -50,7 +50,8 @@ __KERNEL_RCSID(0, "$NetBSD: octeon_intr.
 #include <sys/device.h>
 #include <sys/intr.h>
 #include <sys/kernel.h>
-#include <sys/malloc.h>
+#include <sys/kmem.h>
+#include <sys/atomic.h>
 
 #include <lib/libkern/libkern.h>
 
@@ -71,13 +72,12 @@ static const struct ipl_sr_map octeon_ip
 	[IPL_VM] =		MIPS_SOFT_INT_MASK | MIPS_INT_MASK_0,
 	[IPL_SCHED] =		MIPS_SOFT_INT_MASK | MIPS_INT_MASK_0
 				    | MIPS_INT_MASK_5,
-	[IPL_DDB] =		MIPS_INT_MASK,
+	[IPL_DDB] =		MIPS_SOFT_INT_MASK | MIPS_INT_MASK_0
+				    | MIPS_INT_MASK_1 | MIPS_INT_MASK_5,
 	[IPL_HIGH] =		MIPS_INT_MASK,
     },
 };
 
-#define	NIRQS		64
-
 const char * const octeon_intrnames[NIRQS] = {
 	"workq 0",
 	"workq 1",
@@ -146,149 +146,136 @@ const char * const octeon_intrnames[NIRQ
 };
 
 struct octeon_intrhand {
-	LIST_ENTRY(octeon_intrhand) ih_q;
 	int (*ih_func)(void *);
 	void *ih_arg;
 	int ih_irq;
 	int ih_ipl;
-	int ih_intr;
 };
 
-struct octeon_intrhead {
-	LIST_HEAD(, octeon_intrhand) intr_list;
-	struct evcnt intr_count;
-	int intr_refcnt;
+#ifdef MULTIPROCESSOR
+static int octeon_send_ipi(struct cpu_info *, int);
+static int octeon_ipi_intr(void *);
+
+struct octeon_intrhand ipi_intrhands[2] = {
+	[0] = {
+		.ih_func = octeon_ipi_intr,
+		.ih_arg = (void *)(uintptr_t)__BITS(15,0),
+		.ih_irq = _CIU_INT_MBOX_15_0_SHIFT,
+		.ih_ipl = IPL_SCHED,
+	},
+	[1] = {
+		.ih_func = octeon_ipi_intr,
+		.ih_arg = (void *)(uintptr_t)__BITS(31,16),
+		.ih_irq = _CIU_INT_MBOX_31_16_SHIFT,
+		.ih_ipl = IPL_HIGH,
+	},
 };
+#endif
 
-struct octeon_intrhead octeon_ciu_intrtab[NIRQS];
-
-struct octeon_cpuintr {
-	LIST_HEAD(, octeon_intrhand) cintr_list;
-	struct evcnt cintr_count;
+struct octeon_intrhand *octeon_ciu_intrs[NIRQS] = {
+#ifdef MULTIPROCESSOR
+	[_CIU_INT_MBOX_15_0_SHIFT] = &ipi_intrhands[0],
+	[_CIU_INT_MBOX_31_16_SHIFT] = &ipi_intrhands[1],
+#endif
 };
 
-#define	NINTRS		5	/* MIPS INT0 - INT4 */
-
-struct octeon_cpuintr octeon_cpuintrs[NINTRS];
-const char * const octeon_cpuintrnames[NINTRS] = {
-	"int 0 (IP2)",
-	"int 1 (IP3)",
-	"int 2 ",
-	"int 3 ",
-	"int 4 ",
-};
+kmutex_t octeon_intr_lock;
 
+#define X(a)	MIPS_PHYS_TO_XKPHYS(OCTEON_CCA_NONE, (a))
 
-/* temporary interrupt enable bits */
-uint64_t int0_enable0;
-uint64_t int1_enable0;
+struct cpu_softc octeon_cpu0_softc = {
+	.cpu_ci = &cpu_info_store,
+	.cpu_int0_sum0 = X(CIU_INT0_SUM0),
+	.cpu_int1_sum0 = X(CIU_INT1_SUM0),
+	.cpu_int2_sum0 = X(CIU_INT4_SUM0),
 
+	.cpu_int0_en0 = X(CIU_INT0_EN0),
+	.cpu_int1_en0 = X(CIU_INT1_EN0),
+	.cpu_int2_en0 = X(CIU_INT4_EN00),
 
-#if 0
-/*
- * NOTE: This routine must be called with interrupts disabled in the CPSR.
- */
-static void
-octeon_intr_calculate_masks(void)
-{
-	struct octeon_intrhand *ih;
-	int level, ipl, irq;
+	.cpu_int0_en1 = X(CIU_INT0_EN1),
+	.cpu_int1_en1 = X(CIU_INT1_EN1),
+	.cpu_int2_en1 = X(CIU_INT4_EN01),
 
-	/* First, figure out which IPLs each INT has. */
-	for (level = 0; level < NINTRS; level++) {
-		int levels = 0;
-
-		for (irq = 0; irq < NIRQS; irq++)
-			LIST_FOREACH(ih, &octeon_intrtab[irq].intr_list, ih_q)
-				if (ih->ih_intr == level)
-					levels |= 1 << ih->ih_ipl;
-		octeon_cpuintrs[level].cintr_levels = levels;
-	}
+	.cpu_int32_en = X(CIU_INT32_EN0),
 
-	/* Next, figure out which INTs are used by each IPL. */
-	for (ipl = 0; ipl < _IPL_N; ipl++) {
-		int irqs = 0;
-
-		for (level = 0; level < NINTRS; level++)
-			if (1 << ipl & octeon_cpuintrs[level].cintr_levels)
-				irqs |= MIPS_INT_MASK_0 << level;
-		ipl_sr_bits[ipl] = irqs;
-	}
+#ifdef MULTIPROCESSOR
+	.cpu_mbox_set = X(CIU_MBOX_SET0),
+	.cpu_mbox_clr = X(CIU_MBOX_CLR0),
+#endif
+};
 
-	/*
-	 * IPL_CLOCK should mask clock interrupt even if interrupt handler
-	 * is not registered.
-	 */
-	ipl_sr_bits[IPL_CLOCK] |= MIPS_INT_MASK_5;
+#ifdef MULTIPROCESSOR
+struct cpu_softc octeon_cpu1_softc = {
+	.cpu_int0_sum0 = X(CIU_INT2_SUM0),
+	.cpu_int1_sum0 = X(CIU_INT3_SUM0),
+	.cpu_int2_sum0 = X(CIU_INT4_SUM1),
+
+	.cpu_int0_en0 = X(CIU_INT2_EN0),
+	.cpu_int1_en0 = X(CIU_INT3_EN0),
+	.cpu_int2_en0 = X(CIU_INT4_EN10),
+
+	.cpu_int0_en1 = X(CIU_INT2_EN1),
+	.cpu_int1_en1 = X(CIU_INT3_EN1),
+	.cpu_int2_en1 = X(CIU_INT4_EN11),
 
-	/*
-	 * IPL_NONE is used for hardware interrupts that are never blocked,
-	 * and do not block anything else.
-	 */
-	ipl_sr_bits[IPL_NONE] = 0;
+	.cpu_int32_en = X(CIU_INT32_EN1),
 
-	/*
-	 * Initialize the soft interrupt masks to block themselves.
-	 */
-	ipl_sr_bits[IPL_SOFTCLOCK] |= SI_TO_SRBIT(SI_SOFTCLOCK);
-	ipl_sr_bits[IPL_SOFTNET] |= SI_TO_SRBIT(SI_SOFTNET);
-	ipl_sr_bits[IPL_SOFTSERIAL] |= SI_TO_SRBIT(SI_SOFTSERIAL);
+	.cpu_mbox_set = X(CIU_MBOX_SET1),
+	.cpu_mbox_clr = X(CIU_MBOX_CLR1),
+};
+#endif
 
-	/*
-	 * Enforce a heirarchy that gives "slow" device (or devices with
-	 * limited input buffer space/"real-time" requirements) a better
-	 * chance at not dropping data.
-	 */
-	for (ipl = 1; ipl < _IPL_N; ipl++)
-		ipl_sr_bits[ipl] |= ipl_sr_bits[ipl - 1];
+#undef X
 
-	/*
-	 * splhigh() must block "everything".
-	 */
-	ipl_sr_bits[IPL_HIGH] = MIPS_INT_MASK;
+void
+octeon_intr_init(struct cpu_info *ci)
+{
+	const int cpunum = cpu_index(ci);
+	const char * const xname = cpu_name(ci);
+	struct cpu_softc *cpu;
 
-	/*
-	 * Now compute which INTs must be blocked when servicing any
-	 * given INT.
-	 */
-	for (level = 0; level < NINTRS; level++) {
-		int irqs = (MIPS_INT_MASK_0 << level);
+	ipl_sr_map = octeon_ipl_sr_map;
 
-		for (irq = 0; irq < NIRQS; irq++)
-			LIST_FOREACH(ih, &octeon_intrtab[irq].intr_list, ih_q)
-				if (ih->ih_intr == level)
-					irqs |= ipl_sr_bits[ih->ih_ipl];
-		octeon_cpuintrs[level].cintr_mask = irqs;
+	if (ci->ci_cpuid == 0) {
+		mutex_init(&octeon_intr_lock, MUTEX_DEFAULT, IPL_HIGH);
+		cpu = &octeon_cpu0_softc;
+#ifdef MULTIPROCESSOR
+		mips_locoresw.lsw_send_ipi = octeon_send_ipi;
+#endif
+	} else {
+		KASSERT(cpunum == 1);
+#ifdef MULTIPROCESSOR
+		cpu = &octeon_cpu1_softc;
+#else
+		cpu = NULL;
+#endif
 	}
+	ci->ci_softc = cpu;
 
-//	for (ipl = 0; ipl < _IPL_N; ipl++)
-//		printf("debug: ipl_sr_bits[%.2d] = %.8x\n", ipl, ipl_sr_bits[ipl]);
-}
+#ifdef MULTIPROCESSOR
+	// Enable the IPIs
+	cpu->cpu_int0_enable0 |= __BIT(_CIU_INT_MBOX_15_0_SHIFT);
+	cpu->cpu_int2_enable0 |= __BIT(_CIU_INT_MBOX_31_16_SHIFT);
 #endif
 
-void
-octeon_intr_init(void)
-{
-	ipl_sr_map = octeon_ipl_sr_map;
+	mips64_sd_a64(cpu->cpu_int0_en0, cpu->cpu_int0_enable0);
+	mips64_sd_a64(cpu->cpu_int1_en0, cpu->cpu_int1_enable0);
+	mips64_sd_a64(cpu->cpu_int2_en0, cpu->cpu_int2_enable0);
+
+	mips64_sd_a64(cpu->cpu_int32_en, 0);
+
+	mips64_sd_a64(cpu->cpu_int0_en1, 0);	// WDOG IPL2
+	mips64_sd_a64(cpu->cpu_int1_en1, 0);	// WDOG IPL3
+	mips64_sd_a64(cpu->cpu_int2_en1, 0);	// WDOG IPL4
 
-	octeon_write_csr(CIU_INT0_EN0, 0);
-	octeon_write_csr(CIU_INT1_EN0, 0);
-	octeon_write_csr(CIU_INT32_EN0, 0);
-	octeon_write_csr(CIU_INT0_EN1, 0);
-	octeon_write_csr(CIU_INT1_EN1, 0);
-	octeon_write_csr(CIU_INT32_EN1, 0);
-
-	for (size_t i = 0; i < NINTRS; i++) {
-		LIST_INIT(&octeon_cpuintrs[i].cintr_list);
-		evcnt_attach_dynamic(&octeon_cpuintrs[i].cintr_count,
-		    EVCNT_TYPE_INTR, NULL, "mips", octeon_cpuintrnames[i]);
-	}
+#ifdef MULTIPROCESSOR
+	mips64_sd_a64(cpu->cpu_mbox_clr, __BITS(31,0));
+#endif
 
 	for (size_t i = 0; i < NIRQS; i++) {
-		LIST_INIT(&octeon_ciu_intrtab[i].intr_list);
-		octeon_ciu_intrtab[i].intr_refcnt = 0;
-		evcnt_attach_dynamic(&octeon_ciu_intrtab[i].intr_count,
-		    EVCNT_TYPE_INTR, NULL, "octeon", octeon_intrnames[i]);
+		evcnt_attach_dynamic(&cpu->cpu_intr_evs[i],
+		    EVCNT_TYPE_INTR, NULL, xname, octeon_intrnames[i]);
 	}
 }
 
@@ -313,127 +300,224 @@ octeon_cal_timer(int corefreq)
 }
 
 void *
-octeon_intr_establish(int irq, int req, int level,
-    int (*func)(void *), void *arg)
+octeon_intr_establish(int irq, int ipl, int (*func)(void *), void *arg)
 {
 	struct octeon_intrhand *ih;
-	u_int64_t irq_mask;
-	int s;
 
 	if (irq >= NIRQS)
 		panic("octeon_intr_establish: bogus IRQ %d", irq);
-	if (req > 1)
-		panic("octeon_intr_establish: bogus request %d", req);
+	if (ipl < IPL_VM)
+		panic("octeon_intr_establish: bogus IPL %d", ipl);
 
-	ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
+	ih = kmem_zalloc(sizeof(*ih), KM_NOSLEEP);
 	if (ih == NULL)
 		return (NULL);
 
 	ih->ih_func = func;
 	ih->ih_arg = arg;
 	ih->ih_irq = irq;
-	ih->ih_ipl = level;
-	ih->ih_intr = req;
+	ih->ih_ipl = ipl;
 
-	s = splhigh();
+	mutex_enter(&octeon_intr_lock);
 
 	/*
-	 * First, link it into the tables.
-	 * XXX do we want a separate list (really, should only be one item, not
-	 *     a list anyway) per irq, not per CPU interrupt?
+	 * First, make it known.
 	 */
-	LIST_INSERT_HEAD(&octeon_ciu_intrtab[irq].intr_list, ih, ih_q);
+	KASSERTMSG(octeon_ciu_intrs[irq] == NULL, "irq %d in use! (%p)",
+	    irq, octeon_ciu_intrs[irq]);
+
+	octeon_ciu_intrs[irq] = ih;
+	membar_producer();
 
 	/*
 	 * Now enable it.
 	 */
-	if (octeon_ciu_intrtab[irq].intr_refcnt++ == 0) {
-		irq_mask = 1ULL << irq;
+	const uint64_t irq_mask = __BIT(irq);
+	struct cpu_softc * const cpu0 = &octeon_cpu0_softc;
+#if MULTIPROCESSOR
+	struct cpu_softc * const cpu1 = &octeon_cpu1_softc;
+#endif
 
-		switch (req) {
-		case 0:
-			int0_enable0 |= irq_mask;
-			octeon_write_csr(CIU_INT0_EN0, int0_enable0);
-			break;
-
-		case 1:
-			int1_enable0 |= irq_mask;
-			octeon_write_csr(CIU_INT1_EN0, int1_enable0);
-			break;
-		}
+	switch (ipl) {
+	case IPL_VM:
+		cpu0->cpu_int0_enable0 |= irq_mask;
+		mips64_sd_a64(cpu0->cpu_int0_en0, cpu0->cpu_int0_enable0);
+		break;
+
+	case IPL_SCHED:
+		cpu0->cpu_int1_enable0 |= irq_mask;
+		mips64_sd_a64(cpu0->cpu_int1_en0, cpu0->cpu_int1_enable0);
+#ifdef MULTIPROCESSOR
+		cpu1->cpu_int1_enable0 = cpu0->cpu_int1_enable0;
+		mips64_sd_a64(cpu1->cpu_int1_en0, cpu1->cpu_int1_enable0);
+#endif
+		break;
+
+	case IPL_DDB:
+	case IPL_HIGH:
+		cpu0->cpu_int2_enable0 |= irq_mask;
+		mips64_sd_a64(cpu0->cpu_int2_en0, cpu0->cpu_int2_enable0);
+#ifdef MULTIPROCESSOR
+		cpu1->cpu_int2_enable0 = cpu0->cpu_int2_enable0;
+		mips64_sd_a64(cpu1->cpu_int2_en0, cpu1->cpu_int2_enable0);
+#endif
+		break;
 	}
-	splx(s);
 
-	return (ih);
+	mutex_exit(&octeon_intr_lock);
+
+	return ih;
 }
 
 void
 octeon_intr_disestablish(void *cookie)
 {
-	struct octeon_intrhand *ih = cookie;
-	u_int64_t irq_mask;
-	int irq, req, s;
-
-	irq = ih->ih_irq;
-	req = ih->ih_intr;
+	struct octeon_intrhand * const ih = cookie;
+	const int irq = ih->ih_irq & (NIRQS-1);
+	const int ipl = ih->ih_ipl;
 
-	s = splhigh();
+	mutex_enter(&octeon_intr_lock);
 
 	/*
-	 * First, remove it from the table.
+	 * First disable it.
 	 */
-	LIST_REMOVE(ih, ih_q);
+	const uint64_t irq_mask = ~__BIT(irq);
+	struct cpu_softc * const cpu0 = &octeon_cpu0_softc;
+#if MULTIPROCESSOR
+	struct cpu_softc * const cpu1 = &octeon_cpu1_softc;
+#endif
+
+	switch (ipl) {
+	case IPL_VM:
+		cpu0->cpu_int0_enable0 &= ~irq_mask;
+		mips64_sd_a64(cpu0->cpu_int0_en0, cpu0->cpu_int0_enable0);
+		break;
+
+	case IPL_SCHED:
+		cpu0->cpu_int1_enable0 &= ~irq_mask;
+		mips64_sd_a64(cpu0->cpu_int1_en0, cpu0->cpu_int1_enable0);
+#ifdef MULTIPROCESSOR
+		cpu1->cpu_int1_enable0 = cpu0->cpu_int1_enable0;
+		mips64_sd_a64(cpu1->cpu_int1_en0, cpu1->cpu_int1_enable0);
+#endif
+		break;
+
+	case IPL_DDB:
+	case IPL_HIGH:
+		cpu0->cpu_int2_enable0 &= ~irq_mask;
+		mips64_sd_a64(cpu0->cpu_int2_en0, cpu0->cpu_int2_enable0);
+#ifdef MULTIPROCESSOR
+		cpu1->cpu_int2_enable0 = cpu0->cpu_int2_enable0;
+		mips64_sd_a64(cpu1->cpu_int2_en0, cpu1->cpu_int2_enable0);
+#endif
+		break;
+	}
 
 	/*
-	 * Now, disable it, if there is nothing remaining on the
-	 * list.
+	 * Now remove it since we shouldn't get interrupts for it.
 	 */
-	if (octeon_ciu_intrtab[irq].intr_refcnt-- == 1) {
-		irq &= 63;	/* throw away high bit if set */
-		req &= 1;	/* throw away high bit if set */
-		irq_mask = ~(1ULL << irq);
-
-		switch (req) {
-		case 0:
-			int0_enable0 &= irq_mask;
-			octeon_write_csr(CIU_INT0_EN0, int0_enable0);
-			break;
-
-		case 1:
-			int1_enable0 &= irq_mask;
-			octeon_write_csr(CIU_INT1_EN0, int1_enable0);
-			break;
-		}
-	}
-	free(ih, M_DEVBUF);
+	octeon_ciu_intrs[irq] = NULL;
 
-	splx(s);
+	mutex_exit(&octeon_intr_lock);
+
+	kmem_free(ih, sizeof(*ih));
 }
 
 void
 octeon_iointr(int ipl, vaddr_t pc, uint32_t ipending)
 {
-	struct octeon_intrhand *ih;
-	int level, irq;
+	struct cpu_info * const ci = curcpu();
+	struct cpu_softc * const cpu = ci->ci_softc;
+
+	KASSERT((ipending & ~MIPS_INT_MASK) == 0);
+	KASSERT(ipending & MIPS_HARD_INT_MASK);
 	uint64_t hwpend = 0;
 
-	level = __builtin_clz(ipending);
-	switch (level = 21 - level) {
-	case 0: // MIPS_INT_MASK_0
-		hwpend = octeon_read_csr(CIU_INT0_SUM0) & int0_enable0;
-		break;
+	if (ipending & MIPS_INT_MASK_2) {
+		hwpend = mips64_ld_a64(cpu->cpu_int2_sum0)
+		    & cpu->cpu_int2_enable0;
+	} else if (ipending & MIPS_INT_MASK_1) {
+		hwpend = mips64_ld_a64(cpu->cpu_int1_sum0)
+		    & cpu->cpu_int1_enable0;
+	} else if (ipending & MIPS_INT_MASK_0) {
+		hwpend = mips64_ld_a64(cpu->cpu_int0_sum0)
+		    & cpu->cpu_int0_enable0;
+	} else {
+		panic("octeon_iointr: unexpected ipending %#x", ipending);
+	}
+	while (hwpend != 0) {
+		const int irq = ffs64(hwpend) - 1;
+		hwpend &= ~__BIT(irq);
+		
+		struct octeon_intrhand * const ih = octeon_ciu_intrs[irq];
+		cpu->cpu_intr_evs[irq].ev_count++;
+		if (__predict_true(ih != NULL)) {
+#ifdef MULTIPROCESSOR
+			if (ipl == IPL_VM) {
+				KERNEL_LOCK(1, NULL);
+#endif
+				(*ih->ih_func)(ih->ih_arg);
+#ifdef MULTIPROCESSOR
+				KERNEL_UNLOCK_ONE(NULL);
+			} else {
+				(*ih->ih_func)(ih->ih_arg);
+			}
+#endif
+		}
+	}
+}
 
-	case 1: // MIPS_INT_MASK_1
-		hwpend = octeon_read_csr(CIU_INT1_SUM0) & int1_enable0;
-		break;
+#ifdef MULTIPROCESSOR
+__CTASSERT(NIPIS < 16);
+
+int
+octeon_ipi_intr(void *arg)
+{
+	struct cpu_info * const ci = curcpu();
+	struct cpu_softc * const cpu = ci->ci_softc;
+	uint64_t ipi_mask = (uintptr_t) arg;
+
+	ipi_mask &= mips64_ld_a64(cpu->cpu_mbox_set);
+	mips64_sd_a64(cpu->cpu_mbox_clr, ipi_mask);
+
+	ipi_mask |= (ipi_mask >> 16);
+	ipi_mask &= __BITS(15,0);
+
+	KASSERT(ci->ci_cpl >= IPL_SCHED);
+	KASSERT(ipi_mask < __BIT(NIPIS));
 
-	default:
-		panic("octeon_iointr: illegal interrupt");
+	/* if the request is clear, it was previously processed */
+	if ((ci->ci_request_ipis & ipi_mask) == 0)
+		return 0;
+
+	atomic_or_64(&ci->ci_active_ipis, ipi_mask);
+	atomic_and_64(&ci->ci_request_ipis, ~ipi_mask);
+
+	ipi_process(ci, ipi_mask);
+
+	atomic_and_64(&ci->ci_active_ipis, ~ipi_mask);
+
+	return 1;
+}
+
+int
+octeon_send_ipi(struct cpu_info *ci, int req)
+{
+
+	KASSERT(req < NIPIS);
+	if (ci == NULL) {
+		// only deals with 2 CPUs
+		ci = cpuid_infos[(cpu_number() == 0) ? 1 : 0];
 	}
-	if ((irq = ffs64(hwpend) - 1) < 0)
-		return;
-	octeon_ciu_intrtab[irq].intr_count.ev_count++;
-	LIST_FOREACH(ih, &octeon_ciu_intrtab[irq].intr_list, ih_q) {
-		(*ih->ih_func)(ih->ih_arg);
+
+	struct cpu_softc * const cpu = ci->ci_softc;
+	uint64_t ipi_mask = __BIT(req);
+
+	if (req == IPI_SUSPEND) {
+		ipi_mask <<= 16;
 	}
+
+	mips64_sd_a64(cpu->cpu_mbox_set, ipi_mask);
+	return 0;
 }
+#endif	/* MULTIPROCESSOR */

Index: src/sys/arch/mips/cavium/dev/octeon_ciureg.h
diff -u src/sys/arch/mips/cavium/dev/octeon_ciureg.h:1.1 src/sys/arch/mips/cavium/dev/octeon_ciureg.h:1.2
--- src/sys/arch/mips/cavium/dev/octeon_ciureg.h:1.1	Wed Apr 29 08:32:01 2015
+++ src/sys/arch/mips/cavium/dev/octeon_ciureg.h	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: octeon_ciureg.h,v 1.1 2015/04/29 08:32:01 hikaru Exp $	*/
+/*	$NetBSD: octeon_ciureg.h,v 1.2 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -74,6 +74,12 @@
 #define	CIU_SOFT_RST				UINT64_C(0x0001070000000740)
 #define	CIU_SOFT_PRST				UINT64_C(0x0001070000000748)
 #define	CIU_PCI_INTA				UINT64_C(0x0001070000000750)
+#define	CIU_INT4_SUM0				UINT64_C(0x0001070000000c00)
+#define	CIU_INT4_SUM1				UINT64_C(0x0001070000000c08)
+#define	CIU_INT4_EN00				UINT64_C(0x0001070000000c80)
+#define	CIU_INT4_EN01				UINT64_C(0x0001070000000c88)
+#define	CIU_INT4_EN10				UINT64_C(0x0001070000000c90)
+#define	CIU_INT4_EN11				UINT64_C(0x0001070000000c98)
 
 #define	CIU_INT0_SUM0_OFFSET			0x0000
 #define	CIU_INT1_SUM0_OFFSET			0x0008
Index: src/sys/arch/mips/cavium/dev/octeon_corereg.h
diff -u src/sys/arch/mips/cavium/dev/octeon_corereg.h:1.1 src/sys/arch/mips/cavium/dev/octeon_corereg.h:1.2
--- src/sys/arch/mips/cavium/dev/octeon_corereg.h:1.1	Wed Apr 29 08:32:01 2015
+++ src/sys/arch/mips/cavium/dev/octeon_corereg.h	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: octeon_corereg.h,v 1.1 2015/04/29 08:32:01 hikaru Exp $	*/
+/*	$NetBSD: octeon_corereg.h,v 1.2 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -446,7 +446,8 @@
 
 #define	CP0_CVMCTL_XXX_63_32			UINT64_C(0xffffffff00000000)
 #define	CP0_CVMCTL_FUSE_STARTBIT		UINT64_C(0x0000000080000000)
-#define	CP0_CVMCTL_XXX_30_29			UINT64_C(0x0000000060000000)
+#define	CP0_CVMCTL_XXX_30			UINT64_C(0x0000000040000000)
+#define	CP0_CVMCTL_KASUMI			UINT64_C(0x0000000020000000)
 #define	CP0_CVMCTL_NODFA_CP21			UINT64_C(0x0000000010000000)
 #define	CP0_CVMCTL_NOMUL			UINT64_C(0x0000000008000000)
 #define	CP0_CVMCTL_NOCRYPTO			UINT64_C(0x0000000004000000)
Index: src/sys/arch/mips/cavium/dev/octeon_dwctwo.c
diff -u src/sys/arch/mips/cavium/dev/octeon_dwctwo.c:1.1 src/sys/arch/mips/cavium/dev/octeon_dwctwo.c:1.2
--- src/sys/arch/mips/cavium/dev/octeon_dwctwo.c:1.1	Fri May  1 07:23:47 2015
+++ src/sys/arch/mips/cavium/dev/octeon_dwctwo.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: octeon_dwctwo.c,v 1.1 2015/05/01 07:23:47 hikaru Exp $	*/
+/*	$NetBSD: octeon_dwctwo.c,v 1.2 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright (c) 2015 Masao Uebayashi <[email protected]>
@@ -43,7 +43,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: octeon_dwctwo.c,v 1.1 2015/05/01 07:23:47 hikaru Exp $");
+__KERNEL_RCSID(0, "$NetBSD: octeon_dwctwo.c,v 1.2 2015/06/01 22:55:12 matt Exp $");
 
 #include "opt_octeon.h"
 #include "opt_usb.h"
@@ -308,7 +308,7 @@ octeon_dwc2_attach(device_t parent, devi
 	    config_found(sc->sc_dwc2.sc_dev, &sc->sc_dwc2.sc_bus, usbctlprint);
 
 	sc->sc_ih = octeon_intr_establish(ffs64(CIU_INTX_SUM0_USB) - 1,
-	    0, IPL_BIO, dwc2_intr, sc);
+	    IPL_BIO, dwc2_intr, sc);
 	if (sc->sc_ih == NULL)
 		panic("can't establish common interrupt\n");
 }
Index: src/sys/arch/mips/cavium/dev/octeon_gmx.c
diff -u src/sys/arch/mips/cavium/dev/octeon_gmx.c:1.1 src/sys/arch/mips/cavium/dev/octeon_gmx.c:1.2
--- src/sys/arch/mips/cavium/dev/octeon_gmx.c:1.1	Wed Apr 29 08:32:01 2015
+++ src/sys/arch/mips/cavium/dev/octeon_gmx.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: octeon_gmx.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $	*/
+/*	$NetBSD: octeon_gmx.c,v 1.2 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: octeon_gmx.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $");
+__KERNEL_RCSID(0, "$NetBSD: octeon_gmx.c,v 1.2 2015/06/01 22:55:12 matt Exp $");
 
 #include "opt_octeon.h"
 
@@ -241,7 +241,7 @@ octeon_gmx_attach(device_t parent, devic
 	octeon_gmx_intr_evcnt_attach(sc);
 	if (octeon_gmx_intr_drop_ih == NULL)
 		octeon_gmx_intr_drop_ih = octeon_intr_establish(
-		   ffs64(CIU_INTX_SUM0_GMX_DRP) - 1, 0, IPL_NET,
+		   ffs64(CIU_INTX_SUM0_GMX_DRP) - 1, IPL_NET,
 		   octeon_gmx_intr_drop, NULL);
 #endif
 }
Index: src/sys/arch/mips/cavium/dev/octeon_ipd.c
diff -u src/sys/arch/mips/cavium/dev/octeon_ipd.c:1.1 src/sys/arch/mips/cavium/dev/octeon_ipd.c:1.2
--- src/sys/arch/mips/cavium/dev/octeon_ipd.c:1.1	Wed Apr 29 08:32:01 2015
+++ src/sys/arch/mips/cavium/dev/octeon_ipd.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: octeon_ipd.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $	*/
+/*	$NetBSD: octeon_ipd.c,v 1.2 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: octeon_ipd.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $");
+__KERNEL_RCSID(0, "$NetBSD: octeon_ipd.c,v 1.2 2015/06/01 22:55:12 matt Exp $");
 
 #include "opt_octeon.h"
 
@@ -97,7 +97,7 @@ octeon_ipd_init(struct octeon_ipd_attach
 	octeon_ipd_intr_evcnt_attach(sc);
 	if (octeon_ipd_intr_drop_ih == NULL)
 		octeon_ipd_intr_drop_ih = octeon_intr_establish(
-		   ffs64(CIU_INTX_SUM0_IPD_DRP) - 1, 0, IPL_NET,
+		   ffs64(CIU_INTX_SUM0_IPD_DRP) - 1, IPL_NET,
 		   octeon_ipd_intr_drop, NULL);
 	__octeon_ipd_softc[sc->sc_port] = sc;
 #endif /* OCTEON_ETH_DEBUG */
Index: src/sys/arch/mips/cavium/dev/octeon_mpi.c
diff -u src/sys/arch/mips/cavium/dev/octeon_mpi.c:1.1 src/sys/arch/mips/cavium/dev/octeon_mpi.c:1.2
--- src/sys/arch/mips/cavium/dev/octeon_mpi.c:1.1	Wed Apr 29 08:32:01 2015
+++ src/sys/arch/mips/cavium/dev/octeon_mpi.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: octeon_mpi.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $	*/
+/*	$NetBSD: octeon_mpi.c,v 1.2 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -28,7 +28,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: octeon_mpi.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $");
+__KERNEL_RCSID(0, "$NetBSD: octeon_mpi.c,v 1.2 2015/06/01 22:55:12 matt Exp $");
 
 #include "opt_octeon.h"
 
@@ -146,7 +146,7 @@ octeon_mpi_attach(device_t parent, devic
 	    (0x7d << MPI_CFG_CLKDIV_SHIFT) | MPI_CFG_CSENA | MPI_CFG_ENABLE | MPI_CFG_INT_ENA);
 	/* Enable device interrupts */
 	sc->sc_ih = octeon_intr_establish(ffs64(CIU_INTX_SUM0_MPI) - 1,
-		0, IPL_SERIAL, octeon_mpi_intr, sc);
+		IPL_SERIAL, octeon_mpi_intr, sc);
 	if (sc->sc_ih == NULL)
 		panic("l2sw: can't establish interrupt\n");
 #else
Index: src/sys/arch/mips/cavium/dev/octeon_pci.c
diff -u src/sys/arch/mips/cavium/dev/octeon_pci.c:1.1 src/sys/arch/mips/cavium/dev/octeon_pci.c:1.2
--- src/sys/arch/mips/cavium/dev/octeon_pci.c:1.1	Wed Apr 29 08:32:01 2015
+++ src/sys/arch/mips/cavium/dev/octeon_pci.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: octeon_pci.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $	*/
+/*	$NetBSD: octeon_pci.c,v 1.2 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright (c) 2007, 2008 Internet Initiative Japan, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: octeon_pci.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $");
+__KERNEL_RCSID(0, "$NetBSD: octeon_pci.c,v 1.2 2015/06/01 22:55:12 matt Exp $");
 
 #include "opt_octeon.h"
 
@@ -66,7 +66,7 @@ octeon_pci_init(void)
 {
 #ifdef OCTEON_ETH_DEBUG
 	octeon_pci_intr_rml_ih = octeon_intr_establish(
-	    ffs64(CIU_INTX_SUM0_RML) - 1, 0, IPL_NET, octeon_pci_intr_rml, NULL);
+	    ffs64(CIU_INTX_SUM0_RML) - 1, IPL_NET, octeon_pci_intr_rml, NULL);
 #endif
 }
 
Index: src/sys/arch/mips/cavium/dev/octeon_pow.c
diff -u src/sys/arch/mips/cavium/dev/octeon_pow.c:1.1 src/sys/arch/mips/cavium/dev/octeon_pow.c:1.2
--- src/sys/arch/mips/cavium/dev/octeon_pow.c:1.1	Wed Apr 29 08:32:01 2015
+++ src/sys/arch/mips/cavium/dev/octeon_pow.c	Mon Jun  1 22:55:12 2015
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: octeon_pow.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $");
+__KERNEL_RCSID(0, "$NetBSD: octeon_pow.c,v 1.2 2015/06/01 22:55:12 matt Exp $");
 
 #include "opt_octeon.h"	/* OCTEON_ETH_DEBUG */
 
@@ -328,7 +328,6 @@ octeon_pow_intr_establish(int group, int
 
 	pow_ih->pi_ih = octeon_intr_establish(
 	    ffs64(CIU_INTX_SUM0_WORKQ_0) - 1 + group,
-	    0/* XXX */,
 	    level,
 	    octeon_pow_intr, pow_ih);
 	KASSERT(pow_ih->pi_ih != NULL);
Index: src/sys/arch/mips/cavium/dev/octeon_uart.c
diff -u src/sys/arch/mips/cavium/dev/octeon_uart.c:1.1 src/sys/arch/mips/cavium/dev/octeon_uart.c:1.2
--- src/sys/arch/mips/cavium/dev/octeon_uart.c:1.1	Wed Apr 29 08:32:01 2015
+++ src/sys/arch/mips/cavium/dev/octeon_uart.c	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: octeon_uart.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $	*/
+/*	$NetBSD: octeon_uart.c,v 1.2 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: octeon_uart.c,v 1.1 2015/04/29 08:32:01 hikaru Exp $");
+__KERNEL_RCSID(0, "$NetBSD: octeon_uart.c,v 1.2 2015/06/01 22:55:12 matt Exp $");
 
 #include "opt_octeon.h"
 
@@ -150,7 +150,7 @@ octeon_uart_iobus_attach(device_t parent
 
 	/* XXX pass intr mask via _attach_args -- uebayasi */
 	sc->sc_ih = octeon_intr_establish(ffs64(CIU_INTX_SUM0_UART_0) - 1/* XXX */ + device_unit(self),
-	    IPL_SERIAL > IPL_CLOCK, IPL_SERIAL, comintr, sc_com);
+	    IPL_SERIAL, comintr, sc_com);
 	if (sc->sc_ih == NULL)
 		panic("%s: can't establish interrupt\n",
 		    device_xname(self));

Index: src/sys/arch/mips/conf/files.octeon
diff -u src/sys/arch/mips/conf/files.octeon:1.2 src/sys/arch/mips/conf/files.octeon:1.3
--- src/sys/arch/mips/conf/files.octeon:1.2	Fri May  1 07:23:47 2015
+++ src/sys/arch/mips/conf/files.octeon	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-#	$NetBSD: files.octeon,v 1.2 2015/05/01 07:23:47 hikaru Exp $
+#	$NetBSD: files.octeon,v 1.3 2015/06/01 22:55:12 matt Exp $
 
 file	arch/mips/mips/locore_octeon.S
 file	arch/mips/mips/bus_dma.c
@@ -23,6 +23,13 @@ attach	mainbus at root
 file	arch/mips/cavium/mainbus.c		mainbus
 file	arch/mips/cavium/mainbus_octeon1p.c	mainbus
 
+device	cpunode { [core=-1] }
+attach	cpunode at mainbus
+file	arch/mips/cavium/octeon_cpunode.c	cpunode | cpu
+
+device	cpu
+attach	cpu at cpunode with cpunode_cpu
+
 # I/O Bus
 
 device	iobus {}

Index: src/sys/arch/mips/conf/std.octeon
diff -u src/sys/arch/mips/conf/std.octeon:1.3 src/sys/arch/mips/conf/std.octeon:1.4
--- src/sys/arch/mips/conf/std.octeon:1.3	Mon May 25 23:47:01 2015
+++ src/sys/arch/mips/conf/std.octeon	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-#	$NetBSD: std.octeon,v 1.3 2015/05/25 23:47:01 matt Exp $
+#	$NetBSD: std.octeon,v 1.4 2015/06/01 22:55:12 matt Exp $
 
 machine evbmips mips
 include 	"conf/std"	# MI standard options
@@ -16,8 +16,8 @@ options 	EXEC_ELF64	# exec ELF64 binarie
 options 	COMPAT_NETBSD32
 options 	EXEC_SCRIPT	# exec #! scripts
 
-makeoptions	CFLAGS+="-mips64r2 -march=octeon"
-makeoptions	AFLAGS+="-mips64r2 -march=octeon"
+makeoptions	CFLAGS+="-mips64r2 -march=octeon+"
+makeoptions	AFLAGS+="-mips64r2 -march=octeon+"
 # There is uboot's boot info around 0x100000.
 makeoptions	DEFTEXTADDR="0x80200000"
 makeoptions	BOARDTYPE="octeon"

Index: src/sys/arch/mips/include/cpu.h
diff -u src/sys/arch/mips/include/cpu.h:1.111 src/sys/arch/mips/include/cpu.h:1.112
--- src/sys/arch/mips/include/cpu.h:1.111	Thu May 28 04:16:50 2015
+++ src/sys/arch/mips/include/cpu.h	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.h,v 1.111 2015/05/28 04:16:50 matt Exp $	*/
+/*	$NetBSD: cpu.h,v 1.112 2015/06/01 22:55:12 matt Exp $	*/
 
 /*-
  * Copyright (c) 1992, 1993
@@ -82,7 +82,7 @@ void		  cpuwatch_clr(cpu_watchpoint_t *)
 
 struct cpu_info {
 	struct cpu_data ci_data;	/* MI per-cpu data */
-	struct cpu_info *ci_next;	/* Next CPU in list */
+	void *ci_xnext;			/* unused */
 	struct cpu_softc *ci_softc;	/* chip-dependent hook */
 	device_t ci_dev;		/* owning device */
 	cpuid_t ci_cpuid;		/* Machine-level identifier */
@@ -148,9 +148,15 @@ struct cpu_info {
 
 };
 
+#ifdef MULTIPROCESSOR
 #define	CPU_INFO_ITERATOR		int __unused
 #define	CPU_INFO_FOREACH(cii, ci)	\
-    ci = &cpu_info_store; ci != NULL; ci = ci->ci_next
+    ci = &cpu_info_store; ci != NULL; ci = NULL
+#else
+#define	CPU_INFO_ITERATOR		int
+#define	CPU_INFO_FOREACH(cii, ci)	\
+    cii = 0; cii < MAXCPUS && (ci = cpu_infos[cii]) != NULL; cii++
+#endif
 
 #endif /* !_LOCORE */
 #endif /* _KERNEL */
@@ -229,6 +235,9 @@ struct cpu_info {
 #ifndef _LOCORE
 
 extern struct cpu_info cpu_info_store;
+#ifdef MULTIPROCESSOR
+extern struct cpu_info *cpuid_infos[];
+#endif
 register struct lwp *mips_curlwp asm(MIPS_CURLWP_QUOTED);
 
 #define	curlwp			mips_curlwp

Index: src/sys/arch/mips/include/cpuregs.h
diff -u src/sys/arch/mips/include/cpuregs.h:1.90 src/sys/arch/mips/include/cpuregs.h:1.91
--- src/sys/arch/mips/include/cpuregs.h:1.90	Wed Apr 29 08:32:00 2015
+++ src/sys/arch/mips/include/cpuregs.h	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpuregs.h,v 1.90 2015/04/29 08:32:00 hikaru Exp $	*/
+/*	$NetBSD: cpuregs.h,v 1.91 2015/06/01 22:55:12 matt Exp $	*/
 
 /*
  * Copyright (c) 2009 Miodrag Vallat.
@@ -773,7 +773,7 @@
 #endif
 
 /*
- * Bits defined for for the HWREna (CP0 register 7, select 0).
+ * Bits defined for HWREna (CP0 register 7, select 0).
  */
 #define	MIPS_HWRENA_IMPL31		__BIT(31)
 #define	MIPS_HWRENA_IMPL30		__BIT(30)
@@ -784,6 +784,11 @@
 #define	MIPS_HWRENA_CPUNUM		__BIT(0)
 
 /*
+ * Bits defined for EBASE (CP0 register 15, select 1).
+ */
+#define	MIPS_EBASE_CPUNUM		__BITS(9, 0)
+
+/*
  * Hints for the prefetch instruction
  */
 

Index: src/sys/arch/mips/include/intr.h
diff -u src/sys/arch/mips/include/intr.h:1.8 src/sys/arch/mips/include/intr.h:1.9
--- src/sys/arch/mips/include/intr.h:1.8	Mon May 19 22:47:53 2014
+++ src/sys/arch/mips/include/intr.h	Mon Jun  1 22:55:12 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.h,v 1.8 2014/05/19 22:47:53 rmind Exp $ */
+/* $NetBSD: intr.h,v 1.9 2015/06/01 22:55:12 matt Exp $ */
 
 /*-
  * Copyright (c) 2009, 2010 The NetBSD Foundation, Inc.
@@ -64,6 +64,8 @@
 #define	IST_LEVEL_HIGH	4		/* level triggered, active high */
 #define	IST_LEVEL_LOW	5		/* level triggered, active low */
 
+#define IST_MPSAFE	0x100		/* interrupt is MPSAFE */
+
 #define	IPI_NOP		0		/* do nothing, interrupt only */
 #define	IPI_AST		1		/* force ast */
 #define	IPI_SHOOTDOWN	2		/* do a tlb shootdown */

Index: src/sys/arch/mips/include/lock.h
diff -u src/sys/arch/mips/include/lock.h:1.18 src/sys/arch/mips/include/lock.h:1.19
--- src/sys/arch/mips/include/lock.h:1.18	Sun Feb 20 07:45:47 2011
+++ src/sys/arch/mips/include/lock.h	Mon Jun  1 22:55:13 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: lock.h,v 1.18 2011/02/20 07:45:47 matt Exp $	*/
+/*	$NetBSD: lock.h,v 1.19 2015/06/01 22:55:13 matt Exp $	*/
 
 /*-
  * Copyright (c) 2001, 2007 The NetBSD Foundation, Inc.
@@ -184,8 +184,13 @@ static __inline void
 __cpu_simple_unlock(__cpu_simple_lock_t *lp)
 {
 
+#ifndef _MIPS_ARCH_OCTEONP
 	mb_memory();
+#endif
 	*lp = __SIMPLELOCK_UNLOCKED;
+#ifdef _MIPS_ARCH_OCTEONP
+	mb_write();
+#endif
 }
 
 #endif /* _MIPS_LOCK_H_ */
Index: src/sys/arch/mips/include/mips_opcode.h
diff -u src/sys/arch/mips/include/mips_opcode.h:1.18 src/sys/arch/mips/include/mips_opcode.h:1.19
--- src/sys/arch/mips/include/mips_opcode.h:1.18	Thu Aug 18 21:04:23 2011
+++ src/sys/arch/mips/include/mips_opcode.h	Mon Jun  1 22:55:13 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: mips_opcode.h,v 1.18 2011/08/18 21:04:23 matt Exp $	*/
+/*	$NetBSD: mips_opcode.h,v 1.19 2015/06/01 22:55:13 matt Exp $	*/
 
 /*-
  * Copyright (c) 1992, 1993
@@ -34,6 +34,9 @@
  *	@(#)mips_opcode.h	8.1 (Berkeley) 6/10/93
  */
 
+#ifndef _MIPS_MIPS_OPCODE_H_
+#define _MIPS_MIPS_OPCODE_H_
+
 /*
  * Define the instruction formats and opcode values for the
  * MIPS instruction set.
@@ -317,3 +320,14 @@ typedef union {
 #define COPz_BCL_TF_MASK	0x02		/* MIPS-II, for r4000 port */
 #define COPz_BCL_TRUE	0x02		/* MIPS-II, for r4000 port */
 #define COPz_BCL_FALSE	0x00		/* MIPS-II, for r4000 port */
+
+#define	INSN_LUI_P(insn)	(((insn) >> 26) == OP_LUI)
+#define	INSN_LW_P(insn)		(((insn) >> 26) == OP_LW)
+#define	INSN_SW_P(insn)		(((insn) >> 26) == OP_SW)
+#define	INSN_LD_P(insn)		(((insn) >> 26) == OP_LD)
+#define	INSN_SD_P(insn)		(((insn) >> 26) == OP_SD)
+
+#define INSN_LOAD_P(insn)	(INSN_LD_P(insn) || INSN_LW_P(insn))
+#define INSN_STORE_P(insn)	(INSN_SD_P(insn) || INSN_SW_P(insn))
+
+#endif /* _MIPS_MIPS_OPCODE_H_ */

Index: src/sys/arch/mips/include/locore.h
diff -u src/sys/arch/mips/include/locore.h:1.97 src/sys/arch/mips/include/locore.h:1.98
--- src/sys/arch/mips/include/locore.h:1.97	Sat May  2 18:16:17 2015
+++ src/sys/arch/mips/include/locore.h	Mon Jun  1 22:55:13 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.h,v 1.97 2015/05/02 18:16:17 matt Exp $ */
+/* $NetBSD: locore.h,v 1.98 2015/06/01 22:55:13 matt Exp $ */
 
 /*
  * This file should not be included by MI code!!!
@@ -102,14 +102,14 @@ void	softint_fast_dispatch(struct lwp *,
  * offset, we shift left to clear the upper four bits and then right by 6.
  */
 #define	fixup_addr2offset(x)	((((uint32_t)(uintptr_t)(x)) << 4) >> 6)
-typedef bool (*mips_fixup_callback_t)(int32_t, uint32_t [2]);
+typedef bool (*mips_fixup_callback_t)(int32_t, uint32_t [2], void *);
 struct mips_jump_fixup_info {
 	uint32_t jfi_stub;
 	uint32_t jfi_real;
 };
  
 void	fixup_splcalls(void);				/* splstubs.c */
-bool	mips_fixup_exceptions(mips_fixup_callback_t);
+bool	mips_fixup_exceptions(mips_fixup_callback_t, void *);
 bool	mips_fixup_zero_relative(int32_t, uint32_t [2]);
 intptr_t
 	mips_fixup_addr(const uint32_t *);
@@ -155,6 +155,9 @@ void	mipsNN_cp0_watchlo_write(u_int, int
 uint32_t mipsNN_cp0_watchhi_read(u_int);
 void	mipsNN_cp0_watchhi_write(u_int, uint32_t);
 
+int32_t mipsNN_cp0_ebase_read(void);
+void	mipsNN_cp0_ebase_write(int32_t);
+
 #if (MIPS32R2 + MIPS64R2) > 0
 void	mipsNN_cp0_hwrena_write(uint32_t);
 void	mipsNN_cp0_userlocal_write(void *);
@@ -419,6 +422,7 @@ struct splsw;
 struct mips_vmfreelist;
 struct phys_ram_seg;
 
+void	mips64r2_vector_init(const struct splsw *);
 void	mips_vector_init(const struct splsw *, bool);
 void	mips_init_msgbuf(void);
 void	mips_init_lwp0_uarea(void);

Index: src/sys/arch/mips/mips/cpu_subr.c
diff -u src/sys/arch/mips/mips/cpu_subr.c:1.19 src/sys/arch/mips/mips/cpu_subr.c:1.20
--- src/sys/arch/mips/mips/cpu_subr.c:1.19	Tue May 26 02:09:34 2015
+++ src/sys/arch/mips/mips/cpu_subr.c	Mon Jun  1 22:55:13 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu_subr.c,v 1.19 2015/05/26 02:09:34 matt Exp $	*/
+/*	$NetBSD: cpu_subr.c,v 1.20 2015/06/01 22:55:13 matt Exp $	*/
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.19 2015/05/26 02:09:34 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v 1.20 2015/06/01 22:55:13 matt Exp $");
 
 #include "opt_ddb.h"
 #include "opt_multiprocessor.h"
@@ -67,8 +67,12 @@ __KERNEL_RCSID(0, "$NetBSD: cpu_subr.c,v
 #endif
 #endif
 
+#ifdef MIPS64_OCTEON
+extern struct cpu_softc octeon_cpu0_softc;
+#endif
+
 struct cpu_info cpu_info_store
-#ifdef MULTIPROCESSOR
+#if defined(MULTIPROCESSOR) && !defined(MIPS64_OCTEON)
 	__section(".data1")
 	__aligned(1LU << ilog2((2*sizeof(struct cpu_info)-1)))
 #endif
@@ -84,6 +88,9 @@ struct cpu_info cpu_info_store
 #ifdef MULTIPROCESSOR
 	.ci_flags = CPUF_PRIMARY|CPUF_PRESENT|CPUF_RUNNING,
 #endif
+#ifdef MIPS64_OCTEON
+	.ci_softc = &octeon_cpu0_softc,
+#endif
 };
 
 const pcu_ops_t * const pcu_ops_md_defs[PCU_UNIT_COUNT] = {
@@ -94,6 +101,9 @@ const pcu_ops_t * const pcu_ops_md_defs[
 };
 
 #ifdef MULTIPROCESSOR
+struct cpu_info * cpuid_infos[MAXCPUS] = {
+	[0] = &cpu_info_store,
+};
 
 volatile __cpuset_t cpus_running = 1;
 volatile __cpuset_t cpus_hatched = 1;
@@ -104,16 +114,31 @@ volatile __cpuset_t cpus_halted = 0;
 static int  cpu_ipi_wait(volatile __cpuset_t *, u_long);
 static void cpu_ipi_error(const char *, __cpuset_t, __cpuset_t);
 
-static struct cpu_info *cpu_info_last = &cpu_info_store;
-
 struct cpu_info *
 cpu_info_alloc(struct pmap_tlb_info *ti, cpuid_t cpu_id, cpuid_t cpu_package_id,
 	cpuid_t cpu_core_id, cpuid_t cpu_smt_id)
 {
-	vaddr_t cpu_info_offset = (vaddr_t)&cpu_info_store & PAGE_MASK; 
 	struct pglist pglist;
 	int error;
 
+	KASSERT(cpu_id < MAXCPUS);
+
+#ifdef MIPS64O_OCTEON
+	const vaddr_t cpu_info_offset = 0x800;
+	vaddr_t exc_page = MIPS_UTLB_MISS_EXC_VEC + 0x1000*cpu_id;
+	__CTASSERT(sizeof(struct cpu_info) <= 0x800);
+	__CTASSERT(sizeof(struct pmap_tlb_info) <= 0x400);
+	
+	struct cpu_info * const ci = (void *) (va + cpu_info_offset);
+	memset((void *)va, 0, PAGE_SIZE);
+
+	if (ti == NULL) {
+		ti = ((struct pmap_tlb_info *)ci) - 1;
+		pmap_tlb_info_init(ti);
+	}
+#else
+	const vaddr_t cpu_info_offset = (vaddr_t)&cpu_info_store & PAGE_MASK; 
+
 	/*
 	* Grab a page from the first 512MB (mappable by KSEG0) to use to store
 	* exception vectors and cpu_info for this cpu.
@@ -144,6 +169,16 @@ cpu_info_alloc(struct pmap_tlb_info *ti,
 		pmap_tlb_info_init(ti);
 	}
 
+	/*
+	 * Attach its TLB info (which must be direct-mapped)
+	 */
+#ifdef _LP64
+	KASSERT(MIPS_KSEG0_P(ti) || MIPS_XKPHYS_P(ti));
+#else
+	KASSERT(MIPS_KSEG0_P(ti));
+#endif
+#endif /* MIPS64_OCTEON */
+
 	ci->ci_cpuid = cpu_id;
 	ci->ci_data.cpu_package_id = cpu_package_id;
 	ci->ci_data.cpu_core_id = cpu_core_id;
@@ -155,15 +190,6 @@ cpu_info_alloc(struct pmap_tlb_info *ti,
         ci->ci_divisor_recip = cpu_info_store.ci_divisor_recip;
 	ci->ci_cpuwatch_count = cpu_info_store.ci_cpuwatch_count;
 
-	/*
-	 * Attach its TLB info (which must be direct-mapped)
-	 */
-#ifdef _LP64
-	KASSERT(MIPS_KSEG0_P(ti) || MIPS_XKPHYS_P(ti));
-#else
-	KASSERT(MIPS_KSEG0_P(ti));
-#endif
-
 #ifndef _LP64
 	/*
 	 * If we have more memory than can be mapped by KSEG0, we need to
@@ -249,10 +275,9 @@ cpu_attach_common(device_t self, struct 
 		/*
 		 * Tail insert this onto the list of cpu_info's.
 		 */
-		KASSERT(ci->ci_next == NULL);
-		KASSERT(cpu_info_last->ci_next == NULL);
-		cpu_info_last->ci_next = ci;
-		cpu_info_last = ci;
+		KASSERT(cpuid_infos[ci->ci_cpuid] == NULL);
+		cpuid_infos[ci->ci_cpuid] = ci;
+		membar_producer();
 	}
 	evcnt_attach_dynamic(&ci->ci_evcnt_synci_activate_rqst,
 	    EVCNT_TYPE_MISC, NULL, xname,
@@ -835,6 +860,9 @@ cpu_hatch(struct cpu_info *ci)
 	tlb_invalidate_all();
 	mips3_cp0_wired_write(ti->ti_wired);
 
+	// Show this CPU as present.
+	atomic_or_ulong(&ci->ci_flags, CPUF_PRESENT);
+
 	/*
 	 * Setup HWRENA and USERLOCAL COP0 registers (MIPSxxR2).
 	 */
@@ -903,10 +931,11 @@ cpu_hatch(struct cpu_info *ci)
 void
 cpu_boot_secondary_processors(void)
 {
-	for (struct cpu_info *ci = cpu_info_store.ci_next;
-	     ci != NULL;
-	     ci = ci->ci_next) {
-		KASSERT(!CPU_IS_PRIMARY(ci));
+	CPU_INFO_ITERATOR cii;
+	struct cpu_info *ci;
+	for (CPU_INFO_FOREACH(cii, ci)) {
+		if (CPU_IS_PRIMARY(ci))
+			continue;
 		KASSERT(ci->ci_data.cpu_idlelwp);
 
 		/*

Index: src/sys/arch/mips/mips/locore.S
diff -u src/sys/arch/mips/mips/locore.S:1.191 src/sys/arch/mips/mips/locore.S:1.192
--- src/sys/arch/mips/mips/locore.S:1.191	Tue May 19 00:00:23 2015
+++ src/sys/arch/mips/mips/locore.S	Mon Jun  1 22:55:13 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.S,v 1.191 2015/05/19 00:00:23 matt Exp $	*/
+/*	$NetBSD: locore.S,v 1.192 2015/06/01 22:55:13 matt Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -98,10 +98,10 @@ _C_LABEL(kernel_text):
 	// octeon_cpu_spinup if MP or loop using the wait instruction since
 	// non-primary CPUs can't do anything useful.
 	//
-	mfc0	a0, $15, 1			# EBASE
+	mfc0	a0, MIPS_COP_0_PRID, 1		# EBASE
 	COP0_SYNC
-	and	a0, 0x1ff			# get CPU number
-	beqz	a0, 2f				# normal startup if 0
+	and	a1, a0, 0x1ff			# get CPU number
+	beqz	a1, 2f				# normal startup if 0
 	nop
 #ifdef MULTIPROCESSOR
 	j	_C_LABEL(octeon_cpu_spinup)

Index: src/sys/arch/mips/mips/locore_mips3.S
diff -u src/sys/arch/mips/mips/locore_mips3.S:1.102 src/sys/arch/mips/mips/locore_mips3.S:1.103
--- src/sys/arch/mips/mips/locore_mips3.S:1.102	Tue Aug 16 06:55:11 2011
+++ src/sys/arch/mips/mips/locore_mips3.S	Mon Jun  1 22:55:13 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore_mips3.S,v 1.102 2011/08/16 06:55:11 matt Exp $	*/
+/*	$NetBSD: locore_mips3.S,v 1.103 2015/06/01 22:55:13 matt Exp $	*/
 
 /*
  * Copyright (c) 1997 Jonathan Stone (hereinafter referred to as the author)
@@ -401,6 +401,26 @@ LEAF(mipsNN_cp0_watchhi_write)
 	 mtc0	a1, MIPS_COP_0_WATCH_HI, 7
 END(mipsNN_cp0_watchhi_write)
 
+/*
+ * void mipsNN_cp0_ebase_read(void *);
+ *	Get the value of the CP0 EBASE (PRID, select 1) register.
+ */
+LEAF(mipsNN_cp0_ebase_read)
+	jr	ra
+	 mfc0	v0, MIPS_COP_0_PRID, 1
+END(mipsNN_cp0_ebase_read)
+
+/*
+ * void mipsNN_cp0_ebase_write(void *);
+ *	Set the value of the CP0 EBASE (PRID, select 1) register.
+ */
+LEAF(mipsNN_cp0_ebase_write)
+	and	v0, v0, 0x1ff
+	xor	v0, v0, a0
+	jr	ra
+	 mtc0	v0, MIPS_COP_0_PRID, 1
+END(mipsNN_cp0_ebase_write)
+
 #if (MIPS32R2 + MIPS64R2) > 0
 /*
  * void mipsNN_cp0_userlocal_write(void *);
@@ -690,10 +710,10 @@ END(mips3_cp0_tlb_page_mask_probe)
 #ifdef MULTIPROCESSOR
 /*
  * The presence of this routine here will causes MIPS1 MULTIPROCESSOR kernels
- * to fail, as they should since we won't support much abominations.
+ * to fail, as they should since we won't support such abominations.
  *
- * MD code calls/jumps to with the pointer to this CPU's cpu_info in a1,
- * sp set to ci->ci_data.cpu_idlwp->l_md.md_utf.  gp will be overridden so
+ * MD code calls/jumps to this with the pointer to this CPU's cpu_info in a1,
+ * sp set to ci->ci_data.cpu_idlelwp->l_md.md_utf.  gp will be overridden so
  * 0 can be supplied if needed.  (This happens to match what CFE wants)
  */
 NESTED_NOPROFILE(cpu_trampoline, 0, ra)
@@ -702,10 +722,15 @@ NESTED_NOPROFILE(cpu_trampoline, 0, ra)
 	 * that the cpu_info is a KSEG0 address.
 	 */
 	move	a0, a1
-	PTR_L	MIPS_CURLWP, CPU_INFO_IDLELWP(a0)
+	// Loop until idlelwp is filled in.
+1:	PTR_L	MIPS_CURLWP, CPU_INFO_IDLELWP(a0)
 	nop
+	beqz	MIPS_CURLWP, 1b
+	 nop
 	PTR_S	MIPS_CURLWP, CPU_INFO_CURLWP(a0)
 
+	PTR_L	sp, L_MD_UTF(MIPS_CURLWP)	# fetch KSP
+
 #ifdef _LP64
 	li	v0, MIPS_SR_KX | MIPS_SR_UX	# allow 64bit addressing
 #else

Index: src/sys/arch/mips/mips/locore_octeon.S
diff -u src/sys/arch/mips/mips/locore_octeon.S:1.1 src/sys/arch/mips/mips/locore_octeon.S:1.2
--- src/sys/arch/mips/mips/locore_octeon.S:1.1	Wed Apr 29 08:32:00 2015
+++ src/sys/arch/mips/mips/locore_octeon.S	Mon Jun  1 22:55:13 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore_octeon.S,v 1.1 2015/04/29 08:32:00 hikaru Exp $	*/
+/*	$NetBSD: locore_octeon.S,v 1.2 2015/06/01 22:55:13 matt Exp $	*/
 
 /*
  * Copyright (c) 2007 Internet Initiative Japan, Inc.
@@ -27,9 +27,10 @@
  */
 
 #include <mips/asm.h>
-RCSID("$NetBSD: locore_octeon.S,v 1.1 2015/04/29 08:32:00 hikaru Exp $")
+RCSID("$NetBSD: locore_octeon.S,v 1.2 2015/06/01 22:55:13 matt Exp $")
 
 #include "opt_cputype.h"
+#include "opt_multiprocessor.h"
 
 #include <mips/cpuregs.h>
 #include <arch/mips/cavium/dev/octeon_corereg.h>
@@ -47,7 +48,6 @@ RCSID("$NetBSD: locore_octeon.S,v 1.1 20
 	nop
 
 	.set	noreorder
-	.set	mips3
 	.set	arch=octeon
 
 	.text
@@ -76,14 +76,6 @@ LEAF(mips_cp0_cvmcnt_write)
 	_CP0_WRITE64(CP0_CVMCNT)
 END(mips_cp0_cvmcnt_write)
 
-LEAF(mips_cp0_ebase_read)
-	_CP0_READ64(CP0_EBASE)
-END(mips_cp0_ebase_read)
-
-LEAF(mips_cp0_ebase_write)
-	_CP0_WRITE64(CP0_EBASE)
-END(mips_cp0_ebase_write)
-
 LEAF(mips_cp0_performance_counter_control0_read)
 	_CP0_READ64(CP0_PCCTL)
 END(mips_cp0_performance_counter_control0_read)
@@ -115,3 +107,44 @@ END(mips_cp0_performance_counter_counter
 LEAF(mips_cp0_performance_counter_counter1_write)
 	_CP0_WRITE64(CP0_PCCNT1)
 END(mips_cp0_performance_counter_counter1_write)
+
+#ifdef MULTIPROCESSOR
+
+NESTED_NOPROFILE(octeon_cpu_spinup, 0, ra)
+	//
+	// Since the OCTEON cpus doesn't a COP0 OSCONTEXT register, each core
+	// must has its own exception vector page.  The exceptions will be
+	// modified to refer to that CPU's cpu_info structure.
+	//
+	mfc0	a0, MIPS_COP_0_PRID, 1	# get EBASE
+	ext	s0, a0, 0, 10		# fetch cpunum (MIPSNNR2)
+	ins	a0, zero, 0, 10		# clear it (MIPSNNR2)
+	ins	a0, v0, 12, 10		# insert cpunum as exception address
+	mtc0	a0, MIPS_COP_0_PRID, 1	# set EBASE
+	COP0_SYNC
+
+	// we only can deal with 2 cores
+	li	v0, 1
+	bne	s0, v0, 2f
+	 nop
+	// spin if this isn't cpu 1
+1:	wait
+	b	1b
+	 nop
+
+	// Indicate we've gotten this far
+	PTR_LA	a0, _C_LABEL(cpus_booted)
+	jal	_C_LABEL(atomic_or_64)
+	 sll	a1, v0, s0
+
+	// Wait until cpuid_infos[cpunum] is not NULL.
+2:	PTR_LA	a1, _C_LABEL(cpuid_infos)
+	dsll	s0, s0, PTR_SCALESHIFT	# cpunum -> array index
+	PTR_ADD	t0, a1, s0		# add to array start
+3:	PTR_L	a1, (t0)		# get cpu_info pointer
+	beqz	a1, 3b			# loop until non-NULL
+	 nop
+	j	_C_LABEL(cpu_hatch)
+	 nop
+END(octeon_cpu_spinup)
+#endif /* MULTIPROCESSOR */

Index: src/sys/arch/mips/mips/mips_fixup.c
diff -u src/sys/arch/mips/mips/mips_fixup.c:1.10 src/sys/arch/mips/mips/mips_fixup.c:1.11
--- src/sys/arch/mips/mips/mips_fixup.c:1.10	Wed Nov  9 17:05:50 2011
+++ src/sys/arch/mips/mips/mips_fixup.c	Mon Jun  1 22:55:13 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: mips_fixup.c,v 1.10 2011/11/09 17:05:50 matt Exp $	*/
+/*	$NetBSD: mips_fixup.c,v 1.11 2015/06/01 22:55:13 matt Exp $	*/
 
 /*-
  * Copyright (c) 2010 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mips_fixup.c,v 1.10 2011/11/09 17:05:50 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mips_fixup.c,v 1.11 2015/06/01 22:55:13 matt Exp $");
 
 #include "opt_mips3_wired.h"
 #include "opt_multiprocessor.h"
@@ -44,19 +44,15 @@ __KERNEL_RCSID(0, "$NetBSD: mips_fixup.c
 #include <mips/regnum.h>
 #include <mips/mips_opcode.h>
 
-#define	INSN_LUI_P(insn)	(((insn) >> 26) == OP_LUI)
-#define	INSN_LW_P(insn)		(((insn) >> 26) == OP_LW)
-#define	INSN_SW_P(insn)		(((insn) >> 26) == OP_SW)
-#define	INSN_LD_P(insn)		(((insn) >> 26) == OP_LD)
-#define	INSN_SD_P(insn)		(((insn) >> 26) == OP_SD)
-
-#define INSN_LOAD_P(insn)	(INSN_LD_P(insn) || INSN_LW_P(insn))
-#define INSN_STORE_P(insn)	(INSN_SD_P(insn) || INSN_SW_P(insn))
-
 bool
-mips_fixup_exceptions(mips_fixup_callback_t callback)
+mips_fixup_exceptions(mips_fixup_callback_t callback, void *arg)
 {
+#if (MIPS32 + MIPS32R2 + MIPS64 + MIPS64R2) > 0
+	uint32_t * const start =
+	    (uint32_t *)(intptr_t)(mipsNN_cp0_ebase_read() & ~MIPS_EBASE_CPUNUM);
+#else
 	uint32_t * const start = (uint32_t *)MIPS_KSEG0_START;
+#endif
 	uint32_t * const end = start + (5 * 128) / sizeof(uint32_t);
 	const int32_t addr = (intptr_t)&cpu_info_store;
 	const size_t size = sizeof(cpu_info_store);
@@ -121,7 +117,7 @@ mips_fixup_exceptions(mips_fixup_callbac
 #endif
 				new_insns[0] = lui_insn;
 				new_insns[1] = *insnp;
-				if ((callback)(load_addr, new_insns)) {
+				if ((callback)(load_addr, new_insns, arg)) {
 					if (lui_insnp) {
 						*lui_insnp = new_insns[0];
 						*insnp = new_insns[1];

Index: src/sys/arch/mips/mips/mips_machdep.c
diff -u src/sys/arch/mips/mips/mips_machdep.c:1.264 src/sys/arch/mips/mips/mips_machdep.c:1.265
--- src/sys/arch/mips/mips/mips_machdep.c:1.264	Mon May 25 23:45:54 2015
+++ src/sys/arch/mips/mips/mips_machdep.c	Mon Jun  1 22:55:13 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: mips_machdep.c,v 1.264 2015/05/25 23:45:54 matt Exp $	*/
+/*	$NetBSD: mips_machdep.c,v 1.265 2015/06/01 22:55:13 matt Exp $	*/
 
 /*
  * Copyright 2002 Wasabi Systems, Inc.
@@ -111,7 +111,7 @@
  */
 
 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
-__KERNEL_RCSID(0, "$NetBSD: mips_machdep.c,v 1.264 2015/05/25 23:45:54 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mips_machdep.c,v 1.265 2015/06/01 22:55:13 matt Exp $");
 
 #define __INTR_PRIVATE
 #include "opt_cputype.h"
@@ -239,7 +239,6 @@ extern const mips_locore_jumpvec_t mips6
 #endif
 
 #if defined(MIPS64R2)
-static void	mips64r2_vector_init(const struct splsw *);
 extern const struct locoresw mips64r2_locoresw;
 extern const mips_locore_jumpvec_t mips64r2_locore_vec;
 #endif
@@ -1005,7 +1004,7 @@ mips64_vector_init(const struct splsw *s
 #endif /* MIPS64 */
 
 #if defined(MIPS64R2)
-static void
+void
 mips64r2_vector_init(const struct splsw *splsw)
 {
 	/* r4000 exception handler address */
@@ -1041,7 +1040,13 @@ mips64r2_vector_init(const struct splsw 
 		panic("startup: %s vector code too large",
 		    "interrupt exception");
 
-	memcpy((void *)MIPS_UTLB_MISS_EXC_VEC, mips64r2_tlb_miss,
+	const intptr_t ebase = (intptr_t)mipsNN_cp0_ebase_read();
+	const int cpunum = ebase & MIPS_EBASE_CPUNUM;
+
+	// This may need to be on CPUs other CPU0 so use EBASE to fetch
+	// the appropriate address for exception code.  EBASE also contains
+	// the cpunum so remove that.
+	memcpy((void *)(ebase & ~MIPS_EBASE_CPUNUM), mips64r2_tlb_miss,
 	      mips64r2_intr_end - mips64r2_tlb_miss);
 
 	/*
@@ -1062,7 +1067,7 @@ mips64r2_vector_init(const struct splsw 
 	 * If this CPU doesn't have a COP0 USERLOCAL register, at the end
 	 * of cpu_switch resume overwrite the instructions which update it.
 	 */
-	if (!(cp0flags & MIPS_CP0FL_USERLOCAL)) {
+	if (!(cp0flags & MIPS_CP0FL_USERLOCAL) && cpunum == 0) {
 		extern uint32_t mips64r2_cpu_switch_resume[];
 		for (uint32_t *insnp = mips64r2_cpu_switch_resume;; insnp++) {
 			KASSERT(insnp[0] != JR_RA);
@@ -1078,7 +1083,8 @@ mips64r2_vector_init(const struct splsw 
 	/*
 	 * Copy locore-function vector.
 	 */
-	mips_locore_jumpvec = mips64r2_locore_vec;
+	if (cpunum == 0)
+		mips_locore_jumpvec = mips64r2_locore_vec;
 
 	mips_icache_sync_all();
 	mips_dcache_wbinv_all();

Index: src/sys/arch/mips/rmi/rmixl_cpu.c
diff -u src/sys/arch/mips/rmi/rmixl_cpu.c:1.6 src/sys/arch/mips/rmi/rmixl_cpu.c:1.7
--- src/sys/arch/mips/rmi/rmixl_cpu.c:1.6	Mon Nov 25 03:01:58 2013
+++ src/sys/arch/mips/rmi/rmixl_cpu.c	Mon Jun  1 22:55:13 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: rmixl_cpu.c,v 1.6 2013/11/25 03:01:58 christos Exp $	*/
+/*	$NetBSD: rmixl_cpu.c,v 1.7 2015/06/01 22:55:13 matt Exp $	*/
 
 /*
  * Copyright 2002 Wasabi Systems, Inc.
@@ -38,7 +38,7 @@
 #include "locators.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rmixl_cpu.c,v 1.6 2013/11/25 03:01:58 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rmixl_cpu.c,v 1.7 2015/06/01 22:55:13 matt Exp $");
 
 #include "opt_multiprocessor.h"
 #include "opt_ddb.h"
@@ -321,10 +321,9 @@ cpu_rmixl_hatch(struct cpu_info *ci)
 
 	(void)splhigh();
 
-#ifdef DEBUG
-	uint32_t ebase;
-	asm volatile("dmfc0 %0, $15, 1;" : "=r"(ebase));
-	KASSERT((ebase & __BITS(9,0)) == ci->ci_cpuid);
+#ifdef DIAGNOSTIC
+	uint32_t ebase = mipsNN_cp0_ebase_read();
+	KASSERT((ebase & MIPS_EBASE_CPUNUM) == ci->ci_cpuid);
 	KASSERT(curcpu() == ci);
 #endif
 

Added files:

Index: src/sys/arch/mips/cavium/octeon_cpunode.c
diff -u /dev/null src/sys/arch/mips/cavium/octeon_cpunode.c:1.1
--- /dev/null	Mon Jun  1 22:55:13 2015
+++ src/sys/arch/mips/cavium/octeon_cpunode.c	Mon Jun  1 22:55:12 2015
@@ -0,0 +1,242 @@
+/*-
+ * Copyright (c) 2014 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Matt Thomas of 3am Software Foundry.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+#define __INTR_PRIVATE
+#include <sys/cdefs.h>
+
+__KERNEL_RCSID(0, "$NetBSD");
+
+#include "locators.h"
+
+#include <sys/param.h>
+#include <sys/device.h>
+#include <sys/lwp.h>
+#include <sys/cpu.h>
+
+#include <mips/cache.h>
+#include <mips/cpuset.h>
+#include <mips/mips_opcode.h>
+
+#include <mips/cavium/octeonvar.h>
+#include <mips/cavium/dev/octeon_ciureg.h>
+#include <mips/cavium/dev/octeon_corereg.h>
+
+struct cpunode_attach_args {
+	const char *cnaa_name;
+	int cnaa_cpunum;
+};
+
+static int cpunode_mainbus_match(device_t, cfdata_t, void *);
+static void cpunode_mainbus_attach(device_t, device_t, void *);
+
+static int cpu_cpunode_match(device_t, cfdata_t, void *);
+static void cpu_cpunode_attach(device_t, device_t, void *);
+
+CFATTACH_DECL_NEW(cpunode, 0,
+    cpunode_mainbus_match, cpunode_mainbus_attach, NULL, NULL);
+
+CFATTACH_DECL_NEW(cpunode_cpu, 0,
+    cpu_cpunode_match, cpu_cpunode_attach, NULL, NULL);
+
+volatile __cpuset_t cpus_booted = 1;
+
+static int
+cpunode_mainbus_print(void *aux, const char *pnp)
+{
+	struct cpunode_attach_args * const cnaa = aux;
+
+	aprint_normal(" core %d", cnaa->cnaa_cpunum);
+
+	return UNCONF;
+}
+
+int
+cpunode_mainbus_match(device_t parent, cfdata_t cf, void *aux)
+{
+	
+	return 1;
+}
+
+void
+cpunode_mainbus_attach(device_t parent, device_t self, void *aux)
+{
+	uint64_t fuse = octeon_xkphys_read_8(CIU_FUSE);
+	int cpunum = 0;
+
+	aprint_naive(": %u core%s\n",
+	    popcount32((uint32_t)fuse),
+	    fuse == 1 ? "" : "s");
+
+	aprint_normal(": %u core%s",
+	    popcount32((uint32_t)fuse),
+	    fuse == 1 ? "" : "s");
+	const uint64_t cvmctl = mips_cp0_cvmctl_read();
+	aprint_normal(", %scrypto", (cvmctl & CP0_CVMCTL_NOCRYPTO) ? "no " : "");
+	aprint_normal((cvmctl & CP0_CVMCTL_KASUMI) ? "+kasumi" : "");
+	aprint_normal(", %s64bit-mul", (cvmctl & CP0_CVMCTL_NOMUL) ? "no " : "");
+	if (cvmctl & CP0_CVMCTL_REPUN)
+		aprint_normal(", unaligned-access ok");
+	aprint_normal("\n");
+
+	for (; fuse != 0; fuse >>= 1, cpunum++) {
+		struct cpunode_attach_args cnaa = {
+			.cnaa_name = "cpu",
+			.cnaa_cpunum = cpunum,
+		};
+		config_found(self, &cnaa, cpunode_mainbus_print);
+	}
+}
+
+int
+cpu_cpunode_match(device_t parent, cfdata_t cf, void *aux)
+{
+	struct cpunode_attach_args * const cnaa = aux;
+	const int cpunum = cf->cf_loc[CPUNODECF_CORE];
+
+	return cpunum == CPUNODECF_CORE_DEFAULT
+	    || cpunum == cnaa->cnaa_cpunum;
+}
+
+#if defined(MULTIPROCESSOR)
+static bool
+octeon_fixup_cpu_info_references(int32_t load_addr, uint32_t new_insns[2],
+    void *arg)
+{
+	struct cpu_info * const ci = arg;
+
+	KASSERT(MIPS_KSEG0_P(load_addr));
+	KASSERT(!MIPS_CACHE_VIRTUAL_ALIAS);
+#ifdef MULTIPROCESSOR
+	KASSERT(!CPU_IS_PRIMARY(curcpu()));
+#endif
+	load_addr += (intptr_t)ci - (intptr_t)&cpu_info_store;
+
+	KASSERT((intptr_t)ci <= load_addr);
+	KASSERT(load_addr < (intptr_t)(ci + 1));
+
+	KASSERT(INSN_LUI_P(new_insns[0]));
+	KASSERT(INSN_LOAD_P(new_insns[1]) || INSN_STORE_P(new_insns[1]));
+
+	/*
+	 * Use the lui and load/store instruction as a prototype and
+	 * make it refer to cpu1_info_store instead of cpu_info_store.
+	 */
+	new_insns[0] &= __BITS(31,16);
+	new_insns[1] &= __BITS(31,16);
+	new_insns[0] |= (uint16_t)((load_addr + 0x8000) >> 16);
+	new_insns[1] |= (uint16_t)load_addr;
+#ifdef DEBUG_VERBOSE
+	printf("%s: %08x: insn#1 %08x: lui r%u, %d\n",
+	    __func__, (int32_t)load_addr, new_insns[0],
+	    (new_insns[0] >> 16) & 31,
+	    (int16_t)new_insns[0]);
+	printf("%s: %08x: insn#2 %08x: %c%c r%u, %d(r%u)\n",
+	    __func__, (int32_t)load_addr, new_insns[0],
+	    INSN_LOAD_P(new_insns[1]) ? 'l' : 's',
+	    INSN_LW_P(new_insns[1]) ? 'w' : 'd',
+	    (new_insns[0] >> 16) & 31,
+	    (int16_t)new_insns[1],
+	    (new_insns[0] >> 21) & 31);
+#endif
+	return true;
+}
+
+static void
+octeon_cpu_init(struct cpu_info *ci)
+{
+	bool ok __diagused;
+
+	// First thing is setup the execption vectors for this cpu.
+	mips64r2_vector_init(&mips_splsw);
+
+	// Next rewrite those exceptions to use this cpu's cpu_info.
+	ok = mips_fixup_exceptions(octeon_fixup_cpu_info_references, ci);
+	KASSERT(ok);
+
+	(void) splhigh();
+
+#ifdef DEBUG
+	KASSERT((mipsNN_cp0_ebase_read() & MIPS_EBASE_CPUNUM) == ci->ci_cpuid);
+	KASSERT(curcpu() == ci);
+#endif
+}
+
+static void
+octeon_cpu_run(struct cpu_info *ci)
+{
+}
+#endif /* MULTIPROCESSOR */
+
+static void
+cpu_cpunode_attach_common(device_t self, struct cpu_info *ci)
+{
+	ci->ci_dev = self;
+	self->dv_private = ci;
+
+	aprint_normal(": %lu.%02luMHz (hz cycles = %lu, delay divisor = %lu)\n",
+	    ci->ci_cpu_freq / 1000000,
+	    (ci->ci_cpu_freq % 1000000) / 10000,
+	    ci->ci_cycles_per_hz, ci->ci_divisor_delay);
+
+	aprint_normal("%s: ", device_xname(self));
+	cpu_identify(self);
+	cpu_attach_common(self, ci);
+}
+
+void
+cpu_cpunode_attach(device_t parent, device_t self, void *aux)
+{
+	struct cpunode_attach_args * const cnaa = aux;
+	const int cpunum = cnaa->cnaa_cpunum;
+
+	if (cpunum == 0) {
+		cpu_cpunode_attach_common(self, curcpu());
+#ifdef MULTIPROCESSOR
+		mips_locoresw.lsw_cpu_init = octeon_cpu_init;
+		mips_locoresw.lsw_cpu_run = octeon_cpu_run;
+#endif
+		return;
+	}
+#ifdef MULTIPROCESSOR
+	KASSERTMSG(cpunum == 1, "cpunum %d", cpunum);
+	if (!CPUSET_HAS_P(cpus_booted, cpunum)) {
+		aprint_naive(" disabled\n");
+		aprint_normal(" disabled (unresponsive)\n");
+		return;
+	}
+	struct cpu_info * const ci = cpu_info_alloc(NULL, cpunum, 0, cpunum, 0);
+
+	ci->ci_softc = &octeon_cpu1_softc;
+	ci->ci_softc->cpu_ci = ci;
+
+	cpu_cpunode_attach_common(self, ci);
+#else
+	aprint_naive(": disabled\n");
+	aprint_normal(": disabled (uniprocessor kernel)\n");
+#endif
+}

Reply via email to