mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
ANDROID: KVM: arm64: Restrict protected VM capabilities
Restrict protected VM capabilities based on the fixed-configuration for protected VMs. No functional change intended in current KVM-supported modes (nVHE, VHE). Signed-off-by: Fuad Tabba <tabba@google.com> Bug: 209580772 Change-Id: Ic247aefac8b4046efaa69d24580f7c58aaeeb80d Signed-off-by: Will Deacon <willdeacon@google.com>
This commit is contained in:
@@ -199,6 +199,33 @@
|
||||
ARM64_FEATURE_MASK(ID_AA64ISAR1_I8MM) \
|
||||
)
|
||||
|
||||
/*
|
||||
* Returns the maximum number of breakpoints supported for protected VMs.
|
||||
*/
|
||||
static inline int pkvm_get_max_brps(void)
|
||||
{
|
||||
int num = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_BRPS),
|
||||
PVM_ID_AA64DFR0_ALLOW);
|
||||
|
||||
/*
|
||||
* If breakpoints are supported, the maximum number is 1 + the field.
|
||||
* Otherwise, return 0, which is not compliant with the architecture,
|
||||
* but is reserved and is used here to indicate no debug support.
|
||||
*/
|
||||
return num ? num + 1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the maximum number of watchpoints supported for protected VMs.
|
||||
*/
|
||||
static inline int pkvm_get_max_wrps(void)
|
||||
{
|
||||
int num = FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_WRPS),
|
||||
PVM_ID_AA64DFR0_ALLOW);
|
||||
|
||||
return num ? num + 1 : 0;
|
||||
}
|
||||
|
||||
extern struct memblock_region kvm_nvhe_sym(hyp_memory)[];
|
||||
extern unsigned int kvm_nvhe_sym(hyp_memblock_nr);
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <asm/kvm_arm.h>
|
||||
#include <asm/kvm_asm.h>
|
||||
#include <asm/kvm_mmu.h>
|
||||
#include <asm/kvm_pkvm.h>
|
||||
#include <asm/kvm_emulate.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
@@ -200,9 +201,10 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
|
||||
kvm_unshare_hyp(kvm, kvm + 1);
|
||||
}
|
||||
|
||||
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
static int kvm_check_extension(struct kvm *kvm, long ext)
|
||||
{
|
||||
int r;
|
||||
|
||||
switch (ext) {
|
||||
case KVM_CAP_IRQCHIP:
|
||||
r = vgic_present;
|
||||
@@ -298,6 +300,72 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Checks whether the exctension specified in ext is supported for protected
|
||||
* vms. The capabilities supported by kvm in general are passed in kvm_cap.
|
||||
*/
|
||||
static int pkvm_check_extension(struct kvm *kvm, long ext, int kvm_cap)
|
||||
{
|
||||
int r;
|
||||
|
||||
switch (ext) {
|
||||
case KVM_CAP_IRQCHIP:
|
||||
case KVM_CAP_ARM_PSCI:
|
||||
case KVM_CAP_ARM_PSCI_0_2:
|
||||
case KVM_CAP_NR_VCPUS:
|
||||
case KVM_CAP_MAX_VCPUS:
|
||||
case KVM_CAP_MAX_VCPU_ID:
|
||||
case KVM_CAP_MSI_DEVID:
|
||||
case KVM_CAP_ARM_VM_IPA_SIZE:
|
||||
case KVM_CAP_EXIT_HYPERCALL:
|
||||
r = kvm_cap;
|
||||
break;
|
||||
case KVM_CAP_GUEST_DEBUG_HW_BPS:
|
||||
r = min(kvm_cap, pkvm_get_max_brps());
|
||||
break;
|
||||
case KVM_CAP_GUEST_DEBUG_HW_WPS:
|
||||
r = min(kvm_cap, pkvm_get_max_wrps());
|
||||
break;
|
||||
case KVM_CAP_ARM_PMU_V3:
|
||||
r = kvm_cap && FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_PMUVER),
|
||||
PVM_ID_AA64DFR0_ALLOW);
|
||||
break;
|
||||
case KVM_CAP_ARM_SVE:
|
||||
r = kvm_cap && FIELD_GET(ARM64_FEATURE_MASK(ID_AA64PFR0_SVE),
|
||||
PVM_ID_AA64PFR0_RESTRICT_UNSIGNED);
|
||||
break;
|
||||
case KVM_CAP_ARM_PTRAUTH_ADDRESS:
|
||||
r = kvm_cap &&
|
||||
FIELD_GET(ARM64_FEATURE_MASK(ID_AA64ISAR1_API),
|
||||
PVM_ID_AA64ISAR1_ALLOW) &&
|
||||
FIELD_GET(ARM64_FEATURE_MASK(ID_AA64ISAR1_APA),
|
||||
PVM_ID_AA64ISAR1_ALLOW);
|
||||
break;
|
||||
case KVM_CAP_ARM_PTRAUTH_GENERIC:
|
||||
r = kvm_cap &&
|
||||
FIELD_GET(ARM64_FEATURE_MASK(ID_AA64ISAR1_GPI),
|
||||
PVM_ID_AA64ISAR1_ALLOW) &&
|
||||
FIELD_GET(ARM64_FEATURE_MASK(ID_AA64ISAR1_GPA),
|
||||
PVM_ID_AA64ISAR1_ALLOW);
|
||||
break;
|
||||
default:
|
||||
r = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
|
||||
{
|
||||
int r = kvm_check_extension(kvm, ext);
|
||||
|
||||
if (unlikely(kvm && kvm_vm_is_protected(kvm)))
|
||||
r = pkvm_check_extension(kvm, ext, r);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
long kvm_arch_dev_ioctl(struct file *filp,
|
||||
unsigned int ioctl, unsigned long arg)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user