Skip to content

Commit 9d86c3c

Browse files
ardbiesheuvelwilldeacon
authored andcommitted
arm64/kvm: Avoid invalid physical addresses to signal owner updates
The pKVM stage2 mapping code relies on an invalid physical address to signal to the internal API that only the annotations of descriptors should be updated, and these are stored in the high bits of invalid descriptors covering memory that has been donated to protected guests, and is therefore unmapped from the host stage-2 page tables. Given that these invalid PAs are never stored into the descriptors, it is better to rely on an explicit flag, to clarify the API and to avoid confusion regarding whether or not the output address of a descriptor can ever be invalid to begin with (which is not the case with LPA2). That removes a dependency on the logic that reasons about the maximum PA range, which differs on LPA2 capable CPUs based on whether LPA2 is enabled or not, and will be further clarified in subsequent patches. Cc: Quentin Perret <qperret@google.com> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Quentin Perret <qperret@google.com> Acked-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20241212081841.2168124-12-ardb+git@google.com Signed-off-by: Will Deacon <will@kernel.org>
1 parent f0da169 commit 9d86c3c

File tree

1 file changed

+10
-23
lines changed

1 file changed

+10
-23
lines changed

arch/arm64/kvm/hyp/pgtable.c

Lines changed: 10 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,6 @@ static bool kvm_pgtable_walk_skip_cmo(const struct kvm_pgtable_visit_ctx *ctx)
3535
return unlikely(ctx->flags & KVM_PGTABLE_WALK_SKIP_CMO);
3636
}
3737

38-
static bool kvm_phys_is_valid(u64 phys)
39-
{
40-
u64 parange_max = kvm_get_parange_max();
41-
u8 shift = id_aa64mmfr0_parange_to_phys_shift(parange_max);
42-
43-
return phys < BIT(shift);
44-
}
45-
4638
static bool kvm_block_mapping_supported(const struct kvm_pgtable_visit_ctx *ctx, u64 phys)
4739
{
4840
u64 granule = kvm_granule_size(ctx->level);
@@ -53,7 +45,7 @@ static bool kvm_block_mapping_supported(const struct kvm_pgtable_visit_ctx *ctx,
5345
if (granule > (ctx->end - ctx->addr))
5446
return false;
5547

56-
if (kvm_phys_is_valid(phys) && !IS_ALIGNED(phys, granule))
48+
if (!IS_ALIGNED(phys, granule))
5749
return false;
5850

5951
return IS_ALIGNED(ctx->addr, granule);
@@ -587,6 +579,9 @@ struct stage2_map_data {
587579

588580
/* Force mappings to page granularity */
589581
bool force_pte;
582+
583+
/* Walk should update owner_id only */
584+
bool annotation;
590585
};
591586

592587
u64 kvm_get_vtcr(u64 mmfr0, u64 mmfr1, u32 phys_shift)
@@ -885,18 +880,7 @@ static u64 stage2_map_walker_phys_addr(const struct kvm_pgtable_visit_ctx *ctx,
885880
{
886881
u64 phys = data->phys;
887882

888-
/*
889-
* Stage-2 walks to update ownership data are communicated to the map
890-
* walker using an invalid PA. Avoid offsetting an already invalid PA,
891-
* which could overflow and make the address valid again.
892-
*/
893-
if (!kvm_phys_is_valid(phys))
894-
return phys;
895-
896-
/*
897-
* Otherwise, work out the correct PA based on how far the walk has
898-
* gotten.
899-
*/
883+
/* Work out the correct PA based on how far the walk has gotten */
900884
return phys + (ctx->addr - ctx->start);
901885
}
902886

@@ -908,6 +892,9 @@ static bool stage2_leaf_mapping_allowed(const struct kvm_pgtable_visit_ctx *ctx,
908892
if (data->force_pte && ctx->level < KVM_PGTABLE_LAST_LEVEL)
909893
return false;
910894

895+
if (data->annotation)
896+
return true;
897+
911898
return kvm_block_mapping_supported(ctx, phys);
912899
}
913900

@@ -923,7 +910,7 @@ static int stage2_map_walker_try_leaf(const struct kvm_pgtable_visit_ctx *ctx,
923910
if (!stage2_leaf_mapping_allowed(ctx, data))
924911
return -E2BIG;
925912

926-
if (kvm_phys_is_valid(phys))
913+
if (!data->annotation)
927914
new = kvm_init_valid_leaf_pte(phys, data->attr, ctx->level);
928915
else
929916
new = kvm_init_invalid_leaf_owner(data->owner_id);
@@ -1085,11 +1072,11 @@ int kvm_pgtable_stage2_set_owner(struct kvm_pgtable *pgt, u64 addr, u64 size,
10851072
{
10861073
int ret;
10871074
struct stage2_map_data map_data = {
1088-
.phys = KVM_PHYS_INVALID,
10891075
.mmu = pgt->mmu,
10901076
.memcache = mc,
10911077
.owner_id = owner_id,
10921078
.force_pte = true,
1079+
.annotation = true,
10931080
};
10941081
struct kvm_pgtable_walker walker = {
10951082
.cb = stage2_map_walker,

0 commit comments

Comments
 (0)