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>
This commit is contained in:
parent
6278465696
commit
f8447436d3
@ -3329,6 +3329,7 @@ if have_system or have_user
|
||||
'target/hppa',
|
||||
'target/i386',
|
||||
'target/i386/kvm',
|
||||
'target/loongarch',
|
||||
'target/mips/tcg',
|
||||
'target/nios2',
|
||||
'target/ppc',
|
||||
|
@ -540,6 +540,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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
11
target/loongarch/trace-events
Normal file
11
target/loongarch/trace-events
Normal file
@ -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"
|
1
target/loongarch/trace.h
Normal file
1
target/loongarch/trace.h
Normal file
@ -0,0 +1 @@
|
||||
#include "trace/trace-target_loongarch.h"
|
Loading…
Reference in New Issue
Block a user