OpenBSD/sgi on octane2 - ipi割り込み

取り合えず実装してみたんだが、動いていない模様。
うーん。xheartのデータシートが欲しいよう。

HEART_INTR_IPI(x)はHEART_INTR_MAXよりデカいけど正しいのか分からない。
HEART_IMR(0)はHEART_IMR(cpu_number())に書き直した。

Index: xbow/xheartreg.h
===================================================================
--- xbow/xheartreg.h    (リビジョン 303)
+++ xbow/xheartreg.h    (作業コピー)
@@ -56,3 +56,5 @@

 #define        HEART_INTR_MAX          15
 #define        HEART_INTR_MIN          0
+
+#define HEART_INTR_IPI(x)      (46+(x))
Index: xbow/xheart.c
===================================================================
--- xbow/xheart.c       (リビジョン 371)
+++ xbow/xheart.c       (作業コピー)
@@ -265,6 +265,7 @@
        struct xheart_softc *sc = (void *)xheart_cd.cd_devs[0];
        struct intrhand *ih;
        paddr_t heart;
+       unsigned cpu = cpu_number();

 #ifdef DIAGNOSTIC
        if (intrbit < HEART_INTR_MIN || intrbit > HEART_INTR_MAX)
@@ -297,7 +298,7 @@

        /* XXX this assumes we run on cpu0 */
        heart = PHYS_TO_XKPHYS(HEART_PIU_BASE, CCA_NC);
-       *(volatile uint64_t *)(heart + HEART_IMR(0)) |= 1UL << intrbit;
+       *(volatile uint64_t *)(heart + HEART_IMR(cpu)) |= 1UL << intrbit;

        return 0;
 }
@@ -309,6 +310,7 @@
        struct intrhand *ih;
        paddr_t heart;
        int s;
+       unsigned cpu = cpu_number();

 #ifdef DIAGNOSTIC
        if (intrbit < HEART_INTR_MIN || intrbit > HEART_INTR_MAX)
@@ -324,7 +326,7 @@

        /* XXX this assumes we run on cpu0 */
        heart = PHYS_TO_XKPHYS(HEART_PIU_BASE, CCA_NC);
-       *(volatile uint64_t *)(heart + HEART_IMR(0)) &= ~(1UL << intrbit);
+       *(volatile uint64_t *)(heart + HEART_IMR(cpu)) &= ~(1UL << intrbit);

        intrhand[intrbit] = NULL;

@@ -418,10 +420,11 @@
        intrmask_t mask;
        struct intrhand *ih;
        int rc;
+       unsigned cpu = cpu_number();

        heart = PHYS_TO_XKPHYS(HEART_PIU_BASE, CCA_NC);
        isr = *(volatile uint64_t *)(heart + HEART_ISR);
-       imr = *(volatile uint64_t *)(heart + HEART_IMR(0));
+       imr = *(volatile uint64_t *)(heart + HEART_IMR(cpu));

        isr &= imr;
        if (isr == 0)
@@ -430,7 +433,7 @@
        /*
         * Mask all pending interrupts.
         */
-       *(volatile uint64_t *)(heart + HEART_IMR(0)) &= ~isr;
+       *(volatile uint64_t *)(heart + HEART_IMR(cpu)) &= ~isr;

        /*
         * If interrupts are spl-masked, mark them as pending only.
@@ -472,7 +475,7 @@
                /*
                 * Reenable interrupts which have been serviced.
                 */
-               *(volatile uint64_t *)(heart + HEART_IMR(0)) |= isr;
+               *(volatile uint64_t *)(heart + HEART_IMR(cpu)) |= isr;

                __asm__ (" .set noreorder\n");
                ci->ci_cpl = icpl;

xheart_intr_establishで割り込みハンドラを登録し、HEART_ISR_SET/HEART_ISR_CLRで割り込みをセット/クリアしているつもり。

void
mips64_ipi_init(void)
{
	unsigned cpu = cpu_number();

	xheart_intr_establish(mips64_ipi_intr, NULL,
	    1UL << HEART_INTR_IPI(cpu), IPL_HIGH, "ipi");
}

static int
mips64_ipi_intr(void *arg)
{
	paddr_t heart;
	u_long pending_ipis, bit, cpu = cpu_number();

	disableintr();

	if(!cpu)
		printf("mips64_ipi_intr\n");
	else
		combprintf("mips64_ipi_intr\n");

	/* Load the mailbox register to figure out what we're supposed to do */
	pending_ipis = smp_ipi_mailbox[cpu];

	/*
	 * For various reasons, it is possible to have spurious calls
	 * to this routine, so just bail out now if there are none
	 * pending.
	 */
	if (pending_ipis == 0) {
		enableintr();
		return 0;
	}

	for (bit = 0; bit < MIPS64_NIPIS; bit++)
		if (pending_ipis & (1UL << bit))
			(*ipifuncs[bit])();

	/* Clear the mailbox to clear the interrupt */
	atomic_clearbits_int(&smp_ipi_mailbox[cpu], pending_ipis);
	heart = PHYS_TO_XKPHYS(HEART_PIU_BASE, CCA_NC);
	*(volatile uint64_t*)(heart + HEART_ISR_CLR) = 
	    1UL << HEART_INTR_IPI(cpu);  
	enableintr();
	return 0;
}

void
mips64_send_ipi(unsigned cpu, unsigned ipimask)
{
	paddr_t heart;

#ifdef DIAGNOSTIC
	if (cpu >= CPU_MAXID ||
	    cpu_info[cpu] == NULL)
		panic("mips_send_ipi: bogus cpu_id");
	if (((1UL << cpu) & cpus_running) == 0)
		panic("mips_send_ipi: CPU %ld not running", cpu);
#endif
	atomic_setbits_int(&smp_ipi_mailbox[cpu], ipimask);
	heart = PHYS_TO_XKPHYS(HEART_PIU_BASE, CCA_NC);
	*(volatile uint64_t*)(heart + HEART_ISR_SET) =
	    1UL << HEART_INTR_IPI(cpu);
}

cpu_initclocks()は呼ばないようにしたのに、何故かcpu1へクロック割り込みが散発的に入っているようにみえるのも謎。
呼ばれてるハンドラが間違ってるだけで実はIPIが入っているのかも?しれない。
が、未だ確認出来てない。