Reviewed-by: Bibo, Mao <maobibo@xxxxxxxxxxx> 在 2023/5/30 09:52, Tianrui Zhao 写道: > Implement kvm handle gspr exception interface, including emulate the > reading and writing of cpucfg, csr, iocsr resource. > > Signed-off-by: Tianrui Zhao <zhaotianrui@xxxxxxxxxxx> > --- > arch/loongarch/kvm/exit.c | 115 ++++++++++++++++++++++++++++++++++++++ > 1 file changed, 115 insertions(+) > > diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c > index 3fdb42939a05..26283a9d3c6d 100644 > --- a/arch/loongarch/kvm/exit.c > +++ b/arch/loongarch/kvm/exit.c > @@ -208,3 +208,118 @@ int _kvm_emu_idle(struct kvm_vcpu *vcpu) > > return EMULATE_DONE; > } > + > +static int _kvm_trap_handle_gspr(struct kvm_vcpu *vcpu) > +{ > + enum emulation_result er = EMULATE_DONE; > + struct kvm_run *run = vcpu->run; > + larch_inst inst; > + unsigned long curr_pc; > + int rd, rj; > + unsigned int index; > + > + /* > + * Fetch the instruction. > + */ > + inst.word = vcpu->arch.badi; > + curr_pc = vcpu->arch.pc; > + update_pc(&vcpu->arch); > + > + trace_kvm_exit_gspr(vcpu, inst.word); > + er = EMULATE_FAIL; > + switch (((inst.word >> 24) & 0xff)) { > + case 0x0: > + /* cpucfg GSPR */ > + if (inst.reg2_format.opcode == 0x1B) { > + rd = inst.reg2_format.rd; > + rj = inst.reg2_format.rj; > + ++vcpu->stat.cpucfg_exits; > + index = vcpu->arch.gprs[rj]; > + > + vcpu->arch.gprs[rd] = read_cpucfg(index); > + /* Nested KVM is not supported */ > + if (index == 2) > + vcpu->arch.gprs[rd] &= ~CPUCFG2_LVZP; > + if (index == 6) > + vcpu->arch.gprs[rd] &= ~CPUCFG6_PMP; > + er = EMULATE_DONE; > + } > + break; > + case 0x4: > + /* csr GSPR */ > + er = _kvm_handle_csr(vcpu, inst); > + break; > + case 0x6: > + /* iocsr,cache,idle GSPR */ > + switch (((inst.word >> 22) & 0x3ff)) { > + case 0x18: > + /* cache GSPR */ > + er = EMULATE_DONE; > + trace_kvm_exit_cache(vcpu, KVM_TRACE_EXIT_CACHE); > + break; > + case 0x19: > + /* iocsr/idle GSPR */ > + switch (((inst.word >> 15) & 0x1ffff)) { > + case 0xc90: > + /* iocsr GSPR */ > + er = _kvm_emu_iocsr(inst, run, vcpu); > + break; > + case 0xc91: > + /* idle GSPR */ > + er = _kvm_emu_idle(vcpu); > + break; > + default: > + er = EMULATE_FAIL; > + break; > + } > + break; > + default: > + er = EMULATE_FAIL; > + break; > + } > + break; > + default: > + er = EMULATE_FAIL; > + break; > + } > + > + /* Rollback PC only if emulation was unsuccessful */ > + if (er == EMULATE_FAIL) { > + kvm_err("[%#lx]%s: unsupported gspr instruction 0x%08x\n", > + curr_pc, __func__, inst.word); > + > + kvm_arch_vcpu_dump_regs(vcpu); > + vcpu->arch.pc = curr_pc; > + } > + return er; > +} > + > +/* > + * Execute cpucfg instruction will tirggerGSPR, > + * Also the access to unimplemented csrs 0x15 > + * 0x16, 0x50~0x53, 0x80, 0x81, 0x90~0x95, 0x98 > + * 0xc0~0xff, 0x100~0x109, 0x500~0x502, > + * cache_op, idle_op iocsr ops the same > + */ > +static int _kvm_handle_gspr(struct kvm_vcpu *vcpu) > +{ > + enum emulation_result er = EMULATE_DONE; > + int ret = RESUME_GUEST; > + > + er = _kvm_trap_handle_gspr(vcpu); > + > + if (er == EMULATE_DONE) { > + ret = RESUME_GUEST; > + } else if (er == EMULATE_DO_MMIO) { > + vcpu->run->exit_reason = KVM_EXIT_MMIO; > + ret = RESUME_HOST; > + } else if (er == EMULATE_DO_IOCSR) { > + vcpu->run->exit_reason = KVM_EXIT_LOONGARCH_IOCSR; > + ret = RESUME_HOST; > + } else { > + kvm_err("%s internal error\n", __func__); > + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; > + ret = RESUME_HOST; > + } > + return ret; > +}