mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 02:24:58 -06:00
pull-loongarch-20240111
-----BEGIN PGP SIGNATURE----- iLMEAAEKAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCZZ/QKgAKCRBAov/yOSY+ 34eqBADA48++Z9gETFNheLUHdYEaja2emn+gSaoHLFquyq/l53w8RfrUII+BzV1o T7D8xjlVQldAYZzqQn2pQe2S7r4ggfeNmxGxwJbCTW9sooGMwBnU8+Ix3ruSet7K gI+UHLU4oHk6jdrT384tux2EG+qUmlLN1c7j4G/z1OzKEwFv7Q== =+Pi0 -----END PGP SIGNATURE----- Merge tag 'pull-loongarch-20240111' of https://gitlab.com/gaosong/qemu into staging pull-loongarch-20240111 # -----BEGIN PGP SIGNATURE----- # # iLMEAAEKAB0WIQS4/x2g0v3LLaCcbCxAov/yOSY+3wUCZZ/QKgAKCRBAov/yOSY+ # 34eqBADA48++Z9gETFNheLUHdYEaja2emn+gSaoHLFquyq/l53w8RfrUII+BzV1o # T7D8xjlVQldAYZzqQn2pQe2S7r4ggfeNmxGxwJbCTW9sooGMwBnU8+Ix3ruSet7K # gI+UHLU4oHk6jdrT384tux2EG+qUmlLN1c7j4G/z1OzKEwFv7Q== # =+Pi0 # -----END PGP SIGNATURE----- # gpg: Signature made Thu 11 Jan 2024 11:25:30 GMT # gpg: using RSA key B8FF1DA0D2FDCB2DA09C6C2C40A2FFF239263EDF # gpg: Good signature from "Song Gao <m17746591750@163.com>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: B8FF 1DA0 D2FD CB2D A09C 6C2C 40A2 FFF2 3926 3EDF * tag 'pull-loongarch-20240111' of https://gitlab.com/gaosong/qemu: 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 Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
5429a82cf8
18 changed files with 1209 additions and 257 deletions
|
@ -11,7 +11,9 @@
|
|||
#include "qapi/error.h"
|
||||
#include "qemu/module.h"
|
||||
#include "sysemu/qtest.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "sysemu/tcg.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "kvm/kvm_loongarch.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "cpu.h"
|
||||
#include "internals.h"
|
||||
|
@ -20,8 +22,14 @@
|
|||
#ifndef CONFIG_USER_ONLY
|
||||
#include "sysemu/reset.h"
|
||||
#endif
|
||||
#include "tcg/tcg.h"
|
||||
#include "vec.h"
|
||||
#ifdef CONFIG_KVM
|
||||
#include <linux/kvm.h>
|
||||
#endif
|
||||
#ifdef CONFIG_TCG
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "tcg/tcg.h"
|
||||
#endif
|
||||
|
||||
const char * const regnames[32] = {
|
||||
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
|
||||
|
@ -110,12 +118,15 @@ void loongarch_cpu_set_irq(void *opaque, int irq, int level)
|
|||
return;
|
||||
}
|
||||
|
||||
env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
|
||||
|
||||
if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
} else {
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
if (kvm_enabled()) {
|
||||
kvm_loongarch_set_interrupt(cpu, irq, level);
|
||||
} else if (tcg_enabled()) {
|
||||
env->CSR_ESTAT = deposit64(env->CSR_ESTAT, irq, 1, level != 0);
|
||||
if (FIELD_EX64(env->CSR_ESTAT, CSR_ESTAT, IS)) {
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
} else {
|
||||
cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -140,7 +151,10 @@ static inline bool cpu_loongarch_hw_interrupts_pending(CPULoongArchState *env)
|
|||
|
||||
return (pending & status) != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TCG
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static void loongarch_cpu_do_interrupt(CPUState *cs)
|
||||
{
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
||||
|
@ -322,7 +336,6 @@ static bool loongarch_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_TCG
|
||||
static void loongarch_cpu_synchronize_from_tb(CPUState *cs,
|
||||
const TranslationBlock *tb)
|
||||
{
|
||||
|
@ -518,10 +531,12 @@ static void loongarch_cpu_reset_hold(Object *obj)
|
|||
|
||||
env->CSR_ESTAT = env->CSR_ESTAT & (~MAKE_64BIT_MASK(0, 2));
|
||||
env->CSR_RVACFG = FIELD_DP64(env->CSR_RVACFG, CSR_RVACFG, RBITS, 0);
|
||||
env->CSR_CPUID = cs->cpu_index;
|
||||
env->CSR_TCFG = FIELD_DP64(env->CSR_TCFG, CSR_TCFG, EN, 0);
|
||||
env->CSR_LLBCTL = FIELD_DP64(env->CSR_LLBCTL, CSR_LLBCTL, KLO, 0);
|
||||
env->CSR_TLBRERA = FIELD_DP64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR, 0);
|
||||
env->CSR_MERRCTL = FIELD_DP64(env->CSR_MERRCTL, CSR_MERRCTL, ISMERR, 0);
|
||||
env->CSR_TID = cs->cpu_index;
|
||||
|
||||
env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, TLB_TYPE, 2);
|
||||
env->CSR_PRCFG3 = FIELD_DP64(env->CSR_PRCFG3, CSR_PRCFG3, MTLB_ENTRY, 63);
|
||||
|
@ -538,9 +553,14 @@ 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
|
||||
|
||||
#ifdef CONFIG_TCG
|
||||
restore_fp_status(env);
|
||||
#endif
|
||||
cs->exception_index = -1;
|
||||
}
|
||||
|
||||
|
@ -569,47 +589,6 @@ static void loongarch_cpu_realizefn(DeviceState *dev, Error **errp)
|
|||
lacc->parent_realize(dev, errp);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static void loongarch_qemu_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size)
|
||||
{
|
||||
qemu_log_mask(LOG_UNIMP, "[%s]: Unimplemented reg 0x%" HWADDR_PRIx "\n",
|
||||
__func__, addr);
|
||||
}
|
||||
|
||||
static uint64_t loongarch_qemu_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
switch (addr) {
|
||||
case VERSION_REG:
|
||||
return 0x11ULL;
|
||||
case FEATURE_REG:
|
||||
return 1ULL << IOCSRF_MSI | 1ULL << IOCSRF_EXTIOI |
|
||||
1ULL << IOCSRF_CSRIPI;
|
||||
case VENDOR_REG:
|
||||
return 0x6e6f73676e6f6f4cULL; /* "Loongson" */
|
||||
case CPUNAME_REG:
|
||||
return 0x303030354133ULL; /* "3A5000" */
|
||||
case MISC_FUNC_REG:
|
||||
return 1ULL << IOCSRM_EXTIOI_EN;
|
||||
}
|
||||
return 0ULL;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps loongarch_qemu_ops = {
|
||||
.read = loongarch_qemu_read,
|
||||
.write = loongarch_qemu_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
.valid = {
|
||||
.min_access_size = 4,
|
||||
.max_access_size = 8,
|
||||
},
|
||||
.impl = {
|
||||
.min_access_size = 8,
|
||||
.max_access_size = 8,
|
||||
},
|
||||
};
|
||||
#endif
|
||||
|
||||
static bool loongarch_get_lsx(Object *obj, Error **errp)
|
||||
{
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
|
||||
|
@ -680,17 +659,12 @@ static void loongarch_cpu_init(Object *obj)
|
|||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(obj);
|
||||
CPULoongArchState *env = &cpu->env;
|
||||
|
||||
qdev_init_gpio_in(DEVICE(cpu), loongarch_cpu_set_irq, N_IRQS);
|
||||
#ifdef CONFIG_TCG
|
||||
timer_init_ns(&cpu->timer, QEMU_CLOCK_VIRTUAL,
|
||||
&loongarch_constant_timer_cb, cpu);
|
||||
memory_region_init_io(&env->system_iocsr, OBJECT(cpu), NULL,
|
||||
env, "iocsr", UINT64_MAX);
|
||||
address_space_init(&env->address_space_iocsr, &env->system_iocsr, "IOCSR");
|
||||
memory_region_init_io(&env->iocsr_mem, OBJECT(cpu), &loongarch_qemu_ops,
|
||||
NULL, "iocsr_misc", 0x428);
|
||||
memory_region_add_subregion(&env->system_iocsr, 0, &env->iocsr_mem);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -778,7 +752,9 @@ static struct TCGCPUOps loongarch_tcg_ops = {
|
|||
#include "hw/core/sysemu-cpu-ops.h"
|
||||
|
||||
static const struct SysemuCPUOps loongarch_sysemu_ops = {
|
||||
#ifdef CONFIG_TCG
|
||||
.get_phys_page_debug = loongarch_cpu_get_phys_page_debug,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int64_t loongarch_cpu_get_arch_id(CPUState *cs)
|
||||
|
|
|
@ -319,6 +319,7 @@ typedef struct CPUArchState {
|
|||
uint64_t CSR_PWCH;
|
||||
uint64_t CSR_STLBPS;
|
||||
uint64_t CSR_RVACFG;
|
||||
uint64_t CSR_CPUID;
|
||||
uint64_t CSR_PRCFG1;
|
||||
uint64_t CSR_PRCFG2;
|
||||
uint64_t CSR_PRCFG3;
|
||||
|
@ -350,16 +351,14 @@ typedef struct CPUArchState {
|
|||
uint64_t CSR_DBG;
|
||||
uint64_t CSR_DERA;
|
||||
uint64_t CSR_DSAVE;
|
||||
uint64_t CSR_CPUID;
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
LoongArchTLB tlb[LOONGARCH_TLB_MAX];
|
||||
|
||||
AddressSpace address_space_iocsr;
|
||||
MemoryRegion system_iocsr;
|
||||
MemoryRegion iocsr_mem;
|
||||
AddressSpace *address_space_iocsr;
|
||||
bool load_elf;
|
||||
uint64_t elf_address;
|
||||
uint32_t mp_state;
|
||||
/* Store ipistate to access from this struct */
|
||||
DeviceState *ipistate;
|
||||
#endif
|
||||
|
@ -380,6 +379,8 @@ struct ArchCPU {
|
|||
|
||||
/* 'compatible' string for this CPU for Linux device trees */
|
||||
const char *dtb_compatible;
|
||||
/* used by KVM_REG_LOONGARCH_COUNTER ioctl to access guest time counters */
|
||||
uint64_t kvm_state_counter;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
768
target/loongarch/kvm/kvm.c
Normal file
768
target/loongarch/kvm/kvm.c
Normal file
|
@ -0,0 +1,768 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* QEMU LoongArch KVM
|
||||
*
|
||||
* Copyright (c) 2023 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/kvm.h>
|
||||
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "hw/pci/pci.h"
|
||||
#include "exec/memattrs.h"
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/boards.h"
|
||||
#include "hw/irq.h"
|
||||
#include "qemu/log.h"
|
||||
#include "hw/loader.h"
|
||||
#include "migration/migration.h"
|
||||
#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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
static void kvm_loongarch_vm_stage_change(void *opaque, bool running,
|
||||
RunState state)
|
||||
{
|
||||
int ret;
|
||||
CPUState *cs = opaque;
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
||||
|
||||
if (running) {
|
||||
ret = kvm_set_one_reg(cs, KVM_REG_LOONGARCH_COUNTER,
|
||||
&cpu->kvm_state_counter);
|
||||
if (ret < 0) {
|
||||
trace_kvm_failed_put_counter(strerror(errno));
|
||||
}
|
||||
} else {
|
||||
ret = kvm_get_one_reg(cs, KVM_REG_LOONGARCH_COUNTER,
|
||||
&cpu->kvm_state_counter);
|
||||
if (ret < 0) {
|
||||
trace_kvm_failed_get_counter(strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int kvm_arch_init_vcpu(CPUState *cs)
|
||||
{
|
||||
qemu_add_vm_change_state_handler(kvm_loongarch_vm_stage_change, cs);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_destroy_vcpu(CPUState *cs)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long kvm_arch_vcpu_id(CPUState *cs)
|
||||
{
|
||||
return cs->cpu_index;
|
||||
}
|
||||
|
||||
int kvm_arch_release_virq_post(int virq)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_msi_data_to_gsi(uint32_t data)
|
||||
{
|
||||
abort();
|
||||
}
|
||||
|
||||
int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route,
|
||||
uint64_t address, uint32_t data, PCIDevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
|
||||
int vector, PCIDevice *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_arch_init_irq_routing(KVMState *s)
|
||||
{
|
||||
}
|
||||
|
||||
int kvm_arch_get_default_type(MachineState *ms)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_init(MachineState *ms, KVMState *s)
|
||||
{
|
||||
cap_has_mp_state = kvm_check_extension(s, KVM_CAP_MP_STATE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvm_arch_irqchip_create(KVMState *s)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void kvm_arch_pre_run(CPUState *cs, struct kvm_run *run)
|
||||
{
|
||||
}
|
||||
|
||||
MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
|
||||
{
|
||||
return MEMTXATTRS_UNSPECIFIED;
|
||||
}
|
||||
|
||||
int kvm_arch_process_async_events(CPUState *cs)
|
||||
{
|
||||
return cs->halted;
|
||||
}
|
||||
|
||||
bool kvm_arch_stop_on_emulation_error(CPUState *cs)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool kvm_arch_cpu_check_are_resettable(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
|
||||
{
|
||||
int ret = 0;
|
||||
LoongArchCPU *cpu = LOONGARCH_CPU(cs);
|
||||
CPULoongArchState *env = &cpu->env;
|
||||
MemTxAttrs attrs = {};
|
||||
|
||||
attrs.requester_id = env_cpu(env)->cpu_index;
|
||||
|
||||
trace_kvm_arch_handle_exit(run->exit_reason);
|
||||
switch (run->exit_reason) {
|
||||
case KVM_EXIT_LOONGARCH_IOCSR:
|
||||
address_space_rw(env->address_space_iocsr,
|
||||
run->iocsr_io.phys_addr,
|
||||
attrs,
|
||||
run->iocsr_io.data,
|
||||
run->iocsr_io.len,
|
||||
run->iocsr_io.is_write);
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
warn_report("KVM: unknown exit reason %d", run->exit_reason);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level)
|
||||
{
|
||||
struct kvm_interrupt intr;
|
||||
CPUState *cs = CPU(cpu);
|
||||
|
||||
if (level) {
|
||||
intr.irq = irq;
|
||||
} else {
|
||||
intr.irq = -irq;
|
||||
}
|
||||
|
||||
trace_kvm_set_intr(irq, level);
|
||||
return kvm_vcpu_ioctl(cs, KVM_INTERRUPT, &intr);
|
||||
}
|
||||
|
||||
void kvm_arch_accel_class_init(ObjectClass *oc)
|
||||
{
|
||||
}
|
16
target/loongarch/kvm/kvm_loongarch.h
Normal file
16
target/loongarch/kvm/kvm_loongarch.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* QEMU LoongArch kvm interface
|
||||
*
|
||||
* Copyright (c) 2023 Loongson Technology Corporation Limited
|
||||
*/
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
#ifndef QEMU_KVM_LOONGARCH_H
|
||||
#define QEMU_KVM_LOONGARCH_H
|
||||
|
||||
int kvm_loongarch_set_interrupt(LoongArchCPU *cpu, int irq, int level);
|
||||
void kvm_arch_reset_vcpu(CPULoongArchState *env);
|
||||
|
||||
#endif
|
1
target/loongarch/kvm/meson.build
Normal file
1
target/loongarch/kvm/meson.build
Normal file
|
@ -0,0 +1 @@
|
|||
loongarch_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c'))
|
|
@ -18,3 +18,4 @@ subdir('tcg')
|
|||
|
||||
target_arch += {'loongarch': loongarch_ss}
|
||||
target_system_arch += {'loongarch': loongarch_system_ss}
|
||||
subdir('kvm')
|
||||
|
|
|
@ -17,52 +17,52 @@
|
|||
|
||||
uint64_t helper_iocsrrd_b(CPULoongArchState *env, target_ulong r_addr)
|
||||
{
|
||||
return address_space_ldub(&env->address_space_iocsr, r_addr,
|
||||
return address_space_ldub(env->address_space_iocsr, r_addr,
|
||||
GET_MEMTXATTRS(env), NULL);
|
||||
}
|
||||
|
||||
uint64_t helper_iocsrrd_h(CPULoongArchState *env, target_ulong r_addr)
|
||||
{
|
||||
return address_space_lduw(&env->address_space_iocsr, r_addr,
|
||||
return address_space_lduw(env->address_space_iocsr, r_addr,
|
||||
GET_MEMTXATTRS(env), NULL);
|
||||
}
|
||||
|
||||
uint64_t helper_iocsrrd_w(CPULoongArchState *env, target_ulong r_addr)
|
||||
{
|
||||
return address_space_ldl(&env->address_space_iocsr, r_addr,
|
||||
return address_space_ldl(env->address_space_iocsr, r_addr,
|
||||
GET_MEMTXATTRS(env), NULL);
|
||||
}
|
||||
|
||||
uint64_t helper_iocsrrd_d(CPULoongArchState *env, target_ulong r_addr)
|
||||
{
|
||||
return address_space_ldq(&env->address_space_iocsr, r_addr,
|
||||
return address_space_ldq(env->address_space_iocsr, r_addr,
|
||||
GET_MEMTXATTRS(env), NULL);
|
||||
}
|
||||
|
||||
void helper_iocsrwr_b(CPULoongArchState *env, target_ulong w_addr,
|
||||
target_ulong val)
|
||||
{
|
||||
address_space_stb(&env->address_space_iocsr, w_addr,
|
||||
address_space_stb(env->address_space_iocsr, w_addr,
|
||||
val, GET_MEMTXATTRS(env), NULL);
|
||||
}
|
||||
|
||||
void helper_iocsrwr_h(CPULoongArchState *env, target_ulong w_addr,
|
||||
target_ulong val)
|
||||
{
|
||||
address_space_stw(&env->address_space_iocsr, w_addr,
|
||||
address_space_stw(env->address_space_iocsr, w_addr,
|
||||
val, GET_MEMTXATTRS(env), NULL);
|
||||
}
|
||||
|
||||
void helper_iocsrwr_w(CPULoongArchState *env, target_ulong w_addr,
|
||||
target_ulong val)
|
||||
{
|
||||
address_space_stl(&env->address_space_iocsr, w_addr,
|
||||
address_space_stl(env->address_space_iocsr, w_addr,
|
||||
val, GET_MEMTXATTRS(env), NULL);
|
||||
}
|
||||
|
||||
void helper_iocsrwr_d(CPULoongArchState *env, target_ulong w_addr,
|
||||
target_ulong val)
|
||||
{
|
||||
address_space_stq(&env->address_space_iocsr, w_addr,
|
||||
address_space_stq(env->address_space_iocsr, w_addr,
|
||||
val, GET_MEMTXATTRS(env), NULL);
|
||||
}
|
||||
|
|
15
target/loongarch/trace-events
Normal file
15
target/loongarch/trace-events
Normal file
|
@ -0,0 +1,15 @@
|
|||
# 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_counter(const char *msg) "Failed to get counter from KVM: %s"
|
||||
kvm_failed_put_counter(const char *msg) "Failed to put counter 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"
|
||||
kvm_arch_handle_exit(int num) "kvm arch handle exit, the reason number: %d"
|
||||
kvm_set_intr(int irq, int level) "kvm set interrupt, irq num: %d, level: %d"
|
1
target/loongarch/trace.h
Normal file
1
target/loongarch/trace.h
Normal file
|
@ -0,0 +1 @@
|
|||
#include "trace/trace-target_loongarch.h"
|
Loading…
Add table
Add a link
Reference in a new issue