/* * do_cio_interrupt() handles all normal I/O device IRQ's */ static irqreturn_t do_cio_interrupt(int irq, void *dummy) { struct tpi_info *tpi_info; struct subchannel *sch; struct irb *irb; set_cpu_flag(CIF_NOHZ_DELAY); tpi_info = (struct tpi_info *) &get_irq_regs()->int_code; trace_s390_cio_interrupt(tpi_info); irb = this_cpu_ptr(&cio_irb); sch = (struct subchannel *)(unsigned long) tpi_info->intparm; if (!sch) { /* Clear pending interrupt condition. */ inc_irq_stat(IRQIO_CIO); tsch(tpi_info->schid, irb); return IRQ_HANDLED; } spin_lock(sch->lock); /* Store interrupt response block to lowcore. */ if (tsch(tpi_info->schid, irb) == 0) { /* Keep subchannel information word up to date. */ memcpy (&sch->schib.scsw, &irb->scsw, sizeof (irb->scsw)); /* Call interrupt handler if there is one. */ if (sch->driver && sch->driver->irq) sch->driver->irq(sch); else inc_irq_stat(IRQIO_CIO); } else inc_irq_stat(IRQIO_CIO); spin_unlock(sch->lock); return IRQ_HANDLED; }
static uint8_t execute_NMI(cpu_registers* registers) { clear_nmi_flag(); // NMI clears bit 4 and sets bit 5 for flags push uint8_t NMI_flags = registers->flags | 0x20; NMI_flags &= ~0x10; push_PC_onto_stack(registers, registers->PC - 1); // Sub 1 to get correct PC since it was incremented push_stack(registers, NMI_flags); registers->PC = (read_RAM(0xFFFB) << 8) | read_RAM(0xFFFA); set_cpu_flag(registers, INTERRUPT_FLAG); return 7; }