Message ID | b2f9b79d15166f2c3e4375c0d9bc3268b7696455.1620332081.git.thomas.lendacky@amd.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | KVM: SVM: Move GHCB unmapping to fix RCU warning | expand |
On 5/6/21 3:14 PM, Tom Lendacky wrote: > When an SEV-ES guest is running, the GHCB is unmapped as part of the > vCPU run support. However, kvm_vcpu_unmap() triggers an RCU dereference > warning with CONFIG_PROVE_LOCKING=y because the SRCU lock is released > before invoking the vCPU run support. > > Move the GHCB unmapping into the prepare_guest_switch callback, which is > invoked while still holding the SRCU lock, eliminating the RCU dereference > warning. > > Fixes: 291bd20d5d88 ("KVM: SVM: Add initial support for a VMGEXIT VMEXIT") I added the Fixes: tag in case this is to be sent back to stable. But, 5.11 SVM support doesn't have the prepare_guest_switch callback, it was added in 5.12. This will apply to 5.12 with some fuzz. Thanks, Tom > Reported-by: Borislav Petkov <bp@alien8.de> > Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> > --- > arch/x86/kvm/svm/sev.c | 5 +---- > arch/x86/kvm/svm/svm.c | 3 +++ > arch/x86/kvm/svm/svm.h | 1 + > 3 files changed, 5 insertions(+), 4 deletions(-) > > diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c > index a9d8d6aafdb8..5f70be4e36aa 100644 > --- a/arch/x86/kvm/svm/sev.c > +++ b/arch/x86/kvm/svm/sev.c > @@ -2198,7 +2198,7 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) > return -EINVAL; > } > > -static void pre_sev_es_run(struct vcpu_svm *svm) > +void sev_es_unmap_ghcb(struct vcpu_svm *svm) > { > if (!svm->ghcb) > return; > @@ -2234,9 +2234,6 @@ void pre_sev_run(struct vcpu_svm *svm, int cpu) > struct svm_cpu_data *sd = per_cpu(svm_data, cpu); > int asid = sev_get_asid(svm->vcpu.kvm); > > - /* Perform any SEV-ES pre-run actions */ > - pre_sev_es_run(svm); > - > /* Assign the asid allocated with this SEV guest */ > svm->asid = asid; > > diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c > index a7271f31df47..e9f9aacc8f51 100644 > --- a/arch/x86/kvm/svm/svm.c > +++ b/arch/x86/kvm/svm/svm.c > @@ -1424,6 +1424,9 @@ static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu) > struct vcpu_svm *svm = to_svm(vcpu); > struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu); > > + if (sev_es_guest(vcpu->kvm)) > + sev_es_unmap_ghcb(svm); > + > if (svm->guest_state_loaded) > return; > > diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h > index 84b3133c2251..e44567ceb865 100644 > --- a/arch/x86/kvm/svm/svm.h > +++ b/arch/x86/kvm/svm/svm.h > @@ -581,6 +581,7 @@ void sev_es_init_vmcb(struct vcpu_svm *svm); > void sev_es_create_vcpu(struct vcpu_svm *svm); > void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector); > void sev_es_prepare_guest_switch(struct vcpu_svm *svm, unsigned int cpu); > +void sev_es_unmap_ghcb(struct vcpu_svm *svm); > > /* vmenter.S */ > >
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index a9d8d6aafdb8..5f70be4e36aa 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -2198,7 +2198,7 @@ static int sev_es_validate_vmgexit(struct vcpu_svm *svm) return -EINVAL; } -static void pre_sev_es_run(struct vcpu_svm *svm) +void sev_es_unmap_ghcb(struct vcpu_svm *svm) { if (!svm->ghcb) return; @@ -2234,9 +2234,6 @@ void pre_sev_run(struct vcpu_svm *svm, int cpu) struct svm_cpu_data *sd = per_cpu(svm_data, cpu); int asid = sev_get_asid(svm->vcpu.kvm); - /* Perform any SEV-ES pre-run actions */ - pre_sev_es_run(svm); - /* Assign the asid allocated with this SEV guest */ svm->asid = asid; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index a7271f31df47..e9f9aacc8f51 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -1424,6 +1424,9 @@ static void svm_prepare_guest_switch(struct kvm_vcpu *vcpu) struct vcpu_svm *svm = to_svm(vcpu); struct svm_cpu_data *sd = per_cpu(svm_data, vcpu->cpu); + if (sev_es_guest(vcpu->kvm)) + sev_es_unmap_ghcb(svm); + if (svm->guest_state_loaded) return; diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 84b3133c2251..e44567ceb865 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -581,6 +581,7 @@ void sev_es_init_vmcb(struct vcpu_svm *svm); void sev_es_create_vcpu(struct vcpu_svm *svm); void sev_vcpu_deliver_sipi_vector(struct kvm_vcpu *vcpu, u8 vector); void sev_es_prepare_guest_switch(struct vcpu_svm *svm, unsigned int cpu); +void sev_es_unmap_ghcb(struct vcpu_svm *svm); /* vmenter.S */
When an SEV-ES guest is running, the GHCB is unmapped as part of the vCPU run support. However, kvm_vcpu_unmap() triggers an RCU dereference warning with CONFIG_PROVE_LOCKING=y because the SRCU lock is released before invoking the vCPU run support. Move the GHCB unmapping into the prepare_guest_switch callback, which is invoked while still holding the SRCU lock, eliminating the RCU dereference warning. Fixes: 291bd20d5d88 ("KVM: SVM: Add initial support for a VMGEXIT VMEXIT") Reported-by: Borislav Petkov <bp@alien8.de> Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> --- arch/x86/kvm/svm/sev.c | 5 +---- arch/x86/kvm/svm/svm.c | 3 +++ arch/x86/kvm/svm/svm.h | 1 + 3 files changed, 5 insertions(+), 4 deletions(-)