Skip to content
Permalink
Browse files
KVM: arm64: Trap access to pVM restricted features
Trap accesses to restricted features for VMs running in protected
mode.

Access to feature registers are emulated, and only supported
features are exposed to protected VMs.

Accesses to restricted registers as well as restricted
instructions are trapped, and an undefined exception is injected
into the protected guests, i.e., with EC = 0x0 (unknown reason).
This EC is the one used, according to the Arm Architecture
Reference Manual, for unallocated or undefined system registers
or instructions.

Only affects the functionality of protected VMs. Otherwise,
should not affect non-protected VMs when KVM is running in
protected mode.

Acked-by: Will Deacon <will@kernel.org>
Signed-off-by: Fuad Tabba <tabba@google.com>
  • Loading branch information
Fuad Tabba authored and intel-lab-lkp committed Aug 17, 2021
1 parent 511703a commit c05d33084d216fbdd94a7165aa6e93fd7517e0d8
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 15 deletions.
@@ -33,6 +33,9 @@
extern struct exception_table_entry __start___kvm_ex_table;
extern struct exception_table_entry __stop___kvm_ex_table;

int kvm_handle_pvm_sys64(struct kvm_vcpu *vcpu);
int kvm_handle_pvm_restricted(struct kvm_vcpu *vcpu);

/* Check whether the FP regs were dirtied while in the host-side run loop: */
static inline bool update_fp_enabled(struct kvm_vcpu *vcpu)
{
@@ -159,27 +159,27 @@ static void __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt)
}

static exit_handle_fn hyp_exit_handlers[] = {
[0 ... ESR_ELx_EC_MAX] = NULL,
[0 ... ESR_ELx_EC_MAX] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_WFx] = NULL,
[ESR_ELx_EC_CP15_32] = NULL,
[ESR_ELx_EC_CP15_64] = NULL,
[ESR_ELx_EC_CP14_MR] = NULL,
[ESR_ELx_EC_CP14_LS] = NULL,
[ESR_ELx_EC_CP14_64] = NULL,
[ESR_ELx_EC_CP15_32] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_CP15_64] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_CP14_MR] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_CP14_LS] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_CP14_64] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_HVC32] = NULL,
[ESR_ELx_EC_SMC32] = NULL,
[ESR_ELx_EC_HVC64] = NULL,
[ESR_ELx_EC_SMC64] = NULL,
[ESR_ELx_EC_SYS64] = NULL,
[ESR_ELx_EC_SVE] = NULL,
[ESR_ELx_EC_SYS64] = kvm_handle_pvm_sys64,
[ESR_ELx_EC_SVE] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_IABT_LOW] = NULL,
[ESR_ELx_EC_DABT_LOW] = NULL,
[ESR_ELx_EC_SOFTSTP_LOW] = NULL,
[ESR_ELx_EC_WATCHPT_LOW] = NULL,
[ESR_ELx_EC_BREAKPT_LOW] = NULL,
[ESR_ELx_EC_BKPT32] = NULL,
[ESR_ELx_EC_BRK64] = NULL,
[ESR_ELx_EC_FP_ASIMD] = NULL,
[ESR_ELx_EC_SOFTSTP_LOW] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_WATCHPT_LOW] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_BREAKPT_LOW] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_BKPT32] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_BRK64] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_FP_ASIMD] = kvm_handle_pvm_restricted,
[ESR_ELx_EC_PAC] = NULL,
};

@@ -188,7 +188,11 @@ exit_handle_fn kvm_get_nvhe_exit_handler(struct kvm_vcpu *vcpu)
u32 esr = kvm_vcpu_get_esr(vcpu);
u8 esr_ec = ESR_ELx_EC(esr);

return hyp_exit_handlers[esr_ec];
/* For now, only protected VMs have exit handlers. */
if (unlikely(kvm_vm_is_protected(kern_hyp_va(vcpu->kvm))))
return hyp_exit_handlers[esr_ec];
else
return NULL;
}

/* Switch to the guest for legacy non-VHE systems */

0 comments on commit c05d330

Please sign in to comment.