Arch specific exit reasons have been available for other architectures.
Add arch specific exit reason support for ARM64, which would be used in
KVM stats for monitoring VCPU status.

Signed-off-by: Jing Zhang <jingzhan...@google.com>
---
 arch/arm64/include/asm/kvm_emulate.h |  5 +++
 arch/arm64/include/asm/kvm_host.h    | 33 +++++++++++++++
 arch/arm64/kvm/handle_exit.c         | 62 +++++++++++++++++++++++++---
 arch/arm64/kvm/mmu.c                 |  4 ++
 arch/arm64/kvm/sys_regs.c            |  6 +++
 5 files changed, 105 insertions(+), 5 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_emulate.h 
b/arch/arm64/include/asm/kvm_emulate.h
index fd418955e31e..eb5ec3a479d3 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -319,6 +319,11 @@ static inline bool kvm_vcpu_trap_is_iabt(const struct 
kvm_vcpu *vcpu)
        return kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_IABT_LOW;
 }
 
+static inline bool kvm_vcpu_trap_is_dabt(const struct kvm_vcpu *vcpu)
+{
+       return kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_DABT_LOW;
+}
+
 static inline bool kvm_vcpu_trap_is_exec_fault(const struct kvm_vcpu *vcpu)
 {
        return kvm_vcpu_trap_is_iabt(vcpu) && !kvm_vcpu_abt_iss1tw(vcpu);
diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index f8be56d5342b..0f0cea26ce32 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -278,6 +278,36 @@ struct vcpu_reset_state {
        bool            reset;
 };
 
+enum arm_exit_reason {
+       ARM_EXIT_UNKNOWN,
+       ARM_EXIT_IRQ,
+       ARM_EXIT_EL1_SERROR,
+       ARM_EXIT_HYP_GONE,
+       ARM_EXIT_IL,
+       ARM_EXIT_WFI,
+       ARM_EXIT_WFE,
+       ARM_EXIT_CP15_32,
+       ARM_EXIT_CP15_64,
+       ARM_EXIT_CP14_32,
+       ARM_EXIT_CP14_LS,
+       ARM_EXIT_CP14_64,
+       ARM_EXIT_HVC32,
+       ARM_EXIT_SMC32,
+       ARM_EXIT_HVC64,
+       ARM_EXIT_SMC64,
+       ARM_EXIT_SYS64,
+       ARM_EXIT_SVE,
+       ARM_EXIT_IABT_LOW,
+       ARM_EXIT_DABT_LOW,
+       ARM_EXIT_SOFTSTP_LOW,
+       ARM_EXIT_WATCHPT_LOW,
+       ARM_EXIT_BREAKPT_LOW,
+       ARM_EXIT_BKPT32,
+       ARM_EXIT_BRK64,
+       ARM_EXIT_FP_ASIMD,
+       ARM_EXIT_PAC,
+};
+
 struct kvm_vcpu_arch {
        struct kvm_cpu_context ctxt;
        void *sve_state;
@@ -384,6 +414,9 @@ struct kvm_vcpu_arch {
                u64 last_steal;
                gpa_t base;
        } steal;
+
+       /* Arch specific exit reason */
+       enum arm_exit_reason exit_reason;
 };
 
 /* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 275a27368a04..90a47758b23d 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -49,6 +49,18 @@ static int handle_hvc(struct kvm_vcpu *vcpu)
        return ret;
 }
 
+static int handle_hvc32(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.exit_reason = ARM_EXIT_HVC32;
+       return handle_hvc(vcpu);
+}
+
+static int handle_hvc64(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.exit_reason = ARM_EXIT_HVC64;
+       return handle_hvc(vcpu);
+}
+
 static int handle_smc(struct kvm_vcpu *vcpu)
 {
        /*
@@ -64,12 +76,25 @@ static int handle_smc(struct kvm_vcpu *vcpu)
        return 1;
 }
 
+static int handle_smc32(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.exit_reason = ARM_EXIT_SMC32;
+       return handle_smc(vcpu);
+}
+
+static int handle_smc64(struct kvm_vcpu *vcpu)
+{
+       vcpu->arch.exit_reason = ARM_EXIT_SMC64;
+       return handle_smc(vcpu);
+}
+
 /*
  * Guest access to FP/ASIMD registers are routed to this handler only
  * when the system doesn't support FP/ASIMD.
  */
 static int handle_no_fpsimd(struct kvm_vcpu *vcpu)
 {
+       vcpu->arch.exit_reason = ARM_EXIT_FP_ASIMD;
        kvm_inject_undefined(vcpu);
        return 1;
 }
@@ -91,10 +116,12 @@ static int kvm_handle_wfx(struct kvm_vcpu *vcpu)
        if (kvm_vcpu_get_esr(vcpu) & ESR_ELx_WFx_ISS_WFE) {
                trace_kvm_wfx_arm64(*vcpu_pc(vcpu), true);
                vcpu->stat.wfe_exit_stat++;
+               vcpu->arch.exit_reason = ARM_EXIT_WFE;
                kvm_vcpu_on_spin(vcpu, vcpu_mode_priv(vcpu));
        } else {
                trace_kvm_wfx_arm64(*vcpu_pc(vcpu), false);
                vcpu->stat.wfi_exit_stat++;
+               vcpu->arch.exit_reason = ARM_EXIT_WFI;
                kvm_vcpu_block(vcpu);
                kvm_clear_request(KVM_REQ_UNHALT, vcpu);
        }
@@ -119,12 +146,29 @@ static int kvm_handle_guest_debug(struct kvm_vcpu *vcpu)
 {
        struct kvm_run *run = vcpu->run;
        u32 esr = kvm_vcpu_get_esr(vcpu);
+       u8 esr_ec = ESR_ELx_EC(esr);
 
        run->exit_reason = KVM_EXIT_DEBUG;
        run->debug.arch.hsr = esr;
 
-       if (ESR_ELx_EC(esr) == ESR_ELx_EC_WATCHPT_LOW)
+       switch (esr_ec) {
+       case ESR_ELx_EC_SOFTSTP_LOW:
+               vcpu->arch.exit_reason = ARM_EXIT_SOFTSTP_LOW;
+               break;
+       case ESR_ELx_EC_WATCHPT_LOW:
                run->debug.arch.far = vcpu->arch.fault.far_el2;
+               vcpu->arch.exit_reason = ARM_EXIT_WATCHPT_LOW;
+               break;
+       case ESR_ELx_EC_BREAKPT_LOW:
+               vcpu->arch.exit_reason = ARM_EXIT_BREAKPT_LOW;
+               break;
+       case ESR_ELx_EC_BKPT32:
+               vcpu->arch.exit_reason = ARM_EXIT_BKPT32;
+               break;
+       case ESR_ELx_EC_BRK64:
+               vcpu->arch.exit_reason = ARM_EXIT_BRK64;
+               break;
+       }
 
        return 0;
 }
@@ -136,12 +180,14 @@ static int kvm_handle_unknown_ec(struct kvm_vcpu *vcpu)
        kvm_pr_unimpl("Unknown exception class: esr: %#08x -- %s\n",
                      esr, esr_get_class_string(esr));
 
+       vcpu->arch.exit_reason = ARM_EXIT_UNKNOWN;
        kvm_inject_undefined(vcpu);
        return 1;
 }
 
 static int handle_sve(struct kvm_vcpu *vcpu)
 {
+       vcpu->arch.exit_reason = ARM_EXIT_SVE;
        /* Until SVE is supported for guests: */
        kvm_inject_undefined(vcpu);
        return 1;
@@ -154,6 +200,7 @@ static int handle_sve(struct kvm_vcpu *vcpu)
  */
 static int kvm_handle_ptrauth(struct kvm_vcpu *vcpu)
 {
+       vcpu->arch.exit_reason = ARM_EXIT_PAC;
        kvm_inject_undefined(vcpu);
        return 1;
 }
@@ -166,10 +213,10 @@ static exit_handle_fn arm_exit_handlers[] = {
        [ESR_ELx_EC_CP14_MR]    = kvm_handle_cp14_32,
        [ESR_ELx_EC_CP14_LS]    = kvm_handle_cp14_load_store,
        [ESR_ELx_EC_CP14_64]    = kvm_handle_cp14_64,
-       [ESR_ELx_EC_HVC32]      = handle_hvc,
-       [ESR_ELx_EC_SMC32]      = handle_smc,
-       [ESR_ELx_EC_HVC64]      = handle_hvc,
-       [ESR_ELx_EC_SMC64]      = handle_smc,
+       [ESR_ELx_EC_HVC32]      = handle_hvc32,
+       [ESR_ELx_EC_SMC32]      = handle_smc32,
+       [ESR_ELx_EC_HVC64]      = handle_hvc64,
+       [ESR_ELx_EC_SMC64]      = handle_smc64,
        [ESR_ELx_EC_SYS64]      = kvm_handle_sys_reg,
        [ESR_ELx_EC_SVE]        = handle_sve,
        [ESR_ELx_EC_IABT_LOW]   = kvm_handle_guest_abort,
@@ -230,8 +277,10 @@ int handle_exit(struct kvm_vcpu *vcpu, int exception_index)
 
        switch (exception_index) {
        case ARM_EXCEPTION_IRQ:
+               vcpu->arch.exit_reason = ARM_EXIT_IRQ;
                return 1;
        case ARM_EXCEPTION_EL1_SERROR:
+               vcpu->arch.exit_reason = ARM_EXIT_EL1_SERROR;
                return 1;
        case ARM_EXCEPTION_TRAP:
                return handle_trap_exceptions(vcpu);
@@ -240,6 +289,7 @@ int handle_exit(struct kvm_vcpu *vcpu, int exception_index)
                 * EL2 has been reset to the hyp-stub. This happens when a guest
                 * is pre-empted by kvm_reboot()'s shutdown call.
                 */
+               vcpu->arch.exit_reason = ARM_EXIT_HYP_GONE;
                run->exit_reason = KVM_EXIT_FAIL_ENTRY;
                return 0;
        case ARM_EXCEPTION_IL:
@@ -247,11 +297,13 @@ int handle_exit(struct kvm_vcpu *vcpu, int 
exception_index)
                 * We attempted an illegal exception return.  Guest state must
                 * have been corrupted somehow.  Give up.
                 */
+               vcpu->arch.exit_reason = ARM_EXIT_IL;
                run->exit_reason = KVM_EXIT_FAIL_ENTRY;
                return -EINVAL;
        default:
                kvm_pr_unimpl("Unsupported exception type: %d",
                              exception_index);
+               vcpu->arch.exit_reason = ARM_EXIT_UNKNOWN;
                run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
                return 0;
        }
diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c
index 1a94a7ca48f2..a6a18d113c98 100644
--- a/arch/arm64/kvm/mmu.c
+++ b/arch/arm64/kvm/mmu.c
@@ -1197,6 +1197,10 @@ int kvm_handle_guest_abort(struct kvm_vcpu *vcpu)
 
        fault_ipa = kvm_vcpu_get_fault_ipa(vcpu);
        is_iabt = kvm_vcpu_trap_is_iabt(vcpu);
+       if (is_iabt)
+               vcpu->arch.exit_reason = ARM_EXIT_IABT_LOW;
+       else if (kvm_vcpu_trap_is_dabt(vcpu))
+               vcpu->arch.exit_reason = ARM_EXIT_DABT_LOW;
 
        /* Synchronous External Abort? */
        if (kvm_vcpu_abt_issea(vcpu)) {
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 1d46e185f31e..0915dfa589c7 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -2158,6 +2158,7 @@ static int check_sysreg_table(const struct sys_reg_desc 
*table, unsigned int n,
 
 int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu)
 {
+       vcpu->arch.exit_reason = ARM_EXIT_CP14_LS;
        kvm_inject_undefined(vcpu);
        return 1;
 }
@@ -2325,21 +2326,25 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
 
 int kvm_handle_cp15_64(struct kvm_vcpu *vcpu)
 {
+       vcpu->arch.exit_reason = ARM_EXIT_CP15_64;
        return kvm_handle_cp_64(vcpu, cp15_64_regs, ARRAY_SIZE(cp15_64_regs));
 }
 
 int kvm_handle_cp15_32(struct kvm_vcpu *vcpu)
 {
+       vcpu->arch.exit_reason = ARM_EXIT_CP15_32;
        return kvm_handle_cp_32(vcpu, cp15_regs, ARRAY_SIZE(cp15_regs));
 }
 
 int kvm_handle_cp14_64(struct kvm_vcpu *vcpu)
 {
+       vcpu->arch.exit_reason = ARM_EXIT_CP14_64;
        return kvm_handle_cp_64(vcpu, cp14_64_regs, ARRAY_SIZE(cp14_64_regs));
 }
 
 int kvm_handle_cp14_32(struct kvm_vcpu *vcpu)
 {
+       vcpu->arch.exit_reason = ARM_EXIT_CP14_32;
        return kvm_handle_cp_32(vcpu, cp14_regs, ARRAY_SIZE(cp14_regs));
 }
 
@@ -2397,6 +2402,7 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu)
        int ret;
 
        trace_kvm_handle_sys_reg(esr);
+       vcpu->arch.exit_reason = ARM_EXIT_SYS64;
 
        params = esr_sys64_to_params(esr);
        params.regval = vcpu_get_reg(vcpu, Rt);
-- 
2.33.0.464.g1972c5931b-goog

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

Reply via email to