2 * QEMU S/390 Interrupt support
4 * Copyright IBM Corp. 2012, 2014
6 * This work is licensed under the terms of the GNU GPL, version 2 or (at your
7 * option) any later version. See the COPYING file in the top-level directory.
10 #include "qemu/osdep.h"
12 #include "sysemu/kvm.h"
13 #include "hw/s390x/ioinst.h"
15 #if !defined(CONFIG_USER_ONLY)
16 void cpu_inject_ext(S390CPU
*cpu
, uint32_t code
, uint32_t param
,
19 CPUS390XState
*env
= &cpu
->env
;
21 if (env
->ext_index
== MAX_EXT_QUEUE
- 1) {
22 /* ugh - can't queue anymore. Let's drop. */
27 assert(env
->ext_index
< MAX_EXT_QUEUE
);
29 env
->ext_queue
[env
->ext_index
].code
= code
;
30 env
->ext_queue
[env
->ext_index
].param
= param
;
31 env
->ext_queue
[env
->ext_index
].param64
= param64
;
33 env
->pending_int
|= INTERRUPT_EXT
;
34 cpu_interrupt(CPU(cpu
), CPU_INTERRUPT_HARD
);
37 static void cpu_inject_io(S390CPU
*cpu
, uint16_t subchannel_id
,
38 uint16_t subchannel_number
,
39 uint32_t io_int_parm
, uint32_t io_int_word
)
41 CPUS390XState
*env
= &cpu
->env
;
42 int isc
= IO_INT_WORD_ISC(io_int_word
);
44 if (env
->io_index
[isc
] == MAX_IO_QUEUE
- 1) {
45 /* ugh - can't queue anymore. Let's drop. */
50 assert(env
->io_index
[isc
] < MAX_IO_QUEUE
);
52 env
->io_queue
[env
->io_index
[isc
]][isc
].id
= subchannel_id
;
53 env
->io_queue
[env
->io_index
[isc
]][isc
].nr
= subchannel_number
;
54 env
->io_queue
[env
->io_index
[isc
]][isc
].parm
= io_int_parm
;
55 env
->io_queue
[env
->io_index
[isc
]][isc
].word
= io_int_word
;
57 env
->pending_int
|= INTERRUPT_IO
;
58 cpu_interrupt(CPU(cpu
), CPU_INTERRUPT_HARD
);
61 static void cpu_inject_crw_mchk(S390CPU
*cpu
)
63 CPUS390XState
*env
= &cpu
->env
;
65 if (env
->mchk_index
== MAX_MCHK_QUEUE
- 1) {
66 /* ugh - can't queue anymore. Let's drop. */
71 assert(env
->mchk_index
< MAX_MCHK_QUEUE
);
73 env
->mchk_queue
[env
->mchk_index
].type
= 1;
75 env
->pending_int
|= INTERRUPT_MCHK
;
76 cpu_interrupt(CPU(cpu
), CPU_INTERRUPT_HARD
);
80 * All of the following interrupts are floating, i.e. not per-vcpu.
81 * We just need a dummy cpustate in order to be able to inject in the
84 void s390_sclp_extint(uint32_t parm
)
87 kvm_s390_service_interrupt(parm
);
89 S390CPU
*dummy_cpu
= s390_cpu_addr2state(0);
91 cpu_inject_ext(dummy_cpu
, EXT_SERVICE
, parm
, 0);
95 void s390_io_interrupt(uint16_t subchannel_id
, uint16_t subchannel_nr
,
96 uint32_t io_int_parm
, uint32_t io_int_word
)
99 kvm_s390_io_interrupt(subchannel_id
, subchannel_nr
, io_int_parm
,
102 S390CPU
*dummy_cpu
= s390_cpu_addr2state(0);
104 cpu_inject_io(dummy_cpu
, subchannel_id
, subchannel_nr
, io_int_parm
,
109 void s390_crw_mchk(void)
114 S390CPU
*dummy_cpu
= s390_cpu_addr2state(0);
116 cpu_inject_crw_mchk(dummy_cpu
);