Re: [PATCH v1 4/9] target/loongarch: Implement kvm get/set registers

2023-11-08 Thread Philippe Mathieu-Daudé

Hi Tianrui, Xianglai,

On 8/11/23 02:41, xianglai li wrote:

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.

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| 580 +-
  target/loongarch/trace-events |  11 +
  target/loongarch/trace.h  |   1 +
  6 files changed, 596 insertions(+), 2 deletions(-)
  create mode 100644 target/loongarch/trace-events
  create mode 100644 target/loongarch/trace.h




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(CPULoongArchState 
*env, vaddr *pc,
  }
  
  void loongarch_cpu_list(void);

+void kvm_arch_reset_vcpu(CPULoongArchState *env);


Can we keep the KVM namespace out of generic CPU one?

You add "kvm_loongarch.h" in patch #8 of this series, this seems
a good fit IMHO.

Regards,

Phil.



[PATCH v1 4/9] target/loongarch: Implement kvm get/set registers

2023-11-07 Thread xianglai li
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.

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| 580 +-
 target/loongarch/trace-events |  11 +
 target/loongarch/trace.h  |   1 +
 6 files changed, 596 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 bd65a111aa..a98e48b8e9 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 1eed1b3eb0..0a4d1a9778 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 = 0x1c00;
 memset(env->tlb, 0, sizeof(env->tlb));
+if (kvm_enabled()) {
+kvm_arch_reset_vcpu(env);
+}
 #endif
 
 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(CPULoongArchState 
*env, vaddr *pc,
 }
 
 void loongarch_cpu_list(void);
+void kvm_arch_reset_vcpu(CPULoongArchState *env);
 
 #define cpu_list loongarch_cpu_list
 
diff --git a/target/loongarch/kvm.c b/target/loongarch/kvm.c
index 0d67322fd9..e7c9ef830c 100644
--- a/target/loongarch/kvm.c
+++ b/target/loongarch/kvm.c
@@ -26,19 +26,595 @@
 #include "sysemu/runstate.h"
 #include "cpu-csr.h"
 #include "kvm_loongarch.h"
+#include "trace.h"
 
 static bool cap_has_mp_state;
 const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
 KVM_CAP_LAST_INFO
 };
 
+static int kvm_loongarch_get_regs_core(CPUState *cs)
+{
+int ret = 0;
+int i;
+struct kvm_regs regs;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = &cpu->env;
+
+/* Get the current register set as KVM seems it */
+ret = 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] = 0;
+for (i = 1; i < 32; i++) {
+env->gpr[i] = regs.gpr[i];
+}
+
+env->pc = regs.pc;
+return ret;
+}
+
+static int kvm_loongarch_put_regs_core(CPUState *cs)
+{
+int ret = 0;
+int i;
+struct kvm_regs regs;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = &cpu->env;
+
+/* Set the registers based on QEMU's view of things */
+for (i = 0; i < 32; i++) {
+regs.gpr[i] = env->gpr[i];
+}
+
+regs.pc = env->pc;
+ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, ®s);
+if (ret < 0) {
+trace_kvm_failed_put_regs_core(strerror(errno));
+}
+
+return ret;
+}
+
+static int kvm_loongarch_get_csr(CPUState *cs)
+{
+int ret = 0;
+LoongArchCPU *cpu = LOONGARCH_CPU(cs);
+CPULoongArchState *env = &cpu->env;
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD),
+   &env->CSR_CRMD);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD),
+   &env->CSR_PRMD);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN),
+   &env->CSR_EUEN);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC),
+   &env->CSR_MISC);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG),
+   &env->CSR_ECFG);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT),
+   &env->CSR_ESTAT);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA),
+   &env->CSR_ERA);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV),
+   &env->CSR_BADV);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI),
+   &env->CSR_BADI);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY),
+   &env->CSR_EENTRY);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX),
+   &env->CSR_TLBIDX);
+
+ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLB