KVM: arm64: Add support for relaxing stage-2 perms in generic page-table code
Add support for relaxing the permissions of a stage-2 mapping (i.e. adding additional permissions) to the generic page-table code. Signed-off-by: Will Deacon <will@kernel.org> Signed-off-by: Marc Zyngier <maz@kernel.org> Reviewed-by: Gavin Shan <gshan@redhat.com> Cc: Marc Zyngier <maz@kernel.org> Cc: Quentin Perret <qperret@google.com> Link: https://lore.kernel.org/r/20200911132529.19844-17-will@kernel.org
This commit is contained in:
Родитель
8d5207bef6
Коммит
adcd4e2329
|
@ -236,6 +236,25 @@ kvm_pte_t kvm_pgtable_stage2_mkyoung(struct kvm_pgtable *pgt, u64 addr);
|
|||
*/
|
||||
kvm_pte_t kvm_pgtable_stage2_mkold(struct kvm_pgtable *pgt, u64 addr);
|
||||
|
||||
/**
|
||||
* kvm_pgtable_stage2_relax_perms() - Relax the permissions enforced by a
|
||||
* page-table entry.
|
||||
* @pgt: Page-table structure initialised by kvm_pgtable_stage2_init().
|
||||
* @addr: Intermediate physical address to identify the page-table entry.
|
||||
* @prot: Additional permissions to grant for the mapping.
|
||||
*
|
||||
* The offset of @addr within a page is ignored.
|
||||
*
|
||||
* If there is a valid, leaf page-table entry used to translate @addr, then
|
||||
* relax the permissions in that entry according to the read, write and
|
||||
* execute permissions specified by @prot. No permissions are removed, and
|
||||
* TLB invalidation is performed after updating the entry.
|
||||
*
|
||||
* Return: 0 on success, negative error code on failure.
|
||||
*/
|
||||
int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
|
||||
enum kvm_pgtable_prot prot);
|
||||
|
||||
/**
|
||||
* kvm_pgtable_stage2_is_young() - Test whether a page-table entry has the
|
||||
* access flag set.
|
||||
|
|
|
@ -782,6 +782,26 @@ bool kvm_pgtable_stage2_is_young(struct kvm_pgtable *pgt, u64 addr)
|
|||
return pte & KVM_PTE_LEAF_ATTR_LO_S2_AF;
|
||||
}
|
||||
|
||||
int kvm_pgtable_stage2_relax_perms(struct kvm_pgtable *pgt, u64 addr,
|
||||
enum kvm_pgtable_prot prot)
|
||||
{
|
||||
int ret;
|
||||
kvm_pte_t set = 0, clr = 0;
|
||||
|
||||
if (prot & KVM_PGTABLE_PROT_R)
|
||||
set |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_R;
|
||||
|
||||
if (prot & KVM_PGTABLE_PROT_W)
|
||||
set |= KVM_PTE_LEAF_ATTR_LO_S2_S2AP_W;
|
||||
|
||||
if (prot & KVM_PGTABLE_PROT_X)
|
||||
clr |= KVM_PTE_LEAF_ATTR_HI_S2_XN;
|
||||
|
||||
ret = stage2_update_leaf_attrs(pgt, addr, 1, set, clr, NULL);
|
||||
kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, pgt->mmu, addr, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int stage2_flush_walker(u64 addr, u64 end, u32 level, kvm_pte_t *ptep,
|
||||
enum kvm_pgtable_walk_flags flag,
|
||||
void * const arg)
|
||||
|
|
Загрузка…
Ссылка в новой задаче