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 <qperret@google.com>
[willdeacon@: Move IDs to header and fix S2MPU host_stage2_set_owner() callback]
Bug: 209580772
Change-Id: I37add42a2d7f34aa110c00fd9569d81db279d765
Signed-off-by: Will Deacon <willdeacon@google.com>
This commit is contained in:
Quentin Perret
2021-10-26 10:06:36 +01:00
committed by Will Deacon
parent cc8d7dcc40
commit 5da4a4ca5f
7 changed files with 44 additions and 27 deletions

View File

@@ -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__ */

View File

@@ -0,0 +1,24 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __ARM64_KVM_NVHE_IOMMU_H__
#define __ARM64_KVM_NVHE_IOMMU_H__
#include <linux/types.h>
#include <asm/kvm_host.h>
#include <nvhe/mem_protect.h>
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__ */

View File

@@ -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);

View File

@@ -15,6 +15,7 @@
#include <asm/kvm_hyp.h>
#include <asm/kvm_mmu.h>
#include <nvhe/iommu.h>
#include <nvhe/mem_protect.h>
#include <nvhe/mm.h>
#include <nvhe/pkvm.h>

View File

@@ -13,6 +13,7 @@
#include <linux/arm-smccc.h>
#include <nvhe/iommu.h>
#include <nvhe/memory.h>
#include <nvhe/mm.h>
#include <nvhe/spinlock.h>
@@ -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

View File

@@ -16,6 +16,7 @@
#include <hyp/fault.h>
#include <nvhe/gfp.h>
#include <nvhe/iommu.h>
#include <nvhe/memory.h>
#include <nvhe/mem_protect.h>
#include <nvhe/mm.h>
@@ -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);
}

View File

@@ -12,6 +12,7 @@
#include <nvhe/early_alloc.h>
#include <nvhe/gfp.h>
#include <nvhe/iommu.h>
#include <nvhe/memory.h>
#include <nvhe/mem_protect.h>
#include <nvhe/mm.h>