From nobody Tue Feb 10 23:59:45 2026 Delivered-To: importer2@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer2=patchew.org@nongnu.org Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 169684226730144.206532747493156; Mon, 9 Oct 2023 02:04:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qpmA7-0002M6-8w; Mon, 09 Oct 2023 05:02:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qpm9p-0002EI-66 for qemu-devel@nongnu.org; Mon, 09 Oct 2023 05:02:35 -0400 Received: from mail.loongson.cn ([114.242.206.163]) by eggs.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qpm9f-00060k-N1 for qemu-devel@nongnu.org; Mon, 09 Oct 2023 05:02:32 -0400 Received: from loongson.cn (unknown [10.2.5.185]) by gateway (Coremail) with SMTP id _____8CxtPCWwSNlmT0wAA--.27963S3; Mon, 09 Oct 2023 17:02:14 +0800 (CST) Received: from localhost.localdomain (unknown [10.2.5.185]) by localhost.localdomain (Coremail) with SMTP id AQAAf8Dx_y+TwSNlDW4cAA--.59991S6; Mon, 09 Oct 2023 17:02:14 +0800 (CST) From: xianglai li To: qemu-devel@nongnu.org, kvm@vger.kernel.org Cc: Tianrui Zhao , "Michael S. Tsirkin" , Cornelia Huck , Paolo Bonzini , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Thomas Huth , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Richard Henderson , Peter Maydell , Bibo Mao , Song Gao , Xiaojuan Yang Subject: [PATCH RFC v4 4/9] target/loongarch: Implement kvm get/set registers Date: Mon, 9 Oct 2023 17:01:32 +0800 Message-Id: X-Mailer: git-send-email 2.39.1 In-Reply-To: References: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: AQAAf8Dx_y+TwSNlDW4cAA--.59991S6 X-CM-SenderInfo: 5ol0xt5qjotxo6or00hjvr0hdfq/ X-Coremail-Antispam: 1Uk129KBjDUn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7KY7 ZEXasCq-sGcSsGvfJ3UbIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2Kfnx nUUI43ZEXa7xR_UUUUUUUUU== Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer2=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=114.242.206.163; envelope-from=lixianglai@loongson.cn; helo=mail.loongson.cn X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer2=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer2=patchew.org@nongnu.org X-ZM-MESSAGEID: 1696842269384100003 From: Tianrui Zhao Implement kvm_arch_get/set_registers interfaces, many regs can be get/set in the function, such as core regs, csr regs, fpu regs, mp state, etc. Cc: "Michael S. Tsirkin" Cc: Cornelia Huck Cc: Paolo Bonzini Cc: "Marc-Andr=C3=A9 Lureau" Cc: "Daniel P. Berrang=C3=A9" Cc: Thomas Huth Cc: "Philippe Mathieu-Daud=C3=A9" Cc: Richard Henderson Cc: Peter Maydell Cc: Bibo Mao Cc: Song Gao Cc: Xiaojuan Yang Cc: Tianrui Zhao Signed-off-by: Tianrui Zhao Signed-off-by: xianglai li --- meson.build | 1 + target/loongarch/cpu.c | 3 + target/loongarch/cpu.h | 2 + target/loongarch/kvm.c | 406 +++++++++++++++++++++++++++++++++- target/loongarch/trace-events | 13 ++ target/loongarch/trace.h | 1 + 6 files changed, 424 insertions(+), 2 deletions(-) create mode 100644 target/loongarch/trace-events create mode 100644 target/loongarch/trace.h diff --git a/meson.build b/meson.build index 3bb64b536c..1c71ead833 100644 --- a/meson.build +++ b/meson.build @@ -3305,6 +3305,7 @@ if have_system or have_user 'target/hppa', 'target/i386', 'target/i386/kvm', + 'target/loongarch', 'target/mips/tcg', 'target/nios2', 'target/ppc', diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c index 0d763d8a65..61344c7ad2 100644 --- a/target/loongarch/cpu.c +++ b/target/loongarch/cpu.c @@ -546,6 +546,9 @@ static void loongarch_cpu_reset_hold(Object *obj) #ifndef CONFIG_USER_ONLY env->pc =3D 0x1c000000; memset(env->tlb, 0, sizeof(env->tlb)); + if (kvm_enabled()) { + kvm_arch_reset_vcpu(env); + } #endif =20 restore_fp_status(env); diff --git a/target/loongarch/cpu.h b/target/loongarch/cpu.h index e6a99c83ab..2580dc26e1 100644 --- a/target/loongarch/cpu.h +++ b/target/loongarch/cpu.h @@ -359,6 +359,7 @@ typedef struct CPUArchState { MemoryRegion iocsr_mem; bool load_elf; uint64_t elf_address; + uint32_t mp_state; /* Store ipistate to access from this struct */ DeviceState *ipistate; #endif @@ -477,6 +478,7 @@ static inline void cpu_get_tb_cpu_state(CPULoongArchSta= te *env, vaddr *pc, } =20 void loongarch_cpu_list(void); +void kvm_arch_reset_vcpu(CPULoongArchState *env); =20 #define cpu_list loongarch_cpu_list =20 diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c index 0d67322fd9..8fda80b107 100644 --- a/target/loongarch/kvm.c +++ b/target/loongarch/kvm.c @@ -26,19 +26,421 @@ #include "sysemu/runstate.h" #include "cpu-csr.h" #include "kvm_loongarch.h" +#include "trace.h" =20 static bool cap_has_mp_state; const KVMCapabilityInfo kvm_arch_required_capabilities[] =3D { KVM_CAP_LAST_INFO }; =20 +static int kvm_loongarch_get_regs_core(CPUState *cs) +{ + int ret =3D 0; + int i; + struct kvm_regs regs; + LoongArchCPU *cpu =3D LOONGARCH_CPU(cs); + CPULoongArchState *env =3D &cpu->env; + + /* Get the current register set as KVM seems it */ + ret =3D kvm_vcpu_ioctl(cs, KVM_GET_REGS, ®s); + if (ret < 0) { + trace_kvm_failed_get_regs_core(strerror(errno)); + return ret; + } + /* gpr[0] value is always 0 */ + env->gpr[0] =3D 0; + for (i =3D 1; i < 32; i++) { + env->gpr[i] =3D regs.gpr[i]; + } + + env->pc =3D regs.pc; + return ret; +} + +static int kvm_loongarch_put_regs_core(CPUState *cs) +{ + int ret =3D 0; + int i; + struct kvm_regs regs; + LoongArchCPU *cpu =3D LOONGARCH_CPU(cs); + CPULoongArchState *env =3D &cpu->env; + + /* Set the registers based on QEMU's view of things */ + for (i =3D 0; i < 32; i++) { + regs.gpr[i] =3D env->gpr[i]; + } + + regs.pc =3D env->pc; + ret =3D kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s); + if (ret < 0) { + trace_kvm_failed_put_regs_core(strerror(errno)); + } + + return ret; +} + +static int kvm_larch_getq(CPUState *cs, uint64_t reg_id, + uint64_t *addr) +{ + struct kvm_one_reg csrreg =3D { + .id =3D reg_id, + .addr =3D (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_GET_ONE_REG, &csrreg); +} + +static int kvm_larch_putq(CPUState *cs, uint64_t reg_id, + uint64_t *addr) +{ + struct kvm_one_reg csrreg =3D { + .id =3D reg_id, + .addr =3D (uintptr_t)addr + }; + + return kvm_vcpu_ioctl(cs, KVM_SET_ONE_REG, &csrreg); +} + +#define KVM_GET_ONE_UREG64(cs, ret, regidx, addr) \ + ({ \ + err =3D kvm_larch_getq(cs, KVM_IOC_CSRID(regidx), addr); \ + if (err < 0) { \ + ret =3D err; \ + trace_kvm_failed_get_csr(regidx, strerror(errno)); \ + } \ + }) + +#define KVM_PUT_ONE_UREG64(cs, ret, regidx, addr) \ + ({ \ + err =3D kvm_larch_putq(cs, KVM_IOC_CSRID(regidx), addr); \ + if (err < 0) { \ + ret =3D err; \ + trace_kvm_failed_put_csr(regidx, strerror(errno)); \ + } \ + }) + +static int kvm_loongarch_get_csr(CPUState *cs) +{ + int err, ret =3D 0; + LoongArchCPU *cpu =3D LOONGARCH_CPU(cs); + CPULoongArchState *env =3D &cpu->env; + + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_CRMD, &env->CSR_CRMD); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_PRMD, &env->CSR_PRMD); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_EUEN, &env->CSR_EUEN); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_MISC, &env->CSR_MISC); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_ECFG, &env->CSR_ECFG); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_ESTAT, &env->CSR_ESTAT); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_ERA, &env->CSR_ERA); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_BADV, &env->CSR_BADV); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_BADI, &env->CSR_BADI); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_EENTRY, &env->CSR_EENTRY); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBIDX, &env->CSR_TLBIDX); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBEHI, &env->CSR_TLBEHI); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBELO0, &env->CSR_TLBELO0); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBELO1, &env->CSR_TLBELO1); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_ASID, &env->CSR_ASID); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_PGDL, &env->CSR_PGDL); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_PGDH, &env->CSR_PGDH); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_PGD, &env->CSR_PGD); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_PWCL, &env->CSR_PWCL); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_PWCH, &env->CSR_PWCH); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_STLBPS, &env->CSR_STLBPS); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_RVACFG, &env->CSR_RVACFG); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_CPUID, &env->CSR_CPUID); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_PRCFG1, &env->CSR_PRCFG1); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_PRCFG2, &env->CSR_PRCFG2); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_PRCFG3, &env->CSR_PRCFG3); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(0), &env->CSR_SAVE[0]); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(1), &env->CSR_SAVE[1]); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(2), &env->CSR_SAVE[2]); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(3), &env->CSR_SAVE[3]); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(4), &env->CSR_SAVE[4]); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(5), &env->CSR_SAVE[5]); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(6), &env->CSR_SAVE[6]); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(7), &env->CSR_SAVE[7]); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TID, &env->CSR_TID); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_CNTC, &env->CSR_CNTC); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TICLR, &env->CSR_TICLR); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_LLBCTL, &env->CSR_LLBCTL); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_IMPCTL1, &env->CSR_IMPCTL1); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_IMPCTL2, &env->CSR_IMPCTL2); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRENTRY, &env->CSR_TLBRENT= RY); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRBADV, &env->CSR_TLBRBADV= ); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRERA, &env->CSR_TLBRERA); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRSAVE, &env->CSR_TLBRSAVE= ); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRELO0, &env->CSR_TLBRELO0= ); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRELO1, &env->CSR_TLBRELO1= ); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBREHI, &env->CSR_TLBREHI); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRPRMD, &env->CSR_TLBRPRMD= ); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_DMW(0), &env->CSR_DMW[0]); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_DMW(1), &env->CSR_DMW[1]); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_DMW(2), &env->CSR_DMW[2]); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_DMW(3), &env->CSR_DMW[3]); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TVAL, &env->CSR_TVAL); + KVM_GET_ONE_UREG64(cs, ret, LOONGARCH_CSR_TCFG, &env->CSR_TCFG); + + return ret; +} + +static int kvm_loongarch_put_csr(CPUState *cs) +{ + int err, ret =3D 0; + LoongArchCPU *cpu =3D LOONGARCH_CPU(cs); + CPULoongArchState *env =3D &cpu->env; + + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_CRMD, &env->CSR_CRMD); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_PRMD, &env->CSR_PRMD); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_EUEN, &env->CSR_EUEN); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_MISC, &env->CSR_MISC); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_ECFG, &env->CSR_ECFG); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_ESTAT, &env->CSR_ESTAT); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_ERA, &env->CSR_ERA); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_BADV, &env->CSR_BADV); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_BADI, &env->CSR_BADI); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_EENTRY, &env->CSR_EENTRY); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBIDX, &env->CSR_TLBIDX); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBEHI, &env->CSR_TLBEHI); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBELO0, &env->CSR_TLBELO0); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBELO1, &env->CSR_TLBELO1); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_ASID, &env->CSR_ASID); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_PGDL, &env->CSR_PGDL); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_PGDH, &env->CSR_PGDH); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_PGD, &env->CSR_PGD); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_PWCL, &env->CSR_PWCL); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_PWCH, &env->CSR_PWCH); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_STLBPS, &env->CSR_STLBPS); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_RVACFG, &env->CSR_RVACFG); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_CPUID, &env->CSR_CPUID); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_PRCFG1, &env->CSR_PRCFG1); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_PRCFG2, &env->CSR_PRCFG2); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_PRCFG3, &env->CSR_PRCFG3); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(0), &env->CSR_SAVE[0]); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(1), &env->CSR_SAVE[1]); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(2), &env->CSR_SAVE[2]); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(3), &env->CSR_SAVE[3]); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(4), &env->CSR_SAVE[4]); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(5), &env->CSR_SAVE[5]); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(6), &env->CSR_SAVE[6]); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_SAVE(7), &env->CSR_SAVE[7]); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TID, &env->CSR_TID); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_CNTC, &env->CSR_CNTC); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TICLR, &env->CSR_TICLR); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_LLBCTL, &env->CSR_LLBCTL); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_IMPCTL1, &env->CSR_IMPCTL1); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_IMPCTL2, &env->CSR_IMPCTL2); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRENTRY, &env->CSR_TLBRENT= RY); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRBADV, &env->CSR_TLBRBADV= ); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRERA, &env->CSR_TLBRERA); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRSAVE, &env->CSR_TLBRSAVE= ); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRELO0, &env->CSR_TLBRELO0= ); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRELO1, &env->CSR_TLBRELO1= ); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBREHI, &env->CSR_TLBREHI); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TLBRPRMD, &env->CSR_TLBRPRMD= ); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_DMW(0), &env->CSR_DMW[0]); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_DMW(1), &env->CSR_DMW[1]); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_DMW(2), &env->CSR_DMW[2]); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_DMW(3), &env->CSR_DMW[3]); + /* + * timer cfg must be put at last since it is used to enable + * guest timer + */ + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TVAL, &env->CSR_TVAL); + KVM_PUT_ONE_UREG64(cs, ret, LOONGARCH_CSR_TCFG, &env->CSR_TCFG); + return ret; +} + +static int kvm_loongarch_get_regs_fp(CPUState *cs) +{ + int ret, i; + struct kvm_fpu fpu; + + LoongArchCPU *cpu =3D LOONGARCH_CPU(cs); + CPULoongArchState *env =3D &cpu->env; + + ret =3D kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu); + if (ret < 0) { + trace_kvm_failed_get_fpu(strerror(errno)); + return ret; + } + + env->fcsr0 =3D fpu.fcsr; + for (i =3D 0; i < 32; i++) { + env->fpr[i].vreg.UD[0] =3D fpu.fpr[i].val64[0]; + } + for (i =3D 0; i < 8; i++) { + env->cf[i] =3D fpu.fcc & 0xFF; + fpu.fcc =3D fpu.fcc >> 8; + } + + return ret; +} + +static int kvm_loongarch_put_regs_fp(CPUState *cs) +{ + int ret, i; + struct kvm_fpu fpu; + + LoongArchCPU *cpu =3D LOONGARCH_CPU(cs); + CPULoongArchState *env =3D &cpu->env; + + fpu.fcsr =3D env->fcsr0; + fpu.fcc =3D 0; + for (i =3D 0; i < 32; i++) { + fpu.fpr[i].val64[0] =3D env->fpr[i].vreg.UD[0]; + } + + for (i =3D 0; i < 8; i++) { + fpu.fcc |=3D env->cf[i] << (8 * i); + } + + ret =3D kvm_vcpu_ioctl(cs, KVM_SET_FPU, &fpu); + if (ret < 0) { + trace_kvm_failed_put_fpu(strerror(errno)); + } + + return ret; +} + +void kvm_arch_reset_vcpu(CPULoongArchState *env) +{ + env->mp_state =3D KVM_MP_STATE_RUNNABLE; +} + +static int kvm_loongarch_get_mpstate(CPUState *cs) +{ + int ret =3D 0; + struct kvm_mp_state mp_state; + LoongArchCPU *cpu =3D LOONGARCH_CPU(cs); + CPULoongArchState *env =3D &cpu->env; + + if (cap_has_mp_state) { + ret =3D kvm_vcpu_ioctl(cs, KVM_GET_MP_STATE, &mp_state); + if (ret) { + trace_kvm_failed_get_mpstate(strerror(errno)); + return ret; + } + env->mp_state =3D mp_state.mp_state; + } + + return ret; +} + +static int kvm_loongarch_put_mpstate(CPUState *cs) +{ + int ret =3D 0; + + LoongArchCPU *cpu =3D LOONGARCH_CPU(cs); + CPULoongArchState *env =3D &cpu->env; + + struct kvm_mp_state mp_state =3D { + .mp_state =3D env->mp_state + }; + + if (cap_has_mp_state) { + ret =3D kvm_vcpu_ioctl(cs, KVM_SET_MP_STATE, &mp_state); + if (ret) { + trace_kvm_failed_put_mpstate(strerror(errno)); + } + } + + return ret; +} + +static int kvm_loongarch_get_cpucfg(CPUState *cs) +{ + int i, ret =3D 0; + uint64_t val; + LoongArchCPU *cpu =3D LOONGARCH_CPU(cs); + CPULoongArchState *env =3D &cpu->env; + + for (i =3D 0; i < 21; i++) { + ret =3D kvm_larch_getq(cs, KVM_IOC_CPUCFG(i), &val); + if (ret < 0) { + trace_kvm_failed_get_cpucfg(strerror(errno)); + } + env->cpucfg[i] =3D (uint32_t)val; + } + return ret; +} + +static int kvm_loongarch_put_cpucfg(CPUState *cs) +{ + int i, ret =3D 0; + LoongArchCPU *cpu =3D LOONGARCH_CPU(cs); + CPULoongArchState *env =3D &cpu->env; + uint64_t val; + + for (i =3D 0; i < 21; i++) { + val =3D env->cpucfg[i]; + /* LSX and LASX and LBT are not supported in kvm now */ + if (i =3D=3D 2) { + val &=3D ~(BIT(R_CPUCFG2_LSX_SHIFT) | BIT(R_CPUCFG2_LASX_SHIFT= )); + val &=3D ~(BIT(R_CPUCFG2_LBT_X86_SHIFT) | BIT(R_CPUCFG2_LBT_AR= M_SHIFT) | + BIT(R_CPUCFG2_LBT_MIPS_SHIFT)); + } + ret =3D kvm_larch_putq(cs, KVM_IOC_CPUCFG(i), &val); + if (ret < 0) { + trace_kvm_failed_put_cpucfg(strerror(errno)); + } + } + return ret; +} + int kvm_arch_get_registers(CPUState *cs) { - return 0; + int ret; + + ret =3D kvm_loongarch_get_regs_core(cs); + if (ret) { + return ret; + } + + ret =3D kvm_loongarch_get_csr(cs); + if (ret) { + return ret; + } + + ret =3D kvm_loongarch_get_regs_fp(cs); + if (ret) { + return ret; + } + + ret =3D kvm_loongarch_get_mpstate(cs); + if (ret) { + return ret; + } + + ret =3D kvm_loongarch_get_cpucfg(cs); + return ret; } + int kvm_arch_put_registers(CPUState *cs, int level) { - return 0; + int ret; + + ret =3D kvm_loongarch_put_regs_core(cs); + if (ret) { + return ret; + } + + ret =3D kvm_loongarch_put_csr(cs); + if (ret) { + return ret; + } + + ret =3D kvm_loongarch_put_regs_fp(cs); + if (ret) { + return ret; + } + + ret =3D kvm_loongarch_put_mpstate(cs); + if (ret) { + return ret; + } + + ret =3D kvm_loongarch_put_cpucfg(cs); + return ret; } =20 int kvm_arch_init_vcpu(CPUState *cs) diff --git a/target/loongarch/trace-events b/target/loongarch/trace-events new file mode 100644 index 0000000000..ceba80121b --- /dev/null +++ b/target/loongarch/trace-events @@ -0,0 +1,13 @@ +# See docs/devel/tracing.rst for syntax documentation. + +#kvm.c +kvm_failed_get_regs_core(const char *msg) "Failed to get core regs from KV= M: %s" +kvm_failed_put_regs_core(const char *msg) "Failed to put core regs into KV= M: %s" +kvm_failed_get_csr(int csr, const char *msg) "Failed to get csr 0x%x from = KVM: %s" +kvm_failed_put_csr(int csr, const char *msg) "Failed to put csr 0x%x into = KVM: %s" +kvm_failed_get_fpu(const char *msg) "Failed to get fpu from KVM: %s" +kvm_failed_put_fpu(const char *msg) "Failed to put fpu into KVM: %s" +kvm_failed_get_mpstate(const char *msg) "Failed to get mp_state from KVM: = %s" +kvm_failed_put_mpstate(const char *msg) "Failed to put mp_state into KVM: = %s" +kvm_failed_get_cpucfg(const char *msg) "Failed to get cpucfg from KVM: %s" +kvm_failed_put_cpucfg(const char *msg) "Failed to put cpucfg into KVM: %s" diff --git a/target/loongarch/trace.h b/target/loongarch/trace.h new file mode 100644 index 0000000000..c2ecb78f08 --- /dev/null +++ b/target/loongarch/trace.h @@ -0,0 +1 @@ +#include "trace/trace-target_loongarch.h" --=20 2.39.1