From 9d6994b7e3697da8a6f7db595003e989ba135eb2 Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Mon, 30 Jan 2023 16:07:44 +0000 Subject: [PATCH] ANDROID: KVM: arm64: Introduce module-owned pages In order to let vendor pKVM modules change the permission of host pages, introduce a new concept of module-owned pages. This flag is stored in the vmemmap so it can be set for pages that have been unmapped from the host and for which the stage-2 PTEs are invalid. Bug: 264070847 Change-Id: Ic831d3873cf7d31a2bd9f411306d657cc2f4db01 Signed-off-by: Quentin Perret --- arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 1 + arch/arm64/kvm/hyp/include/nvhe/memory.h | 1 + arch/arm64/kvm/hyp/nvhe/mem_protect.c | 6 +++++- 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h index ef1573d26036..7e625669bce2 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h +++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h @@ -32,6 +32,7 @@ enum pkvm_page_state { /* Meta-states which aren't encoded directly in the PTE's SW bits */ PKVM_NOPAGE = BIT(0), PKVM_PAGE_RESTRICTED_PROT = BIT(1), + PKVM_MODULE_DONT_TOUCH = BIT(2), }; #define PKVM_PAGE_STATE_PROT_MASK (KVM_PGTABLE_PROT_SW0 | KVM_PGTABLE_PROT_SW1) diff --git a/arch/arm64/kvm/hyp/include/nvhe/memory.h b/arch/arm64/kvm/hyp/include/nvhe/memory.h index a8d4a5b919d2..74d7d3b506c0 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/memory.h +++ b/arch/arm64/kvm/hyp/include/nvhe/memory.h @@ -13,6 +13,7 @@ */ #define HOST_PAGE_NEED_POISONING BIT(0) #define HOST_PAGE_PENDING_RECLAIM BIT(1) +#define MODULE_OWNED_PAGE BIT(2) struct hyp_page { unsigned short refcount; diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index 56ac2519b0e5..944fc2f7c5e3 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -903,15 +903,19 @@ static int check_page_state_range(struct kvm_pgtable *pgt, u64 addr, u64 size, static enum pkvm_page_state host_get_page_state(kvm_pte_t pte, u64 addr) { + bool is_memory = addr_is_memory(addr); enum pkvm_page_state state = 0; enum kvm_pgtable_prot prot; + if (is_memory && hyp_phys_to_page(addr)->flags & MODULE_OWNED_PAGE) + return PKVM_MODULE_DONT_TOUCH; + if (!kvm_pte_valid(pte) && pte) return PKVM_NOPAGE; prot = kvm_pgtable_stage2_pte_prot(pte); if (kvm_pte_valid(pte)) { - if ((prot & KVM_PGTABLE_PROT_RWX) != default_host_prot(addr_is_memory(addr))) + if ((prot & KVM_PGTABLE_PROT_RWX) != default_host_prot(is_memory)) state = PKVM_PAGE_RESTRICTED_PROT; }