mirror of
https://github.com/torvalds/linux.git
synced 2026-04-18 06:44:00 -04:00
KVM: arm64: Generalise kvm_pgtable_stage2_set_owner()
kvm_pgtable_stage2_set_owner() can be generalised into a way to store up to 59 bits in the page tables alongside a 4-bit 'type' identifier specific to the format of the 59-bit payload. Introduce kvm_pgtable_stage2_annotate() and move the existing invalid ptes (for locked ptes and donated pages) over to the new scheme. Tested-by: Fuad Tabba <tabba@google.com> Tested-by: Mostafa Saleh <smostafa@google.com> Signed-off-by: Will Deacon <will@kernel.org> Link: https://patch.msgid.link/20260330144841.26181-22-will@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
committed by
Marc Zyngier
parent
664d616903
commit
c6ba94640c
@@ -114,11 +114,6 @@ static kvm_pte_t kvm_init_valid_leaf_pte(u64 pa, kvm_pte_t attr, s8 level)
|
||||
return pte;
|
||||
}
|
||||
|
||||
static kvm_pte_t kvm_init_invalid_leaf_owner(u8 owner_id)
|
||||
{
|
||||
return FIELD_PREP(KVM_INVALID_PTE_OWNER_MASK, owner_id);
|
||||
}
|
||||
|
||||
static int kvm_pgtable_visitor_cb(struct kvm_pgtable_walk_data *data,
|
||||
const struct kvm_pgtable_visit_ctx *ctx,
|
||||
enum kvm_pgtable_walk_flags visit)
|
||||
@@ -581,7 +576,7 @@ void kvm_pgtable_hyp_destroy(struct kvm_pgtable *pgt)
|
||||
struct stage2_map_data {
|
||||
const u64 phys;
|
||||
kvm_pte_t attr;
|
||||
u8 owner_id;
|
||||
kvm_pte_t pte_annot;
|
||||
|
||||
kvm_pte_t *anchor;
|
||||
kvm_pte_t *childp;
|
||||
@@ -798,7 +793,11 @@ static bool stage2_pte_is_counted(kvm_pte_t pte)
|
||||
|
||||
static bool stage2_pte_is_locked(kvm_pte_t pte)
|
||||
{
|
||||
return !kvm_pte_valid(pte) && (pte & KVM_INVALID_PTE_LOCKED);
|
||||
if (kvm_pte_valid(pte))
|
||||
return false;
|
||||
|
||||
return FIELD_GET(KVM_INVALID_PTE_TYPE_MASK, pte) ==
|
||||
KVM_INVALID_PTE_TYPE_LOCKED;
|
||||
}
|
||||
|
||||
static bool stage2_try_set_pte(const struct kvm_pgtable_visit_ctx *ctx, kvm_pte_t new)
|
||||
@@ -829,6 +828,7 @@ static bool stage2_try_break_pte(const struct kvm_pgtable_visit_ctx *ctx,
|
||||
struct kvm_s2_mmu *mmu)
|
||||
{
|
||||
struct kvm_pgtable_mm_ops *mm_ops = ctx->mm_ops;
|
||||
kvm_pte_t locked_pte;
|
||||
|
||||
if (stage2_pte_is_locked(ctx->old)) {
|
||||
/*
|
||||
@@ -839,7 +839,9 @@ static bool stage2_try_break_pte(const struct kvm_pgtable_visit_ctx *ctx,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!stage2_try_set_pte(ctx, KVM_INVALID_PTE_LOCKED))
|
||||
locked_pte = FIELD_PREP(KVM_INVALID_PTE_TYPE_MASK,
|
||||
KVM_INVALID_PTE_TYPE_LOCKED);
|
||||
if (!stage2_try_set_pte(ctx, locked_pte))
|
||||
return false;
|
||||
|
||||
if (!kvm_pgtable_walk_skip_bbm_tlbi(ctx)) {
|
||||
@@ -964,7 +966,7 @@ static int stage2_map_walker_try_leaf(const struct kvm_pgtable_visit_ctx *ctx,
|
||||
if (!data->annotation)
|
||||
new = kvm_init_valid_leaf_pte(phys, data->attr, ctx->level);
|
||||
else
|
||||
new = kvm_init_invalid_leaf_owner(data->owner_id);
|
||||
new = data->pte_annot;
|
||||
|
||||
/*
|
||||
* Skip updating the PTE if we are trying to recreate the exact
|
||||
@@ -1118,16 +1120,18 @@ int kvm_pgtable_stage2_map(struct kvm_pgtable *pgt, u64 addr, u64 size,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int kvm_pgtable_stage2_set_owner(struct kvm_pgtable *pgt, u64 addr, u64 size,
|
||||
void *mc, u8 owner_id)
|
||||
int kvm_pgtable_stage2_annotate(struct kvm_pgtable *pgt, u64 addr, u64 size,
|
||||
void *mc, enum kvm_invalid_pte_type type,
|
||||
kvm_pte_t pte_annot)
|
||||
{
|
||||
int ret;
|
||||
struct stage2_map_data map_data = {
|
||||
.mmu = pgt->mmu,
|
||||
.memcache = mc,
|
||||
.owner_id = owner_id,
|
||||
.force_pte = true,
|
||||
.annotation = true,
|
||||
.pte_annot = pte_annot |
|
||||
FIELD_PREP(KVM_INVALID_PTE_TYPE_MASK, type),
|
||||
};
|
||||
struct kvm_pgtable_walker walker = {
|
||||
.cb = stage2_map_walker,
|
||||
@@ -1136,7 +1140,10 @@ int kvm_pgtable_stage2_set_owner(struct kvm_pgtable *pgt, u64 addr, u64 size,
|
||||
.arg = &map_data,
|
||||
};
|
||||
|
||||
if (owner_id > KVM_MAX_OWNER_ID)
|
||||
if (pte_annot & ~KVM_INVALID_PTE_ANNOT_MASK)
|
||||
return -EINVAL;
|
||||
|
||||
if (!type || type == KVM_INVALID_PTE_TYPE_LOCKED)
|
||||
return -EINVAL;
|
||||
|
||||
ret = kvm_pgtable_walk(pgt, addr, size, &walker);
|
||||
|
||||
Reference in New Issue
Block a user