ANDROID: KVM: arm64: Restore memcache representation

Recently, order was added to memcache, and the idea was to encode the
order in the PAGE_SIZE bits as memcache is always page aligned.
However, due to wrong usage of FIELD_*, now the address is shifted
by PAGE_SIZE, which can cause address corruption under some
configurations.

Also, the naming of the macros make things confusing, just use
PAGE_MASK as it make things more clear.

Bug: 357781595
Bug: 333874255
Bug: 277989609
Bug: 278749606

Change-Id: I2782f8995b7230300b524e2197b607426b2ed250
Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
Mostafa Saleh
2024-04-13 11:49:12 +00:00
committed by Keir Fraser
parent f319b13d12
commit 9e0cc972dd
2 changed files with 7 additions and 9 deletions
+4 -6
View File
@@ -85,8 +85,6 @@ void kvm_reset_vcpu(struct kvm_vcpu *vcpu);
void kvm_arm_vcpu_destroy(struct kvm_vcpu *vcpu);
/* Head holds page head and it's order. */
#define HYP_MC_PTR_MASK GENMASK_ULL(63, PAGE_SHIFT)
#define HYP_MC_ORDER_MASK GENMASK_ULL(PAGE_SHIFT - 1, 0)
struct kvm_hyp_memcache {
phys_addr_t head;
unsigned long nr_pages;
@@ -99,8 +97,8 @@ static inline void push_hyp_memcache(struct kvm_hyp_memcache *mc,
unsigned long order)
{
*p = mc->head;
mc->head = FIELD_PREP(HYP_MC_PTR_MASK, to_pa(p)) |
FIELD_PREP(HYP_MC_ORDER_MASK, order);
mc->head = (to_pa(p) & PAGE_MASK) |
FIELD_PREP(~PAGE_MASK, order);
mc->nr_pages++;
}
@@ -108,12 +106,12 @@ static inline void *pop_hyp_memcache(struct kvm_hyp_memcache *mc,
void *(*to_va)(phys_addr_t phys),
unsigned long *order)
{
phys_addr_t *p = to_va(FIELD_GET(HYP_MC_PTR_MASK, mc->head));
phys_addr_t *p = to_va(mc->head & PAGE_MASK);
if (!mc->nr_pages)
return NULL;
*order = FIELD_GET(HYP_MC_ORDER_MASK, mc->head);
*order = FIELD_GET(~PAGE_MASK, mc->head);
mc->head = *p;
mc->nr_pages--;
+3 -3
View File
@@ -478,10 +478,10 @@ static void *admit_host_page(void *arg, unsigned long order)
if (!host_mc->nr_pages)
return NULL;
mc_order = FIELD_GET(HYP_MC_ORDER_MASK, host_mc->head);
mc_order = FIELD_GET(~PAGE_MASK, host_mc->head);
BUG_ON(order != mc_order);
p = FIELD_GET(HYP_MC_PTR_MASK, host_mc->head);
p = host_mc->head & PAGE_MASK;
/*
* The host still owns the pages in its memcache, so we need to go
* through a full host-to-hyp donation cycle to change it. Fortunately,
@@ -529,7 +529,7 @@ int refill_hyp_pool(struct hyp_pool *pool, struct kvm_hyp_memcache *host_mc)
void *p;
while (host_mc->nr_pages) {
order = host_mc->head & (PAGE_SIZE - 1);
order = FIELD_GET(~PAGE_MASK, host_mc->head);
p = admit_host_page(host_mc, order);
if (!p)
return -EINVAL;