From 5da4a4ca5f6805c27ccd1fc48e4bec11764819d2 Mon Sep 17 00:00:00 2001 From: Quentin Perret Date: Tue, 26 Oct 2021 10:06:36 +0100 Subject: [PATCH] ANDROID: BACKPORT: KVM: arm64: Make owner ids 32 bits wide We will soon need more than 8 bits to encode all possible owner ids in KVM protected mode. To prepare the ground for this, introduce a new type for owner_ids, and make it a 32bits wide. Signed-off-by: Quentin Perret [willdeacon@: Move IDs to header and fix S2MPU host_stage2_set_owner() callback] Bug: 209580772 Change-Id: I37add42a2d7f34aa110c00fd9569d81db279d765 Signed-off-by: Will Deacon --- arch/arm64/include/asm/kvm_hyp.h | 14 ----------- arch/arm64/kvm/hyp/include/nvhe/iommu.h | 24 +++++++++++++++++++ arch/arm64/kvm/hyp/include/nvhe/mem_protect.h | 7 ++++-- arch/arm64/kvm/hyp/nvhe/hyp-main.c | 1 + arch/arm64/kvm/hyp/nvhe/iommu/s2mpu.c | 8 +++++-- arch/arm64/kvm/hyp/nvhe/mem_protect.c | 16 ++++++------- arch/arm64/kvm/hyp/nvhe/setup.c | 1 + 7 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 arch/arm64/kvm/hyp/include/nvhe/iommu.h diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h index 328ce108d0f1..1ac15eb60f8e 100644 --- a/arch/arm64/include/asm/kvm_hyp.h +++ b/arch/arm64/include/asm/kvm_hyp.h @@ -123,18 +123,4 @@ extern u64 kvm_nvhe_sym(id_aa64mmfr0_el1_sys_val); extern u64 kvm_nvhe_sym(id_aa64mmfr1_el1_sys_val); extern u64 kvm_nvhe_sym(id_aa64mmfr2_el1_sys_val); -struct kvm_iommu_ops { - int (*init)(void); - bool (*host_smc_handler)(struct kvm_cpu_context *host_ctxt); - bool (*host_mmio_dabt_handler)(struct kvm_cpu_context *host_ctxt, - phys_addr_t fault_pa, unsigned int len, - bool is_write, int rd); - void (*host_stage2_set_owner)(phys_addr_t addr, size_t size, u8 owner_id); - int (*host_stage2_adjust_mmio_range)(phys_addr_t addr, phys_addr_t *start, - phys_addr_t *end); -}; - -extern struct kvm_iommu_ops kvm_iommu_ops; -extern const struct kvm_iommu_ops kvm_s2mpu_ops; - #endif /* __ARM64_KVM_HYP_H__ */ diff --git a/arch/arm64/kvm/hyp/include/nvhe/iommu.h b/arch/arm64/kvm/hyp/include/nvhe/iommu.h new file mode 100644 index 000000000000..78f88dbc8856 --- /dev/null +++ b/arch/arm64/kvm/hyp/include/nvhe/iommu.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +#ifndef __ARM64_KVM_NVHE_IOMMU_H__ +#define __ARM64_KVM_NVHE_IOMMU_H__ + +#include +#include + +#include + +struct kvm_iommu_ops { + int (*init)(void); + bool (*host_smc_handler)(struct kvm_cpu_context *host_ctxt); + bool (*host_mmio_dabt_handler)(struct kvm_cpu_context *host_ctxt, + phys_addr_t fault_pa, unsigned int len, + bool is_write, int rd); + void (*host_stage2_set_owner)(phys_addr_t addr, size_t size, pkvm_id owner_id); + int (*host_stage2_adjust_mmio_range)(phys_addr_t addr, phys_addr_t *start, + phys_addr_t *end); +}; + +extern struct kvm_iommu_ops kvm_iommu_ops; +extern const struct kvm_iommu_ops kvm_s2mpu_ops; + +#endif /* __ARM64_KVM_NVHE_IOMMU_H__ */ diff --git a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h index d1db0b29d27f..fa83c2fa7b9d 100644 --- a/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h +++ b/arch/arm64/kvm/hyp/include/nvhe/mem_protect.h @@ -51,7 +51,10 @@ struct host_kvm { }; extern struct host_kvm host_kvm; -extern const u8 pkvm_hyp_id; +typedef u32 pkvm_id; +static const pkvm_id pkvm_host_id = 0; +static const pkvm_id pkvm_hyp_id = 1; +static const pkvm_id pkvm_guest_id = 2; extern unsigned long hyp_nr_cpus; @@ -64,7 +67,7 @@ int __pkvm_host_share_guest(u64 pfn, u64 gfn, struct kvm_vcpu *vcpu); bool addr_is_memory(phys_addr_t phys); int host_stage2_idmap_locked(phys_addr_t addr, u64 size, enum kvm_pgtable_prot prot); -int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, u8 owner_id); +int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, pkvm_id owner_id); int kvm_host_prepare_stage2(void *pgt_pool_base); int kvm_guest_prepare_stage2(struct kvm_shadow_vm *vm, void *pgd); void handle_host_mem_abort(struct kvm_cpu_context *host_ctxt); diff --git a/arch/arm64/kvm/hyp/nvhe/hyp-main.c b/arch/arm64/kvm/hyp/nvhe/hyp-main.c index 1d6d8a740d3e..8e43c96470de 100644 --- a/arch/arm64/kvm/hyp/nvhe/hyp-main.c +++ b/arch/arm64/kvm/hyp/nvhe/hyp-main.c @@ -15,6 +15,7 @@ #include #include +#include #include #include #include diff --git a/arch/arm64/kvm/hyp/nvhe/iommu/s2mpu.c b/arch/arm64/kvm/hyp/nvhe/iommu/s2mpu.c index ab4d8aefcb3c..ad5716cd51ee 100644 --- a/arch/arm64/kvm/hyp/nvhe/iommu/s2mpu.c +++ b/arch/arm64/kvm/hyp/nvhe/iommu/s2mpu.c @@ -13,6 +13,7 @@ #include +#include #include #include #include @@ -254,10 +255,13 @@ static void set_mpt_range_locked(struct mpt *mpt, phys_addr_t first_byte, __range_invalidation(dev, first_byte, last_byte); } -static void s2mpu_host_stage2_set_owner(phys_addr_t addr, size_t size, u8 owner_id) +static void s2mpu_host_stage2_set_owner(phys_addr_t addr, size_t size, + pkvm_id owner_id) { + enum mpt_prot prot; + /* Grant access only to the default owner of the page table (ID=0). */ - enum mpt_prot prot = owner_id ? MPT_PROT_NONE : MPT_PROT_RW; + prot = owner_id == pkvm_host_id ? MPT_PROT_RW : MPT_PROT_NONE; /* * NOTE: The following code refers to 'end' as the exclusive upper diff --git a/arch/arm64/kvm/hyp/nvhe/mem_protect.c b/arch/arm64/kvm/hyp/nvhe/mem_protect.c index 3d3b1e96f9b0..062258f91fa3 100644 --- a/arch/arm64/kvm/hyp/nvhe/mem_protect.c +++ b/arch/arm64/kvm/hyp/nvhe/mem_protect.c @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -28,9 +29,6 @@ struct host_kvm host_kvm; static struct hyp_pool host_s2_pool; -const u8 pkvm_host_id = 0; -const u8 pkvm_hyp_id = 1; - static DEFINE_PER_CPU(struct kvm_shadow_vm *, __current_vm); #define current_vm (*this_cpu_ptr(&__current_vm)) @@ -513,14 +511,14 @@ int host_stage2_idmap_locked(phys_addr_t addr, u64 size, return host_stage2_try(__host_stage2_idmap, addr, addr + size, prot); } -#define KVM_INVALID_PTE_OWNER_MASK GENMASK(9, 2) -static kvm_pte_t kvm_init_invalid_leaf_owner(u8 owner_id) +#define KVM_INVALID_PTE_OWNER_MASK GENMASK(32, 1) +static kvm_pte_t kvm_init_invalid_leaf_owner(pkvm_id owner_id) { return FIELD_PREP(KVM_INVALID_PTE_OWNER_MASK, owner_id); } int host_stage2_set_owner_locked(phys_addr_t addr, u64 size, - u8 owner_id) + pkvm_id owner_id) { kvm_pte_t annotation = kvm_init_invalid_leaf_owner(owner_id); int ret; @@ -682,7 +680,7 @@ struct pkvm_mem_donation { const struct pkvm_mem_transition tx; }; -static u8 completer_owner_id(const struct pkvm_mem_transition *tx) +static pkvm_id completer_owner_id(const struct pkvm_mem_transition *tx) { switch (tx->completer.id) { case PKVM_ID_HOST: @@ -797,7 +795,7 @@ static int host_initiate_unshare(u64 *completer_addr, static int host_initiate_donation(u64 *completer_addr, const struct pkvm_mem_transition *tx) { - u8 owner_id = completer_owner_id(tx); + pkvm_id owner_id = completer_owner_id(tx); u64 size = tx->nr_pages * PAGE_SIZE; *completer_addr = tx->initiator.host.completer_addr; @@ -823,7 +821,7 @@ static int host_ack_donation(u64 addr, const struct pkvm_mem_transition *tx) static int host_complete_donation(u64 addr, const struct pkvm_mem_transition *tx) { u64 size = tx->nr_pages * PAGE_SIZE; - u8 host_id = completer_owner_id(tx); + pkvm_id host_id = completer_owner_id(tx); return host_stage2_set_owner_locked(addr, size, host_id); } diff --git a/arch/arm64/kvm/hyp/nvhe/setup.c b/arch/arm64/kvm/hyp/nvhe/setup.c index 5c8d45d31bf2..3e5099074dae 100644 --- a/arch/arm64/kvm/hyp/nvhe/setup.c +++ b/arch/arm64/kvm/hyp/nvhe/setup.c @@ -12,6 +12,7 @@ #include #include +#include #include #include #include