@@ -405,6 +405,18 @@ static inline bool __hyp_handle_ptrauth(struct kvm_vcpu *vcpu)
return true;
}
+typedef int (*exit_handle_fn)(struct kvm_vcpu *);
+
+exit_handle_fn kvm_get_nvhe_exit_handler(struct kvm_vcpu *vcpu);
+
+static exit_handle_fn kvm_get_hyp_exit_handler(struct kvm_vcpu *vcpu)
+{
+ if (is_nvhe_hyp_code())
+ return kvm_get_nvhe_exit_handler(vcpu);
+ else
+ return NULL;
+}
+
/*
* Return true when we were able to fixup the guest exit and should return to
* the guest, false when we should restore the host state and return to the
@@ -412,6 +424,8 @@ static inline bool __hyp_handle_ptrauth(struct kvm_vcpu *vcpu)
*/
static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
{
+ exit_handle_fn exit_handler;
+
if (ARM_EXCEPTION_CODE(*exit_code) != ARM_EXCEPTION_IRQ)
vcpu->arch.fault.esr_el2 = read_sysreg_el2(SYS_ESR);
@@ -492,6 +506,11 @@ static inline bool fixup_guest_exit(struct kvm_vcpu *vcpu, u64 *exit_code)
goto guest;
}
+ /* Check if there's an exit handler and allow it to handle the exit. */
+ exit_handler = kvm_get_hyp_exit_handler(vcpu);
+ if (exit_handler && exit_handler(vcpu))
+ goto guest;
+
exit:
/* Return to the host kernel and handle the exit */
return false;
@@ -165,6 +165,41 @@ static void __pmu_switch_to_host(struct kvm_cpu_context *host_ctxt)
write_sysreg(pmu->events_host, pmcntenset_el0);
}
+typedef int (*exit_handle_fn)(struct kvm_vcpu *);
+
+static exit_handle_fn hyp_exit_handlers[] = {
+ [0 ... ESR_ELx_EC_MAX] = NULL,
+ [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_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_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_PAC] = NULL,
+};
+
+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];
+}
+
/* Switch to the guest for legacy non-VHE systems */
int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
{
Add an array of pointers to handlers for various trap reasons in nVHE code. The current code selects how to fixup a guest on exit based on a series of if/else statements. Future patches will also require different handling for guest exists. Create an array of handlers to consolidate them. No functional change intended as the array isn't populated yet. Signed-off-by: Fuad Tabba <tabba@google.com> --- arch/arm64/kvm/hyp/include/hyp/switch.h | 19 ++++++++++++++ arch/arm64/kvm/hyp/nvhe/switch.c | 35 +++++++++++++++++++++++++ 2 files changed, 54 insertions(+)