ANDROID: KVM: arm64: Skip prefaulting ptes which will be modified later
Block mappings can be split as part of a page table update. When prefaulting entries during the split, it is pointless to install valid ptes which will later be modified by the same walk. At the same time, push the check for pte_is_counted into the prefault handler, where it logically belongs. Bug: 308373293 Change-Id: If4599b2860aa62d82ce8db019a8410c2d883de71 Signed-off-by: Keir Fraser <keirf@google.com>
This commit is contained in:
parent
fbc707442c
commit
4fa87d4d8f
1 changed files with 18 additions and 11 deletions
|
|
@ -783,19 +783,27 @@ static int stage2_map_walk_table_pre(u64 addr, u64 end, u32 level,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static void stage2_map_prefault_idmap(u64 addr, u32 level, kvm_pte_t *ptep,
|
||||
kvm_pte_t attr)
|
||||
static void stage2_map_prefault_idmap(struct kvm_pgtable_pte_ops *pte_ops,
|
||||
u64 addr, u64 end, u32 level,
|
||||
kvm_pte_t *ptep, kvm_pte_t block_pte)
|
||||
{
|
||||
u64 granule = kvm_granule_size(level);
|
||||
u64 pa, granule;
|
||||
int i;
|
||||
|
||||
if (!kvm_pte_valid(attr))
|
||||
WARN_ON(pte_ops->pte_is_counted_cb(block_pte, level-1));
|
||||
|
||||
if (!kvm_pte_valid(block_pte))
|
||||
return;
|
||||
|
||||
for (i = 0; i < PTRS_PER_PTE; ++i, ++ptep, addr += granule) {
|
||||
kvm_pte_t pte = kvm_init_valid_leaf_pte(addr, attr, level);
|
||||
/* We can write non-atomically: ptep isn't yet live. */
|
||||
*ptep = pte;
|
||||
pa = ALIGN_DOWN(addr, kvm_granule_size(level-1));
|
||||
granule = kvm_granule_size(level);
|
||||
for (i = 0; i < PTRS_PER_PTE; ++i, ++ptep, pa += granule) {
|
||||
kvm_pte_t pte = kvm_init_valid_leaf_pte(pa, block_pte, level);
|
||||
/* Skip ptes in the range being modified by the caller. */
|
||||
if ((pa < addr) || (pa >= end)) {
|
||||
/* We can write non-atomically: ptep isn't yet live. */
|
||||
*ptep = pte;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -830,9 +838,8 @@ static int stage2_map_walk_leaf(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
|
|||
return -ENOMEM;
|
||||
|
||||
if (pgt->flags & KVM_PGTABLE_S2_IDMAP) {
|
||||
WARN_ON(pte_ops->pte_is_counted_cb(pte, level));
|
||||
addr = ALIGN_DOWN(addr, kvm_granule_size(level));
|
||||
stage2_map_prefault_idmap(addr, level + 1, childp, pte);
|
||||
stage2_map_prefault_idmap(pte_ops, addr, end, level + 1,
|
||||
childp, pte);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue