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が入っているのかも?しれない。
が、未だ確認出来てない。