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:
committed by
Keir Fraser
parent
f319b13d12
commit
9e0cc972dd
@@ -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--;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user