Ejemplo n.º 1
0
void
cpu_intr(struct trapframe *tf)
{
	struct intr_event *event;
	register_t cause, status;
	int hard, i, intr;

	critical_enter();

	cause = mips_rd_cause();
	status = mips_rd_status();
	intr = (cause & MIPS_INT_MASK) >> 8;
	/*
	 * Do not handle masked interrupts. They were masked by 
	 * pre_ithread function (mips_mask_XXX_intr) and will be 
	 * unmasked once ithread is through with handler
	 */
	intr &= (status & MIPS_INT_MASK) >> 8;
	while ((i = fls(intr)) != 0) {
		intr &= ~(1 << (i - 1));
		switch (i) {
		case 1: case 2:
			/* Software interrupt. */
			i--; /* Get a 0-offset interrupt. */
			hard = 0;
			event = softintr_events[i];
			mips_intrcnt_inc(mips_intr_counters[i]);
			break;
		default:
			/* Hardware interrupt. */
			i -= 2; /* Trim software interrupt bits. */
			i--; /* Get a 0-offset interrupt. */
			hard = 1;
			event = hardintr_events[i];
			mips_intrcnt_inc(mips_intr_counters[NSOFT_IRQS + i]);
			break;
		}

		if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
			printf("stray %s interrupt %d\n",
			    hard ? "hard" : "soft", i);
			continue;
		}

		if (intr_event_handle(event, tf) != 0) {
			printf("stray %s interrupt %d\n", 
			    hard ? "hard" : "soft", i);
		}
	}

	KASSERT(i == 0, ("all interrupts handled"));

	critical_exit();

#ifdef HWPMC_HOOKS
	if (pmc_hook && (PCPU_GET(curthread)->td_pflags & TDP_CALLCHAIN))
		pmc_hook(PCPU_GET(curthread), PMC_FN_USER_CALLCHAIN, tf);
#endif
}
Ejemplo n.º 2
0
static int
apb_filter(void *arg)
{
	struct apb_softc *sc = arg;
	struct intr_event *event;
	uint32_t reg, irq;
	struct thread *td;
	struct trapframe *tf;

	reg = ATH_READ_REG(AR71XX_MISC_INTR_STATUS);
	for (irq = 0; irq < APB_NIRQS; irq++) {
		if (reg & (1 << irq)) {

			switch (ar71xx_soc) {
			case AR71XX_SOC_AR7240:
			case AR71XX_SOC_AR7241:
			case AR71XX_SOC_AR7242:
			case AR71XX_SOC_AR9330:
			case AR71XX_SOC_AR9331:
			case AR71XX_SOC_AR9341:
			case AR71XX_SOC_AR9342:
			case AR71XX_SOC_AR9344:
				/* ACK/clear the given interrupt */
				ATH_WRITE_REG(AR71XX_MISC_INTR_STATUS,
				    (1 << irq));
				break;
			default:
				/* fallthrough */
				break;
			}

			event = sc->sc_eventstab[irq];
			if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
				if (irq == APB_INTR_PMC) {
					td = PCPU_GET(curthread);
					tf = td->td_intr_frame;

					if (pmc_intr)
						(*pmc_intr)(PCPU_GET(cpuid), tf);

					mips_intrcnt_inc(sc->sc_intr_counter[irq]);

					continue;
				}
				/* Ignore timer interrupts */
				if (irq != 0 && irq != 8 && irq != 9 && irq != 10)
					printf("Stray APB IRQ %d\n", irq);
				continue;
			}

			intr_event_handle(event, PCPU_GET(curthread)->td_intr_frame);
			mips_intrcnt_inc(sc->sc_intr_counter[irq]);
		}
	}

	return (FILTER_HANDLED);
}
Ejemplo n.º 3
0
Archivo: ciu.c Proyecto: coyizumi/cs111
static int
ciu_intr(void *arg)
{
	struct ciu_softc *sc;
	uint64_t en0_sum, en1_sum;
	uint64_t en0_mask, en1_mask;
	int irq_index;
	int error;

	sc = arg;
	(void)sc;

	en0_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(cvmx_get_core_num()*2));
	en1_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1);

	en0_mask = cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num()*2));
	en1_mask = cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num()*2));

	en0_sum &= en0_mask;
	en1_sum &= en1_mask;

	if (en0_sum == 0 && en1_sum == 0)
		return (FILTER_STRAY);

	irq_index = 0;
	for (irq_index = 0; en0_sum != 0; irq_index++, en0_sum >>= 1) {
		if ((en0_sum & 1) == 0)
			continue;

		mips_intrcnt_inc(ciu_en0_intrcnt[irq_index]);

		error = intr_event_handle(ciu_en0_intr_events[irq_index], NULL);
		if (error != 0)
			printf("%s: stray en0 irq%d\n", __func__, irq_index);
	}

	irq_index = 0;
	for (irq_index = 0; en1_sum != 0; irq_index++, en1_sum >>= 1) {
		if ((en1_sum & 1) == 0)
			continue;

		mips_intrcnt_inc(ciu_en1_intrcnt[irq_index]);

		error = intr_event_handle(ciu_en1_intr_events[irq_index], NULL);
		if (error != 0)
			printf("%s: stray en1 irq%d\n", __func__, irq_index);
	}

	return (FILTER_HANDLED);
}
Ejemplo n.º 4
0
void
cpu_intr(struct trapframe *tf)
{
	struct intr_event *ie;
	uint64_t eirr, eimr;
	int i;

	critical_enter();

	/* find a list of enabled interrupts */
	eirr = read_c0_eirr64();
	eimr = read_c0_eimr64();
	eirr &= eimr;
	
	if (eirr == 0) { 
		critical_exit();
		return;
	}
	/*
	 * No need to clear the EIRR here as the handler writes to
	 * compare which ACKs the interrupt.
	 */
	if (eirr & (1 << IRQ_TIMER)) {
		intr_event_handle(xlr_interrupts[IRQ_TIMER].ie, tf);
		critical_exit();
		return;
	}
	
	/* FIXME sched pin >? LOCK>? */
	for (i = sizeof(eirr) * 8 - 1; i >= 0; i--) {
		if ((eirr & (1ULL << i)) == 0)
			continue;

		ie = xlr_interrupts[i].ie;
		/* Don't account special IRQs */
		switch (i) {
		case IRQ_IPI:
		case IRQ_MSGRING:
			break;
		default:
			mips_intrcnt_inc(mips_intr_counters[i]);
		}

		/* Ack the IRQ on the CPU */
		write_c0_eirr64(1ULL << i);
		if (intr_event_handle(ie, tf) != 0) {
			printf("stray interrupt %d\n", i);
		}
	}
	critical_exit();
}
Ejemplo n.º 5
0
static int
apb_filter(void *arg)
{
	struct apb_softc *sc = arg;
	struct intr_event *event;
	uint32_t reg, irq;

	if(ar531x_soc >= AR531X_SOC_AR5315)
		reg = ATH_READ_REG(AR5315_SYSREG_BASE +
			AR5315_SYSREG_MISC_INTSTAT);
	else
		reg = ATH_READ_REG(AR5312_SYSREG_BASE +
			AR5312_SYSREG_MISC_INTSTAT);

	for (irq = 0; irq < APB_NIRQS; irq++) {
		if (reg & (1 << irq)) {

			if(ar531x_soc >= AR531X_SOC_AR5315) {
				ATH_WRITE_REG(AR5315_SYSREG_BASE +
				    AR5315_SYSREG_MISC_INTSTAT,
				    reg & ~(1 << irq));
			} else {
				ATH_WRITE_REG(AR5312_SYSREG_BASE +
				    AR5312_SYSREG_MISC_INTSTAT,
				    reg & ~(1 << irq));
			}

			event = sc->sc_eventstab[irq];
			if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
				if(irq == 1 && ar531x_soc < AR531X_SOC_AR5315) {
					ATH_READ_REG(AR5312_SYSREG_BASE +
						AR5312_SYSREG_AHBPERR);
					ATH_READ_REG(AR5312_SYSREG_BASE +
						AR5312_SYSREG_AHBDMAE);
				}
				/* Ignore non handle interrupts */
				if (irq != 0 && irq != 6)
					printf("Stray APB IRQ %d\n", irq);

				continue;
			}

			intr_event_handle(event, PCPU_GET(curthread)->td_intr_frame);
			mips_intrcnt_inc(sc->sc_intr_counter[irq]);
		}
	}

	return (FILTER_HANDLED);
}
Ejemplo n.º 6
0
static int
apb_intr(void *arg)
{
	struct apb_softc *sc = arg;
	struct intr_event *event;
	uint32_t reg, irq;

	reg = ATH_READ_REG(AR71XX_MISC_INTR_STATUS);
	for (irq = 0; irq < APB_NIRQS; irq++) {
		if (reg & (1 << irq)) {

			switch (ar71xx_soc) {
			case AR71XX_SOC_AR7240:
			case AR71XX_SOC_AR7241:
			case AR71XX_SOC_AR7242:
				/* Ack/clear the irq on status register for AR724x */
				ATH_WRITE_REG(AR71XX_MISC_INTR_STATUS,
				    reg & ~(1 << irq));
				break;
			default:
				/* fallthrough */
				break;
			}

			event = sc->sc_eventstab[irq];
			if (!event || TAILQ_EMPTY(&event->ie_handlers)) {
				/* Ignore timer interrupts */
				if (irq != 0)
					printf("Stray APB IRQ %d\n", irq);
				continue;
			}

			/* TODO: frame instead of NULL? */
			intr_event_handle(event, NULL);
			mips_intrcnt_inc(sc->sc_intr_counter[irq]);
		}
	}

	return (FILTER_HANDLED);
}