- disable keyring option - loongarch: Change the UEFI loading mode to loongarch - target/loongarch: Fix qtest test-hmp error when KVM-only build - target/loongarch/kvm: Enable LSX/LASX extension - target/loongarch: Set cpuid CSR register only once with kvm mode - configure: Add linux header compile support for LoongArch - hw/intc/loongarch_extioi: Add vmstate post_load support - hw/intc/loongarch_extioi: Add dynamic cpu number support - hw/loongarch/virt: Set iocsr address space per-board rather than percpu - hw/intc/loongarch_ipi: Use MemTxAttrs interface for ipi ops - target/loongarch: Add loongarch kvm into meson build - target/loongarch: Implement set vcpu intr for kvm - target/loongarch: Restrict TCG-specific code - target/loongarch: Implement kvm_arch_handle_exit - target/loongarch: Implement kvm_arch_init_vcpu - target/loongarch: Implement kvm_arch_init function - target/loongarch: Implement kvm get/set registers - target/loongarch: Supplement vcpu env initial when vcpu reset - target/loongarch: Define some kvm_arch interfaces - linux-headers: Synchronize linux headers from linux v6.7.0-rc8 - linux-headers: Update to Linux v6.7-rc5 - target/loongarch: move translate modules to tcg/ - target/loongarch/meson: move gdbstub.c to loongarch.ss - target/loongarch: Add timer information dump support - hw/loongarch/virt: Align high memory base address with super page size Signed-off-by: Jiabo Feng <fengjiabo1@huawei.com> (cherry picked from commit b2263e41ffa3428f1d9f9ff6e214c8e3a19e06e8)
725 lines
23 KiB
Diff
725 lines
23 KiB
Diff
From 0884653d8583aaaa5585caf38246518439bcfdfd Mon Sep 17 00:00:00 2001
|
|
From: Tianrui Zhao <zhaotianrui@loongson.cn>
|
|
Date: Fri, 5 Jan 2024 15:57:59 +0800
|
|
Subject: [PATCH] target/loongarch: Implement kvm get/set registers
|
|
|
|
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 <zhaotianrui@loongson.cn>
|
|
Signed-off-by: xianglai li <lixianglai@loongson.cn>
|
|
Reviewed-by: Song Gao <gaosong@loongson.cn>
|
|
Change-Id: Ia8fc48fe08b1768853f7729e77d37cdf270031e4
|
|
Message-Id: <20240105075804.1228596-5-zhaotianrui@loongson.cn>
|
|
Signed-off-by: Song Gao <gaosong@loongson.cn>
|
|
---
|
|
meson.build | 1 +
|
|
target/loongarch/cpu.c | 3 +
|
|
target/loongarch/cpu.h | 1 +
|
|
target/loongarch/internals.h | 5 +-
|
|
target/loongarch/kvm/kvm.c | 580 +++++++++++++++++++++++++++++++++-
|
|
target/loongarch/trace-events | 11 +
|
|
target/loongarch/trace.h | 1 +
|
|
7 files changed, 599 insertions(+), 3 deletions(-)
|
|
create mode 100644 target/loongarch/trace-events
|
|
create mode 100644 target/loongarch/trace.h
|
|
|
|
diff --git a/meson.build b/meson.build
|
|
index 6c77d9687d..445f2b7c2b 100644
|
|
--- a/meson.build
|
|
+++ b/meson.build
|
|
@@ -3358,6 +3358,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 021592798a..275833eec8 100644
|
|
--- a/target/loongarch/cpu.c
|
|
+++ b/target/loongarch/cpu.c
|
|
@@ -553,6 +553,9 @@ static void loongarch_cpu_reset_hold(Object *obj)
|
|
#ifndef CONFIG_USER_ONLY
|
|
env->pc = 0x1c000000;
|
|
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 f6d5ef0852..f4a89bd626 100644
|
|
--- a/target/loongarch/cpu.h
|
|
+++ b/target/loongarch/cpu.h
|
|
@@ -360,6 +360,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
|
|
diff --git a/target/loongarch/internals.h b/target/loongarch/internals.h
|
|
index c492863cc5..0beb034748 100644
|
|
--- a/target/loongarch/internals.h
|
|
+++ b/target/loongarch/internals.h
|
|
@@ -31,8 +31,10 @@ void G_NORETURN do_raise_exception(CPULoongArchState *env,
|
|
|
|
const char *loongarch_exception_name(int32_t exception);
|
|
|
|
+#ifdef CONFIG_TCG
|
|
int ieee_ex_to_loongarch(int xcpt);
|
|
void restore_fp_status(CPULoongArchState *env);
|
|
+#endif
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
extern const VMStateDescription vmstate_loongarch_cpu;
|
|
@@ -44,12 +46,13 @@ uint64_t cpu_loongarch_get_constant_timer_counter(LoongArchCPU *cpu);
|
|
uint64_t cpu_loongarch_get_constant_timer_ticks(LoongArchCPU *cpu);
|
|
void cpu_loongarch_store_constant_timer_config(LoongArchCPU *cpu,
|
|
uint64_t value);
|
|
-
|
|
+#ifdef CONFIG_TCG
|
|
bool loongarch_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|
MMUAccessType access_type, int mmu_idx,
|
|
bool probe, uintptr_t retaddr);
|
|
|
|
hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
|
|
+#endif
|
|
#endif /* !CONFIG_USER_ONLY */
|
|
|
|
uint64_t read_fcc(CPULoongArchState *env);
|
|
diff --git a/target/loongarch/kvm/kvm.c b/target/loongarch/kvm/kvm.c
|
|
index 0d67322fd9..e7c9ef830c 100644
|
|
--- a/target/loongarch/kvm/kvm.c
|
|
+++ b/target/loongarch/kvm/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_TLBEHI),
|
|
+ &env->CSR_TLBEHI);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO0),
|
|
+ &env->CSR_TLBELO0);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO1),
|
|
+ &env->CSR_TLBELO1);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ASID),
|
|
+ &env->CSR_ASID);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDL),
|
|
+ &env->CSR_PGDL);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDH),
|
|
+ &env->CSR_PGDH);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGD),
|
|
+ &env->CSR_PGD);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCL),
|
|
+ &env->CSR_PWCL);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCH),
|
|
+ &env->CSR_PWCH);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_STLBPS),
|
|
+ &env->CSR_STLBPS);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG),
|
|
+ &env->CSR_RVACFG);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
|
|
+ &env->CSR_CPUID);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1),
|
|
+ &env->CSR_PRCFG1);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG2),
|
|
+ &env->CSR_PRCFG2);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG3),
|
|
+ &env->CSR_PRCFG3);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(0)),
|
|
+ &env->CSR_SAVE[0]);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(1)),
|
|
+ &env->CSR_SAVE[1]);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(2)),
|
|
+ &env->CSR_SAVE[2]);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(3)),
|
|
+ &env->CSR_SAVE[3]);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(4)),
|
|
+ &env->CSR_SAVE[4]);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(5)),
|
|
+ &env->CSR_SAVE[5]);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(6)),
|
|
+ &env->CSR_SAVE[6]);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(7)),
|
|
+ &env->CSR_SAVE[7]);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TID),
|
|
+ &env->CSR_TID);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CNTC),
|
|
+ &env->CSR_CNTC);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TICLR),
|
|
+ &env->CSR_TICLR);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_LLBCTL),
|
|
+ &env->CSR_LLBCTL);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL1),
|
|
+ &env->CSR_IMPCTL1);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL2),
|
|
+ &env->CSR_IMPCTL2);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRENTRY),
|
|
+ &env->CSR_TLBRENTRY);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRBADV),
|
|
+ &env->CSR_TLBRBADV);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRERA),
|
|
+ &env->CSR_TLBRERA);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRSAVE),
|
|
+ &env->CSR_TLBRSAVE);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO0),
|
|
+ &env->CSR_TLBRELO0);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO1),
|
|
+ &env->CSR_TLBRELO1);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBREHI),
|
|
+ &env->CSR_TLBREHI);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRPRMD),
|
|
+ &env->CSR_TLBRPRMD);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(0)),
|
|
+ &env->CSR_DMW[0]);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(1)),
|
|
+ &env->CSR_DMW[1]);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(2)),
|
|
+ &env->CSR_DMW[2]);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)),
|
|
+ &env->CSR_DMW[3]);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
|
|
+ &env->CSR_TVAL);
|
|
+
|
|
+ ret |= kvm_get_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TCFG),
|
|
+ &env->CSR_TCFG);
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int kvm_loongarch_put_csr(CPUState *cs)
|
|
+{
|
|
+ int ret = 0;
|
|
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
|
+ CPULoongArchState *env = &cpu->env;
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CRMD),
|
|
+ &env->CSR_CRMD);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRMD),
|
|
+ &env->CSR_PRMD);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EUEN),
|
|
+ &env->CSR_EUEN);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_MISC),
|
|
+ &env->CSR_MISC);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ECFG),
|
|
+ &env->CSR_ECFG);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ESTAT),
|
|
+ &env->CSR_ESTAT);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ERA),
|
|
+ &env->CSR_ERA);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADV),
|
|
+ &env->CSR_BADV);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_BADI),
|
|
+ &env->CSR_BADI);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_EENTRY),
|
|
+ &env->CSR_EENTRY);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBIDX),
|
|
+ &env->CSR_TLBIDX);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBEHI),
|
|
+ &env->CSR_TLBEHI);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO0),
|
|
+ &env->CSR_TLBELO0);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBELO1),
|
|
+ &env->CSR_TLBELO1);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_ASID),
|
|
+ &env->CSR_ASID);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDL),
|
|
+ &env->CSR_PGDL);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGDH),
|
|
+ &env->CSR_PGDH);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PGD),
|
|
+ &env->CSR_PGD);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCL),
|
|
+ &env->CSR_PWCL);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PWCH),
|
|
+ &env->CSR_PWCH);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_STLBPS),
|
|
+ &env->CSR_STLBPS);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_RVACFG),
|
|
+ &env->CSR_RVACFG);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CPUID),
|
|
+ &env->CSR_CPUID);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG1),
|
|
+ &env->CSR_PRCFG1);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG2),
|
|
+ &env->CSR_PRCFG2);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_PRCFG3),
|
|
+ &env->CSR_PRCFG3);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(0)),
|
|
+ &env->CSR_SAVE[0]);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(1)),
|
|
+ &env->CSR_SAVE[1]);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(2)),
|
|
+ &env->CSR_SAVE[2]);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(3)),
|
|
+ &env->CSR_SAVE[3]);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(4)),
|
|
+ &env->CSR_SAVE[4]);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(5)),
|
|
+ &env->CSR_SAVE[5]);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(6)),
|
|
+ &env->CSR_SAVE[6]);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_SAVE(7)),
|
|
+ &env->CSR_SAVE[7]);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TID),
|
|
+ &env->CSR_TID);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_CNTC),
|
|
+ &env->CSR_CNTC);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TICLR),
|
|
+ &env->CSR_TICLR);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_LLBCTL),
|
|
+ &env->CSR_LLBCTL);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL1),
|
|
+ &env->CSR_IMPCTL1);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_IMPCTL2),
|
|
+ &env->CSR_IMPCTL2);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRENTRY),
|
|
+ &env->CSR_TLBRENTRY);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRBADV),
|
|
+ &env->CSR_TLBRBADV);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRERA),
|
|
+ &env->CSR_TLBRERA);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRSAVE),
|
|
+ &env->CSR_TLBRSAVE);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO0),
|
|
+ &env->CSR_TLBRELO0);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRELO1),
|
|
+ &env->CSR_TLBRELO1);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBREHI),
|
|
+ &env->CSR_TLBREHI);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TLBRPRMD),
|
|
+ &env->CSR_TLBRPRMD);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(0)),
|
|
+ &env->CSR_DMW[0]);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(1)),
|
|
+ &env->CSR_DMW[1]);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(2)),
|
|
+ &env->CSR_DMW[2]);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_DMW(3)),
|
|
+ &env->CSR_DMW[3]);
|
|
+ /*
|
|
+ * timer cfg must be put at last since it is used to enable
|
|
+ * guest timer
|
|
+ */
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(LOONGARCH_CSR_TVAL),
|
|
+ &env->CSR_TVAL);
|
|
+
|
|
+ ret |= kvm_set_one_reg(cs, KVM_IOC_CSRID(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 = LOONGARCH_CPU(cs);
|
|
+ CPULoongArchState *env = &cpu->env;
|
|
+
|
|
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_FPU, &fpu);
|
|
+ if (ret < 0) {
|
|
+ trace_kvm_failed_get_fpu(strerror(errno));
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ env->fcsr0 = fpu.fcsr;
|
|
+ for (i = 0; i < 32; i++) {
|
|
+ env->fpr[i].vreg.UD[0] = fpu.fpr[i].val64[0];
|
|
+ }
|
|
+ for (i = 0; i < 8; i++) {
|
|
+ env->cf[i] = fpu.fcc & 0xFF;
|
|
+ fpu.fcc = fpu.fcc >> 8;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int kvm_loongarch_put_regs_fp(CPUState *cs)
|
|
+{
|
|
+ int ret, i;
|
|
+ struct kvm_fpu fpu;
|
|
+
|
|
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
|
+ CPULoongArchState *env = &cpu->env;
|
|
+
|
|
+ fpu.fcsr = env->fcsr0;
|
|
+ fpu.fcc = 0;
|
|
+ for (i = 0; i < 32; i++) {
|
|
+ fpu.fpr[i].val64[0] = env->fpr[i].vreg.UD[0];
|
|
+ }
|
|
+
|
|
+ for (i = 0; i < 8; i++) {
|
|
+ fpu.fcc |= env->cf[i] << (8 * i);
|
|
+ }
|
|
+
|
|
+ ret = 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 = KVM_MP_STATE_RUNNABLE;
|
|
+}
|
|
+
|
|
+static int kvm_loongarch_get_mpstate(CPUState *cs)
|
|
+{
|
|
+ int ret = 0;
|
|
+ struct kvm_mp_state mp_state;
|
|
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
|
+ CPULoongArchState *env = &cpu->env;
|
|
+
|
|
+ if (cap_has_mp_state) {
|
|
+ ret = kvm_vcpu_ioctl(cs, KVM_GET_MP_STATE, &mp_state);
|
|
+ if (ret) {
|
|
+ trace_kvm_failed_get_mpstate(strerror(errno));
|
|
+ return ret;
|
|
+ }
|
|
+ env->mp_state = mp_state.mp_state;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int kvm_loongarch_put_mpstate(CPUState *cs)
|
|
+{
|
|
+ int ret = 0;
|
|
+
|
|
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
|
+ CPULoongArchState *env = &cpu->env;
|
|
+
|
|
+ struct kvm_mp_state mp_state = {
|
|
+ .mp_state = env->mp_state
|
|
+ };
|
|
+
|
|
+ if (cap_has_mp_state) {
|
|
+ ret = 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 = 0;
|
|
+ uint64_t val;
|
|
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
|
+ CPULoongArchState *env = &cpu->env;
|
|
+
|
|
+ for (i = 0; i < 21; i++) {
|
|
+ ret = kvm_get_one_reg(cs, KVM_IOC_CPUCFG(i), &val);
|
|
+ if (ret < 0) {
|
|
+ trace_kvm_failed_get_cpucfg(strerror(errno));
|
|
+ }
|
|
+ env->cpucfg[i] = (uint32_t)val;
|
|
+ }
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static int kvm_loongarch_put_cpucfg(CPUState *cs)
|
|
+{
|
|
+ int i, ret = 0;
|
|
+ LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
|
+ CPULoongArchState *env = &cpu->env;
|
|
+ uint64_t val;
|
|
+
|
|
+ for (i = 0; i < 21; i++) {
|
|
+ val = env->cpucfg[i];
|
|
+ /* LSX and LASX and LBT are not supported in kvm now */
|
|
+ if (i == 2) {
|
|
+ val &= ~(BIT(R_CPUCFG2_LSX_SHIFT) | BIT(R_CPUCFG2_LASX_SHIFT));
|
|
+ val &= ~(BIT(R_CPUCFG2_LBT_X86_SHIFT) |
|
|
+ BIT(R_CPUCFG2_LBT_ARM_SHIFT) |
|
|
+ BIT(R_CPUCFG2_LBT_MIPS_SHIFT));
|
|
+ }
|
|
+ ret = kvm_set_one_reg(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 = kvm_loongarch_get_regs_core(cs);
|
|
+ if (ret) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = kvm_loongarch_get_csr(cs);
|
|
+ if (ret) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = kvm_loongarch_get_regs_fp(cs);
|
|
+ if (ret) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = kvm_loongarch_get_mpstate(cs);
|
|
+ if (ret) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = kvm_loongarch_get_cpucfg(cs);
|
|
+ return ret;
|
|
}
|
|
+
|
|
int kvm_arch_put_registers(CPUState *cs, int level)
|
|
{
|
|
- return 0;
|
|
+ int ret;
|
|
+
|
|
+ ret = kvm_loongarch_put_regs_core(cs);
|
|
+ if (ret) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = kvm_loongarch_put_csr(cs);
|
|
+ if (ret) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = kvm_loongarch_put_regs_fp(cs);
|
|
+ if (ret) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = kvm_loongarch_put_mpstate(cs);
|
|
+ if (ret) {
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ret = kvm_loongarch_put_cpucfg(cs);
|
|
+ return ret;
|
|
}
|
|
|
|
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..6827ab566a
|
|
--- /dev/null
|
|
+++ b/target/loongarch/trace-events
|
|
@@ -0,0 +1,11 @@
|
|
+# See docs/devel/tracing.rst for syntax documentation.
|
|
+
|
|
+#kvm.c
|
|
+kvm_failed_get_regs_core(const char *msg) "Failed to get core regs from KVM: %s"
|
|
+kvm_failed_put_regs_core(const char *msg) "Failed to put core regs 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"
|
|
--
|
|
2.27.0
|
|
|