summaryrefslogtreecommitdiff
path: root/arch/arm64
diff options
context:
space:
mode:
authorKeisuke Nishimura <keisuke.nishimura@inria.fr>2024-11-30 15:49:53 +0100
committerOliver Upton <oliver.upton@linux.dev>2024-12-03 16:22:10 -0800
commitbe7e611274224b23776469d7f7ce50e25ac53142 (patch)
tree0a9db03a68ccd2cbe157252f43cd56959e7fb56a /arch/arm64
parent03c7527e97f73081633d773f9f8c2373f9854b25 (diff)
downloadlwn-be7e611274224b23776469d7f7ce50e25ac53142.tar.gz
lwn-be7e611274224b23776469d7f7ce50e25ac53142.zip
KVM: arm64: vgic-its: Add error handling in vgic_its_cache_translation
The return value of xa_store() needs to be checked. This fix adds an error handling path that resolves the kref inconsistency on failure. As suggested by Oliver Upton, this function does not return the error code intentionally because the translation cache is best effort. Fixes: 8201d1028caa ("KVM: arm64: vgic-its: Maintain a translation cache per ITS") Signed-off-by: Keisuke Nishimura <keisuke.nishimura@inria.fr> Suggested-by: Oliver Upton <oliver.upton@linux.dev> Acked-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20241130144952.23729-1-keisuke.nishimura@inria.fr Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Diffstat (limited to 'arch/arm64')
-rw-r--r--arch/arm64/kvm/vgic/vgic-its.c12
1 files changed, 11 insertions, 1 deletions
diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
index f4c4494645c3..fb96802799c6 100644
--- a/arch/arm64/kvm/vgic/vgic-its.c
+++ b/arch/arm64/kvm/vgic/vgic-its.c
@@ -608,12 +608,22 @@ static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
lockdep_assert_held(&its->its_lock);
vgic_get_irq_kref(irq);
+ old = xa_store(&its->translation_cache, cache_key, irq, GFP_KERNEL_ACCOUNT);
+
+ /*
+ * Put the reference taken on @irq if the store fails. Intentionally do
+ * not return the error as the translation cache is best effort.
+ */
+ if (xa_is_err(old)) {
+ vgic_put_irq(kvm, irq);
+ return;
+ }
+
/*
* We could have raced with another CPU caching the same
* translation behind our back, ensure we don't leak a
* reference if that is the case.
*/
- old = xa_store(&its->translation_cache, cache_key, irq, GFP_KERNEL_ACCOUNT);
if (old)
vgic_put_irq(kvm, old);
}