Commit f303406e authored by Claudio Imbrenda's avatar Claudio Imbrenda
Browse files

KVM: s390: Fix a deadlock



In some scenarios, a deadlock can happen, involving _do_shadow_pte().

Convert all usages of pgste_get_lock() to pgste_get_trylock() in
_do_shadow_pte() and return -EAGAIN. All callers can already deal with
-EAGAIN being returned.

Fixes: e38c884d ("KVM: s390: Switch to new gmap")
Tested-by: default avatarChristian Borntraeger <borntraeger@linux.ibm.com>
Reviewed-by: default avatarJanosch Frank <frankja@linux.ibm.com>
Reviewed-by: default avatarChristoph Schlameuss <schlameuss@linux.ibm.com>
Signed-off-by: default avatarClaudio Imbrenda <imbrenda@linux.ibm.com>
parent 5ee8dbf5
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -1434,7 +1434,8 @@ static int _do_shadow_pte(struct gmap *sg, gpa_t raddr, union pte *ptep_h, union
	if (rc)
		return rc;

	pgste = pgste_get_lock(ptep_h);
	if (!pgste_get_trylock(ptep_h, &pgste))
		return -EAGAIN;
	newpte = _pte(f->pfn, f->writable, !p, 0);
	newpte.s.d |= ptep->s.d;
	newpte.s.sd |= ptep->s.sd;
@@ -1444,7 +1445,8 @@ static int _do_shadow_pte(struct gmap *sg, gpa_t raddr, union pte *ptep_h, union
	pgste_set_unlock(ptep_h, pgste);

	newpte = _pte(f->pfn, 0, !p, 0);
	pgste = pgste_get_lock(ptep);
	if (!pgste_get_trylock(ptep, &pgste))
		return -EAGAIN;
	pgste = __dat_ptep_xchg(ptep, pgste, newpte, gpa_to_gfn(raddr), sg->asce, uses_skeys(sg));
	pgste_set_unlock(ptep, pgste);