bd3f16ac30
Move cpu_inject_* to the only C file where they are used. Move ioinst.h declarations that need S390CPU to cpu.h, to make ioinst.h independent of cpu.h. Move channel declarations that only need SubchDev from cpu.h to css.h, to make more channel users independent of cpu.h. Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
121 lines
3.2 KiB
C
121 lines
3.2 KiB
C
/*
|
|
* QEMU S/390 Interrupt support
|
|
*
|
|
* Copyright IBM Corp. 2012, 2014
|
|
*
|
|
* This work is licensed under the terms of the GNU GPL, version 2 or (at your
|
|
* option) any later version. See the COPYING file in the top-level directory.
|
|
*/
|
|
|
|
#include "qemu/osdep.h"
|
|
#include "cpu.h"
|
|
#include "sysemu/kvm.h"
|
|
#include "hw/s390x/ioinst.h"
|
|
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param,
|
|
uint64_t param64)
|
|
{
|
|
CPUS390XState *env = &cpu->env;
|
|
|
|
if (env->ext_index == MAX_EXT_QUEUE - 1) {
|
|
/* ugh - can't queue anymore. Let's drop. */
|
|
return;
|
|
}
|
|
|
|
env->ext_index++;
|
|
assert(env->ext_index < MAX_EXT_QUEUE);
|
|
|
|
env->ext_queue[env->ext_index].code = code;
|
|
env->ext_queue[env->ext_index].param = param;
|
|
env->ext_queue[env->ext_index].param64 = param64;
|
|
|
|
env->pending_int |= INTERRUPT_EXT;
|
|
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
|
|
}
|
|
|
|
static void cpu_inject_io(S390CPU *cpu, uint16_t subchannel_id,
|
|
uint16_t subchannel_number,
|
|
uint32_t io_int_parm, uint32_t io_int_word)
|
|
{
|
|
CPUS390XState *env = &cpu->env;
|
|
int isc = IO_INT_WORD_ISC(io_int_word);
|
|
|
|
if (env->io_index[isc] == MAX_IO_QUEUE - 1) {
|
|
/* ugh - can't queue anymore. Let's drop. */
|
|
return;
|
|
}
|
|
|
|
env->io_index[isc]++;
|
|
assert(env->io_index[isc] < MAX_IO_QUEUE);
|
|
|
|
env->io_queue[env->io_index[isc]][isc].id = subchannel_id;
|
|
env->io_queue[env->io_index[isc]][isc].nr = subchannel_number;
|
|
env->io_queue[env->io_index[isc]][isc].parm = io_int_parm;
|
|
env->io_queue[env->io_index[isc]][isc].word = io_int_word;
|
|
|
|
env->pending_int |= INTERRUPT_IO;
|
|
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
|
|
}
|
|
|
|
static void cpu_inject_crw_mchk(S390CPU *cpu)
|
|
{
|
|
CPUS390XState *env = &cpu->env;
|
|
|
|
if (env->mchk_index == MAX_MCHK_QUEUE - 1) {
|
|
/* ugh - can't queue anymore. Let's drop. */
|
|
return;
|
|
}
|
|
|
|
env->mchk_index++;
|
|
assert(env->mchk_index < MAX_MCHK_QUEUE);
|
|
|
|
env->mchk_queue[env->mchk_index].type = 1;
|
|
|
|
env->pending_int |= INTERRUPT_MCHK;
|
|
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD);
|
|
}
|
|
|
|
/*
|
|
* All of the following interrupts are floating, i.e. not per-vcpu.
|
|
* We just need a dummy cpustate in order to be able to inject in the
|
|
* non-kvm case.
|
|
*/
|
|
void s390_sclp_extint(uint32_t parm)
|
|
{
|
|
if (kvm_enabled()) {
|
|
kvm_s390_service_interrupt(parm);
|
|
} else {
|
|
S390CPU *dummy_cpu = s390_cpu_addr2state(0);
|
|
|
|
cpu_inject_ext(dummy_cpu, EXT_SERVICE, parm, 0);
|
|
}
|
|
}
|
|
|
|
void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr,
|
|
uint32_t io_int_parm, uint32_t io_int_word)
|
|
{
|
|
if (kvm_enabled()) {
|
|
kvm_s390_io_interrupt(subchannel_id, subchannel_nr, io_int_parm,
|
|
io_int_word);
|
|
} else {
|
|
S390CPU *dummy_cpu = s390_cpu_addr2state(0);
|
|
|
|
cpu_inject_io(dummy_cpu, subchannel_id, subchannel_nr, io_int_parm,
|
|
io_int_word);
|
|
}
|
|
}
|
|
|
|
void s390_crw_mchk(void)
|
|
{
|
|
if (kvm_enabled()) {
|
|
kvm_s390_crw_mchk();
|
|
} else {
|
|
S390CPU *dummy_cpu = s390_cpu_addr2state(0);
|
|
|
|
cpu_inject_crw_mchk(dummy_cpu);
|
|
}
|
|
}
|
|
|
|
#endif
|