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
+}