From 8247932e264c6eb54369a461e852cd6c38455cf1 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Fri, 30 Jun 2023 17:39:13 +0100 Subject: [PATCH] ANDROID: KVM: arm64: Use atomic refcount helpers for 'struct hyp_page::refcount' Convert the 'struct hyp_page' refcount manipulation functions over to the new atomic refcount helpers. For now, this will make absolutely no difference because the 'struct hyp_pool' locking is still serialising everything. One step at a time... Bug: 357781595 Change-Id: I827042ab26104331a853e95a66a222d5e9e61c55 Signed-off-by: Will Deacon Signed-off-by: Fuad Tabba --- arch/arm64/kvm/hyp/include/nvhe/memory.h | 18 +++++++----------- arch/arm64/kvm/hyp/nvhe/mem_protect.c | 2 +- arch/arm64/kvm/hyp/nvhe/page_alloc.c | 5 ++++- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/arch/arm64/kvm/hyp/include/nvhe/memory.h b/arch/arm64/kvm/hyp/include/nvhe/memory.h index ab205c4d6774..74474c82667b 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/memory.h +++ b/arch/arm64/kvm/hyp/include/nvhe/memory.h @@ -6,6 +6,7 @@ #include #include +#include struct hyp_page { unsigned short refcount; @@ -39,37 +40,32 @@ static inline phys_addr_t hyp_virt_to_phys(void *addr) #define hyp_page_to_pool(page) (((struct hyp_page *)page)->pool) /* - * Refcounting for 'struct hyp_page'. - * hyp_pool::lock must be held if atomic access to the refcount is required. + * Refcounting wrappers for 'struct hyp_page'. */ static inline int hyp_page_count(void *addr) { struct hyp_page *p = hyp_virt_to_page(addr); - return p->refcount; + return hyp_refcount_get(p->refcount); } static inline void hyp_page_ref_inc(struct hyp_page *p) { - BUG_ON(p->refcount == USHRT_MAX); - p->refcount++; + hyp_refcount_inc(p->refcount); } static inline void hyp_page_ref_dec(struct hyp_page *p) { - BUG_ON(!p->refcount); - p->refcount--; + hyp_refcount_dec(p->refcount); } static inline int hyp_page_ref_dec_and_test(struct hyp_page *p) { - hyp_page_ref_dec(p); - return (p->refcount == 0); + return hyp_refcount_dec(p->refcount) == 0; } static inline void hyp_set_page_refcounted(struct hyp_page *p) { - BUG_ON(p->refcount); - p->refcount = 1; + hyp_refcount_set(p->refcount, 1); } #endif /* __KVM_HYP_MEMORY_H */ diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index caba3e4bd09e..ab5e73a82857 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -202,7 +202,7 @@ static void *guest_s2_zalloc_page(void *mc) memset(addr, 0, PAGE_SIZE); p = hyp_virt_to_page(addr); memset(p, 0, sizeof(*p)); - p->refcount = 1; + hyp_set_page_refcounted(p); return addr; } diff --git a/arch/arm64/kvm/hyp/nvhe/page_alloc.c b/arch/arm64/kvm/hyp/nvhe/page_alloc.c index e691290d3765..169cdb43b4b8 100644 --- a/arch/arm64/kvm/hyp/nvhe/page_alloc.c +++ b/arch/arm64/kvm/hyp/nvhe/page_alloc.c @@ -55,7 +55,10 @@ static struct hyp_page *__find_buddy_avail(struct hyp_pool *pool, { struct hyp_page *buddy = __find_buddy_nocheck(pool, p, order); - if (!buddy || buddy->order != order || buddy->refcount) + if (!buddy) + return NULL; + + if (buddy->order != order || hyp_refcount_get(buddy->refcount)) return NULL; return buddy;