From patchwork Thu Oct 4 04:53:51 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul Mackerras X-Patchwork-Id: 978643 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=kvm-ppc-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ozlabs.org Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; secure) header.d=ozlabs.org header.i=@ozlabs.org header.b="eEsA8ure"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 42QgXB645Kz9sRp for ; Thu, 4 Oct 2018 14:54:02 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726752AbeJDLpZ (ORCPT ); Thu, 4 Oct 2018 07:45:25 -0400 Received: from ozlabs.org ([203.11.71.1]:44255 "EHLO ozlabs.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726852AbeJDLpZ (ORCPT ); Thu, 4 Oct 2018 07:45:25 -0400 Received: by ozlabs.org (Postfix, from userid 1003) id 42QgX55htXz9s5c; Thu, 4 Oct 2018 14:53:57 +1000 (AEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ozlabs.org; s=201707; t=1538628837; bh=5tg6CwHx9nTVGOjW7qjPwxnr1OEM6xssUkDYllE+OZ0=; h=Date:From:To:Cc:Subject:From; b=eEsA8ureSDz73teOB4FKm2XNZsdV0LMT7TRLZEmOcnQKIKR0XZnBRM84YCIQowDq5 G3jB7YJfd+wMBwWWuzwO7sFouSdrjTs9SN92ksjhzgmYBPFnZJ2HfDYn8+HKh13N0e n+yuRLYTNIl0CSTjpil5HJGCk+dm/Dc2F2k9WT5WjOiYycJy/evFg+aYPrqyigN4LP EVL7JChqCZQr2qBtDuj7WAfZMQ1uO3ZUzVMCdz6XxCv0cNTDg9lfDgF00X0PNeOaqa QbjbKGKOQWw9Qcc9IYai+G/iehfNx3qxeihlS4xRX9cnYq3PKMrOO90pefGivo2bvK wAGgog2Fgu8lg== Date: Thu, 4 Oct 2018 14:53:51 +1000 From: Paul Mackerras To: kvm-ppc@vger.kernel.org, kvm@vger.kernel.org Cc: Nick Piggin , David Gibson , "Aneesh Kumar K.V" Subject: [PATCH] KVM: PPC: Book3S HV: Avoid crash from THP collapse during radix page fault Message-ID: <20181004045351.GC16300@fergus> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.5.24 (2015-08-30) Sender: kvm-ppc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm-ppc@vger.kernel.org Commit 71d29f43b633 ("KVM: PPC: Book3S HV: Don't use compound_order to determine host mapping size", 2018-09-11) added a call to __find_linux_pte() and a dereference of the returned PTE pointer to the radix page fault path in the common case where the page is normal system memory. Previously, __find_linux_pte() was only called for mappings to physical addresses which don't have a page struct (e.g. memory-mapped I/O) or where the page struct is marked as reserved memory. This exposes us to the possibility that the returned PTE pointer could be NULL, for example in the case of a concurrent THP collapse operation. Dereferencing the returned NULL pointer causes a host crash. To fix this, we check for NULL, and if it is NULL, we retry the operation by returning to the guest, with the expectation that it will generate the same page fault again (unless of course it has been fixed up by another CPU in the meantime). Fixes: 71d29f43b633 ("KVM: PPC: Book3S HV: Don't use compound_order to determine host mapping size") Signed-off-by: Paul Mackerras --- arch/powerpc/kvm/book3s_64_mmu_radix.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/powerpc/kvm/book3s_64_mmu_radix.c b/arch/powerpc/kvm/book3s_64_mmu_radix.c index 933c574e1cf7..998f8d089ac7 100644 --- a/arch/powerpc/kvm/book3s_64_mmu_radix.c +++ b/arch/powerpc/kvm/book3s_64_mmu_radix.c @@ -646,6 +646,16 @@ int kvmppc_book3s_radix_page_fault(struct kvm_run *run, struct kvm_vcpu *vcpu, */ local_irq_disable(); ptep = __find_linux_pte(vcpu->arch.pgdir, hva, NULL, &shift); + /* + * If the PTE disappeared temporarily due to a THP + * collapse, just return and let the guest try again. + */ + if (!ptep) { + local_irq_enable(); + if (page) + put_page(page); + return RESUME_GUEST; + } pte = *ptep; local_irq_enable();