Module Name:    src
Committed By:   matt
Date:           Fri Mar 28 21:39:10 UTC 2014

Modified Files:
        src/sys/arch/arm/arm32: arm32_boot.c arm32_machdep.c cpu.c
        src/sys/arch/arm/cortex: gic.c gic_reg.h
        src/sys/arch/arm/include: locore.h
        src/sys/arch/arm/vfp: vfp_init.c

Log Message:
Various MP changes.


To generate a diff of this commit:
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/arm32/arm32_boot.c
cvs rdiff -u -r1.101 -r1.102 src/sys/arch/arm/arm32/arm32_machdep.c
cvs rdiff -u -r1.103 -r1.104 src/sys/arch/arm/arm32/cpu.c
cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/cortex/gic.c
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/arm/cortex/gic_reg.h
cvs rdiff -u -r1.15 -r1.16 src/sys/arch/arm/include/locore.h
cvs rdiff -u -r1.36 -r1.37 src/sys/arch/arm/vfp/vfp_init.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/arm/arm32/arm32_boot.c
diff -u src/sys/arch/arm/arm32/arm32_boot.c:1.6 src/sys/arch/arm/arm32/arm32_boot.c:1.7
--- src/sys/arch/arm/arm32/arm32_boot.c:1.6	Mon Mar  3 08:52:30 2014
+++ src/sys/arch/arm/arm32/arm32_boot.c	Fri Mar 28 21:39:09 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: arm32_boot.c,v 1.6 2014/03/03 08:52:30 matt Exp $	*/
+/*	$NetBSD: arm32_boot.c,v 1.7 2014/03/28 21:39:09 matt Exp $	*/
 
 /*
  * Copyright (c) 2002, 2003, 2005  Genetec Corporation.  All rights reserved.
@@ -123,7 +123,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(1, "$NetBSD: arm32_boot.c,v 1.6 2014/03/03 08:52:30 matt Exp $");
+__KERNEL_RCSID(1, "$NetBSD: arm32_boot.c,v 1.7 2014/03/28 21:39:09 matt Exp $");
 
 #include "opt_ddb.h"
 #include "opt_kgdb.h"
@@ -132,6 +132,8 @@ __KERNEL_RCSID(1, "$NetBSD: arm32_boot.c
 #include <sys/reboot.h>
 #include <sys/cpu.h>
 #include <sys/intr.h>
+#include <sys/atomic.h>
+#include <sys/device.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -320,19 +322,34 @@ cpu_hatch(struct cpu_info *ci, cpuid_t c
 	 */
 	splhigh();
 
+#ifdef VERBOSE_INIT_ARM
 	printf("%s(%s): ", __func__, ci->ci_data.cpu_name);
+#endif
+	uint32_t mpidr = armreg_mpidr_read();
+	if (mpidr & MPIDR_MT) {
+		ci->ci_data.cpu_smt_id = mpidr & MPIDR_AFF0;
+		ci->ci_data.cpu_core_id = mpidr & MPIDR_AFF1;
+		ci->ci_data.cpu_package_id = mpidr & MPIDR_AFF2;
+	} else {
+		ci->ci_data.cpu_core_id = mpidr & MPIDR_AFF0;
+		ci->ci_data.cpu_package_id = mpidr & MPIDR_AFF1;
+	}
 
 	/*
 	 * Make sure we have the right vector page.
 	 */
+#ifdef VERBOSE_INIT_ARM
 	printf(" vectors");
+#endif
 	arm32_vector_init(systempage.pv_va, ARM_VEC_ALL);
 
 	/*
-	 * Initialize the stack for each mode (we are already running on the SVC32
-	 * stack of the idlelwp).
+	 * Initialize the stack for each mode (we are already running on the
+	 * SVC32 stack of the idlelwp).
 	 */
+#ifdef VERBOSE_INIT_ARM
 	printf(" stacks");
+#endif
 	set_stackptr(PSR_FIQ32_MODE,
 	    fiqstack.pv_va + cpu_index(ci) * FIQ_STACK_SIZE * PAGE_SIZE);
 	set_stackptr(PSR_IRQ32_MODE,
@@ -345,13 +362,14 @@ cpu_hatch(struct cpu_info *ci, cpuid_t c
 	ci->ci_lastlwp = NULL;
 	ci->ci_pmap_lastuser = NULL;
 #ifdef ARM_MMU_EXTENDED
+#ifdef VERBOSE_INIT_ARM
 	printf(" tlb");
+#endif
 	/*
 	 * Attach to the tlb.
 	 */
 	ci->ci_pmap_cur = pmap_kernel();
 	ci->ci_pmap_asid_cur = KERNEL_PID;
-	pmap_tlb_info_attach(&pmap_tlb0_info, ci);
 #endif
 
 #ifdef CPU_CORTEX
@@ -364,24 +382,32 @@ cpu_hatch(struct cpu_info *ci, cpuid_t c
 	}
 #endif
 
+	aprint_naive("%s", device_xname(ci->ci_dev));
+	aprint_normal("%s", device_xname(ci->ci_dev));
+	identify_arm_cpu(ci->ci_dev, ci);
+#ifdef VERBOSE_INIT_ARM
+	printf(" vfp");
+#endif
+	vfp_attach(ci);
+
+#ifdef VERBOSE_INIT_ARM
 	printf(" interrupts");
+#endif
 	/*
 	 * Let the interrupts do what they need to on this CPU.
 	 */
 	intr_cpu_init(ci);
 
+#ifdef VERBOSE_INIT_ARM
 	printf(" md(%p)", md_cpu_init);
+#endif
 	if (md_cpu_init != NULL)
 		(*md_cpu_init)(ci);
 
-#if 0
-	/*
-	 * Tell the MI code we are alive!
-	 */
-	printf(" mi_cpu");
-	mi_cpu_running(ci);
-#endif
-
+#ifdef VERBOSE_INIT_ARM
 	printf(" done!\n");
+#endif
+	atomic_and_32(&arm_cpu_mbox, ~(1 << cpuid));
+	__asm __volatile("sev; sev; sev");
 }
 #endif /* MULTIPROCESSOR */

Index: src/sys/arch/arm/arm32/arm32_machdep.c
diff -u src/sys/arch/arm/arm32/arm32_machdep.c:1.101 src/sys/arch/arm/arm32/arm32_machdep.c:1.102
--- src/sys/arch/arm/arm32/arm32_machdep.c:1.101	Mon Mar  3 08:15:36 2014
+++ src/sys/arch/arm/arm32/arm32_machdep.c	Fri Mar 28 21:39:09 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: arm32_machdep.c,v 1.101 2014/03/03 08:15:36 matt Exp $	*/
+/*	$NetBSD: arm32_machdep.c,v 1.102 2014/03/28 21:39:09 matt Exp $	*/
 
 /*
  * Copyright (c) 1994-1998 Mark Brinicombe.
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: arm32_machdep.c,v 1.101 2014/03/03 08:15:36 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: arm32_machdep.c,v 1.102 2014/03/28 21:39:09 matt Exp $");
 
 #include "opt_modular.h"
 #include "opt_md.h"
@@ -683,16 +683,17 @@ cpu_uarea_alloc_idlelwp(struct cpu_info 
 void
 cpu_boot_secondary_processors(void)
 {
-	uint32_t mbox;
-	kcpuset_export_u32(kcpuset_attached, &mbox, sizeof(mbox));
-#ifdef VERBOSE_ARM_INIT
-	printf("%s: writing mbox with %#x\n", __func__, mbox);
+#ifdef VERBOSE_INIT_ARM
+	printf("%s: writing mbox with %#x\n", __func__, arm_cpu_hatched);
 #endif
-	atomic_swap_32(&arm_cpu_mbox, mbox);
+	arm_cpu_mbox = arm_cpu_hatched;
 	membar_producer();
 #ifdef _ARM_ARCH_7
 	__asm __volatile("sev; sev; sev");
 #endif
+	while (arm_cpu_mbox) {
+		__asm("wfe");
+	}
 }
 
 void
@@ -701,23 +702,7 @@ xc_send_ipi(struct cpu_info *ci)
 	KASSERT(kpreempt_disabled());
 	KASSERT(curcpu() != ci);
 
-
-	if (ci) {
-		/* Unicast, remote CPU */
-		printf("%s: -> %s", __func__, ci->ci_data.cpu_name);
-		intr_ipi_send(ci->ci_kcpuset, IPI_XCALL);
-	} else {
-		printf("%s: -> !%s", __func__, ci->ci_data.cpu_name);
-		/* Broadcast to all but ourselves */
-		kcpuset_t *kcp;
-		kcpuset_create(&kcp, (ci != NULL));
-		KASSERT(kcp != NULL);
-		kcpuset_copy(kcp, kcpuset_running);
-		kcpuset_clear(kcp, cpu_index(ci));
-		intr_ipi_send(kcp, IPI_XCALL);
-		kcpuset_destroy(kcp);
-	}
-	printf("\n");
+	intr_ipi_send(ci != NULL ? ci->ci_kcpuset : NULL, IPI_XCALL);
 }
 #endif /* MULTIPROCESSOR */
 

Index: src/sys/arch/arm/arm32/cpu.c
diff -u src/sys/arch/arm/arm32/cpu.c:1.103 src/sys/arch/arm/arm32/cpu.c:1.104
--- src/sys/arch/arm/arm32/cpu.c:1.103	Mon Mar 24 20:06:31 2014
+++ src/sys/arch/arm/arm32/cpu.c	Fri Mar 28 21:39:09 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: cpu.c,v 1.103 2014/03/24 20:06:31 christos Exp $	*/
+/*	$NetBSD: cpu.c,v 1.104 2014/03/28 21:39:09 matt Exp $	*/
 
 /*
  * Copyright (c) 1995 Mark Brinicombe.
@@ -46,7 +46,7 @@
 
 #include <sys/param.h>
 
-__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.103 2014/03/24 20:06:31 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.104 2014/03/28 21:39:09 matt Exp $");
 
 #include <sys/systm.h>
 #include <sys/conf.h>
@@ -64,15 +64,15 @@ extern const char *cpu_arch;
 
 #ifdef MULTIPROCESSOR
 volatile u_int arm_cpu_hatched = 0;
-u_int arm_cpu_max = 0;
-uint32_t arm_cpu_mbox __cacheline_aligned = 0;
-uint32_t arm_cpu_marker[2]  __cacheline_aligned = { 0, 0 };
+volatile uint32_t arm_cpu_mbox __cacheline_aligned = 0;
+uint32_t arm_cpu_marker[2] __cacheline_aligned = { 0, 0 };
+u_int arm_cpu_max = 1;
 #endif
 
 /* Prototypes */
-void identify_arm_cpu(device_t dv, struct cpu_info *);
-void identify_cortex_caches(device_t dv);
-void identify_features(device_t dv);
+void identify_arm_cpu(device_t, struct cpu_info *);
+void identify_cortex_caches(device_t);
+void identify_features(device_t);
 
 /*
  * Identify the master (boot) CPU
@@ -99,11 +99,22 @@ cpu_attach(device_t dv, cpuid_t id)
 		KASSERT(ci != NULL);
 		ci->ci_cpl = IPL_HIGH;
 		ci->ci_cpuid = id;
+		uint32_t mpidr = armreg_mpidr_read();
+		if (mpidr & MPIDR_MT) {
+			ci->ci_data.cpu_smt_id = mpidr & MPIDR_AFF0;
+			ci->ci_data.cpu_core_id = mpidr & MPIDR_AFF1;
+			ci->ci_data.cpu_package_id = mpidr & MPIDR_AFF2;
+		} else {
+			ci->ci_data.cpu_core_id = mpidr & MPIDR_AFF0;
+			ci->ci_data.cpu_package_id = mpidr & MPIDR_AFF1;
+		}
 		ci->ci_data.cpu_core_id = id;
 		ci->ci_data.cpu_cc_freq = cpu_info_store.ci_data.cpu_cc_freq;
 		ci->ci_arm_cpuid = cpu_info_store.ci_arm_cpuid;
 		ci->ci_arm_cputype = cpu_info_store.ci_arm_cputype;
 		ci->ci_arm_cpurev = cpu_info_store.ci_arm_cpurev;
+		ci->ci_ctrl = cpu_info_store.ci_ctrl;
+		ci->ci_undefsave[2] = cpu_info_store.ci_undefsave[2];
 		cpu_info[ci->ci_cpuid] = ci;
 		if ((arm_cpu_hatched & (1 << id)) == 0) {
 			ci->ci_dev = dv;
@@ -157,15 +168,27 @@ cpu_attach(device_t dv, cpuid_t id)
 	    NULL, xname, "permission abort (S)");
 	evcnt_attach_dynamic_nozero(&ci->ci_abt_evs[FAULT_PERM_P], EVCNT_TYPE_TRAP,
 	    NULL, xname, "permission abort (P)");
+	evcnt_attach_dynamic_nozero(&ci->ci_und_ev, EVCNT_TYPE_TRAP,
+	    NULL, xname, "undefined insn traps");
+	evcnt_attach_dynamic_nozero(&ci->ci_und_cp15_ev, EVCNT_TYPE_TRAP,
+	    NULL, xname, "undefined cp15 insn traps");
 
 #ifdef MULTIPROCESSOR
 	/*
 	 * and we are done if this is a secondary processor.
 	 */
-	if (!CPU_IS_PRIMARY(ci)) {
+	if (id != 0) {
+#if 1
+		aprint_naive("\n");
+		aprint_normal("\n");
+#else
 		aprint_naive(": %s\n", cpu_getmodel());
 		aprint_normal(": %s\n", cpu_getmodel());
+#endif
 		mi_cpu_attach(ci);
+#ifdef ARM_MMU_EXTENDED
+		pmap_tlb_info_attach(&pmap_tlb0_info, ci);
+#endif
 		return;
 	}
 #endif
@@ -204,7 +227,7 @@ cpu_attach(device_t dv, cpuid_t id)
  	}
 #endif
 
-	vfp_attach();		/* XXX SMP */
+	vfp_attach(ci);		/* XXX SMP */
 }
 
 enum cpu_class {
@@ -585,48 +608,58 @@ print_cache_info(device_t dv, struct arm
 	}
 }
 
+static enum cpu_class
+identify_arm_model(uint32_t cpuid, char *buf, size_t len)
+{
+	enum cpu_class cpu_class = CPU_CLASS_NONE;
+	for (const struct cpuidtab *id = cpuids; id->cpuid != 0; id++) {
+		if (id->cpuid == (cpuid & CPU_ID_CPU_MASK)) {
+			const char *steppingstr =
+			    id->cpu_steppings[cpuid & CPU_ID_REVISION_MASK];
+			cpu_arch = id->cpu_arch;
+			cpu_class = id->cpu_class;
+			snprintf(buf, len, "%s%s%s (%s V%s core)",
+			    id->cpu_classname,
+			    steppingstr[0] == '*' ? "" : " ",
+			    &steppingstr[steppingstr[0] == '*'],
+			    cpu_classes[cpu_class].class_name,
+			    cpu_arch);
+			return cpu_class;
+		}
+	}
+
+	snprintf(buf, len, "unknown CPU (ID = 0x%x)", cpuid);
+	return cpu_class;
+}
+
 void
 identify_arm_cpu(device_t dv, struct cpu_info *ci)
 {
-	enum cpu_class cpu_class = CPU_CLASS_NONE;
-	const u_int cpuid = ci->ci_arm_cpuid;
+	const uint32_t arm_cpuid = ci->ci_arm_cpuid;
 	const char * const xname = device_xname(dv);
-	const char *steppingstr;
-	int i;
+	char model[128];
 
-	if (cpuid == 0) {
+	if (arm_cpuid == 0) {
 		aprint_error("Processor failed probe - no CPU ID\n");
 		return;
 	}
 
-	for (i = 0; cpuids[i].cpuid != 0; i++)
-		if (cpuids[i].cpuid == (cpuid & CPU_ID_CPU_MASK)) {
-			cpu_class = cpuids[i].cpu_class;
-			cpu_arch = cpuids[i].cpu_arch;
-			steppingstr = cpuids[i].cpu_steppings[cpuid &
-			    CPU_ID_REVISION_MASK];
-			cpu_setmodel("%s%s%s (%s V%s core)",
-			    cpuids[i].cpu_classname,
-			    steppingstr[0] == '*' ? "" : " ",
-			    &steppingstr[steppingstr[0] == '*'],
-			    cpu_classes[cpu_class].class_name,
-			    cpu_arch);
-			break;
-		}
-
-	if (cpuids[i].cpuid == 0)
-		cpu_setmodel("unknown CPU (ID = 0x%x)", cpuid);
+	const enum cpu_class cpu_class = identify_arm_model(arm_cpuid,
+	     model, sizeof(model));
+	if (ci->ci_cpuid == 0) {
+		cpu_setmodel("%s", model);
+	}
 
 	if (ci->ci_data.cpu_cc_freq != 0) {
 		char freqbuf[8];
 		humanize_number(freqbuf, sizeof(freqbuf), ci->ci_data.cpu_cc_freq,
 		    "Hz", 1000);
 
-		aprint_naive(": %s %s\n", freqbuf, cpu_getmodel());
-		aprint_normal(": %s %s\n", freqbuf, cpu_getmodel());
+		aprint_naive(": %s %s\n", freqbuf, model);
+		aprint_normal(": %s %s\n", freqbuf, model);
 	} else {
-		aprint_naive(": %s\n", cpu_getmodel());
-		aprint_normal(": %s\n", cpu_getmodel());
+		aprint_naive(": %s\n", model);
+		aprint_normal(": %s\n", model);
 	}
 
 	aprint_normal("%s:", xname);
@@ -679,7 +712,7 @@ identify_arm_cpu(device_t dv, struct cpu
 
 	aprint_normal("\n");
 
-	if (CPU_ID_CORTEX_P(cpuid) || CPU_ID_ARM11_P(cpuid) || CPU_ID_MV88SV58XX_P(cpuid)) {
+	if (CPU_ID_CORTEX_P(arm_cpuid) || CPU_ID_ARM11_P(arm_cpuid) || CPU_ID_MV88SV58XX_P(arm_cpuid)) {
 		identify_features(dv);
 	}
 
@@ -791,6 +824,7 @@ identify_features(device_t dv)
 	cpu_memory_model_features[2] = armreg_mmfr2_read();
 	cpu_memory_model_features[3] = armreg_mmfr3_read();
 
+#if 0
 	if (__SHIFTOUT(cpu_memory_model_features[3], __BITS(23,20))) {
 		/*
 		 * Updates to the translation tables do not require a clean
@@ -799,6 +833,7 @@ identify_features(device_t dv)
 		 */
 		pmap_needs_pte_sync = 0;
 	}
+#endif
 
 	cpu_processor_features[0] = armreg_pfr0_read();
 	cpu_processor_features[1] = armreg_pfr1_read();

Index: src/sys/arch/arm/cortex/gic.c
diff -u src/sys/arch/arm/cortex/gic.c:1.6 src/sys/arch/arm/cortex/gic.c:1.7
--- src/sys/arch/arm/cortex/gic.c:1.6	Tue Mar  4 15:24:38 2014
+++ src/sys/arch/arm/cortex/gic.c	Fri Mar 28 21:39:09 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: gic.c,v 1.6 2014/03/04 15:24:38 matt Exp $	*/
+/*	$NetBSD: gic.c,v 1.7 2014/03/28 21:39:09 matt Exp $	*/
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -28,16 +28,19 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include "opt_ddb.h"
+
 #define _INTR_PRIVATE
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.6 2014/03/04 15:24:38 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.7 2014/03/28 21:39:09 matt Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
 #include <sys/device.h>
 #include <sys/evcnt.h>
 #include <sys/intr.h>
+#include <sys/cpu.h>
 #include <sys/proc.h>
 #include <sys/xcall.h>		/* for xc_ipi_handler */
 
@@ -92,6 +95,9 @@ static struct armgic_softc {
 	uint32_t sc_gic_type;
 	uint32_t sc_gic_valid_lines[1024/32];
 	uint32_t sc_enabled_local;
+#ifdef MULTIPROCESSOR
+	uint32_t sc_mptargets;
+#endif
 } armgic_softc = {
 	.sc_pic = {
 		.pic_ops = &armgic_picops,
@@ -341,6 +347,11 @@ armgic_establish_irq(struct pic_softc *p
 		 * to the primary cpu.
 		 */
 		targets &= ~(0xff << byte_shift);
+#ifdef MULTIPROCESSOR
+		if (is->is_mpsafe) {
+			targets |= sc->sc_mptargets;
+		} else
+#endif
 		targets |= 1 << byte_shift;
 		gicd_write(sc, targets_reg, targets);
 
@@ -361,6 +372,14 @@ armgic_establish_irq(struct pic_softc *p
 			    pic->pic_name, is->is_irq, cfg, new_cfg);
 #endif
 		}
+#ifdef MULTIPROCESSOR
+	} else {
+		/*
+		 * All group 0 interrupts are per processor and MPSAFE by
+		 * default.
+		 */
+		is->is_mpsafe = true;
+#endif
 	}
 
 	/* 
@@ -411,18 +430,42 @@ armgic_cpu_init_priorities(struct armgic
 	}
 }
 
+static void
+armgic_cpu_init_targets(struct armgic_softc *sc)
+{
+	/*
+	 * Update the mpsafe targets 
+	 */
+	for (size_t irq = 32; irq < sc->sc_gic_lines; irq++) {
+		struct intrsource * const is = sc->sc_pic.pic_sources[irq];
+		const bus_size_t targets_reg = GICD_ITARGETSRn(irq / 4);
+		if (is != NULL && is->is_mpsafe) {
+			const u_int byte_shift = 0xff << (8 * (irq & 3));
+			uint32_t targets = gicd_read(sc, targets_reg);
+			targets |= sc->sc_mptargets << byte_shift;
+			gicd_write(sc, targets_reg, targets);
+		}
+	}
+}
+
 void
 armgic_cpu_init(struct pic_softc *pic, struct cpu_info *ci)
 {
 	struct armgic_softc * const sc = PICTOSOFTC(pic);
-	if (!CPU_IS_PRIMARY(ci) && sc->sc_enabled_local) {
-		armgic_cpu_init_priorities(sc);
-	}
+	sc->sc_mptargets |= 1 << cpu_index(ci);
 	KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl);
+	if (!CPU_IS_PRIMARY(ci)) {
+		if (sc->sc_mptargets != 1) {
+			armgic_cpu_init_targets(sc);
+		}
+		if (sc->sc_enabled_local) {
+			armgic_cpu_init_priorities(sc);
+			gicd_write(sc, GICD_ISENABLERn(0),
+			    sc->sc_enabled_local);
+		}
+	}
 	gicc_write(sc, GICC_PMR, armgic_ipl_to_priority(ci->ci_cpl));	// set PMR
 	gicc_write(sc, GICC_CTRL, GICC_CTRL_V1_Enable);	// enable interrupt
-	if (!CPU_IS_PRIMARY(ci) && sc->sc_enabled_local)
-		gicd_write(sc, GICD_ISENABLERn(0), sc->sc_enabled_local);
 	cpsie(I32_bit);					// allow IRQ exceptions
 }
 
@@ -431,19 +474,28 @@ armgic_ipi_send(struct pic_softc *pic, c
 {
 	struct armgic_softc * const sc = PICTOSOFTC(pic);
 
+#if 0
 	if (ipi == IPI_NOP) {
 		__asm __volatile("sev");
 		return;
 	}
+#endif
 
-	uint32_t targets;
-	kcpuset_export_u32(kcp, &targets, sizeof(targets));
-	uint32_t sgir = __SHIFTOUT(ARMGIC_SGI_IPIBASE + ipi, GICD_SGIR_SGIINTID);
-	sgir |= __SHIFTOUT(targets, GICD_SGIR_TargetList);
+	uint32_t sgir = __SHIFTIN(ARMGIC_SGI_IPIBASE + ipi, GICD_SGIR_SGIINTID);
+	if (kcp != NULL) {
+		uint32_t targets;
+		kcpuset_export_u32(kcp, &targets, sizeof(targets));
+		sgir |= __SHIFTIN(targets, GICD_SGIR_TargetList);
+		sgir |= GICD_SGIR_TargetListFilter_List;
+	} else {
+		if (ncpu == 1)
+			return;
+		sgir |= GICD_SGIR_TargetListFilter_NotMe;
+	}
 
-	printf("%s: %s: %#x", __func__, curcpu()->ci_data.cpu_name, sgir);
+	//printf("%s: %s: %#x", __func__, curcpu()->ci_data.cpu_name, sgir);
 	gicd_write(sc, GICD_SGIR, sgir);
-	printf("\n");
+	//printf("\n");
 }
 #endif
 
@@ -553,9 +605,13 @@ armgic_attach(device_t parent, device_t 
 	    pic_ipi_nop, (void *)-1);
 	intr_establish(ARMGIC_SGI_IPIBASE + IPI_XCALL, IPL_VM, IST_EDGE,
 	    pic_ipi_xcall, (void *)-1);
-#if 0	/* Not needed */
 	intr_establish(ARMGIC_SGI_IPIBASE + IPI_NOP, IPL_VM, IST_EDGE,
 	    pic_ipi_nop, (void *)-1);
+	intr_establish(ARMGIC_SGI_IPIBASE + IPI_SHOOTDOWN, IPL_VM, IST_EDGE,
+	    pic_ipi_shootdown, (void *)-1);
+#ifdef DDB
+	intr_establish(ARMGIC_SGI_IPIBASE + IPI_DDB, IPL_HIGH, IST_EDGE,
+	    pic_ipi_ddb, NULL);
 #endif
 #ifdef __HAVE_PREEMPTION
 	intr_establish(ARMGIC_SGI_IPIBASE + IPI_KPREEMPT, IPL_VM, IST_EDGE,

Index: src/sys/arch/arm/cortex/gic_reg.h
diff -u src/sys/arch/arm/cortex/gic_reg.h:1.1 src/sys/arch/arm/cortex/gic_reg.h:1.2
--- src/sys/arch/arm/cortex/gic_reg.h:1.1	Sat Sep  1 00:03:14 2012
+++ src/sys/arch/arm/cortex/gic_reg.h	Fri Mar 28 21:39:09 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: gic_reg.h,v 1.1 2012/09/01 00:03:14 matt Exp $	*/
+/*	$NetBSD: gic_reg.h,v 1.2 2014/03/28 21:39:09 matt Exp $	*/
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -199,4 +199,14 @@
 #define	GICv1_ICCHPIR		GICC_HPPIR
 #define	GICv1_ICCIIDR		GICC_IIDR
 
+/* GICv2m (MSI) */
+
+#define GIC_MSI_TYPER		0x0008
+#define GIC_MSI_SETSPI		0x0040
+#define GIC_MSI_PIDR2		0x0fe8
+#define GIC_MSI_IIDR		0x0ffc
+
+#define GIC_MSI_TYPER_BASE	__BITS(25,16)	// Starting SPI of MSIs
+#define GIC_MSI_TYPER_NUMBER	__BITS(9,0)	// Count of MSIs
+
 #endif /* !_ARM_CORTEX_GICREG_H_ */

Index: src/sys/arch/arm/include/locore.h
diff -u src/sys/arch/arm/include/locore.h:1.15 src/sys/arch/arm/include/locore.h:1.16
--- src/sys/arch/arm/include/locore.h:1.15	Tue Mar 18 07:05:46 2014
+++ src/sys/arch/arm/include/locore.h	Fri Mar 28 21:39:09 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: locore.h,v 1.15 2014/03/18 07:05:46 matt Exp $	*/
+/*	$NetBSD: locore.h,v 1.16 2014/03/28 21:39:09 matt Exp $	*/
 
 /*
  * Copyright (c) 1994-1996 Mark Brinicombe.
@@ -164,7 +164,11 @@ extern int cpu_memory_model_features[4];
 extern int cpu_processor_features[2];
 extern int cpu_media_and_vfp_features[2];
 
+extern bool arm_has_tlbiasid_p;
+#ifdef MULTIPROCESSOR
 extern u_int arm_cpu_max;
+extern volatile u_int arm_cpu_hatched;
+#endif
 
 #if !defined(CPU_ARMV7)
 #define	CPU_IS_ARMV7_P()		false
@@ -229,15 +233,41 @@ read_thumb_insn(vaddr_t va, bool user_p)
 	return insn;
 }
 
+static inline void
+arm_dmb(void)
+{
+	if (CPU_IS_ARMV6_P())
+		armreg_dmb_write(0);
+	else if (CPU_IS_ARMV7_P())
+		__asm __volatile("dmb");
+}
+
+static inline void
+arm_dsb(void)
+{
+	if (CPU_IS_ARMV6_P())
+		armreg_dsb_write(0);
+	else if (CPU_IS_ARMV7_P())
+		__asm __volatile("dsb");
+}
+
+static inline void
+arm_isb(void)
+{
+	if (CPU_IS_ARMV6_P())
+		armreg_isb_write(0);
+	else if (CPU_IS_ARMV7_P())
+		__asm __volatile("isb");
+}
+
 /*
  * Random cruft
  */
 
 struct lwp;
 
-/* locore.S */
-void atomic_set_bit(u_int *, u_int);
-void atomic_clear_bit(u_int *, u_int);
+/* cpu.c */
+void	identify_arm_cpu(device_t, struct cpu_info *);
 
 /* cpuswitch.S */
 struct pcb;
@@ -259,7 +289,7 @@ void	swi_handler(trapframe_t *);
 void	ucas_ras_check(trapframe_t *);
 
 /* vfp_init.c */
-void	vfp_attach(void);
+void	vfp_attach(struct cpu_info *);
 void	vfp_discardcontext(bool);
 void	vfp_savecontext(void);
 void	vfp_kernel_acquire(void);

Index: src/sys/arch/arm/vfp/vfp_init.c
diff -u src/sys/arch/arm/vfp/vfp_init.c:1.36 src/sys/arch/arm/vfp/vfp_init.c:1.37
--- src/sys/arch/arm/vfp/vfp_init.c:1.36	Tue Mar 18 07:03:22 2014
+++ src/sys/arch/arm/vfp/vfp_init.c	Fri Mar 28 21:39:09 2014
@@ -1,4 +1,4 @@
-/*      $NetBSD: vfp_init.c,v 1.36 2014/03/18 07:03:22 matt Exp $ */
+/*      $NetBSD: vfp_init.c,v 1.37 2014/03/28 21:39:09 matt Exp $ */
 
 /*
  * Copyright (c) 2008 ARM Ltd
@@ -141,10 +141,6 @@ const pcu_ops_t arm_vfp_ops = {
 	.pcu_state_release = vfp_state_release,
 };
 
-struct evcnt vfpevent_use;
-struct evcnt vfpevent_reuse;
-struct evcnt vfpevent_fpe;
-
 /* determine what bits can be changed */
 uint32_t vfp_fpscr_changable = VFP_FPSCR_CSUM;
 /* default to run fast */
@@ -173,10 +169,6 @@ vfp_test(u_int address, u_int insn, trap
 uint32_t vfp_fpscr_changable = VFP_FPSCR_CSUM|VFP_FPSCR_ESUM|VFP_FPSCR_RMODE;
 #endif /* FPU_VFP */
 
-struct evcnt vfp_fpscr_ev = 
-    EVCNT_INITIALIZER(EVCNT_TYPE_TRAP, NULL, "VFP", "FPSCR traps");
-EVCNT_ATTACH_STATIC(vfp_fpscr_ev);
-
 static int
 vfp_fpscr_handler(u_int address, u_int insn, trapframe_t *frame, int fault_code)
 {
@@ -216,7 +208,7 @@ vfp_fpscr_handler(u_int address, u_int i
 		pcb->pcb_vfp.vfp_fpscr |= *regp & vfp_fpscr_changable;
 	}
 
-	vfp_fpscr_ev.ev_count++;
+	curcpu()->ci_vfp_evs[0].ev_count++;
 		
 	frame->tf_pc += INSN_SIZE;
 	return 0;
@@ -228,50 +220,37 @@ vfp_fpscr_handler(u_int address, u_int i
  * instructions.
  */
 void
-vfp_attach(void)
-{
-	install_coproc_handler(VFP_COPROC, vfp_fpscr_handler);
-}
-
-#else
-#if 0
-static bool
-vfp_patch_branch(uintptr_t code, uintptr_t func, uintptr_t newfunc)
+vfp_attach(struct cpu_info *ci)
 {
-	for (;; code += sizeof(uint32_t)) {
-		uint32_t insn = *(uint32_t *)code; 
-		if ((insn & 0xffd08000) == 0xe8908000)	/* ldm ... { pc } */
-			return false;
-		if ((insn & 0xfffffff0) == 0xe12fff10)	/* bx rN */
-			return false;
-		if ((insn & 0xf1a0f000) == 0xe1a0f000)	/* mov pc, ... */
-			return false;
-		if ((insn >> 25) != 0x75)		/* not b/bl insn */
-			continue;
-		intptr_t imm26 = ((int32_t)insn << 8) >> 6;
-		if (code + imm26 + 8 == func) {
-			int32_t imm24 = (newfunc - (code + 8)) >> 2;
-			uint32_t new_insn = (insn & 0xff000000)
-			   | (imm24 & 0xffffff);
-			KASSERTMSG((uint32_t)((imm24 >> 24) + 1) <= 1, "%x",
-			    ((imm24 >> 24) + 1));
-			*(uint32_t *)code = new_insn;
-			cpu_idcache_wbinv_range(code, sizeof(uint32_t));
-			return true;
-		}
+	if (CPU_IS_PRIMARY(ci)) {
+		install_coproc_handler(VFP_COPROC, vfp_fpscr_handler);
 	}
+	evcnt_attach_dynamic(&ci->ci_vfp_evs[0], EVCNT_TYPE_TRAP, NULL,
+	    ci->ci_cpuname, "vfp fpscr traps");
 }
-#endif
 
+#else
 void
-vfp_attach(void)
+vfp_attach(struct cpu_info *ci)
 {
-	struct cpu_info * const ci = curcpu();
 	const char *model = NULL;
 
-	if (CPU_ID_ARM11_P(curcpu()->ci_arm_cpuid)
-	    || CPU_ID_MV88SV58XX_P(curcpu()->ci_arm_cpuid)
-	    || CPU_ID_CORTEX_P(curcpu()->ci_arm_cpuid)) {
+	if (CPU_ID_ARM11_P(ci->ci_arm_cpuid)
+	    || CPU_ID_MV88SV58XX_P(ci->ci_arm_cpuid)
+	    || CPU_ID_CORTEX_P(ci->ci_arm_cpuid)) {
+#if 0
+		const uint32_t nsacr = armreg_nsacr_read();
+		const uint32_t nsacr_vfp = __BITS(VFP_COPROC,VFP_COPROC2);
+		if ((nsacr & nsacr_vfp) != nsacr_vfp) {
+			aprint_normal_dev(ci->ci_dev, "VFP access denied\n");
+			install_coproc_handler(VFP_COPROC, vfp_fpscr_handler);
+			ci->ci_vfp_id = 0;
+			evcnt_attach_dynamic(&ci->ci_vfp_evs[0],
+			    EVCNT_TYPE_TRAP, NULL, ci->ci_cpuname,
+			    "vfp fpscr traps");
+			return;
+		}
+#endif
 		const uint32_t cpacr_vfp = CPACR_CPn(VFP_COPROC);
 		const uint32_t cpacr_vfp2 = CPACR_CPn(VFP_COPROC2);
 
@@ -281,15 +260,6 @@ vfp_attach(void)
 		uint32_t cpacr = armreg_cpacr_read();
 		cpacr |= __SHIFTIN(CPACR_ALL, cpacr_vfp);
 		cpacr |= __SHIFTIN(CPACR_ALL, cpacr_vfp2);
-#if 0
-		if (CPU_ID_CORTEX_P(curcpu()->ci_arm_cpuid)) {
-			/*
-			 * Disable access to the upper 16 FP registers and NEON.
-			 */
-			cpacr |= CPACR_V7_D32DIS;
-			cpacr |= CPACR_V7_ASEDIS;
-		}
-#endif
 		armreg_cpacr_write(cpacr);
 
 		/*
@@ -302,6 +272,9 @@ vfp_attach(void)
 			aprint_normal_dev(ci->ci_dev, "No VFP detected\n");
 			install_coproc_handler(VFP_COPROC, vfp_fpscr_handler);
 			ci->ci_vfp_id = 0;
+			evcnt_attach_dynamic(&ci->ci_vfp_evs[0],
+			    EVCNT_TYPE_TRAP, NULL, ci->ci_cpuname,
+			    "vfp fpscr traps");
 			return;
 		}
 	}
@@ -337,8 +310,12 @@ vfp_attach(void)
 	case FPU_VFP_CORTEXA8:
 	case FPU_VFP_CORTEXA9:
 	case FPU_VFP_CORTEXA15:
-		model = "NEON MPE (VFP 3.0+)";
-		cpu_neon_present = 1;
+		if (armreg_cpacr_read() & CPACR_V7_ASEDIS) {
+			model = "VFP 4.0+";
+		} else {
+			model = "NEON MPE (VFP 3.0+)";
+			cpu_neon_present = 1;
+		}
 		break;
 	default:
 		aprint_normal_dev(ci->ci_dev, "unrecognized VFP version %#x\n",
@@ -357,50 +334,45 @@ vfp_attach(void)
 		uint32_t f0 = armreg_mvfr0_read();
 		uint32_t f1 = armreg_mvfr0_read();
 		aprint_normal("vfp%d at %s: %s%s%s%s%s\n",
-		    device_unit(curcpu()->ci_dev),
-		    device_xname(curcpu()->ci_dev),
+		    device_unit(ci->ci_dev),
+		    device_xname(ci->ci_dev),
 		    model,
 		    ((f0 & ARM_MVFR0_ROUNDING_MASK) ? ", rounding" : ""),
 		    ((f0 & ARM_MVFR0_EXCEPT_MASK) ? ", exceptions" : ""),
 		    ((f1 & ARM_MVFR1_D_NAN_MASK) ? ", NaN propogation" : ""),
 		    ((f1 & ARM_MVFR1_FTZ_MASK) ? ", denormals" : ""));
 		aprint_verbose("vfp%d: mvfr: [0]=%#x [1]=%#x\n",
-		    device_unit(curcpu()->ci_dev), f0, f1);
-		if (cpu_media_and_vfp_features[0] & ARM_MVFR0_ROUNDING_MASK) {
-			vfp_fpscr_changable |= VFP_FPSCR_RMODE;
-		}
-		if (cpu_media_and_vfp_features[0] & ARM_MVFR0_EXCEPT_MASK) {
-			vfp_fpscr_changable |= VFP_FPSCR_ESUM;
-		}
-		// If hardware supports propogation of NaNs, select it.
-		if (cpu_media_and_vfp_features[1] & ARM_MVFR1_D_NAN_MASK) {
-			vfp_fpscr_default &= ~VFP_FPSCR_DN;
-			vfp_fpscr_changable |= VFP_FPSCR_DN;
-		}
-		// If hardware supports denormalized numbers, use it.
-		if (cpu_media_and_vfp_features[1] & ARM_MVFR1_FTZ_MASK) {
-			vfp_fpscr_default &= ~VFP_FPSCR_FZ;
-			vfp_fpscr_changable |= VFP_FPSCR_FZ;
-		}
-	}
-	evcnt_attach_dynamic(&vfpevent_use, EVCNT_TYPE_MISC, NULL,
-	    "VFP", "coproc use");
-	evcnt_attach_dynamic(&vfpevent_reuse, EVCNT_TYPE_MISC, NULL,
-	    "VFP", "coproc re-use");
-	evcnt_attach_dynamic(&vfpevent_fpe, EVCNT_TYPE_TRAP, NULL,
-	    "VFP", "coproc fault");
+		    device_unit(ci->ci_dev), f0, f1);
+		if (CPU_IS_PRIMARY(ci)) {
+			if (f0 & ARM_MVFR0_ROUNDING_MASK) {
+				vfp_fpscr_changable |= VFP_FPSCR_RMODE;
+			}
+			if (f1 & ARM_MVFR0_EXCEPT_MASK) {
+				vfp_fpscr_changable |= VFP_FPSCR_ESUM;
+			}
+			// If hardware supports propogation of NaNs, select it.
+			if (f1 & ARM_MVFR1_D_NAN_MASK) {
+				vfp_fpscr_default &= ~VFP_FPSCR_DN;
+				vfp_fpscr_changable |= VFP_FPSCR_DN;
+			}
+			// If hardware supports denormalized numbers, use it.
+			if (cpu_media_and_vfp_features[1] & ARM_MVFR1_FTZ_MASK) {
+				vfp_fpscr_default &= ~VFP_FPSCR_FZ;
+				vfp_fpscr_changable |= VFP_FPSCR_FZ;
+			}
+		}
+	}
+	evcnt_attach_dynamic(&ci->ci_vfp_evs[0], EVCNT_TYPE_MISC, NULL,
+	    ci->ci_cpuname, "vfp coproc use");
+	evcnt_attach_dynamic(&ci->ci_vfp_evs[1], EVCNT_TYPE_MISC, NULL,
+	    ci->ci_cpuname, "vfp coproc re-use");
+	evcnt_attach_dynamic(&ci->ci_vfp_evs[2], EVCNT_TYPE_TRAP, NULL,
+	    ci->ci_cpuname, "vfp coproc fault");
 	install_coproc_handler(VFP_COPROC, vfp_handler);
 	install_coproc_handler(VFP_COPROC2, vfp_handler);
 #ifdef CPU_CORTEX
 	install_coproc_handler(CORE_UNKNOWN_HANDLER, neon_handler);
 #endif
-
-#if 0
-	vfp_patch_branch((uintptr_t)pmap_copy_page_generic,
-	   (uintptr_t)bcopy_page, (uintptr_t)bcopy_page_vfp);
-	vfp_patch_branch((uintptr_t)pmap_zero_page_generic,
-	   (uintptr_t)bzero_page, (uintptr_t)bzero_page_vfp);
-#endif
 }
 
 /* The real handler for VFP bounces.  */
@@ -434,7 +406,7 @@ vfp_handler(u_int address, u_int insn, t
 		ksiginfo_t ksi;
 		KASSERT(fpexc & VFP_FPEXC_EN);
 
-		vfpevent_fpe.ev_count++;
+		curcpu()->ci_vfp_evs[2].ev_count++;
 
 		/*
 		 * Need the clear the exception condition so any signal
@@ -533,10 +505,10 @@ vfp_state_load(lwp_t *l, u_int flags)
 	 */
 	if (__predict_false((flags & PCU_LOADED) == 0)) {
 		KASSERT(flags & PCU_RELOAD);
-		vfpevent_use.ev_count++;
+		curcpu()->ci_vfp_evs[0].ev_count++;
 		pcb->pcb_vfp.vfp_fpscr = vfp_fpscr_default;
 	} else {
-		vfpevent_reuse.ev_count++;
+		curcpu()->ci_vfp_evs[1].ev_count++;
 	}
 
 	uint32_t fpexc = armreg_fpexc_read();

Reply via email to