On Fri, Aug 02, 2024 at 01:01:36PM -0700, Sean Christopherson wrote: > To avoid jitter on KVM_RUN due to synchronize_rcu(), use a rwlock instead > of RCU to protect vcpu->pid, a.k.a. the pid of the task last used to a > vCPU. When userspace is doing M:N scheduling of tasks to vCPUs, e.g. to > run SEV migration helper vCPUs during post-copy, the synchronize_rcu() > needed to change the PID associated with the vCPU can stall for hundreds > of milliseconds, which is problematic for latency sensitive post-copy > operations. > > In the directed yield path, do not acquire the lock if it's contended, > i.e. if the associated PID is changing, as that means the vCPU's task is > already running. > > Reported-by: Steve Rutherford <srutherford@xxxxxxxxxx> > Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> > --- > arch/arm64/include/asm/kvm_host.h | 2 +- > include/linux/kvm_host.h | 3 ++- > virt/kvm/kvm_main.c | 32 +++++++++++++++++-------------- > 3 files changed, 21 insertions(+), 16 deletions(-) > > diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h > index a33f5996ca9f..7199cb014806 100644 > --- a/arch/arm64/include/asm/kvm_host.h > +++ b/arch/arm64/include/asm/kvm_host.h > @@ -1115,7 +1115,7 @@ int __kvm_arm_vcpu_set_events(struct kvm_vcpu *vcpu, > void kvm_arm_halt_guest(struct kvm *kvm); > void kvm_arm_resume_guest(struct kvm *kvm); > > -#define vcpu_has_run_once(vcpu) !!rcu_access_pointer((vcpu)->pid) > +#define vcpu_has_run_once(vcpu) (!!READ_ONCE((vcpu)->pid)) > > #ifndef __KVM_NVHE_HYPERVISOR__ > #define kvm_call_hyp_nvhe(f, ...) \ > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h > index 689e8be873a7..d6f4e8b2b44c 100644 > --- a/include/linux/kvm_host.h > +++ b/include/linux/kvm_host.h > @@ -342,7 +342,8 @@ struct kvm_vcpu { > #ifndef __KVM_HAVE_ARCH_WQP > struct rcuwait wait; > #endif > - struct pid __rcu *pid; > + struct pid *pid; > + rwlock_t pid_lock; > int sigset_active; > sigset_t sigset; > unsigned int halt_poll_ns; Adding yet another lock is never exciting, but this looks fine. Can you nest this lock inside of the vcpu->mutex acquisition in kvm_vm_ioctl_create_vcpu() so lockdep gets the picture? > @@ -4466,7 +4469,7 @@ static long kvm_vcpu_ioctl(struct file *filp, > r = -EINVAL; > if (arg) > goto out; > - oldpid = rcu_access_pointer(vcpu->pid); > + oldpid = vcpu->pid; It'd be good to add a comment here about how this is guarded by the vcpu->mutex, as Steve points out. -- Thanks, Oliver