/* service interrupts are floating therefore we must not pass an cpustate */ void s390_sclp_extint(uint32_t parm) { S390CPU *dummy_cpu = s390_cpu_addr2state(0); CPUS390XState *env = &dummy_cpu->env; if (kvm_enabled()) { #ifdef CONFIG_KVM kvm_s390_interrupt_internal(env, KVM_S390_INT_SERVICE, parm, 0, 1); #endif } else { env->psw.addr += 4; cpu_inject_ext(env, EXT_SERVICE, parm, 0); } }
void s390_cpu_do_interrupt(CPUState *cs) { S390CPU *cpu = S390_CPU(cs); CPUS390XState *env = &cpu->env; qemu_log_mask(CPU_LOG_INT, "%s: %d at pc=%" PRIx64 "\n", __func__, cs->exception_index, env->psw.addr); s390_cpu_set_state(CPU_STATE_OPERATING, cpu); /* handle machine checks */ if ((env->psw.mask & PSW_MASK_MCHECK) && (cs->exception_index == -1)) { if (env->pending_int & INTERRUPT_MCHK) { cs->exception_index = EXCP_MCHK; } } /* handle external interrupts */ if ((env->psw.mask & PSW_MASK_EXT) && cs->exception_index == -1) { if (env->pending_int & INTERRUPT_EXT) { /* code is already in env */ cs->exception_index = EXCP_EXT; } else if (env->pending_int & INTERRUPT_TOD) { cpu_inject_ext(cpu, 0x1004, 0, 0); cs->exception_index = EXCP_EXT; env->pending_int &= ~INTERRUPT_EXT; env->pending_int &= ~INTERRUPT_TOD; } else if (env->pending_int & INTERRUPT_CPUTIMER) { cpu_inject_ext(cpu, 0x1005, 0, 0); cs->exception_index = EXCP_EXT; env->pending_int &= ~INTERRUPT_EXT; env->pending_int &= ~INTERRUPT_TOD; } } /* handle I/O interrupts */ if ((env->psw.mask & PSW_MASK_IO) && (cs->exception_index == -1)) { if (env->pending_int & INTERRUPT_IO) { cs->exception_index = EXCP_IO; } } switch (cs->exception_index) { case EXCP_PGM: do_program_interrupt(env); break; case EXCP_SVC: do_svc_interrupt(env); break; case EXCP_EXT: do_ext_interrupt(env); break; case EXCP_IO: do_io_interrupt(env); break; case EXCP_MCHK: do_mchk_interrupt(env); break; } cs->exception_index = -1; if (!env->pending_int) { cs->interrupt_request &= ~CPU_INTERRUPT_HARD; } }