.. | .. |
---|
2 | 2 | /* |
---|
3 | 3 | * handling diagnose instructions |
---|
4 | 4 | * |
---|
5 | | - * Copyright IBM Corp. 2008, 2011 |
---|
| 5 | + * Copyright IBM Corp. 2008, 2020 |
---|
6 | 6 | * |
---|
7 | 7 | * Author(s): Carsten Otte <cotte@de.ibm.com> |
---|
8 | 8 | * Christian Borntraeger <borntraeger@de.ibm.com> |
---|
.. | .. |
---|
10 | 10 | |
---|
11 | 11 | #include <linux/kvm.h> |
---|
12 | 12 | #include <linux/kvm_host.h> |
---|
13 | | -#include <asm/pgalloc.h> |
---|
14 | 13 | #include <asm/gmap.h> |
---|
15 | 14 | #include <asm/virtio-ccw.h> |
---|
16 | 15 | #include "kvm-s390.h" |
---|
.. | .. |
---|
158 | 157 | |
---|
159 | 158 | tid = vcpu->run->s.regs.gprs[(vcpu->arch.sie_block->ipa & 0xf0) >> 4]; |
---|
160 | 159 | vcpu->stat.diagnose_9c++; |
---|
161 | | - VCPU_EVENT(vcpu, 5, "diag time slice end directed to %d", tid); |
---|
162 | 160 | |
---|
| 161 | + /* yield to self */ |
---|
163 | 162 | if (tid == vcpu->vcpu_id) |
---|
164 | | - return 0; |
---|
| 163 | + goto no_yield; |
---|
165 | 164 | |
---|
| 165 | + /* yield to invalid */ |
---|
166 | 166 | tcpu = kvm_get_vcpu_by_id(vcpu->kvm, tid); |
---|
167 | | - if (tcpu) |
---|
168 | | - kvm_vcpu_yield_to(tcpu); |
---|
| 167 | + if (!tcpu) |
---|
| 168 | + goto no_yield; |
---|
| 169 | + |
---|
| 170 | + /* target already running */ |
---|
| 171 | + if (READ_ONCE(tcpu->cpu) >= 0) |
---|
| 172 | + goto no_yield; |
---|
| 173 | + |
---|
| 174 | + if (kvm_vcpu_yield_to(tcpu) <= 0) |
---|
| 175 | + goto no_yield; |
---|
| 176 | + |
---|
| 177 | + VCPU_EVENT(vcpu, 5, "diag time slice end directed to %d: done", tid); |
---|
| 178 | + return 0; |
---|
| 179 | +no_yield: |
---|
| 180 | + VCPU_EVENT(vcpu, 5, "diag time slice end directed to %d: ignored", tid); |
---|
| 181 | + vcpu->stat.diagnose_9c_ignored++; |
---|
169 | 182 | return 0; |
---|
170 | 183 | } |
---|
171 | 184 | |
---|
.. | .. |
---|
187 | 200 | return -EOPNOTSUPP; |
---|
188 | 201 | } |
---|
189 | 202 | |
---|
| 203 | + /* |
---|
| 204 | + * no need to check the return value of vcpu_stop as it can only have |
---|
| 205 | + * an error for protvirt, but protvirt means user cpu state |
---|
| 206 | + */ |
---|
190 | 207 | if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm)) |
---|
191 | 208 | kvm_s390_vcpu_stop(vcpu); |
---|
192 | 209 | vcpu->run->s390_reset_flags |= KVM_S390_RESET_SUBSYSTEM; |
---|