diff options
Diffstat (limited to 'arch/s390/kvm/gaccess.c')
-rw-r--r-- | arch/s390/kvm/gaccess.c | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index a7559f7207df..d30db40437dc 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c | |||
@@ -259,10 +259,14 @@ struct aste { | |||
259 | 259 | ||
260 | int ipte_lock_held(struct kvm_vcpu *vcpu) | 260 | int ipte_lock_held(struct kvm_vcpu *vcpu) |
261 | { | 261 | { |
262 | union ipte_control *ic = &vcpu->kvm->arch.sca->ipte_control; | 262 | if (vcpu->arch.sie_block->eca & 1) { |
263 | int rc; | ||
263 | 264 | ||
264 | if (vcpu->arch.sie_block->eca & 1) | 265 | read_lock(&vcpu->kvm->arch.sca_lock); |
265 | return ic->kh != 0; | 266 | rc = kvm_s390_get_ipte_control(vcpu->kvm)->kh != 0; |
267 | read_unlock(&vcpu->kvm->arch.sca_lock); | ||
268 | return rc; | ||
269 | } | ||
266 | return vcpu->kvm->arch.ipte_lock_count != 0; | 270 | return vcpu->kvm->arch.ipte_lock_count != 0; |
267 | } | 271 | } |
268 | 272 | ||
@@ -274,16 +278,20 @@ static void ipte_lock_simple(struct kvm_vcpu *vcpu) | |||
274 | vcpu->kvm->arch.ipte_lock_count++; | 278 | vcpu->kvm->arch.ipte_lock_count++; |
275 | if (vcpu->kvm->arch.ipte_lock_count > 1) | 279 | if (vcpu->kvm->arch.ipte_lock_count > 1) |
276 | goto out; | 280 | goto out; |
277 | ic = &vcpu->kvm->arch.sca->ipte_control; | 281 | retry: |
282 | read_lock(&vcpu->kvm->arch.sca_lock); | ||
283 | ic = kvm_s390_get_ipte_control(vcpu->kvm); | ||
278 | do { | 284 | do { |
279 | old = READ_ONCE(*ic); | 285 | old = READ_ONCE(*ic); |
280 | while (old.k) { | 286 | if (old.k) { |
287 | read_unlock(&vcpu->kvm->arch.sca_lock); | ||
281 | cond_resched(); | 288 | cond_resched(); |
282 | old = READ_ONCE(*ic); | 289 | goto retry; |
283 | } | 290 | } |
284 | new = old; | 291 | new = old; |
285 | new.k = 1; | 292 | new.k = 1; |
286 | } while (cmpxchg(&ic->val, old.val, new.val) != old.val); | 293 | } while (cmpxchg(&ic->val, old.val, new.val) != old.val); |
294 | read_unlock(&vcpu->kvm->arch.sca_lock); | ||
287 | out: | 295 | out: |
288 | mutex_unlock(&vcpu->kvm->arch.ipte_mutex); | 296 | mutex_unlock(&vcpu->kvm->arch.ipte_mutex); |
289 | } | 297 | } |
@@ -296,12 +304,14 @@ static void ipte_unlock_simple(struct kvm_vcpu *vcpu) | |||
296 | vcpu->kvm->arch.ipte_lock_count--; | 304 | vcpu->kvm->arch.ipte_lock_count--; |
297 | if (vcpu->kvm->arch.ipte_lock_count) | 305 | if (vcpu->kvm->arch.ipte_lock_count) |
298 | goto out; | 306 | goto out; |
299 | ic = &vcpu->kvm->arch.sca->ipte_control; | 307 | read_lock(&vcpu->kvm->arch.sca_lock); |
308 | ic = kvm_s390_get_ipte_control(vcpu->kvm); | ||
300 | do { | 309 | do { |
301 | old = READ_ONCE(*ic); | 310 | old = READ_ONCE(*ic); |
302 | new = old; | 311 | new = old; |
303 | new.k = 0; | 312 | new.k = 0; |
304 | } while (cmpxchg(&ic->val, old.val, new.val) != old.val); | 313 | } while (cmpxchg(&ic->val, old.val, new.val) != old.val); |
314 | read_unlock(&vcpu->kvm->arch.sca_lock); | ||
305 | wake_up(&vcpu->kvm->arch.ipte_wq); | 315 | wake_up(&vcpu->kvm->arch.ipte_wq); |
306 | out: | 316 | out: |
307 | mutex_unlock(&vcpu->kvm->arch.ipte_mutex); | 317 | mutex_unlock(&vcpu->kvm->arch.ipte_mutex); |
@@ -311,24 +321,29 @@ static void ipte_lock_siif(struct kvm_vcpu *vcpu) | |||
311 | { | 321 | { |
312 | union ipte_control old, new, *ic; | 322 | union ipte_control old, new, *ic; |
313 | 323 | ||
314 | ic = &vcpu->kvm->arch.sca->ipte_control; | 324 | retry: |
325 | read_lock(&vcpu->kvm->arch.sca_lock); | ||
326 | ic = kvm_s390_get_ipte_control(vcpu->kvm); | ||
315 | do { | 327 | do { |
316 | old = READ_ONCE(*ic); | 328 | old = READ_ONCE(*ic); |
317 | while (old.kg) { | 329 | if (old.kg) { |
330 | read_unlock(&vcpu->kvm->arch.sca_lock); | ||
318 | cond_resched(); | 331 | cond_resched(); |
319 | old = READ_ONCE(*ic); | 332 | goto retry; |
320 | } | 333 | } |
321 | new = old; | 334 | new = old; |
322 | new.k = 1; | 335 | new.k = 1; |
323 | new.kh++; | 336 | new.kh++; |
324 | } while (cmpxchg(&ic->val, old.val, new.val) != old.val); | 337 | } while (cmpxchg(&ic->val, old.val, new.val) != old.val); |
338 | read_unlock(&vcpu->kvm->arch.sca_lock); | ||
325 | } | 339 | } |
326 | 340 | ||
327 | static void ipte_unlock_siif(struct kvm_vcpu *vcpu) | 341 | static void ipte_unlock_siif(struct kvm_vcpu *vcpu) |
328 | { | 342 | { |
329 | union ipte_control old, new, *ic; | 343 | union ipte_control old, new, *ic; |
330 | 344 | ||
331 | ic = &vcpu->kvm->arch.sca->ipte_control; | 345 | read_lock(&vcpu->kvm->arch.sca_lock); |
346 | ic = kvm_s390_get_ipte_control(vcpu->kvm); | ||
332 | do { | 347 | do { |
333 | old = READ_ONCE(*ic); | 348 | old = READ_ONCE(*ic); |
334 | new = old; | 349 | new = old; |
@@ -336,6 +351,7 @@ static void ipte_unlock_siif(struct kvm_vcpu *vcpu) | |||
336 | if (!new.kh) | 351 | if (!new.kh) |
337 | new.k = 0; | 352 | new.k = 0; |
338 | } while (cmpxchg(&ic->val, old.val, new.val) != old.val); | 353 | } while (cmpxchg(&ic->val, old.val, new.val) != old.val); |
354 | read_unlock(&vcpu->kvm->arch.sca_lock); | ||
339 | if (!new.kh) | 355 | if (!new.kh) |
340 | wake_up(&vcpu->kvm->arch.ipte_wq); | 356 | wake_up(&vcpu->kvm->arch.ipte_wq); |
341 | } | 357 | } |