Rework the system instruction emulation framework to handle potentially all system instruction traps other than MSR/MRS instructions. Those system instructions would be AT and TLBI instructions controlled by HCR_EL2.NV, AT, and TTLB bits.
Signed-off-by: Jintack Lim <jintack....@linaro.org> --- arch/arm64/kvm/sys_regs.c | 66 ++++++++++++++++++----------------------------- 1 file changed, 25 insertions(+), 41 deletions(-) diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index 88ce172..481bea64 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -1621,6 +1621,11 @@ static bool access_id_aa64mmfr0_el1(struct kvm_vcpu *v, { SYS_DESC(SYS_SP_EL2), NULL, reset_special, SP_EL2, 0}, }; +#define SYS_INSN_TO_DESC(insn, access_fn, forward_fn) \ + { SYS_DESC((insn)), (access_fn), NULL, 0, 0, NULL, NULL, (forward_fn) } +static struct sys_reg_desc sys_insn_descs[] = { +}; + #define reg_to_match_value(x) \ ({ \ unsigned long val; \ @@ -1674,6 +1679,25 @@ static void perform_access(struct kvm_vcpu *vcpu, kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); } +static int emulate_sys_instr(struct kvm_vcpu *vcpu, struct sys_reg_params *p) +{ + + const struct sys_reg_desc *r; + + /* Search from the system instruction table. */ + r = find_reg(p, sys_insn_descs, ARRAY_SIZE(sys_insn_descs)); + + if (likely(r)) { + perform_access(vcpu, p, r); + } else { + kvm_err("Unsupported guest sys instruction at: %lx\n", + *vcpu_pc(vcpu)); + print_sys_reg_instr(p); + kvm_inject_undefined(vcpu); + } + return 1; +} + static bool trap_dbgidr(struct kvm_vcpu *vcpu, struct sys_reg_params *p, const struct sys_reg_desc *r) @@ -2236,47 +2260,6 @@ static int emulate_sys_reg(struct kvm_vcpu *vcpu, return 1; } -static int emulate_tlbi(struct kvm_vcpu *vcpu, - struct sys_reg_params *params) -{ - /* TODO: support tlbi instruction emulation*/ - kvm_inject_undefined(vcpu); - return 1; -} - -static int emulate_at(struct kvm_vcpu *vcpu, - struct sys_reg_params *params) -{ - /* TODO: support address translation instruction emulation */ - kvm_inject_undefined(vcpu); - return 1; -} - -static int emulate_sys_instr(struct kvm_vcpu *vcpu, - struct sys_reg_params *params) -{ - int ret = 0; - - /* - * Forward this trap to the virtual EL2 if the virtual HCR_EL2.NV - * bit is set. - */ - if (forward_nv_traps(vcpu)) - return kvm_inject_nested_sync(vcpu, kvm_vcpu_get_hsr(vcpu)); - - /* TLB maintenance instructions*/ - if (params->CRn == 0b1000) - ret = emulate_tlbi(vcpu, params); - /* Address Translation instructions */ - else if (params->CRn == 0b0111 && params->CRm == 0b1000) - ret = emulate_at(vcpu, params); - - if (ret) - kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu)); - - return ret; -} - static void reset_sys_reg_descs(struct kvm_vcpu *vcpu, const struct sys_reg_desc *table, size_t num) { @@ -2754,6 +2737,7 @@ void kvm_sys_reg_table_init(void) BUG_ON(check_sysreg_table(cp15_regs, ARRAY_SIZE(cp15_regs))); BUG_ON(check_sysreg_table(cp15_64_regs, ARRAY_SIZE(cp15_64_regs))); BUG_ON(check_sysreg_table(invariant_sys_regs, ARRAY_SIZE(invariant_sys_regs))); + BUG_ON(check_sysreg_table(sys_insn_descs, ARRAY_SIZE(sys_insn_descs))); /* We abuse the reset function to overwrite the table itself. */ for (i = 0; i < ARRAY_SIZE(invariant_sys_regs); i++) -- 1.9.1 _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm