diff options
author | Marc Zyngier <maz@kernel.org> | 2024-02-14 16:18:16 +0300 |
---|---|---|
committer | Oliver Upton <oliver.upton@linux.dev> | 2024-02-19 20:13:01 +0300 |
commit | cc5f84fbb008ff0904e0a8c0fb207cee2eb99bc9 (patch) | |
tree | 42c8c9ccaf40dfc3f41dabaa1c7c82860321beb0 /arch/arm64/kvm/sys_regs.c | |
parent | 19f3e7ea29f8f485f06b47f7c38f9e9e81013ada (diff) | |
download | linux-cc5f84fbb008ff0904e0a8c0fb207cee2eb99bc9.tar.xz |
KVM: arm64: Use the xarray as the primary sysreg/sysinsn walker
Since we always start sysreg/sysinsn handling by searching the
xarray, use it as the source of the index in the correct sys_reg_desc
array.
This allows some cleanup, such as moving the handling of unknown
sysregs in a single location.
Reviewed-by: Joey Gouly <joey.gouly@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20240214131827.2856277-16-maz@kernel.org
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
Diffstat (limited to 'arch/arm64/kvm/sys_regs.c')
-rw-r--r-- | arch/arm64/kvm/sys_regs.c | 63 |
1 files changed, 19 insertions, 44 deletions
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c index a410e99f827e..bc076ef8440b 100644 --- a/arch/arm64/kvm/sys_regs.c +++ b/arch/arm64/kvm/sys_regs.c @@ -3395,12 +3395,6 @@ int kvm_handle_cp14_32(struct kvm_vcpu *vcpu) return kvm_handle_cp_32(vcpu, ¶ms, cp14_regs, ARRAY_SIZE(cp14_regs)); } -static bool is_imp_def_sys_reg(struct sys_reg_params *params) -{ - // See ARM DDI 0487E.a, section D12.3.2 - return params->Op0 == 3 && (params->CRn & 0b1011) == 0b1011; -} - /** * emulate_sys_reg - Emulate a guest access to an AArch64 system register * @vcpu: The VCPU pointer @@ -3409,44 +3403,22 @@ static bool is_imp_def_sys_reg(struct sys_reg_params *params) * Return: true if the system register access was successful, false otherwise. */ static bool emulate_sys_reg(struct kvm_vcpu *vcpu, - struct sys_reg_params *params) + struct sys_reg_params *params) { const struct sys_reg_desc *r; r = find_reg(params, sys_reg_descs, ARRAY_SIZE(sys_reg_descs)); - if (likely(r)) { perform_access(vcpu, params, r); return true; } - if (is_imp_def_sys_reg(params)) { - kvm_inject_undefined(vcpu); - } else { - print_sys_reg_msg(params, - "Unsupported guest sys_reg access at: %lx [%08lx]\n", - *vcpu_pc(vcpu), *vcpu_cpsr(vcpu)); - kvm_inject_undefined(vcpu); - } - return false; -} - -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)); + print_sys_reg_msg(params, + "Unsupported guest sys_reg access at: %lx [%08lx]\n", + *vcpu_pc(vcpu), *vcpu_cpsr(vcpu)); + kvm_inject_undefined(vcpu); - 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; + return false; } static void kvm_reset_id_regs(struct kvm_vcpu *vcpu) @@ -3502,31 +3474,34 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu) */ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu) { + const struct sys_reg_desc *desc = NULL; struct sys_reg_params params; unsigned long esr = kvm_vcpu_get_esr(vcpu); int Rt = kvm_vcpu_sys_get_rt(vcpu); + int sr_idx; trace_kvm_handle_sys_reg(esr); - if (__check_nv_sr_forward(vcpu)) + if (__check_nv_sr_forward(vcpu, &sr_idx)) return 1; params = esr_sys64_to_params(esr); params.regval = vcpu_get_reg(vcpu, Rt); /* System registers have Op0=={2,3}, as per DDI487 J.a C5.1.2 */ - if (params.Op0 == 2 || params.Op0 == 3) { - if (!emulate_sys_reg(vcpu, ¶ms)) - return 1; + if (params.Op0 == 2 || params.Op0 == 3) + desc = &sys_reg_descs[sr_idx]; + else + desc = &sys_insn_descs[sr_idx]; - if (!params.is_write) - vcpu_set_reg(vcpu, Rt, params.regval); + perform_access(vcpu, ¶ms, desc); - return 1; - } + /* Read from system register? */ + if (!params.is_write && + (params.Op0 == 2 || params.Op0 == 3)) + vcpu_set_reg(vcpu, Rt, params.regval); - /* Hints, PSTATE (Op0 == 0) and System instructions (Op0 == 1) */ - return emulate_sys_instr(vcpu, ¶ms); + return 1; } /****************************************************************************** |