]>
Commit | Line | Data |
---|---|---|
000a1a38 CB |
1 | /* |
2 | * QEMU S/390 Interrupt support | |
3 | * | |
79afc36d | 4 | * Copyright IBM Corp. 2012, 2014 |
000a1a38 CB |
5 | * |
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. | |
8 | */ | |
9 | ||
9615495a | 10 | #include "qemu/osdep.h" |
000a1a38 | 11 | #include "cpu.h" |
9c17d615 | 12 | #include "sysemu/kvm.h" |
bd3f16ac PB |
13 | #include "hw/s390x/ioinst.h" |
14 | ||
15 | #if !defined(CONFIG_USER_ONLY) | |
16 | void cpu_inject_ext(S390CPU *cpu, uint32_t code, uint32_t param, | |
17 | uint64_t param64) | |
18 | { | |
19 | CPUS390XState *env = &cpu->env; | |
20 | ||
21 | if (env->ext_index == MAX_EXT_QUEUE - 1) { | |
22 | /* ugh - can't queue anymore. Let's drop. */ | |
23 | return; | |
24 | } | |
25 | ||
26 | env->ext_index++; | |
27 | assert(env->ext_index < MAX_EXT_QUEUE); | |
28 | ||
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; | |
32 | ||
33 | env->pending_int |= INTERRUPT_EXT; | |
34 | cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); | |
35 | } | |
36 | ||
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) | |
40 | { | |
41 | CPUS390XState *env = &cpu->env; | |
42 | int isc = IO_INT_WORD_ISC(io_int_word); | |
43 | ||
44 | if (env->io_index[isc] == MAX_IO_QUEUE - 1) { | |
45 | /* ugh - can't queue anymore. Let's drop. */ | |
46 | return; | |
47 | } | |
48 | ||
49 | env->io_index[isc]++; | |
50 | assert(env->io_index[isc] < MAX_IO_QUEUE); | |
51 | ||
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; | |
56 | ||
57 | env->pending_int |= INTERRUPT_IO; | |
58 | cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); | |
59 | } | |
60 | ||
61 | static void cpu_inject_crw_mchk(S390CPU *cpu) | |
62 | { | |
63 | CPUS390XState *env = &cpu->env; | |
64 | ||
65 | if (env->mchk_index == MAX_MCHK_QUEUE - 1) { | |
66 | /* ugh - can't queue anymore. Let's drop. */ | |
67 | return; | |
68 | } | |
69 | ||
70 | env->mchk_index++; | |
71 | assert(env->mchk_index < MAX_MCHK_QUEUE); | |
72 | ||
73 | env->mchk_queue[env->mchk_index].type = 1; | |
74 | ||
75 | env->pending_int |= INTERRUPT_MCHK; | |
76 | cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HARD); | |
77 | } | |
000a1a38 | 78 | |
79afc36d CH |
79 | /* |
80 | * All of the following interrupts are floating, i.e. not per-vcpu. | |
de13d216 CH |
81 | * We just need a dummy cpustate in order to be able to inject in the |
82 | * non-kvm case. | |
79afc36d | 83 | */ |
000a1a38 CB |
84 | void s390_sclp_extint(uint32_t parm) |
85 | { | |
000a1a38 | 86 | if (kvm_enabled()) { |
de13d216 | 87 | kvm_s390_service_interrupt(parm); |
000a1a38 | 88 | } else { |
de13d216 | 89 | S390CPU *dummy_cpu = s390_cpu_addr2state(0); |
de13d216 | 90 | |
f9466733 | 91 | cpu_inject_ext(dummy_cpu, EXT_SERVICE, parm, 0); |
000a1a38 CB |
92 | } |
93 | } | |
79afc36d | 94 | |
de13d216 CH |
95 | void s390_io_interrupt(uint16_t subchannel_id, uint16_t subchannel_nr, |
96 | uint32_t io_int_parm, uint32_t io_int_word) | |
79afc36d CH |
97 | { |
98 | if (kvm_enabled()) { | |
de13d216 | 99 | kvm_s390_io_interrupt(subchannel_id, subchannel_nr, io_int_parm, |
79afc36d CH |
100 | io_int_word); |
101 | } else { | |
de13d216 CH |
102 | S390CPU *dummy_cpu = s390_cpu_addr2state(0); |
103 | ||
104 | cpu_inject_io(dummy_cpu, subchannel_id, subchannel_nr, io_int_parm, | |
79afc36d CH |
105 | io_int_word); |
106 | } | |
107 | } | |
108 | ||
de13d216 | 109 | void s390_crw_mchk(void) |
79afc36d CH |
110 | { |
111 | if (kvm_enabled()) { | |
de13d216 | 112 | kvm_s390_crw_mchk(); |
79afc36d | 113 | } else { |
de13d216 CH |
114 | S390CPU *dummy_cpu = s390_cpu_addr2state(0); |
115 | ||
116 | cpu_inject_crw_mchk(dummy_cpu); | |
79afc36d CH |
117 | } |
118 | } | |
119 | ||
000a1a38 | 120 | #endif |