All of lore.kernel.org
 help / color / mirror / Atom feed
From: Amit Machhiwal <amachhiw@linux.ibm.com>
To: Shrikanth Hegde <sshegde@linux.ibm.com>
Cc: Amit Machhiwal <amachhiw@linux.ibm.com>,
	Madhavan Srinivasan <maddy@linux.ibm.com>,
	linuxppc-dev@lists.ozlabs.org,
	Nicholas Piggin <npiggin@gmail.com>,
	Michael Ellerman <mpe@ellerman.id.au>,
	"Christophe Leroy (CS GROUP)" <chleroy@kernel.org>,
	"Ritesh Harjani (IBM)" <ritesh.list@gmail.com>,
	kvm-ppc@vger.kernel.org, kvm@vger.kernel.org,
	linux-kernel@vger.kernel.org,
	Gautam Menghani <gautam@linux.ibm.com>,
	Harsh Prateek Bora <harshpb@linux.ibm.com>,
	R Nageswara Sastry <rnsastry@linux.ibm.com>,
	Alexander Graf <agraf@suse.de>,
	linux-hardening@vger.kernel.org, stable@vger.kernel.org,
	Avi Kivity <avi@redhat.com>
Subject: Re: [RESEND PATCH 2/3] KVM: PPC: Book3S HV: Add preempt_disable() around virtual-mode HPTE bit-lock users
Date: Wed, 30 Sep 2026 19:08:26 +0530	[thread overview]
Message-ID: <20260930180232.ffed855b-03-amachhiw@linux.ibm.com> (raw)
In-Reply-To: <57f589e4-b7cc-43d1-8d02-732d10118833@linux.ibm.com>

Hi Shrikanth,

Thanks for taking a look at this patch.  Please find my responses inline.

On 2026/09/29 11:48 AM, Shrikanth Hegde wrote:
> 
> 
> On 9/28/26 5:58 PM, Amit Machhiwal wrote:
> > kvmppc_hv_find_lock_hpte() requires virtual-mode callers to run with
> > preemption disabled, because it can return with HPTE_V_HVLOCK still held
> > until the caller later unlocks the HPTE.  Existing virtual-mode callers
> > in book3s_64_mmu_hv.c already follow that rule.
> > 

<..snip..>

> > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> > index aa51968e206a..52f72f30baf0 100644
> > --- a/arch/powerpc/kvm/book3s_hv.c
> > +++ b/arch/powerpc/kvm/book3s_hv.c
> > @@ -1212,9 +1212,11 @@ int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu)
> >   	case H_CLEAR_REF:
> >   	case H_PROTECT:
> >   	case H_BULK_REMOVE:
> > +		preempt_disable();
> >   		idx = srcu_read_lock(&kvm->srcu);
> 
> Please add a comment above kvmppc_pseries_do_hpt_hcall, saying preemption
> is disabled and one cannot make any blocking call.

Sure, will do.

> 
> >   		ret = kvmppc_pseries_do_hpt_hcall(vcpu, req);
> >   		srcu_read_unlock(&kvm->srcu, idx);
> > +		preempt_enable();
> >   		if (ret == H_TOO_HARD)
> >   			return RESUME_HOST;
> >   		break;
> > @@ -1834,8 +1836,10 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
> >   		else
> >   			vsid = vcpu->arch.fault_gpa;
> > +		preempt_disable();
> >   		err = kvmppc_hpte_hv_fault(vcpu, vcpu->arch.fault_dar,
> >   				vsid, vcpu->arch.fault_dsisr, true);
> > +		preempt_enable();
> >   		if (err == 0) {
> >   			r = RESUME_GUEST;
> >   		} else if (err == -1 || err == -2) {
> > @@ -1881,8 +1885,10 @@ static int kvmppc_handle_exit_hv(struct kvm_vcpu *vcpu,
> >   		else
> >   			vsid = vcpu->arch.fault_gpa;
> > +		preempt_disable();
> >   		err = kvmppc_hpte_hv_fault(vcpu, vcpu->arch.fault_dar,
> >   				vsid, vcpu->arch.fault_dsisr, false);
> > +		preempt_enable();
> >   		if (err == 0) {
> >   			r = RESUME_GUEST;
> >   		} else if (err == -1) {
> 
> Please check if below is possible case.
> 
> https://sashiko.dev/#/patchset/20260928113704.48912-4-amachhiw%40linux.ibm.com

Thank you for raising this point and bringing Sashiko AI's review comment to
attention.  After conducting a deep-dive audit of the preemption paths and the
virtual-mode locking context, it looks like Sashiko's finding is legitimate, and
extremely subtle.

The Deadlock Mechanism:
=======================

In this patch we added preempt_disable() / preempt_enable() pairs exclusively
around the guest vCPU HPT hcall paths (kvmppc_pseries_do_hpt_hcall) and page
fault paths (kvmppc_hpte_hv_fault) in virtual mode to satisfy the HPTE locking
preemption contract.

However, several host-side virtual-mode paths still acquire and hold the HPTE
bit-lock (HPTE_V_HVLOCK) with preemption enabled.  Specifically:

- While MMU notifier paths (unmapping, aging) and the dirty-log path are safe
  (since they are called with kvm->mmu_lock held, which disables preemption),
  the memslot flushing path (kvmppc_core_flush_memslot_hv() ->
  kvm_unmap_rmapp()) runs with only the slots_arch_lock mutex held, leaving
  preemption fully enabled.

If a host-side thread executing kvm_unmap_rmapp() successfully acquires the
HPTE_V_HVLOCK on CPU X and is preempted, a guest vCPU thread subsequently
scheduled on CPU X will enter the hcall or fault path, disable preemption (via
the current change), and spin indefinitely on try_lock_hpte().  Because
preemption is disabled on the spinning vCPU, it will never yield CPU X.  The
preempted host-side lock owner can never be rescheduled on CPU X to release the
lock.

This converts a potential latency/livelock issue into a permanent hard deadlock.

Proposed Solution:
==================

To make this fix completely watertight and eliminate the deadlock window, no
thread must ever be preempted while holding HPTE_V_HVLOCK in virtual mode.  This
means we must disable preemption during the lock-hold window on both the
vCPU-side and the host-side paths.

In the next version, I'll be making following changes:

Host-Side Preemption Disabling: Add preempt_disable() / preempt_enable()
brackets around the HPTE_V_HVLOCK hold windows inside the four host-side
virtual-mode functions in arch/powerpc/kvm/book3s_64_mmu_hv.c:

  - kvm_unmap_rmapp()
  - kvm_age_rmapp()
  - kvm_test_clear_dirty_npages()
  - resize_hpt_rehash_hpte()

For example, inside kvm_unmap_rmapp():

 diff --git a/arch/powerpc/kvm/book3s_64_mmu_hv.c b/arch/powerpc/kvm/book3s_64_mmu_hv.c
 index 2ccb3d138f46..59da958e09cb 100644
 --- a/arch/powerpc/kvm/book3s_64_mmu_hv.c
 +++ b/arch/powerpc/kvm/book3s_64_mmu_hv.c
 @@ -823,7 +823,9 @@ static void kvm_unmap_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
                  */
                 i = *rmapp & KVMPPC_RMAP_INDEX;
                 hptep = (__be64 *) (kvm->arch.hpt.virt + (i << 4));
 +               preempt_disable();
                 if (!try_lock_hpte(hptep, HPTE_V_HVLOCK)) {
 +                       preempt_enable();
                         /* unlock rmap before spinning on the HPTE lock */
                         unlock_rmap(rmapp);
                         while (be64_to_cpu(hptep[0]) & HPTE_V_HVLOCK)
 @@ -834,6 +836,7 @@ static void kvm_unmap_rmapp(struct kvm *kvm, struct kvm_memory_slot *memslot,
                 kvmppc_unmap_hpte(kvm, i, memslot, rmapp, gfn);
                 unlock_rmap(rmapp);
                 __unlock_hpte(hptep, be64_to_cpu(hptep[0]));
 +               preempt_enable();
         }
  }

To ensure complete consistency and verify there are no other potential
preemption deadlock sites, I conducted a full audit of all 8 occurrences of
try_lock_hpte() inside arch/powerpc/kvm/book3s_64_mmu_hv.c.

The proposed v2 fixes simply bring the host-side lock users into alignment with
the established, pre-existing design pattern used by every other virtual-mode
caller of try_lock_hpte() in this file:

- Established safe callers (4) — already wrapped in preempt_disable() /
  preempt_enable() blocks by design:
	- kvmppc_book3s_hv_page_fault()
	- read_hpte_for_cma()
	- kvmppc_hpte_hv_page_debug()

- Symmetrical alignment in v2 (4):
	- kvm_unmap_rmapp()
	- kvm_age_rmapp()
	- kvm_test_clear_dirty_npages()
	- resize_hpt_rehash_hpte()

This ensures 100% preemption-safety symmetry across all virtual-mode
lock-holding windows in KVM.

I hope this sounds good to you.

Thanks,
Amit

  reply	other threads:[~2026-09-30 13:38 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-28 12:28 [RESEND PATCH 0/3] KVM: PPC: Fixes for Book3S HV HPT locking and paired-single decoding Amit Machhiwal
2026-09-28 12:28 ` [RESEND PATCH 1/3] KVM: PPC: Book3S HV: Add SRCU protection for virtual-mode HPT hcalls Amit Machhiwal
2026-09-28 13:27   ` Ritesh Harjani
2026-09-28 12:28 ` [RESEND PATCH 2/3] KVM: PPC: Book3S HV: Add preempt_disable() around virtual-mode HPTE bit-lock users Amit Machhiwal
2026-09-28 13:42   ` Ritesh Harjani
2026-09-29  6:18   ` Shrikanth Hegde
2026-09-30 13:38     ` Amit Machhiwal [this message]
2026-09-28 12:28 ` [RESEND PATCH 3/3] KVM: PPC: Fix get_d_signext() 12-bit displacement for paired-single D-form Amit Machhiwal
2026-10-12  3:31 ` [RESEND PATCH 0/3] KVM: PPC: Fixes for Book3S HV HPT locking and paired-single decoding Madhavan Srinivasan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260930180232.ffed855b-03-amachhiw@linux.ibm.com \
    --to=amachhiw@linux.ibm.com \
    --cc=agraf@suse.de \
    --cc=avi@redhat.com \
    --cc=chleroy@kernel.org \
    --cc=gautam@linux.ibm.com \
    --cc=harshpb@linux.ibm.com \
    --cc=kvm-ppc@vger.kernel.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linuxppc-dev@lists.ozlabs.org \
    --cc=maddy@linux.ibm.com \
    --cc=mpe@ellerman.id.au \
    --cc=npiggin@gmail.com \
    --cc=ritesh.list@gmail.com \
    --cc=rnsastry@linux.ibm.com \
    --cc=sshegde@linux.ibm.com \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.