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();