113 lines
2.9 KiB
C
113 lines
2.9 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* Copyright (C) 2021 Google LLC
|
|
* Author: Fuad Tabba <tabba@google.com>
|
|
*/
|
|
|
|
#ifndef __ARM64_KVM_NVHE_PKVM_H__
|
|
#define __ARM64_KVM_NVHE_PKVM_H__
|
|
|
|
#include <asm/kvm_pkvm.h>
|
|
|
|
#include <nvhe/gfp.h>
|
|
#include <nvhe/spinlock.h>
|
|
|
|
/*
|
|
* A container for the vcpu state that hyp needs to maintain for protected VMs.
|
|
*/
|
|
struct shadow_vcpu_state {
|
|
struct kvm_shadow_vm *vm;
|
|
struct kvm_vcpu vcpu;
|
|
};
|
|
|
|
/*
|
|
* Holds the relevant data for running a protected vm.
|
|
*/
|
|
struct kvm_shadow_vm {
|
|
/* A unique id to the shadow structs in the hyp shadow area. */
|
|
int shadow_handle;
|
|
|
|
/* Number of vcpus for the vm. */
|
|
int created_vcpus;
|
|
|
|
/* Pointers to the shadow vcpus of the shadow vm. */
|
|
struct kvm_vcpu *vcpus[KVM_MAX_VCPUS];
|
|
|
|
/* Primary vCPU pending entry to the pvmfw */
|
|
struct kvm_vcpu *pvmfw_entry_vcpu;
|
|
|
|
/* The host's kvm structure. */
|
|
struct kvm *host_kvm;
|
|
|
|
/* The total size of the donated shadow area. */
|
|
size_t shadow_area_size;
|
|
|
|
/*
|
|
* The number of vcpus initialized and ready to run in the shadow vm.
|
|
* Modifying this is protected by shadow_lock.
|
|
*/
|
|
unsigned int nr_vcpus;
|
|
|
|
struct kvm_arch arch;
|
|
struct kvm_pgtable pgt;
|
|
struct kvm_pgtable_mm_ops mm_ops;
|
|
struct hyp_pool pool;
|
|
hyp_spinlock_t lock;
|
|
|
|
/* Array of the shadow state pointers per vcpu. */
|
|
struct shadow_vcpu_state *shadow_vcpus[0];
|
|
};
|
|
|
|
static inline bool vcpu_is_protected(struct kvm_vcpu *vcpu)
|
|
{
|
|
if (!is_protected_kvm_enabled())
|
|
return false;
|
|
|
|
return vcpu->arch.pkvm.shadow_vm->arch.pkvm.enabled;
|
|
}
|
|
|
|
extern phys_addr_t pvmfw_base;
|
|
extern phys_addr_t pvmfw_size;
|
|
|
|
void hyp_shadow_table_init(void *tbl);
|
|
int __pkvm_init_shadow(struct kvm *kvm, void *shadow_va, size_t size, void *pgd);
|
|
int __pkvm_init_shadow_vcpu(unsigned int shadow_handle,
|
|
struct kvm_vcpu *host_vcpu,
|
|
void *shadow_vcpu_hva);
|
|
int __pkvm_teardown_shadow(int shadow_handle);
|
|
struct kvm_vcpu *get_shadow_vcpu(int shadow_handle, unsigned int vcpu_idx);
|
|
void put_shadow_vcpu(struct kvm_vcpu *vcpu);
|
|
|
|
u64 pvm_read_id_reg(const struct kvm_vcpu *vcpu, u32 id);
|
|
bool kvm_handle_pvm_sysreg(struct kvm_vcpu *vcpu, u64 *exit_code);
|
|
bool kvm_handle_pvm_restricted(struct kvm_vcpu *vcpu, u64 *exit_code);
|
|
void kvm_reset_pvm_sys_regs(struct kvm_vcpu *vcpu);
|
|
int kvm_check_pvm_sysreg_table(void);
|
|
|
|
void pkvm_reset_vcpu(struct kvm_vcpu *vcpu);
|
|
|
|
bool kvm_handle_pvm_hvc64(struct kvm_vcpu *vcpu, u64 *exit_code);
|
|
|
|
struct kvm_vcpu *pvm_mpidr_to_vcpu(struct kvm_shadow_vm *vm, unsigned long mpidr);
|
|
|
|
static inline bool pvm_has_pvmfw(struct kvm_shadow_vm *vm)
|
|
{
|
|
return vm->arch.pkvm.pvmfw_load_addr != PVMFW_INVALID_LOAD_ADDR;
|
|
}
|
|
|
|
static inline bool ipa_in_pvmfw_region(struct kvm_shadow_vm *vm, u64 ipa)
|
|
{
|
|
struct kvm_protected_vm *pkvm = &vm->arch.pkvm;
|
|
|
|
if (!pvm_has_pvmfw(vm))
|
|
return false;
|
|
|
|
return ipa - pkvm->pvmfw_load_addr < pvmfw_size;
|
|
}
|
|
|
|
int pkvm_load_pvmfw_pages(struct kvm_shadow_vm *vm, u64 ipa, phys_addr_t phys,
|
|
u64 size);
|
|
void pkvm_clear_pvmfw_pages(void);
|
|
|
|
#endif /* __ARM64_KVM_NVHE_PKVM_H__ */
|