Message ID | 20220729091632.777999-2-emil.renner.berthing@canonical.com |
---|---|
State | New |
Headers | show |
Series | Fix RISC-V KVM with u-boot | expand |
On 29.07.22 11:16, Emil Renner Berthing wrote: > From: Anup Patel <apatel@ventanamicro.com> > > BugLink: https://bugs.launchpad.net/bugs/1980594 > > The kvm_riscv_check_vcpu_requests() is called with SRCU read lock held > and for KVM_REQ_SLEEP request it will block the VCPU without releasing > SRCU read lock. This causes KVM ioctls (such as KVM_IOEVENTFD) from > other VCPUs of the same Guest/VM to hang/deadlock if there is any > synchronize_srcu() or synchronize_srcu_expedited() in the path. > > To fix the above in kvm_riscv_check_vcpu_requests(), we should do SRCU > read unlock before blocking the VCPU and do SRCU read lock after VCPU > wakeup. > > Fixes: cce69aff689e ("RISC-V: KVM: Implement VCPU interrupts and requests handling") > Reported-by: Bin Meng <bmeng.cn@gmail.com> > Signed-off-by: Anup Patel <apatel@ventanamicro.com> > Reviewed-by: Atish Patra <atishp@rivosinc.com> > Tested-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> > Tested-by: Bin Meng <bmeng.cn@gmail.com> > Signed-off-by: Anup Patel <anup@brainfault.org> > (backported from commit be82abe6a76ba8e76f25312566182b0f13c4fbf9) > [esmil: open code the srcu lock/unlock that now has static inline wrappers] > Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com> Acked-by: Stefan Bader <stefan.bader@canonical.com> > --- > arch/riscv/kvm/vcpu.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c > index aad430668bb4..5c00a6526dca 100644 > --- a/arch/riscv/kvm/vcpu.c > +++ b/arch/riscv/kvm/vcpu.c > @@ -673,9 +673,11 @@ static void kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu) > > if (kvm_request_pending(vcpu)) { > if (kvm_check_request(KVM_REQ_SLEEP, vcpu)) { > + srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); > rcuwait_wait_event(wait, > (!vcpu->arch.power_off) && (!vcpu->arch.pause), > TASK_INTERRUPTIBLE); > + vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); > > if (vcpu->arch.power_off || vcpu->arch.pause) { > /*
On 29.07.22 11:16, Emil Renner Berthing wrote: > From: Anup Patel <apatel@ventanamicro.com> > > BugLink: https://bugs.launchpad.net/bugs/1980594 > > The kvm_riscv_check_vcpu_requests() is called with SRCU read lock held > and for KVM_REQ_SLEEP request it will block the VCPU without releasing > SRCU read lock. This causes KVM ioctls (such as KVM_IOEVENTFD) from > other VCPUs of the same Guest/VM to hang/deadlock if there is any > synchronize_srcu() or synchronize_srcu_expedited() in the path. > > To fix the above in kvm_riscv_check_vcpu_requests(), we should do SRCU > read unlock before blocking the VCPU and do SRCU read lock after VCPU > wakeup. > > Fixes: cce69aff689e ("RISC-V: KVM: Implement VCPU interrupts and requests handling") > Reported-by: Bin Meng <bmeng.cn@gmail.com> > Signed-off-by: Anup Patel <apatel@ventanamicro.com> > Reviewed-by: Atish Patra <atishp@rivosinc.com> > Tested-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com> > Tested-by: Bin Meng <bmeng.cn@gmail.com> > Signed-off-by: Anup Patel <anup@brainfault.org> > (backported from commit be82abe6a76ba8e76f25312566182b0f13c4fbf9) > [esmil: open code the srcu lock/unlock that now has static inline wrappers] > Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com> Acked-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com> Thanks > --- > arch/riscv/kvm/vcpu.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c > index aad430668bb4..5c00a6526dca 100644 > --- a/arch/riscv/kvm/vcpu.c > +++ b/arch/riscv/kvm/vcpu.c > @@ -673,9 +673,11 @@ static void kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu) > > if (kvm_request_pending(vcpu)) { > if (kvm_check_request(KVM_REQ_SLEEP, vcpu)) { > + srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); > rcuwait_wait_event(wait, > (!vcpu->arch.power_off) && (!vcpu->arch.pause), > TASK_INTERRUPTIBLE); > + vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); > > if (vcpu->arch.power_off || vcpu->arch.pause) { > /*
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c index aad430668bb4..5c00a6526dca 100644 --- a/arch/riscv/kvm/vcpu.c +++ b/arch/riscv/kvm/vcpu.c @@ -673,9 +673,11 @@ static void kvm_riscv_check_vcpu_requests(struct kvm_vcpu *vcpu) if (kvm_request_pending(vcpu)) { if (kvm_check_request(KVM_REQ_SLEEP, vcpu)) { + srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); rcuwait_wait_event(wait, (!vcpu->arch.power_off) && (!vcpu->arch.pause), TASK_INTERRUPTIBLE); + vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); if (vcpu->arch.power_off || vcpu->arch.pause) { /*