Index: sys/arm/arm/generic_timer.c =================================================================== --- sys/arm/arm/generic_timer.c +++ sys/arm/arm/generic_timer.c @@ -86,6 +86,7 @@ uint32_t clkfreq; struct eventtimer et; bool physical; + uint32_t irq_is_initialized[MAXCPU]; }; static struct arm_tmr_softc *arm_tmr_sc = NULL; @@ -199,6 +200,23 @@ return (get_cntxct(arm_tmr_sc->physical)); } +static void +arm_tmr_init_secondary(struct arm_tmr_softc * sc) +{ + int i; + + /* Ensure irq_is_initialized[0] is observable */ + rmb(); + + /* Check if interrupt was initialized */ + if (__predict_false(sc->irq_is_initialized[0] == 0)) + panic("TMR intr was not initialized on CPU0"); + + /* Unmask interrupts on secondary core */ + for (i = 0; i < 3; i++) + arm_unmask_irq(rman_get_start(sc->res[i])); +} + static int arm_tmr_start(struct eventtimer *et, sbintime_t first, sbintime_t period) { @@ -207,6 +225,13 @@ sc = (struct arm_tmr_softc *)et->et_priv; + /* + * Check if timer is initialized on current CPU. + * If not, run init_secondary. + */ + if (atomic_cmpset_32(&sc->irq_is_initialized[curcpu], 0, 1)) + arm_tmr_init_secondary(sc); + if (first != 0) { counts = ((uint32_t)et->et_frequency * first) >> 32; ctrl = get_ctrl(sc->physical); @@ -381,6 +406,10 @@ } } + /* Mark the interrupt as irq_is_initialized and ensure visibility */ + sc->irq_is_initialized[curcpu] = 1; + wmb(); + disable_user_access(); arm_tmr_timecount.tc_frequency = sc->clkfreq; Index: sys/arm64/arm64/intr_machdep.c =================================================================== --- sys/arm64/arm64/intr_machdep.c +++ sys/arm64/arm64/intr_machdep.c @@ -446,6 +446,13 @@ critical_exit(); } +void +arm_unmask_irq(u_int irq) +{ + + PIC_UNMASK(root_pic, irq); +} + #ifdef SMP void arm_setup_ipihandler(driver_filter_t *filt, u_int ipi)